[GRASS-user] Control of camera position in NVIZ

Maris Nartiss maris.gis at gmail.com
Wed Feb 29 02:07:56 EST 2012

it's possible to control NVIZ from a script. You can export Your road
via v.out.ascii and use the road vertices to set camera position and
the next vertice to set a point where camera points to.

I have been playing around with it some time a go. There might be a
better way now thanks to recent developments in NVIZ scripting
capabilities, still I'm attaching an old TCL script file that I was
using to create animation of fly over a lake while changing a lake
level by loading it from a raster map created by r.lake. If You are
familiar a bit with TCL, You will be able to change that script to
just move camera instead of moving camera and changing raster map too.

Good luck,

2012/2/29 Patrick Proffitt <rpp136 at psu.edu>:
> Using NVIZ, I have been able to visualize a segment of roadway my research
> group scanned with LiDAR.  The visualization is perfect for what we are
> looking for, but there are two things we'd like to do next that I am having
> difficulty with.
> 1) We'd like to make an animation of the roadway from a drivers POV.  Using
> the visualization utilities in NVIZ I have been able to manually adjust the
> viewing perspective of the visualization to a point that looks good, as in
> it looks like what the driver would see if they were in a vehicle and the
> vehicle was on the edge of the visualized surface (or very close to it).
> However is there anyway to advance the camera forward, again as if on a
> vehicle, as if it's driving ON the roadway?  From what I can tell, the
> 'camera', or POV for viewing the visualized surface, can be anywhere on a
> radius away from the surface, however I cannot make the camera advance to
> hover over part of the visualized surface.  I can get a good POV shot for a
> vehicle about to get started on the roadway, but not for driving across it.
> I'd like to make an animation with frame 1 being what I have now, but frame
> 2 etc being that exact same orientation, but with the camera having
> 'advanced' down the roadway.  I cannot seem to make frames 2 onwards.
> 2)  In the future we'd like to collect camera images of the driver's POV
> looking out the front windshield, so that we'd have an image from the
> orientation we'd like to see.  Right now I am adjusting the angles until it
> 'looks good' - is there anyway to use this out-the-windshield image to
> EXACTLY align the visualization into that orientation so that  the image and
> the visualization are identically aligned?  I am also aware of the
> orthophoto utilities in GRASS, however without these images I have been
> unable to play with that.  Will orthophoto do this?
> I recently found POV-Ray which I will be playing with shortly, but I'm
> curious as to if anyone else has had these same needs and if so how you
> worked with it.
> Thanks!
> Patrick
> _______________________________________________
> grass-user mailing list
> grass-user at lists.osgeo.org
> http://lists.osgeo.org/mailman/listinfo/grass-user
-------------- next part --------------
# How it works:
# 1) Create NVIZ state file;
# 2) Copy surface ID that You will change (in this example it is lake with changing water level);
# 3) Set camera position;
# 4) Play script in NVIZ.
# This script is based on d.nviz output. I wrote it a year(?) a go and now wonder - how it is
# possible that it works?
# Anyway - a good beginning for creating own, custom animation script.
# Maris, 05. 02. 2007.
# This is really ugly!
# Maris, 09. 08. 2007.

# NVIZ state file
SendScriptLineWait "load_state_aux /some/path/to/nviz_state3" script_play

puts "Starts... ";
set FRAMES 264;

# surf*foo is random generated when loading surface. Some normal way must exist,
# currently it is copied from state file. (Lake surface ID in nviz state file)
set mhandle3 [ReturnMapHandle surf*1138896892];

# More info in source:
# src/vizualisation/nviz/anim_support.c
SendScriptLine "Nclear_keys"
SendScriptLine "Nupdate_frames"
SendScriptLine "Nset_numsteps $FRAMES"
SendScriptLine "Nupdate_frames"
#SendScriptLine "Nset_interp_mode linear"
SendScriptLine "Nset_interp_mode spline"
SendScriptLine "Nset_tension 0.1"
SendScriptLine "Nupdate_frames"

# Single camera position with real coordinates
# Use d.where or similar to get camera positions
# position.c - RTFM :)
## Camera position (last is Z)
SendScriptLine "Nmove_to_real 584633.854316 6409321.829185 90"
## Camera target
SendScriptLine "Nset_focus_real 573750.33564192 6401754.65674798 55"
## Create keyframe. First integer sets interval between keyframes
SendScriptLine "Nadd_key 1 KF_ALL_MASK 1 0.0"

SendScriptLine "Nmove_to_real 591744.816528 6402709.021853 280"
SendScriptLine "Nset_focus_real 573750.33564192 6401754.65674798 55"
SendScriptLine "Nadd_key 2 KF_ALL_MASK 1 0.0"

SendScriptLine "Nmove_to_real 590487.090928 6392080.094127 600"
SendScriptLine "Nset_focus_real 573750.33564192 6401754.65674798 55"
SendScriptLine "Nadd_key 3.5 KF_ALL_MASK 1 0.0"

SendScriptLine "Nmove_to_real 580760.958497 6386028.557726 1000"
SendScriptLine "Nset_focus_real 573750.33564192 6401754.65674798 55"
SendScriptLine "Nadd_key 5.5 KF_ALL_MASK 1 0.0"

SendScriptLine "Nmove_to_real 570099.802071 6387302.139704 2000"
SendScriptLine "Nset_focus_real 573750.33564192 6401754.65674798 55"
SendScriptLine "Nadd_key 9 KF_ALL_MASK 1 0.0"

set num 0

for {set frame 1} {$frame <= $FRAMES} {incr frame} {
set name frame
set num2 [format "%04d" $num]
append name $num2 ".ppm"
# Change perspective per frame(zoom out) :)
#set persp [expr ($frame  * 2)+60 ]
#SendScriptLine "Nchange_persp $persp"

SendScriptLine "global NVIZ_BLANK_MAPS"
 SendScriptLine "set NVIZ_BLANK_MAPS {}"
 if {$frame < $FRAMES} then { ; # Maps are redrawn on evey fourth frame. No need to draw every frame, as they appear in movie too fast (15-30fps).
  if {[lsearch {} $frame] == -1} then {
   if {[lsearch {} $frame] > -1}  then {
    SendScriptLine "lappend NVIZ_BLANK_MAPS [ExtractMapID $mhandle3]"
   } else {
    set foo [expr int($frame/3)+1]; # redraw every 3rd frame
    # list of all maps - frames. Nasty, but works :)
    # if maps are named like foo001 foo002, is possible to use some loop instead of lindex ;)
    # First - set values for displayed surface
    SendScriptLine "$mhandle3 set_att topo [lindex {bun_391 at lake_fill bun_392 at lake_fill bun_393 at lake_fill } $foo]"
    # Then set surface color
    SendScriptLine "$mhandle3 set_att color [lindex {bun_391 at lake_fill bun_392 at lake_fill bun_393 at lake_fill } $foo]"
    # IIRC this was surface position - I set it a bit abowe it's values, so it always is on top.
    # Like - if lake max depth is 15m (-15m) and it's located 30m asl, last value (here read from lindex) has to be >45.
    SendScriptLine "$mhandle3 set_trans 0 0 [lindex {40.0 40.1 40.2} $foo]"
    # Last thing - set resolution.
    SendScriptLine "$mhandle3 set_res poly 1 1"
#    puts "foo: $foo frame $frame";
SendScriptLine "Ndo_framestep $frame 1"
#puts "Ndo_framestep $frame 1"
after 1;
# Save frame
SendScriptLine "Nwrite_ppm $name "
incr num
SendScriptLine "Noff_screen 0"
SendScriptLine "set ScriptPlaying 0"
puts "DONE!"

More information about the grass-user mailing list