/*----------------------------------------------------------------------------*/ /* Scenome 1.0 SubdividePreviewMesh */ /* */ /* SUBDIVIDE_PREVIEW_MESH.SSL */ /* */ /* Copyright (c) 2007 Scenomics. All Rights Reserved. */ /*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/ /* AddNode Function */ /*----------------------------------------------------------------------------*/ function int AddNode( Node new_node, Group parentNode ) { Model.AddNode( new_node, parentNode, -1 ); Model.Deselect( parentNode ); return 1; } /*----------------------------------------------------------------------------*/ /* SubdividePreviewMesh */ /*----------------------------------------------------------------------------*/ // This command subdivides a preview mesh into smaller tiles by using the // tessellation of the preview mesh to establish tessellation rules. // DO NOT MODIFY THIS SCRIPT! If you wish to make changes // to this script please create a copy first. Do not forget to change // the macro name and generate a unique GUID. macro SubdividePreviewMesh() [ Category="Mesh Commands", Guid="{7C521533-C85D-4BC5-AEAC-89F8C7C36AFC}", Image=".\\icons\\subdivide_geographic_tiles_icon.bmp" ] { for( int i = 0; i < Model.GetSelectCount(); ++i ) { Node node = Model.GetSelectedNode( i ).GetNode(); // Find the parent of the selected preview mesh node. Node parentNode = node.Parent(); // Find the grandparent of the selected preview mesh node. // The new output is created as sibling nodes of the preview mesh parent. Node grandParent = parentNode.Parent(); // Hide the parent of the preview mesh node so we can see the new output. parentNode.Visible = !parentNode.Visible; // Get the preview mesh palette group. Group existingPalette = (Group)((Group)parentNode).Children[ 0 ]; // Get the preview mesh material node. Material inputMAT = (Material)((Group)existingPalette).Children[ 0 ]; inputMAT.AmbientColor.SetRGB(102,102,102); // Get the preview mesh texture node. Texture inputTEX = (Texture)((Group)existingPalette).Children[ 1 ]; // Perform type checking. if( node.IsDerived( ParametricMesh ) ) { // Create objects from the construction history. Modifier parameters will be copied and // in some cases modified as necessary to subdivide the geographic tile. ExportOptionsModifier inputEOM = (ExportOptionsModifier)((ParametricMesh)node).Children[ 0 ]; TerrainOptionsModifier inputTOM = (TerrainOptionsModifier)((ParametricMesh)node).Children[ 1 ]; RectanglePrimitive inputRGM = (RectanglePrimitive)((ParametricMesh)node).Children[ 2 ]; DisplaceModifier inputDPM = (DisplaceModifier)((ParametricMesh)node).Children[ 3 ]; GeographicProjectionModifier inputGPM = (GeographicProjectionModifier)((ParametricMesh)node).Children[ 4 ]; DynamicTextureModifier inputDTM = (DynamicTextureModifier)((ParametricMesh)node).Children[ 5 ]; CalculateNormalsModifier inputCNM = (CalculateNormalsModifier)((ParametricMesh)node).Children[ 6 ]; // Derive loop iteration variables from the RectangleGeometryModifier tessellation values. int colCount = inputRGM.XSubdivision; int rowCount = inputRGM.YSubdivision; // copy values from input OrthoImageryOptionsModifier int outputUseTextureDirectory = inputTOM.UseTextureFile; string outputTexturePath = inputTOM.TextureFile; string outputPreviewTextureWidth = inputTOM.PreviewTextureWidth; string outputPreviewTextureHeight = inputTOM.PreviewTextureHeight; string outputTessellationX = inputEOM.TileTessellationX; string outputTessellationY = inputEOM.TileTessellationY; string outputTextureDirectory = inputTOM.TileTextureDirectory; string outputTileTextureWidth = inputTOM.TileTextureWidth; string outputTileTextureHeight = inputTOM.TileTextureHeight; // copy values from input ExportOptionsModifier int outputExternalize = inputEOM.Externalize; string outputExportDirectory = inputEOM.ExternalDirectory; string outputLocalDatabasePath = inputEOM.LocalDatabasePath; int outputLODCount = inputEOM.LODCount; // copy values from input RectangleGeometryModifier double outputRectangleMinimumX = inputRGM.XMin; double outputRectangleMinimumY = inputRGM.YMin; double outputRectangleMaximumX = inputRGM.XMax; double outputRectangleMaximumY = inputRGM.YMax; int outputRectangleTessellationX = inputRGM.XSubdivision; int outputRectangleTessellationY = inputRGM.YSubdivision; // copy values from input RectangleGeometryModifier for( int r = 0; r < rowCount; ++r ) { for( int c = 0; c < colCount; ++c ) { // Add the new container group. Group topLevel = new Group; topLevel.Name = "PreviewMesh: " + outputLocalDatabasePath + "_" + ( r + 1 ) + "x" + ( c + 1 ); AddNode( topLevel, (Group)grandParent ); // Add the new palette group. Group newPalette = new Group; newPalette.Name = "Palette " + ( r + 1 ) + "x" + ( c + 1 ); AddNode( newPalette, (Group)topLevel ); // Create a new image and save it as a bitmap on the hard disk. string texturepath = ".\\temporary_texture\\"; string textureimagefilename = texturepath + ( r + 1 ) + "x" + ( c + 1 ) + ".bmp"; // Create a new texture node and link it to the new bitmap created above. Texture newTexture = new Texture; newTexture.External = 1; newTexture.PathToFile = textureimagefilename; newTexture.Name = "Texture: " + ( r + 1 ) + "x" + ( c + 1 ); // Create a new material node and link it to the texture node created above. Material newMaterial = new Material; newMaterial.Name = "Material: " + ( r + 1 ) + "x" + ( c + 1 ); newMaterial.AmbientColor.SetRGB(102,102,102); newMaterial.TextureLink = newTexture; AddNode( newMaterial, (Group)newPalette ); AddNode( newTexture, (Group)newPalette ); // Create a a new mesh and link it to the palette group created above. ParametricMesh newPreviewMesh = new ParametricMesh; newPreviewMesh.Name = ( r + 1 ) + "x" + ( c + 1 ); newPreviewMesh.PaletteGroup = newPalette; AddNode( newPreviewMesh, (Group)topLevel ); // Add the construction history and copy/modify the existing modifier parameters as necessary. ExportOptionsModifier newExportOptionsModifier = new ExportOptionsModifier; newExportOptionsModifier.Name = "ExportOptionsLayer"; newExportOptionsModifier.TileTessellationX = outputTessellationX; newExportOptionsModifier.TileTessellationY = outputTessellationY; newExportOptionsModifier.Externalize = outputExternalize; newExportOptionsModifier.ExternalDirectory = outputExportDirectory + "_" + ( r + 1 ) + "x" + ( c + 1 ); TerrainOptionsModifier newTerrainOptionsModifier = new TerrainOptionsModifier; newTerrainOptionsModifier.Name = "OrthoImageryLayer"; newTerrainOptionsModifier.UseTextureFile = inputTOM.UseTextureFile; newTerrainOptionsModifier.TextureFile = outputTexturePath; newTerrainOptionsModifier.TileTextureDirectory = outputTextureDirectory; newTerrainOptionsModifier.PreviewTextureWidth = outputPreviewTextureWidth; newTerrainOptionsModifier.PreviewTextureHeight = outputPreviewTextureHeight; newTerrainOptionsModifier.Enable = "True"; string subtraction = " "; string SubtractTerms = ( subtraction + outputExportDirectory ); newExportOptionsModifier.LocalDatabasePath = outputLocalDatabasePath + "_" + ( r + 1 ) + "x" + ( c + 1 ); newExportOptionsModifier.LODCount = outputLODCount; if( newExportOptionsModifier.LODCount > 1 ) { int simplify = 0; int simplifyIncrement = 100 / newExportOptionsModifier.LODCount; for( int lod = 0; lod < newExportOptionsModifier.LODCount; ++lod ) { newExportOptionsModifier.SimplifyPercentages[lod] = simplify; simplify += simplifyIncrement; } } newTerrainOptionsModifier.Enable = !newTerrainOptionsModifier.Enable; AddNode( newExportOptionsModifier, (Group)newPreviewMesh ); AddNode( newTerrainOptionsModifier, (Group)newPreviewMesh ); RectanglePrimitive newRectanglePrimitive = new RectanglePrimitive; int xsubcopy = inputRGM.XSubdivision; int ysubcopy = inputRGM.YSubdivision; newRectanglePrimitive.Name = "GeometryLayer: " + xsubcopy + "x" + ysubcopy; // This can't be a straightforward copy. We have to do some math to establish // the correct new tile extents along X and Y. // First establish the minimum coordinates. double StartX = inputRGM.XMin; double StartY = inputRGM.YMin; // Now establish the range for each tile by dividing the span along x/y by the input tessellation. double RangeX = ( inputRGM.XMax - inputRGM.XMin ) / inputRGM.XSubdivision; double RangeY = ( inputRGM.YMax - inputRGM.YMin ) / inputRGM.YSubdivision; // Now set the new output coordinates, using the minimum coordinates as the basis. newRectanglePrimitive.XMin = StartX + ( RangeX * r ); newRectanglePrimitive.YMin = StartY + ( RangeY * c ); newRectanglePrimitive.XMax = StartX + RangeX * ( r + 1 ); newRectanglePrimitive.YMax = StartY + RangeY * ( c + 1 ); // Application.Log.LogString ( "range: " + RangeX + " x " + RangeY ); // newRectanglePrimitive.XMin = outputRectangleMinimumX; // newRectanglePrimitive.YMin = outputRectangleMinimumY; // newRectanglePrimitive.XMax = outputRectangleMaximumX; // newRectanglePrimitive.YMax = outputRectangleMaximumY; newRectanglePrimitive.MaterialLink = newMaterial; newRectanglePrimitive.XSubdivision = outputRectangleTessellationX; newRectanglePrimitive.YSubdivision = outputRectangleTessellationY; int zone = ( newRectanglePrimitive.XMin + ( newRectanglePrimitive.XMax - newRectanglePrimitive.XMin ) / 2 + 180 ) / 6 + 1; AddNode( newRectanglePrimitive, (Group)newPreviewMesh ); DisplaceModifier newDisplaceModifier = new DisplaceModifier; newDisplaceModifier.Name = "ElevationLayer"; newDisplaceModifier.Translation = inputDPM.Translation; newDisplaceModifier.MapFile = inputDPM.MapFile; // This can't be a straightforward copy. We have to do some math to establish // the correct new displacement extents along X and Y. // First establish the minimum coordinates. double StartCornerX = inputDPM.CornerX; double StartCornerY = inputDPM.CornerY; double DisplaceWidth = inputDPM.Width; double DisplaceHeight = inputDPM.Length; // Now establish the range for each tile by dividing the span along x/y by the input tessellation. double DisplaceRangeX = DisplaceWidth / inputRGM.XSubdivision; double DisplaceRangeY = DisplaceHeight / inputRGM.YSubdivision ; Application.Log.LogString ( DisplaceRangeX + " x " + DisplaceRangeY ); // Now set the new output coordinates, using the minimum coordinates as the basis. newDisplaceModifier.CornerX = StartCornerX + ( DisplaceRangeX * r ); newDisplaceModifier.CornerY = StartCornerY + ( DisplaceRangeY * c ); newDisplaceModifier.Width = StartCornerX + DisplaceRangeX; newDisplaceModifier.Length = StartCornerY + DisplaceRangeY; newDisplaceModifier.ImageryIs24Bit = inputDPM.ImageryIs24Bit; newDisplaceModifier.MinimumHeight = inputDPM.MinimumHeight; newDisplaceModifier.MaximumHeight = inputDPM.MaximumHeight; newDisplaceModifier.OverallMinimumHeight = inputDPM.OverallMinimumHeight; newDisplaceModifier.OverallMaximumHeight = inputDPM.OverallMaximumHeight; AddNode( newDisplaceModifier, (Group)newPreviewMesh ); GeographicProjectionModifier newGeographicProjectionModifier = new GeographicProjectionModifier; newGeographicProjectionModifier.SetProjection( inputGPM.GetProjection() ); newGeographicProjectionModifier.UTMZone = inputGPM.UTMZone; newGeographicProjectionModifier.Name = "GeographicProjectionLayer"; AddNode( newGeographicProjectionModifier, (Group)newPreviewMesh ); DynamicTextureModifier newDynamicTextureModifier = new DynamicTextureModifier; newDynamicTextureModifier.Name = "DynamicTextureLayer"; AddNode( newDynamicTextureModifier, (Group)newPreviewMesh ); CalculateNormalsModifier newCalculateNormalsModifier = new CalculateNormalsModifier; newCalculateNormalsModifier.Name = "CalculateLightingLayer"; AddNode( newCalculateNormalsModifier, (Group)newPreviewMesh ); } } } } }