###################### # # PATHcHT2.SML # # Demonstration of movie generation from 3D display using # 2D vector objects to derive viewer position (flight) path # and path of view center. Both 2D and 3D views are # copied into each movie frame. Current viewer position and # view center positions are shown in each 2D frame. # # Script uses input DEM for surface, an input raster drape layer, and # two input vector objects, each with a single line, one defining the # ground trace of the viewer position and the other defining the ground # trace of the view center. # # Computes flight path at constant height above the # surface. View center moves on the surface. # Both paths are partitioned into equal segments to set # positions for capturing frames (to produce smoother motion). # # Flight path and view center path are marked in frame by "trails" # of circle symbols behind current positions. # # Requires TNTmips Version 6.5 # ##################### clear(); #### Set movie format, frame rate, and recording time # Movie format (Possible values : "MPEG"(All platform) or "AVI"(Windows only) string format$; format$ = "AVI"; # Frame rate # Possible values : # "MOVIE_FRAMERATE_23_976" 23.976 (24000/1001) fps - NTSC encapsulated film rate # "MOVIE_FRAMERATE_24" 24 fps - Standard international cinema film rate # "MOVIE_FRAMERATE_25" 25 fps - PAL (625/50) video frame rate # "MOVIE_FRAMERATE_29_970" 29.97 (30000/1001) fps - NTSC video frame rate # "MOVIE_FRAMERATE_30" 30 fps - NTSC drop-frame (525/60) video frame rate # "MOVIE_FRAMERATE_50" 50 fps - Double frame rate / progressive PAL # "MOVIE_FRAMERATE_59_940" 59.94 (60000/1001) fps - Double frame rate NTSC # "MOVIE_FRAMERATE_60" 60 fps - Double frame rate drop-frame NTSC string framerate$; framerate$ = "MOVIE_FRAMERATE_24"; # Recording time (seconds) numeric time; time = 60; ####### Get RVC objects to load raster Surface, RastDrape; vector FlightPathVec, ViewCenterVec; print("Select raster to use for surface"); GetInputRaster(Surface); print("Select raster to use for drape layer"); GetInputRaster(RastDrape); print("Select 3D vector to use for flight path"); GetInputVector(FlightPathVec); print("Select vector to use for view center path"); GetInputVector(ViewCenterVec); ###### RVC style object to draw center point and viewer point string styleFilename$; string styleObjectname$; GetInputObject("Style","Select style object for center and viewer point symbols:", styleFilename$, styleObjectname$); string viewer$; viewer$ = "VIEWER"; string center$; center$ = "CENTER"; ######## Create display group with 2d and 3d views print("START"); # Size of squared 2D view and 3D view; # Should be evenly divisible by 8 numeric size; size = 320; # Zoom out factor for 2D view numeric zoomfactor; zoomfactor = 1.0; # Create group print("Creating Group"); class GRE_GROUP group; group = GroupCreate(); # Create flag to create view without iconbar, scrollbars, status line and scale/position line # This is important to maintain fixed window size for movie generation string flags$; flags$ = "NoScalePosLine,NoIconBar,NoScrollbars,NoStatusLine"; # Create dialog and 2D view print("Creating dialog and 2D view"); class XmForm dialog2d; class GRE_VIEW view2d; dialog2d = CreateFormDialog("VIEW 2D"); view2d = GroupCreateView(group,dialog2d,"",size,size,flags$); view2d.BackgroundColor.red = 67; view2d.BackgroundColor.green = 100; view2d.BackgroundColor.blue = 100; # Create dialog and 3D view print("Creating dialog and 3D view"); class XmForm dialog3d; class GRE_VIEW3D view3d; dialog3d = CreateFormDialog("VIEW 3D"); view3d = GroupCreate3DView(group,dialog3d,"",size,size,flags$); view3d.BackgroundColor.red = 67; view3d.BackgroundColor.green = 100; view3d.BackgroundColor.blue = 100; # Add layers to group GroupQuickAddRasterVar(group,Surface,1); GroupQuickAddRasterVar(group,RastDrape,0); # Open both views DialogOpen(dialog2d); DialogOpen(dialog3d); # Full redraw of both views ViewRedrawFull(view2d); ViewRedrawFull(view3d); ViewZoomOut(view2d,zoomfactor,1); ####### Set up parameters for movie frame # Destination of each view in frame for movie numeric x2d, y2d, x3d, y3d, w, h; x2d = 0; y2d = 0; x3d = size; y3d = 0; w = 2 * size; h = size; # Create text string for annotation in frame string frameTitle$; frameTitle$ = "Muddy Mountains, NV"; # Font size for annotation in frame numeric fontsize; fontsize = 16; # Define color for text annotation in frame class Color black; black.red = 0; black.green = 0; black.blue = 0; # Define color for flight path symbols class Color colorf; colorf.red = 0; colorf.green = 100; colorf.blue = 0; # Define color for center path symbols class Color colorc; colorc.red = 100; colorc.green = 0; colorc.blue = 0; # Create frame print("Creating frame for movie"); class Frame frame; frame = FrameCreate(w,h); # Create graphics context (GC) for frame print("Creating GC for frame and activate it"); ActivateGC(FrameCreateGC(frame)); DrawTextSetHeightPixels(fontsize); DrawUseStyleObject(styleFilename$,styleObjectname$); ######## Set some more movie parameters # Initialize Movie print("Initializing Movie"); class Movie movie; movie = MovieInit(); # Check framerate and force it to "MOVIE_FRAMERATE_24" if it is invalid numeric rate; rate = 24; if (framerate$ == "MOVIE_FRAMERATE_23_976") rate = 23.976; if (framerate$ == "MOVIE_FRAMERATE_25") rate = 25.0; if (framerate$ == "MOVIE_FRAMERATE_29_970") rate = 29.970; if (framerate$ == "MOVIE_FRAMERATE_30") rate = 30.0; if (framerate$ == "MOVIE_FRAMERATE_50") rate = 50.0; if (framerate$ == "MOVIE_FRAMERATE_59_940") rate = 59.940; if (framerate$ == "MOVIE_FRAMERATE_60") rate = 60.0; if (rate == 24.0) framerate$ = "MOVIE_FRAMERATE_24"; # Set Movie Parameters print("Setting Movie Parameters"); MovieSetFormat(movie,format$); MovieSetFrameRate(movie,framerate$); MovieSetFrameWidth(movie,w); MovieSetFrameHeight(movie,h); # Make Output File string ext$; ext$ = MovieGetFileExt(movie); string filename$; filename$ = GetOutputFileName("","Make filename for movie",ext$); printf("Filename = %s\n",filename$); # Check recording time if (time <= 1.0) time = 1.0; # Calculate number of frames numeric numFrames = time * rate; ####### Get georeference parameters for layers and reset to group projection ####### (defined by raster drape layer) # Georeference for surface layer class Georef georefS; georefS = GetLastUsedGeorefObject(Surface); GeorefSetProjection(georefS,group.Projection); # Georeference for flight path vector object class Georef georefFlight; georefFlight = GetLastUsedGeorefObject(FlightPathVec); GeorefSetProjection(georefFlight,group.Projection); # Georeference for view center path vector object class Georef georefCent; georefCent = GetLastUsedGeorefObject(ViewCenterVec); GeorefSetProjection(georefCent,group.Projection); ####### Compute flight path from 2D vector line # Create arrays to hold vertex x and y coordinates for input flight path line numeric numflight; # number of vertices in flight path line array numeric xarrayf [1]; # array to hold x-coordinates of flight line vertices array numeric yarrayf [1]; # array to hold y-coordinates of flight line vertices # Get x and y coordinates of line vertices numflight = GetVectorLinePointList(FlightPathVec,xarrayf,yarrayf,1); # Transform vertex coordinates for flight path to map coordinates for group # and find surface Z-value for each vertex array numeric zarrayf [numflight]; # array to hold z-coordinates of flight line vertices numeric obj_x; numeric obj_y; numeric map_x; numeric map_y; numeric i; for i = 1 to numflight { obj_x = xarrayf[i]; obj_y = yarrayf[i]; ObjectToMap(FlightPathVec,obj_x,obj_y,georefFlight,map_x,map_y); xarrayf[i] = map_x; yarrayf[i] = map_y; MapToObject(georefS,map_x,map_y,Surface,obj_x,obj_y); zarrayf[i] = Surface[obj_y,obj_x]; } # Set height of flight path above surface and compute array of # z-values for path numeric heightAboveSurf; heightAboveSurf = 1000; for i = 1 to numflight { zarrayf[i] = zarrayf[i] + heightAboveSurf; } # Compute length of 3D flight path and movement increment numeric dx; numeric dy; numeric dz; numeric dl; numeric lengthf; # flight path length in meters numeric incFlight; # movement increment along flight path lengthf = 0; for i = 1 to (numflight - 1) { dx = xarrayf[i+1] - xarrayf[i]; dy = yarrayf[i+1] - yarrayf[i]; dz = zarrayf[i+1] - zarrayf[i]; dl = sqrt( dx*dx + dy*dy + dz*dz ); lengthf = lengthf + dl; } incFlight = lengthf / (numFrames - 1); # Recalculate equal-distance vertices for flight path array numeric xarrayf_eq [numFrames]; # array to hold x-coordinates of flight line vertices array numeric yarrayf_eq [numFrames]; # array to hold y-coordinates of flight line vertices array numeric zarrayf_eq [numFrames]; # array to hold z-coordinates of flight line vertices xarrayf_eq[1] = xarrayf[1]; yarrayf_eq[1] = yarrayf[1]; zarrayf_eq[1] = zarrayf[1]; numeric numvert_eq; numeric indexf; numeric coef; numeric sum; numeric rest; numvert_eq = 1; indexf = 1; rest = 0.0; while (numvert_eq < (numFrames - 1)) { dx = xarrayf[indexf+1] - xarrayf[indexf]; dy = yarrayf[indexf+1] - yarrayf[indexf]; dz = zarrayf[indexf+1] - zarrayf[indexf]; dl = sqrt( dx*dx + dy*dy + dz*dz ); rest = rest + dl; sum = 0.0; while ((rest > incFlight) and (numvert_eq < (numFrames - 1) ) ) { rest = rest - incFlight; sum = sum + incFlight; numvert_eq = numvert_eq + 1; coef = sum / dl; xarrayf_eq[numvert_eq] = xarrayf[indexf] + coef * dx; yarrayf_eq[numvert_eq] = yarrayf[indexf] + coef * dy; zarrayf_eq[numvert_eq] = zarrayf[indexf] + coef * dz; } indexf = indexf + 1; } xarrayf_eq[numFrames] = xarrayf[numflight]; yarrayf_eq[numFrames] = yarrayf[numflight]; zarrayf_eq[numFrames] = zarrayf[numflight]; ##### Compute view center path from 2D vector line # Create arrays to hold vertex coordinates of view center line # Arrays will be resized automatically by the GetVectorLinePointList function numeric numcent; # number of vertices in view center line array numeric xarrayc [1]; # array to hold x-coordinates of center line vertices array numeric yarrayc [1]; # array to hold y-coordinates of center line vertices # Get x and y coordinates of line vertices numcent = GetVectorLinePointList(ViewCenterVec,xarrayc,yarrayc,1); # Transform vertex coordinates for view center path to map coordinates for group # and find surface Z-value for each vertex array numeric zarrayc [numcent]; # array to hold z-coordinates of center line vertices for i = 1 to numcent { obj_x = xarrayc[i]; obj_y = yarrayc[i]; ObjectToMap(ViewCenterVec,obj_x,obj_y,georefCent,map_x,map_y); xarrayc[i] = map_x; yarrayc[i] = map_y; MapToObject(georefS,map_x,map_y,Surface,obj_x,obj_y); zarrayc[i] = Surface[obj_y,obj_x]; } # Compute length of view center path and movement increment numeric lengthc; # view center path 3D length in map meters numeric incCent; # movement increment along view center path lengthc = 0; for i = 1 to (numcent-1) { dx = xarrayc[i+1] - xarrayc[i]; dy = yarrayc[i+1] - yarrayc[i]; dz = zarrayc[i+1] - zarrayc[i]; dl = sqrt( dx*dx + dy*dy + dz*dz ); lengthc = lengthc + dl; } incCent = lengthc / numFrames; # Recalculate equal-distance vertices for center path array numeric xarrayc_eq [numFrames]; # array to hold x-coordinates of center line vertices array numeric yarrayc_eq [numFrames]; # array to hold y-coordinates of center line vertices array numeric zarrayc_eq [numFrames]; # array to hold z-coordinates of center line vertices xarrayc_eq[1] = xarrayc[1]; # first vertex is the same for new path yarrayc_eq[1] = yarrayc[1]; zarrayc_eq[1] = zarrayc[1]; numeric numcent_eq; numeric indexc; numcent_eq = 1; indexc = 1; rest = 0.0; while (numcent_eq < (numFrames - 1)) { dx = xarrayc[indexc+1] - xarrayc[indexc]; dy = yarrayc[indexc+1] - yarrayc[indexc]; dz = zarrayc[indexc+1] - zarrayc[indexc]; dl = sqrt( dx*dx + dy*dy + dz*dz ); rest = rest + dl; sum = 0.0; while ((rest > incCent) and ( numcent_eq < (numFrames - 1) ) ) { rest = rest - incCent; sum = sum + incCent; numcent_eq = numcent_eq + 1; coef = sum / dl; xarrayc_eq[numcent_eq] = xarrayc[indexc] + coef * dx; yarrayc_eq[numcent_eq] = yarrayc[indexc] + coef * dy; zarrayc_eq[numcent_eq] = zarrayc[indexc] + coef * dz; } indexc = indexc + 1; } xarrayc_eq[numFrames] = xarrayc[numcent]; # last vertex is the same also yarrayc_eq[numFrames] = yarrayc[numcent]; zarrayc_eq[numFrames] = zarrayc[numcent]; ##### Set up arrays for drawing "trails" of previous viewer and center positions array numeric xarrayfs[numFrames]; # arrays for viewer position in screen coordinates array numeric yarrayfs[numFrames]; array numeric xarraycs[numFrames]; # arrays for center position in screen coordinates array numeric yarraycs[numFrames]; ##### Set up viewpoint and viewer position variables class VIEWPOINT3D vp; vp = view3d.ViewPoint; class POINT3D fpt; # flight path location class POINT3D cpt; # center point location class POINT2D point; # 2D point for location symbols ##### Start recording movie to file MovieStart(movie,filename$); # Loop for each frame for i = 1 to numFrames { SetStatusMessage(sprintf("Processing frame %d of %d",i,numFrames)); # Set viewer position and center position and redraw views fpt.x = xarrayf_eq[i]; fpt.y = yarrayf_eq[i]; fpt.z = zarrayf_eq[i]; vp.SetViewerPosition(fpt); cpt.x = xarrayc_eq[i]; cpt.y = yarrayc_eq[i]; cpt.z = zarrayc_eq[i]; vp.SetCenter(cpt); # ViewRedrawDirect(view3d,"NoBlankScreen"); # This new function added after release of TNTmips 6.5 # can redraw the view without blanking it first. Use of # this function eliminates "flashing" of the view as the # movie is initially rendered. It has no effect on the # output movie file. For 6.5 release version, use the # function in the next statement. ViewRedraw(view3d); # Copy 2d view and 3d view to destination frame FrameCopyFromView(frame,view2d,0,0,size,size,x2d,y2d); FrameCopyFromView(frame,view3d,0,0,size,size,x3d,y3d); # Draw previous center points in 2d frame numeric j; for j = 1 to (i - 1) { SetColor(colorc); FillCircle(xarraycs[j],yarraycs[j],2); } # Draw center point in 2d frame point.x = vp.CenterPoint.x; point.y = vp.CenterPoint.y; point = TransPoint2D(point,ViewGetTransMapToView(view2d,group.Projection)); point = TransPoint2D(point,ViewGetTransViewToScreen(view2d)); DrawSetPointStyle(center$); DrawPoint(point.x,point.y); xarraycs[i] = point.x; yarraycs[i] = point.y; # Draw previous viewer points in 2d frame for j = 1 to (i - 1) { SetColor(colorf); FillCircle(xarrayfs[j],yarrayfs[j],2); } # Draw viewer position point in 2d frame point.x = vp.ViewPos.x; point.y = vp.ViewPos.y; point = TransPoint2D(point,ViewGetTransMapToView(view2d,group.Projection)); point = TransPoint2D(point,ViewGetTransViewToScreen(view2d)); DrawSetPointStyle(viewer$); DrawPoint(point.x,point.y); xarrayfs[i] = point.x; yarrayfs[i] = point.y; # Draw text to top of frame DrawTextSetColors(black); DrawTextSimple(frameTitle$,2,fontsize); # Add frame to movie MovieAddFrame(movie,frame); } # End of main processing loop # Stop and Exit movie MovieStop(movie); MovieExit(movie); # Close dialogs DialogClose(dialog2d); DialogClose(dialog3d); print("END");