/// <summary> /// Builds the bottom side of a cube into this Geometry (Built up of 4 vertices, so texture coordinates and normals are set) /// </summary> public static BuiltVerticesRange BuildCubeBottom(this GeometrySurface target, Vector3 start, Vector3 size) { var dest = start + size; return(target.BuildRect( new Vector3(start.X, start.Y, dest.Z), new Vector3(dest.X, start.Y, dest.Z), new Vector3(dest.X, start.Y, start.Z), new Vector3(start.X, start.Y, start.Z), new Vector3(0f, -1f, 0f))); }
/// <summary> /// Create a 4 Side Pyramid /// </summary> public static BuiltVerticesRange BuildPyramid(this GeometrySurface target, float width, float height) { width = Math.Max(EngineMath.TOLERANCE_FLOAT_POSITIVE, width); height = Math.Max(EngineMath.TOLERANCE_FLOAT_POSITIVE, height); var halfWidth = width / 2f; var lowerMiddle = new Vector3(0f, -(height / 2f), 0f); var start = new Vector3(lowerMiddle.X - halfWidth, lowerMiddle.Y, lowerMiddle.Z - halfWidth); var dest = start + new Vector3(width, 0f, width); var centerTopCoordination = new Vector3((dest.X + start.X) / 2, start.Y + height, (dest.Z + start.Z) / 2); target.BuildRect( new Vector3(start.X, dest.Y, start.Z), new Vector3(start.X, dest.Y, dest.Z), new Vector3(dest.X, dest.Y, dest.Z), new Vector3(dest.X, dest.Y, start.Z), new Vector3(0f, -1f, 0f)); target.BuildTriangle( new Vector3(start.X, dest.Y, start.Z), new Vector3(dest.X, dest.Y, start.Z), centerTopCoordination); target.BuildTriangle( new Vector3(start.X, dest.Y, dest.Z), new Vector3(start.X, dest.Y, start.Z), centerTopCoordination); target.BuildTriangle( new Vector3(dest.X, dest.Y, dest.Z), new Vector3(start.X, dest.Y, dest.Z), centerTopCoordination); target.BuildTriangle( new Vector3(dest.X, dest.Y, start.Z), new Vector3(dest.X, dest.Y, dest.Z), centerTopCoordination); return(new BuiltVerticesRange(target.Owner, target.Owner.CountVertices - 4, 4)); }
/// <summary> /// Builds a cylinder into the geometry with correct texture coordinates and normals. /// </summary> /// <param name="target">Target <see cref="GeometrySurface"/>.</param> /// <param name="bottomMiddle">Coordinate of bottom middle.</param> /// <param name="radius">The radius of the cylinder.</param> /// <param name="height">The height of the cylinder.</param> /// <param name="countOfSegments">Total count of segments to generate.</param> /// <param name="buildBottom">Build bottom of the cylinder.</param> /// <param name="buildSides">Build sides of the cylinder.</param> /// <param name="buildTop">Build top side of the cylinder.</param> public static BuiltVerticesRange BuildCylinder( this GeometrySurface target, Vector3 bottomMiddle, float radius, float height, int countOfSegments, bool buildSides, bool buildBottom, bool buildTop) { var startVertex = target.Owner.CountVertices; radius = Math.Max(EngineMath.TOLERANCE_FLOAT_POSITIVE, radius); height = Math.Max(EngineMath.TOLERANCE_FLOAT_POSITIVE, height); countOfSegments = Math.Max(3, countOfSegments); var diameter = radius * 2f; // Get texture offsets var texX = 1f; var texY = 1f; var texSegmentY = 1f; var texSegmentX = 1f; if (target.IsTextureTileModeEnabled(out var tileSize)) { texX = diameter / tileSize.X; texY = diameter / tileSize.Y; texSegmentY = height / tileSize.Y; texSegmentX = EngineMath.RAD_180DEG * diameter / tileSize.X; } // Specify bottom and top middle coordinates var bottomCoordinate = bottomMiddle; var topCoordinate = new Vector3(bottomMiddle.X, bottomMiddle.Y + height, bottomMiddle.Z); // Create bottom and top vertices var bottomVertex = new VertexBasic(bottomCoordinate, new Vector2(texX / 2f, texY / 2f), new Vector3(0f, -1f, 0f)); var topVertex = new VertexBasic(topCoordinate, new Vector2(texX / 2f, texY / 2f), new Vector3(0f, 1f, 0f)); // AddObject bottom and top vertices to the geometry var bottomVertexIndex = target.Owner.AddVertex(bottomVertex); var topVertexIndex = target.Owner.AddVertex(topVertex); // Generate all segments var fullRadian = EngineMath.RAD_360DEG; var countOfSegmentsF = (float)countOfSegments; for (var loop = 0; loop < countOfSegments; loop++) { // Calculate rotation values for each segment border var startRadian = fullRadian * (loop / countOfSegmentsF); var targetRadian = fullRadian * ((loop + 1) / countOfSegmentsF); var normalRadian = startRadian + (targetRadian - startRadian) / 2f; // Generate all normals var sideNormal = Vector3Ex.NormalFromHVRotation(normalRadian, 0f); var sideLeftNormal = Vector3Ex.NormalFromHVRotation(startRadian, 0f); var sideRightNormal = Vector3Ex.NormalFromHVRotation(targetRadian, 0f); // var sideLeftTexCoord = new Vector2(0.5f + sideLeftNormal.X * radius, 0.5f + sideLeftNormal.Z * radius); var sideRightTexCoord = new Vector2(0.5f + sideRightNormal.X * radius, 0.5f + sideRightNormal.Z * radius); // Generate all points var sideLeftBottomCoord = bottomCoordinate + sideLeftNormal * radius; var sideRightBottomCoord = bottomCoordinate + sideRightNormal * radius; var sideLeftTopCoord = new Vector3(sideLeftBottomCoord.X, sideLeftBottomCoord.Y + height, sideLeftBottomCoord.Z); var sideRightTopCoord = new Vector3(sideRightBottomCoord.X, sideRightBottomCoord.Y + height, sideRightBottomCoord.Z); // AddObject segment bottom triangle if (buildBottom) { var segmentBottomLeft = bottomVertex.Copy(sideLeftBottomCoord, sideLeftTexCoord); var segmentBottomRight = bottomVertex.Copy(sideRightBottomCoord, sideRightTexCoord); target.AddTriangle( bottomVertexIndex, target.Owner.AddVertex(segmentBottomLeft), target.Owner.AddVertex(segmentBottomRight)); } // AddObject segment top triangle if (buildTop) { var segmentTopLeft = topVertex.Copy(sideLeftTopCoord, sideLeftTexCoord); var segmentTopRight = topVertex.Copy(sideRightTopCoord, sideRightTexCoord); target.AddTriangle( topVertexIndex, target.Owner.AddVertex(segmentTopRight), target.Owner.AddVertex(segmentTopLeft)); } if (buildSides) { // Calculate texture coords for side segment var texCoordSegmentStart = new Vector2(texSegmentX * (loop / (float)countOfSegments), 0f); var texCoordSegmentTarget = new Vector2(texSegmentX * ((loop + 1) / (float)countOfSegments), texSegmentY); // AddObject segment side target.BuildRect(sideLeftBottomCoord, sideRightBottomCoord, sideRightTopCoord, sideLeftTopCoord, sideNormal, texCoordSegmentStart, texCoordSegmentTarget); } } return(new BuiltVerticesRange(target.Owner, startVertex, target.Owner.CountVertices - startVertex)); }