public static void GeneratePrism(int axis, double radius, double height, int segments, bool insideOut, out Vector3[] positions, out Vector3[] normals, out Vector4[] tangents, out Vector2[] texCoords, out int[] indices, out Face[] faces) { if (radius <= 0 || segments < 3) { GetEmptyData(out positions, out normals, out tangents, out texCoords, out indices, out faces); return; } int segmentsHeight = 1; int nextVertex = 0; Point[] polygon = GenerateCircleZ(segments + 1, radius, 360, ref nextVertex); FromZAxisToAxis(polygon, axis); var halfVector = GetAxisVector(axis) * height * 0.5; Matrix4[] m = GetTransformsOfLinePath(segmentsHeight + 1, -halfVector, halfVector); Point center0 = new Point(m[0] * Vector3.Zero, nextVertex++); Point center1 = new Point(m[m.Length - 1] * Vector3.Zero, nextVertex++); Point[][] legs = GenerateLegs(polygon, m, nextVertex, false); int rawVertexCount = CommonPipeBuilder.GetLegsRawVertexCount(legs) + 2 * CommonPipeBuilder.GetPolygonAdaptiveRawVertexCount(polygon); var builder = new CommonPipeBuilder(rawVertexCount, segments * (legs.Length - 1) + 2); builder.AddLegs(legs, insideOut); builder.AddPolygonAdaptive(legs[0], center0, !insideOut, !insideOut); builder.AddPolygonAdaptive(legs[legs.Length - 1], center1, insideOut, insideOut); builder.GetData(out positions, out normals, out tangents, out texCoords, out indices, out faces); }
public static void GenerateDoor(int axis, double width, double height, double depth, double doorWidth, double doorHeight, bool insideOut, out Vector3[] positions, out Vector3[] normals, out Vector4[] tangents, out Vector2[] texCoords, out int[] indices, out Face[] faces) { if (width <= doorWidth) { width = Math.Max(width, doorWidth); doorWidth = width - 1e-6; } if (height <= doorHeight) { height = Math.Max(height, doorHeight); doorHeight = height - 1e-6; } if (width <= 0 || height <= 0 || doorWidth <= 0 || doorHeight <= 0) { GetEmptyData(out positions, out normals, out tangents, out texCoords, out indices, out faces); return; } double halfWidth = width * 0.5; double halfWidthInner = doorWidth * 0.5; double heightInner = doorHeight; int segmentsDepth = 1; Point[] pointsInner = { new Point(new Vector3(halfWidthInner, 0, 0), 0), new Point(new Vector3(halfWidthInner, heightInner, 0), 1), new Point(new Vector3(-halfWidthInner, heightInner, 0), 2), new Point(new Vector3(-halfWidthInner, 0, 0), 3), }; Point[] pointsOuter = { new Point(new Vector3(halfWidth, 0, 0), 4), new Point(new Vector3(halfWidth, height, 0), 5), new Point(new Vector3(-halfWidth, height, 0), 6), new Point(new Vector3(-halfWidth, 0, 0), 7), }; int nextVertex = 8; FromZAxisToAxis(pointsInner, axis); FromZAxisToAxis(pointsOuter, axis); var halfVector = 0.5 * depth * GetAxisVector(axis); Matrix4[] m = GetTransformsOfLinePath(segmentsDepth + 1, -halfVector, halfVector); Point[][] legsInner = GenerateLegs(pointsInner, m, nextVertex, false); Point[][] legsOuter = GenerateLegs(pointsOuter, m, nextVertex, false); int rawVertexCount = CommonPipeBuilder.GetLegsRawVertexCount(legsInner) + 2 * CommonPipeBuilder.GetPolygon2RawVertexCount(legsOuter[0]); var builder = new CommonPipeBuilder(rawVertexCount, 3 + 2); builder.AddLegs(legsInner, !insideOut); builder.AddPolygon2(legsOuter[0], legsInner[0], !insideOut, !insideOut); //normal противоположна от направления смещения legs поэтому !insideOut builder.AddPolygon2(legsOuter[legsOuter.Length - 1], legsInner[legsInner.Length - 1], insideOut, insideOut); builder.GetData(out positions, out normals, out tangents, out texCoords, out indices, out faces); }
public static void GeneratePolygonBasedPolyhedron(Vector3[] points, bool clockwise, double height, bool insideOut, out Vector3[] positions, out Vector3[] normals, out Vector4[] tangents, out Vector2[] texCoords, out int[] indices, out Face[] faces) { if (points.Length < 3) { GetEmptyData(out positions, out normals, out tangents, out texCoords, out indices, out faces); return; } var normal = Plane.FromPoints(points[0], points[1], points[2]).Normal; if (clockwise) { normal = -normal; insideOut = !insideOut; } int segmentsHeight = 1; Point[] polygon = new Point[points.Length + 1]; for (int i = 0; i < points.Length; i++) { polygon[i] = new Point(points[i], i); } polygon[polygon.Length - 1] = polygon[0]; int nextVertex = points.Length; //var halfVector = normal * height * 0.5; Matrix4[] m = GetTransformsOfLinePath(segmentsHeight + 1, Vector3.Zero, normal * height); Point[][] legs = GenerateLegs(polygon, m, nextVertex, false); Vector3[] pos = new Vector3[points.Length]; for (int i = 0; i < points.Length; i++) { pos[i] = legs[0][i].Position; } int[] triangles = MathAlgorithms.TriangulatePolygon(pos); //the same for the top and the bottom int rawVertexCount = CommonPipeBuilder.GetLegsRawVertexCount(legs) + 2 * triangles.Length; var builder = new CommonPipeBuilder(rawVertexCount, points.Length * (legs.Length - 1) + 2); builder.AddLegs(legs, insideOut); builder.AddPolygon(legs[0], triangles, !insideOut, !insideOut); builder.AddPolygon(legs[legs.Length - 1], triangles, insideOut, insideOut); builder.GetData(out positions, out normals, out tangents, out texCoords, out indices, out faces); }
public static void GeneratePipe(int axis, double radius, double height, double thickness, int segments, int segmentsHeight, bool insideOut, out Vector3[] positions, out Vector3[] normals, out Vector4[] tangents, out Vector2[] texCoords, out int[] indices, out Face[] faces) { if (radius < thickness) { thickness = radius - 1e-6; } if (radius <= 0 || segments < 3) { GetEmptyData(out positions, out normals, out tangents, out texCoords, out indices, out faces); return; } bool hasTopBottom = 0 < thickness; int legPointCount = segments + 1; int vertexOffset = 0; Point[] polygonOuter = GenerateCircleZ(legPointCount, radius, 360, ref vertexOffset); FromZAxisToAxis(polygonOuter, axis); Point[] polygonInner = GenerateCircleZ(legPointCount, radius - thickness, 360, ref vertexOffset); FromZAxisToAxis(polygonInner, axis); var halfVector = 0.5 * height * GetAxisVector(axis); Matrix4[] m = GetTransformsOfLinePath(segmentsHeight + 1, -halfVector, halfVector); var legsOuter = GenerateLegs(polygonOuter, m, vertexOffset, false); var legsInner = GenerateLegs(polygonInner, m, vertexOffset, false); int rawVertexCount = 2 * CommonPipeBuilder.GetLegsRawVertexCount(legsOuter) + (hasTopBottom ? 2 * CommonPipeBuilder.GetPolygon2RawVertexCount(polygonOuter) : 0); int faceCount = 2 * segments * (legsOuter.Length - 1) + (hasTopBottom ? 2 : 0); var builder = new CommonPipeBuilder(rawVertexCount, faceCount, true); builder.AddLegs(legsOuter, insideOut, 1); builder.AddLegs(legsInner, !insideOut, 1); if (hasTopBottom) { //top,bottom builder.AddPolygon2(legsOuter[0], legsInner[0], !insideOut, false); builder.AddPolygon2(legsOuter[legsOuter.Length - 1], legsInner[legsInner.Length - 1], insideOut, false); } builder.GetData(out positions, out normals, out tangents, out texCoords, out indices, out faces); }
public static void GenerateTorus(int axis, double radius, int segments, Degree circumference, double tubeRadius, int tubeSegments, Degree tubeCircumference, /*bool smooth, */ bool insideOut, out Vector3[] positions, out Vector3[] normals, out Vector4[] tangents, out Vector2[] texCoords, out int[] indices, out Face[] faces) { if (radius < tubeRadius) { tubeRadius = radius; } bool loopOfLegs = Math.Abs(circumference.ToDouble() - 360) < 1e-5; bool endCapes = !loopOfLegs; if (radius <= 0 || tubeRadius <= 0 || segments < 3 || tubeSegments < 3 || circumference <= 0 || tubeCircumference <= 0) { GetEmptyData(out positions, out normals, out tangents, out texCoords, out indices, out faces); return; } ReplaceAxes(out int axis0, out int axis1, axis); int nextVertex = 0; Point[] polygon = GenerateCircleZ(tubeSegments + 1, tubeRadius, tubeCircumference, ref nextVertex); FromZAxisToAxis(polygon, axis0); //сечение тора Matrix4[] m = GetTransformsOfRotationCircle(segments + 1, axis, circumference, (radius - tubeRadius) * GetAxisVector(axis1)); var legs = GenerateLegs(polygon, m, nextVertex, loopOfLegs); int rawVertexCount = CommonPipeBuilder.GetLegsRawVertexCount(legs) + (endCapes ? 2 * CommonPipeBuilder.GetPolygonAdaptiveRawVertexCount(polygon) : 0); var builder = new CommonPipeBuilder(rawVertexCount, (legs.Length - 1) * tubeSegments + (endCapes ? 2 : 0), true); builder.AddLegs(legs, insideOut, 1); //ToDo ?? Нужны ли крышки когда circumference<360 ? Может опцию endCapes ? //Add capes if (endCapes) { nextVertex *= legs.Length; Point center0 = new Point(m[0] * Vector3.Zero, nextVertex++); Point center1 = new Point(m[m.Length - 1] * Vector3.Zero, nextVertex++); builder.AddPolygonAdaptive(legs[0], center0, !insideOut, !insideOut); //normal противоположна от направления смещения legs поэтому !insideOut builder.AddPolygonAdaptive(legs[legs.Length - 1], center1, insideOut, insideOut); } builder.GetData(out positions, out normals, out tangents, out texCoords, out indices, out faces); }
//ToDo : Логичнее когда главное направление для оси, в направлении входа. При axis=1,2 арка стоит, при axis=2 лежит на боку - тогда задать default axis=2 //ToDo ??? Надо ли сделать чтобы нижние поверхности были паралельны земле при circumference<180 ?(тогда угол у внутреннего кольца будет меньше). public static void GenerateArch(int axis, double radius, double thickness, double depth, int segments, int segmentsDepth, Degree circumference, bool endCapes, bool insideOut, out Vector3[] positions, out Vector3[] normals, out Vector4[] tangents, out Vector2[] texCoords, out int[] indices, out Face[] faces) { if (radius < thickness) { thickness = radius; } if (radius <= 0 || segments < 2 || segmentsDepth < 0 || circumference <= 0) { GetEmptyData(out positions, out normals, out tangents, out texCoords, out indices, out faces); return; } //ToDo ??? endCapes это передняя/задняя или нижние поверхности ? bool frontBack = endCapes && 1e-8 < thickness; bool bottom = endCapes; int legPointCount = segments + 1; int nextVertex = 0; double startAngle = ((Math.PI - circumference.InRadians()) / 2); Point[] outer = GenerateCircleZ(legPointCount, radius, circumference, ref nextVertex, startAngle); FromZAxisToAxis(outer, axis); Point[] inner = GenerateCircleZ(legPointCount, radius - thickness, circumference, ref nextVertex, startAngle); FromZAxisToAxis(inner, axis); Point[] down1 = { inner[0], outer[0] }; Point[] down2 = { outer[outer.Length - 1], inner[inner.Length - 1] }; var halfVector = 0.5 * depth * GetAxisVector(axis); Matrix4[] m = GetTransformsOfLinePath(segmentsDepth + 1, -halfVector, halfVector); var legsOuter = GenerateLegs(outer, m, nextVertex, false); var legsInner = GenerateLegs(inner, m, nextVertex, false); Point[][] legsDown1 = null; Point[][] legsDown2 = null; if (bottom) { legsDown1 = GenerateLegs(down1, m, nextVertex, false); legsDown2 = GenerateLegs(down2, m, nextVertex, false); } int rawVertexCount = 2 * CommonPipeBuilder.GetLegsRawVertexCount(legsOuter) + (legsDown1 == null ? 0 : 2 * CommonPipeBuilder.GetLegsRawVertexCount(legsDown1)) + (frontBack ? 2 * CommonPipeBuilder.GetPolygon2RawVertexCount(outer) : 0); int faceCount = 2 * segments * (legsOuter.Length - 1) + 2 * (bottom ? legsOuter.Length - 1 : 0) + (frontBack ? 2 : 0); var builder = new CommonPipeBuilder(rawVertexCount, faceCount, true); builder.AddLegs(legsOuter, insideOut, 1); builder.AddLegs(legsInner, !insideOut, 1); if (bottom) { builder.AddLegs(legsDown1, insideOut); builder.AddLegs(legsDown2, insideOut); } if (frontBack) { builder.AddPolygon2(legsOuter[0], legsInner[0], !insideOut, !insideOut); //normal противоположна от направления смещения legs поэтому !insideOut builder.AddPolygon2(legsOuter[legsOuter.Length - 1], legsInner[legsInner.Length - 1], insideOut, insideOut); } builder.GetData(out positions, out normals, out tangents, out texCoords, out indices, out faces); }