Search code examples
rgisrayshader

How can I convert a rayshader map into a mp4 video while keeping the labels, compass and title during the animation?


Thanks to this wonderful tutorial I've created a gif of a 3D map in order to visualize the spread of a 12 meters sea level rise in the downtown of Wellington !

Screeshot of the map:

Now I would like to know if it was possible to keep the labels, the scalebar and the compass in a video created with the "render_movie" function ? I've been looking to many tutorials but without success so far ! Could someone help me out with that please ?

#GENERATE MP4:

n_frames <- 1080 
waterdepths <- transition_values(from = 0, to = 12.3, steps = n_frames) 

# video transition variables

theta <- transition_values(from = -45, to = 180, steps = n_frames, one_way = TRUE, type = "lin")
phi <- transition_values(from = 40, to = 10, steps = n_frames, one_way = TRUE, type = "cos")
zoom <- transition_values(from = 0.8, to = 0.3, steps = n_frames, one_way = TRUE, type = "cos")

library(av)

zscale <- 2
elev_matrix %>% 
  sphere_shade(sunangle = 270, texture = "imhof1", zscale = zscale) %>%
  add_water(detect_water(elev_matrix), color = "imhof4") %>%
  add_shadow(ambient_shade(elev_matrix, zscale = zscale), 0.5) %>%
  add_shadow(ray_shade(elev_matrix, zscale = zscale, lambert = TRUE), 0.5) %>%
  add_overlay(overlay_img, alphalayer = 0.8) %>%
  plot_3d(elev_matrix, solid = TRUE, shadow = TRUE, zscale = zscale, 
          water = TRUE, watercolor = "imhof3", wateralpha = 0.8, 
          waterlinecolor = "#ffffff", waterlinealpha = 0.5,
          waterdepth = waterdepths/zscale, windowsize = c(1500, 1250))

render_label(elev_matrix, x = 700, y = 650, z = 1500, 
             zscale = 4, text = "Wellington", linecolor="black", freetype=FALSE)

render_label(elev_matrix, x = 1405, y = 1190, z = 800, 
             zscale = 4, text = "Mount Victoria", textcolor = "black", linecolor="darkred",dashed = TRUE, freetype=FALSE)

render_scalebar(limits=c(0, 5, 10),label_unit = "km",position = "W", y=50,
                scale_length = c(0.33,1))

render_compass(position = "E")


render_movie(
  filename = "wellington.mp4", type = "custom",
  frames = 1080,
  phi = phi,
  theta = theta,
  zoom = zoom
)

Unfortunately I only manage to get a nice scene around wellington with this last part of the code (but with no labels and no sea level rising...) :(


Solution

  • Problem solved (make sure ffmpeg path is well set up though) :

    Code:

    
    #generate mp4
    n_frames <- 1080 
    waterdepths <- transition_values(from = 0.5, to = 12.3, steps = n_frames) 
    
    #video transition variables
    theta <- transition_values(from = -15, to = 180, steps = n_frames, one_way = FALSE, type = "lin") 
    phi <- transition_values(from = 40, to = 15, steps = n_frames, one_way = FALSE, type = "cos")
    zoom <- transition_values(from = 0.8, to = 0.3, steps = n_frames, one_way = FALSE, type = "cos") 
    
    
    library(av)
    zscale <- 2
    elev_matrix %>% 
      sphere_shade(sunangle = 270, texture = "imhof1", zscale = zscale) %>%
      add_shadow(ambient_shade(elev_matrix, zscale = zscale), 0.5) %>%
      add_shadow(ray_shade(elev_matrix, zscale = zscale, lambert = TRUE), 0.5) %>%
      add_overlay(overlay_img, alphalayer = 0.8) %>%
      plot_3d(elev_matrix, solid = TRUE, shadow = TRUE, zscale = zscale, 
      windowsize = c(1200, 1000))   
    
    
    render_label(elev_matrix, x = 700, y = 650, z = 1500, 
                 zscale = 2, text = "Wellington", linecolor="black", freetype=FALSE)
    
    render_label(elev_matrix, x = 1405, y = 1190, z = 800, 
                 zscale = 2, text = "Mount Victoria", textcolor = "black", linecolor="darkred",dashed = TRUE, freetype=FALSE)
    
    
    
    for(i in 1:1080) {
    
    render_water(elev_matrix, watercolor = "lightblue", wateralpha = 0.8, 
                   waterlinecolor = "#ffffff", waterlinealpha = 0.5,
                   waterdepth = waterdepths[i]/zscale)
    
    render_camera(theta=theta[i], phi=phi[i], zoom=zoom[i])
    
    render_snapshot(filename = sprintf("welli%i.png", i), 
                    title_text = "Wellington, New Zealand | Imagery: ESRI_Imagery | DSM: 1m, source: Open Topography",
                    title_bar_color = "#1f5214", title_color = "white", title_bar_alpha = 1)
    }
    rgl::rgl.close()
    
    
    av::av_encode_video(sprintf("welli%d.png",seq(1,1080,by=1)), framerate = 30,
                       output = "wellington.mp4")