internal FormatYielder Spawn(UnparsableAst child, ChildLocation childLocation = ChildLocation.Unknown) { if (childLocation == ChildLocation.Unknown) { return(new FormatYielder(this) { topAncestorCacheForLeft = UnparsableAst.NonCalculated }); } else { bool isLeftMostChild = childLocation == ChildLocation.Only || direction == Unparser.Direction.LeftToRight && childLocation == ChildLocation.First || direction == Unparser.Direction.RightToLeft && childLocation == ChildLocation.Last; return(new FormatYielder(this) { topAncestorCacheForLeft = isLeftMostChild ? this.topAncestorCacheForLeft : (child ?? UnparsableAst.NonCalculated) }); } }
/// <summary> /// Create child tile terrain mesh /// Build the mesh with one extra vertice all around for proper normals calculations later on. /// Use the struts vertices to that effect. Struts are properly folded after normals calculations. /// </summary> protected void CreateElevatedMesh(ChildLocation corner, CustomVertex.PositionNormalTextured[] vertices, double meshBaseRadius, float[,] heightData) { // Figure out child lat/lon boundaries (radians) double north = MathEngine.DegreesToRadians(North); double west = MathEngine.DegreesToRadians(West); // Texture coordinate offsets float TuOffset = 0; float TvOffset = 0; switch (corner) { case ChildLocation.NorthWest: // defaults are all good break; case ChildLocation.NorthEast: west = MathEngine.DegreesToRadians(0.5 * (West + East)); TuOffset = 0.5f; break; case ChildLocation.SouthWest: north = MathEngine.DegreesToRadians(0.5 * (North + South)); TvOffset = 0.5f; break; case ChildLocation.SouthEast: north = MathEngine.DegreesToRadians(0.5 * (North + South)); west = MathEngine.DegreesToRadians(0.5 * (West + East)); TuOffset = 0.5f; TvOffset = 0.5f; break; } double latitudeRadianSpan = MathEngine.DegreesToRadians(LatitudeSpan); double longitudeRadianSpan = MathEngine.DegreesToRadians(LongitudeSpan); double layerRadius = (double)QuadTileSet.LayerRadius; double scaleFactor = 1.0 / vertexCountElevated; int terrainLongitudeIndex = (int)(TuOffset * vertexCountElevated) + 1; int terrainLatitudeIndex = (int)(TvOffset * vertexCountElevated) + 1; int vertexCountElevatedPlus1 = vertexCountElevated / 2 + 1; double radius = 0; int vertexIndex = 0; for (int latitudeIndex = -1; latitudeIndex <= vertexCountElevatedPlus1; latitudeIndex++) { double latitudeFactor = latitudeIndex * scaleFactor; double latitude = north - latitudeFactor * latitudeRadianSpan; // Cache trigonometric values double cosLat = Math.Cos(latitude); double sinLat = Math.Sin(latitude); for (int longitudeIndex = -1; longitudeIndex <= vertexCountElevatedPlus1; longitudeIndex++) { // Top of mesh for all (real terrain + struts) radius = layerRadius + heightData[terrainLatitudeIndex + latitudeIndex, terrainLongitudeIndex + longitudeIndex] * verticalExaggeration; double longitudeFactor = longitudeIndex * scaleFactor; // Texture coordinates vertices[vertexIndex].Tu = TuOffset + (float)longitudeFactor; vertices[vertexIndex].Tv = TvOffset + (float)latitudeFactor; // Convert from spherical (radians) to cartesian double longitude = west + longitudeFactor * longitudeRadianSpan; double radCosLat = radius * cosLat; vertices[vertexIndex].X = (float)(radCosLat * Math.Cos(longitude) - localOrigin.X); vertices[vertexIndex].Y = (float)(radCosLat * Math.Sin(longitude) - localOrigin.Y); vertices[vertexIndex].Z = (float)(radius * sinLat - localOrigin.Z); vertexIndex++; } } }
/// <summary> /// Create child tile terrain mesh /// </summary> protected void CreateElevatedMesh(ChildLocation corner, CustomVertex.PositionTextured[] vertices, double meshBaseRadius, float[,] heightData) { // Figure out child lat/lon boundaries (radians) double north = MathEngine.DegreesToRadians(North); double west = MathEngine.DegreesToRadians(West); // Texture coordinate offsets float TuOffset = 0; float TvOffset = 0; switch (corner) { case ChildLocation.NorthWest: // defaults are all good break; case ChildLocation.NorthEast: west = MathEngine.DegreesToRadians(0.5 * (West + East)); TuOffset = 0.5f; break; case ChildLocation.SouthWest: north = MathEngine.DegreesToRadians(0.5 * (North + South)); TvOffset = 0.5f; break; case ChildLocation.SouthEast: north = MathEngine.DegreesToRadians(0.5 * (North + South)); west = MathEngine.DegreesToRadians(0.5 * (West + East)); TuOffset = 0.5f; TvOffset = 0.5f; break; } double latitudeRadianSpan = MathEngine.DegreesToRadians(LatitudeSpan); double longitudeRadianSpan = MathEngine.DegreesToRadians(LongitudeSpan); double layerRadius = (double)QuadTileSet.LayerRadius; double scaleFactor = 1.0 / vertexCountElevated; int terrainLongitudeIndex = (int)(TuOffset * vertexCountElevated); int terrainLatitudeIndex = (int)(TvOffset * vertexCountElevated); int vertexCountElevatedPlus1 = vertexCountElevated / 2 + 1; double radius = 0; int vertexIndex = 0; for (int latitudeIndex = -1; latitudeIndex <= vertexCountElevatedPlus1; latitudeIndex++) { int latitudePoint = latitudeIndex; if (latitudePoint < 0) { latitudePoint = 0; } else if (latitudePoint >= vertexCountElevatedPlus1) { latitudePoint = vertexCountElevatedPlus1 - 1; } double latitudeFactor = latitudePoint * scaleFactor; double latitude = north - latitudeFactor * latitudeRadianSpan; // Cache trigonometric values double cosLat = Math.Cos(latitude); double sinLat = Math.Sin(latitude); for (int longitudeIndex = -1; longitudeIndex <= vertexCountElevatedPlus1; longitudeIndex++) { int longitudePoint = longitudeIndex; if (longitudePoint < 0) { longitudePoint = 0; } else if (longitudePoint >= vertexCountElevatedPlus1) { longitudePoint = vertexCountElevatedPlus1 - 1; } if (longitudeIndex != longitudePoint || latitudeIndex != latitudePoint) { if (heightData != null && (!renderStruts || m_CurrentOpacity < 255)) { radius = layerRadius + heightData[terrainLatitudeIndex + latitudePoint, terrainLongitudeIndex + longitudePoint] * verticalExaggeration; } else { radius = meshBaseRadius; } // // Mesh base (flat) // radius = meshBaseRadius; } else { // Top of mesh (real terrain) radius = layerRadius + heightData[terrainLatitudeIndex + latitudeIndex, terrainLongitudeIndex + longitudeIndex] * verticalExaggeration; } double longitudeFactor = longitudePoint * scaleFactor; // Texture coordinates vertices[vertexIndex].Tu = TuOffset + (float)longitudeFactor; vertices[vertexIndex].Tv = TvOffset + (float)latitudeFactor; // Convert from spherical (radians) to cartesian double longitude = west + longitudeFactor * longitudeRadianSpan; double radCosLat = radius * cosLat; vertices[vertexIndex].X = (float)(radCosLat * Math.Cos(longitude) - localOrigin.X); vertices[vertexIndex].Y = (float)(radCosLat * Math.Sin(longitude) - localOrigin.Y); vertices[vertexIndex].Z = (float)(radius * sinLat - localOrigin.Z); vertexIndex++; } } }
internal FormatYielder Spawn(ChildLocation childLocation = ChildLocation.Unknown) { return(Spawn(child: null, childLocation: childLocation)); }
internal FormatYielder Spawn(UnparsableAst child, ChildLocation childLocation = ChildLocation.Unknown) { if (childLocation == ChildLocation.Unknown) { return new FormatYielder(this) { topAncestorCacheForLeft = UnparsableAst.NonCalculated }; } else { bool isLeftMostChild = childLocation == ChildLocation.Only || direction == Unparser.Direction.LeftToRight && childLocation == ChildLocation.First || direction == Unparser.Direction.RightToLeft && childLocation == ChildLocation.Last; return new FormatYielder(this) { topAncestorCacheForLeft = isLeftMostChild ? this.topAncestorCacheForLeft : (child ?? UnparsableAst.NonCalculated) }; } }
internal FormatYielder Spawn(ChildLocation childLocation = ChildLocation.Unknown) { return Spawn(child: null, childLocation: childLocation); }