public static void GenerateCurve(CurveDesc shapeDesc, Transform transform, Vector2 texScale, bool insideOut, out IList <CSGVertex> vertices, out IList <uint> indices) { CurveSegment[] segments = GenerateSegments(shapeDesc); CSGPlane[] planes = GeneratePlanes(shapeDesc, transform, texScale, segments); CreateVBAndIB(planes, out vertices, out indices, insideOut); }
private static CurveSegment[] GenerateSegments(CurveDesc shapeDesc) { CurveSegment[] segments = new CurveSegment[shapeDesc.NumSegments]; IntersectionFace[] faces = new IntersectionFace[shapeDesc.NumSegments + 1]; float depthPerSegment = shapeDesc.StartingCuboid.Depth / shapeDesc.NumSegments; Quaternion yawPerSegment = Quaternion.FromAxialRotation(Vector3.DOWN, shapeDesc.YawRotationRads / shapeDesc.NumSegments); Quaternion pitchPerSegment = Quaternion.FromAxialRotation(Vector3.LEFT, shapeDesc.PitchRotationRads / shapeDesc.NumSegments); Quaternion rollPerSegment = Quaternion.FromAxialRotation(Vector3.FORWARD, shapeDesc.RollRotationRads / shapeDesc.NumSegments); Quaternion yawPitchRoll = yawPerSegment * pitchPerSegment * rollPerSegment; faces[0] = new IntersectionFace( new Vector3(shapeDesc.StartingCuboid.GetCorner(Cuboid.CuboidCorner.FrontTopLeft), z: 0f), new Vector3(shapeDesc.StartingCuboid.GetCorner(Cuboid.CuboidCorner.FrontTopRight), z: 0f), new Vector3(shapeDesc.StartingCuboid.GetCorner(Cuboid.CuboidCorner.FrontBottomLeft), z: 0f), new Vector3(shapeDesc.StartingCuboid.GetCorner(Cuboid.CuboidCorner.FrontBottomRight), z: 0f) ); for (int s = 1; s <= shapeDesc.NumSegments; ++s) { faces[s] = faces[s - 1].ApplyRot(yawPitchRoll); } Vector3 defaultMovement = Vector3.FORWARD * depthPerSegment; for (int s = 1; s <= shapeDesc.NumSegments; ++s) { for (int m = 0; m < s; ++m) { faces[s] = faces[s].Move(defaultMovement * yawPerSegment.Subrotation(m + 1) * pitchPerSegment.Subrotation(m + 1)); } } for (int s = 0; s < shapeDesc.NumSegments; ++s) { segments[s] = new CurveSegment(null); IntersectionFace backFace = faces[s]; IntersectionFace frontFace = faces[s + 1]; segments[s].BackTopLeft = backFace.TopLeft; segments[s].BackTopRight = backFace.TopRight; segments[s].BackBottomLeft = backFace.BottomLeft; segments[s].BackBottomRight = backFace.BottomRight; segments[s].FrontTopLeft = frontFace.TopLeft; segments[s].FrontTopRight = frontFace.TopRight; segments[s].FrontBottomLeft = frontFace.BottomLeft; segments[s].FrontBottomRight = frontFace.BottomRight; } return(segments); }
public static IEnumerable <Vector3> GetTrapezoidalPrismVertices(CurveDesc shapeDesc, Transform transform) { CSGPlane[] planes = GeneratePlanes(shapeDesc, transform, Vector2.ONE, GenerateSegments(shapeDesc)); Vector3[] result = new Vector3[shapeDesc.NumSegments * 8]; for (int pI = 1, pN = 0; pI < planes.Length - 1; pI += 8, ++pN) { var topVertsA = planes[pI].Vertices; var topVertsB = planes[pI + 1].Vertices; result[pN * 8 + 0] = topVertsA[0].Position; result[pN * 8 + 1] = topVertsA[1].Position; result[pN * 8 + 2] = topVertsA[2].Position; result[pN * 8 + 3] = topVertsB[1].Position; var bottomVertsA = planes[pI + 2].Vertices; var bottomVertsB = planes[pI + 3].Vertices; result[pN * 8 + 4] = bottomVertsA[0].Position; result[pN * 8 + 5] = bottomVertsA[1].Position; result[pN * 8 + 6] = bottomVertsA[2].Position; result[pN * 8 + 7] = bottomVertsB[1].Position; } return(result); }
private static unsafe CSGPlane[] GeneratePlanes(CurveDesc shapeDesc, Transform transform, Vector2 texScale, CurveSegment[] segments) { float depthPerSegment = shapeDesc.StartingCuboid.Depth / shapeDesc.NumSegments; CSGPlane[] planes = new CSGPlane[shapeDesc.NumSegments * 8 + 2]; #region UV Planes Vector2 invTexScale = 1f / texScale; float minX, minY, minZ, maxX, maxY, maxZ; minX = minY = minZ = Single.MaxValue; maxX = maxY = maxZ = Single.MinValue; Action <Vector3> testAction = vec => { if (vec.X < minX) { minX = vec.X; } if (vec.X > maxX) { maxX = vec.X; } if (vec.Y < minY) { minY = vec.Y; } if (vec.Y > maxY) { maxY = vec.Y; } if (vec.Z < minZ) { minZ = vec.Z; } if (vec.Z > maxZ) { maxZ = vec.Z; } }; foreach (var segment in segments) { testAction(segment.FrontTopLeft); testAction(segment.BackTopLeft); testAction(segment.FrontBottomLeft); testAction(segment.BackBottomLeft); testAction(segment.FrontTopRight); testAction(segment.BackTopRight); testAction(segment.FrontBottomRight); testAction(segment.BackBottomRight); } float xMid = minX + (maxX - minX) * 0.5f; float yMid = minY + (maxY - minY) * 0.5f; float zMid = minZ + (maxZ - minZ) * 0.5f; #endregion for (int segmentIndex = 0, planeIndex = 0; segmentIndex < shapeDesc.NumSegments; ++segmentIndex) { CurveSegment segment = segments[segmentIndex]; Plane facePlane; CSGVertex[] faceVertices; Vector3 faceNormal; #region Back if (segmentIndex == 0) { facePlane = Plane.FromPoints(segment.BackBottomLeft, segment.BackTopRight, segment.BackBottomRight); faceNormal = facePlane.Normal; faceVertices = new[] { new CSGVertex( segment.BackBottomLeft, faceNormal, new Vector2(segment.BackBottomLeft.X - xMid, segment.BackBottomLeft.Y - yMid).Scale(invTexScale) ), new CSGVertex( segment.BackBottomRight, faceNormal, new Vector2(segment.BackBottomRight.X - xMid, segment.BackBottomRight.Y - yMid).Scale(invTexScale) ), new CSGVertex( segment.BackTopRight, faceNormal, new Vector2(segment.BackTopRight.X - xMid, segment.BackTopRight.Y - yMid).Scale(invTexScale) ), new CSGVertex( segment.BackTopLeft, faceNormal, new Vector2(segment.BackTopLeft.X - xMid, segment.BackTopLeft.Y - yMid).Scale(invTexScale) ), }; planes[planeIndex++] = new CSGPlane(facePlane, faceVertices); } #endregion #region Top facePlane = Plane.FromPoints(segment.BackTopLeft, segment.FrontTopLeft, segment.FrontTopRight); faceNormal = facePlane.Normal; faceVertices = new[] { new CSGVertex( segment.BackTopLeft, faceNormal, new Vector2(segment.BackTopLeft.X - xMid, segment.BackTopLeft.Z - zMid).Scale(invTexScale) ), new CSGVertex( segment.FrontTopLeft, faceNormal, new Vector2(segment.FrontTopLeft.X - xMid, segment.FrontTopLeft.Z - zMid).Scale(invTexScale) ), new CSGVertex( segment.FrontTopRight, faceNormal, new Vector2(segment.FrontTopRight.X - xMid, segment.FrontTopRight.Z - zMid).Scale(invTexScale) ), }; planes[planeIndex++] = new CSGPlane(facePlane, faceVertices); facePlane = Plane.FromPoints(segment.FrontTopRight, segment.BackTopRight, segment.BackTopLeft); faceNormal = facePlane.Normal; faceVertices = new[] { new CSGVertex( segment.FrontTopRight, faceNormal, new Vector2(segment.FrontTopRight.X - xMid, segment.FrontTopRight.Z - zMid).Scale(invTexScale) ), new CSGVertex( segment.BackTopRight, faceNormal, new Vector2(segment.BackTopRight.X - xMid, segment.BackTopRight.Z - zMid).Scale(invTexScale) ), new CSGVertex( segment.BackTopLeft, faceNormal, new Vector2(segment.BackTopLeft.X - xMid, segment.BackTopLeft.Z - zMid).Scale(invTexScale) ), }; planes[planeIndex++] = new CSGPlane(facePlane, faceVertices); #endregion #region Bottom facePlane = Plane.FromPoints(segment.FrontBottomRight, segment.FrontBottomLeft, segment.BackBottomLeft); faceNormal = facePlane.Normal; faceVertices = new[] { new CSGVertex( segment.FrontBottomRight, faceNormal, new Vector2(segment.FrontBottomRight.X - xMid, segment.FrontBottomRight.Z - zMid).Scale(invTexScale) ), new CSGVertex( segment.FrontBottomLeft, faceNormal, new Vector2(segment.FrontBottomLeft.X - xMid, segment.FrontBottomLeft.Z - zMid).Scale(invTexScale) ), new CSGVertex( segment.BackBottomLeft, faceNormal, new Vector2(segment.BackBottomLeft.X - xMid, segment.BackBottomLeft.Z - zMid).Scale(invTexScale) ), }; planes[planeIndex++] = new CSGPlane(facePlane, faceVertices); facePlane = Plane.FromPoints(segment.BackBottomLeft, segment.BackBottomRight, segment.FrontBottomRight); faceNormal = facePlane.Normal; faceVertices = new[] { new CSGVertex( segment.BackBottomLeft, faceNormal, new Vector2(segment.BackBottomLeft.X - xMid, segment.BackBottomLeft.Z - zMid).Scale(invTexScale) ), new CSGVertex( segment.BackBottomRight, faceNormal, new Vector2(segment.BackBottomRight.X - xMid, segment.BackBottomRight.Z - zMid).Scale(invTexScale) ), new CSGVertex( segment.FrontBottomRight, faceNormal, new Vector2(segment.FrontBottomRight.X - xMid, segment.FrontBottomRight.Z - zMid).Scale(invTexScale) ), }; planes[planeIndex++] = new CSGPlane(facePlane, faceVertices); #endregion #region Left facePlane = Plane.FromPoints(segment.BackBottomLeft, segment.FrontBottomLeft, segment.FrontTopLeft); faceNormal = facePlane.Normal; faceVertices = new[] { new CSGVertex( segment.BackBottomLeft, faceNormal, new Vector2(segment.BackBottomLeft.Y - yMid, segment.BackBottomLeft.Z - zMid).Scale(invTexScale) ), new CSGVertex( segment.FrontBottomLeft, faceNormal, new Vector2(segment.FrontBottomLeft.Y - yMid, segment.FrontBottomLeft.Z - zMid).Scale(invTexScale) ), new CSGVertex( segment.FrontTopLeft, faceNormal, new Vector2(segment.FrontTopLeft.Y - yMid, segment.FrontTopLeft.Z - zMid).Scale(invTexScale) ), }; planes[planeIndex++] = new CSGPlane(facePlane, faceVertices); facePlane = Plane.FromPoints(segment.FrontTopLeft, segment.BackTopLeft, segment.BackBottomLeft); faceNormal = facePlane.Normal; faceVertices = new[] { new CSGVertex( segment.FrontTopLeft, faceNormal, new Vector2(segment.FrontTopLeft.Y - yMid, segment.FrontTopLeft.Z - zMid).Scale(invTexScale) ), new CSGVertex( segment.BackTopLeft, faceNormal, new Vector2(segment.BackTopLeft.Y - yMid, segment.BackTopLeft.Z - zMid).Scale(invTexScale) ), new CSGVertex( segment.BackBottomLeft, faceNormal, new Vector2(segment.BackBottomLeft.Y - yMid, segment.BackBottomLeft.Z - zMid).Scale(invTexScale) ), }; planes[planeIndex++] = new CSGPlane(facePlane, faceVertices); #endregion #region Right facePlane = Plane.FromPoints(segment.FrontTopRight, segment.FrontBottomRight, segment.BackBottomRight); faceNormal = facePlane.Normal; faceVertices = new[] { new CSGVertex( segment.FrontTopRight, faceNormal, new Vector2(segment.FrontTopRight.Y - yMid, segment.FrontTopRight.Z - zMid).Scale(invTexScale) ), new CSGVertex( segment.FrontBottomRight, faceNormal, new Vector2(segment.FrontBottomRight.Y - yMid, segment.FrontBottomRight.Z - zMid).Scale(invTexScale) ), new CSGVertex( segment.BackBottomRight, faceNormal, new Vector2(segment.BackBottomRight.Y - yMid, segment.BackBottomRight.Z - zMid).Scale(invTexScale) ), }; planes[planeIndex++] = new CSGPlane(facePlane, faceVertices); facePlane = Plane.FromPoints(segment.BackBottomRight, segment.BackTopRight, segment.FrontTopRight); faceNormal = facePlane.Normal; faceVertices = new[] { new CSGVertex( segment.BackBottomRight, faceNormal, new Vector2(segment.BackBottomRight.Y - yMid, segment.BackBottomRight.Z - zMid).Scale(invTexScale) ), new CSGVertex( segment.BackTopRight, faceNormal, new Vector2(segment.BackTopRight.Y - yMid, segment.BackTopRight.Z - zMid).Scale(invTexScale) ), new CSGVertex( segment.FrontTopRight, faceNormal, new Vector2(segment.FrontTopRight.Y - yMid, segment.FrontTopRight.Z - zMid).Scale(invTexScale) ), }; planes[planeIndex++] = new CSGPlane(facePlane, faceVertices); #endregion #region Front if (segmentIndex == segments.Length - 1) { facePlane = Plane.FromPoints(segment.FrontBottomRight, segment.FrontTopLeft, segment.FrontBottomLeft); faceNormal = facePlane.Normal; faceVertices = new[] { new CSGVertex( segment.FrontBottomRight, faceNormal, new Vector2(segment.FrontBottomRight.X - xMid, segment.FrontBottomRight.Y - yMid).Scale(invTexScale) ), new CSGVertex( segment.FrontBottomLeft, faceNormal, new Vector2(segment.FrontBottomLeft.X - xMid, segment.FrontBottomLeft.Y - yMid).Scale(invTexScale) ), new CSGVertex( segment.FrontTopLeft, faceNormal, new Vector2(segment.FrontTopLeft.X - xMid, segment.FrontTopLeft.Y - yMid).Scale(invTexScale) ), new CSGVertex( segment.FrontTopRight, faceNormal, new Vector2(segment.FrontTopRight.X - xMid, segment.FrontTopRight.Y - yMid).Scale(invTexScale) ) }; planes[planeIndex++] = new CSGPlane(facePlane, faceVertices); } #endregion } for (int i = 0; i < planes.Length; ++i) { planes[i] = planes[i].Transform(transform, shapeDesc.StartingCuboid.CenterPoint); } return(planes); }