예제 #1
0
        /// <summary>
        /// Builds a smooth surfaced grid with the origin in the bottom-left corner.
        /// </summary>
        /// <remarks>
        /// The grid is comprised of quads with no shared vertices, allowing flat shading.
        /// </remarks>
        /// <param name="meshBuilder">Mesh builder.</param>
        /// <param name="cellWidth">Cell width.</param>
        /// <param name="cellLength">Cell length.</param>
        /// <param name="segmentCount">Segment count.</param>
        /// <param name="heightFunc">Height func.</param>
        public static void BuildSmoothGrid(this IMeshBuilder meshBuilder, float cellWidth, float cellLength, int segmentCount, Func <int, int, float> heightFunc)
        {
            int baseIndex = 0;

            for (int i = 0; i < segmentCount; i++)
            {
                for (int j = 0; j < segmentCount; j++)
                {
                    var x = cellWidth * j;
                    var z = cellLength * i;

                    meshBuilder.Vertices.Add(new Vector3(x, heightFunc(j, i), z));
                    meshBuilder.Vertices.Add(new Vector3(x, heightFunc(j, i + 1), z + cellLength));
                    meshBuilder.Vertices.Add(new Vector3(x + cellWidth, heightFunc(j + 1, i + 1), z + cellLength));
                    meshBuilder.Vertices.Add(new Vector3(x + cellWidth, heightFunc(j + 1, i), z));

                    meshBuilder.Normals.Add(Vector3.up);
                    meshBuilder.Normals.Add(Vector3.up);
                    meshBuilder.Normals.Add(Vector3.up);
                    meshBuilder.Normals.Add(Vector3.up);

                    meshBuilder.AddTriangle(baseIndex, baseIndex + 1, baseIndex + 2);
                    meshBuilder.AddTriangle(baseIndex, baseIndex + 2, baseIndex + 3);

                    baseIndex += 4;
                }
            }
        }
예제 #2
0
        public static void ExtrudeToCenter(this IMeshBuilder meshBuilder, IMeshSelection meshSelection)
        {
            var p = Vector3.zero;

            for (int i = 0; i < meshSelection.Count; i++)
            {
                p += meshBuilder.Vertices[meshSelection[i]];
            }
            p = p / meshSelection.Count;

            meshBuilder.Vertices.Add(p);
            meshBuilder.UVs.Add(Vector2.zero);
//            meshBuilder.Colors.Add(new Color(1f, 1f, 1f, 1f));

            for (int i = 0; i < meshSelection.Count - 1; i++)
            {
                var i1 = meshSelection[i];
                var i2 = meshBuilder.Vertices.Count - 1;
                var i3 = meshSelection[i + 1];
                meshBuilder.AddTriangle(i1, i2, i3);
            }

            // Add the final face.
            meshBuilder.AddTriangle(meshBuilder.Vertices.Count - 2, meshBuilder.Vertices.Count - 1, meshSelection[0]);
        }
예제 #3
0
        /// <summary>
        /// Builds a single quad based on a position offset and width and length vectors.
        /// </summary>
        /// <param name="meshBuilder">The mesh builder currently being added to.</param>
        /// <param name="offset">A position offset for the quad.</param>
        /// <param name="widthDir">The width vector of the quad.</param>
        /// <param name="lengthDir">The length vector of the quad.</param>
        public static void BuildQuad(this IMeshBuilder meshBuilder, Vector3 offset, Vector3 widthDir, Vector3 lengthDir)
        {
            Vector3 normal = Vector3.Cross(lengthDir, widthDir).normalized;

            meshBuilder.Vertices.Add(offset);
            meshBuilder.UVs.Add(new Vector2(0.0f, 0.0f));
            meshBuilder.Normals.Add(normal);

            meshBuilder.Vertices.Add(offset + lengthDir);
            meshBuilder.UVs.Add(new Vector2(0.0f, 1.0f));
            meshBuilder.Normals.Add(normal);

            meshBuilder.Vertices.Add(offset + lengthDir + widthDir);
            meshBuilder.UVs.Add(new Vector2(1.0f, 1.0f));
            meshBuilder.Normals.Add(normal);

            meshBuilder.Vertices.Add(offset + widthDir);
            meshBuilder.UVs.Add(new Vector2(1.0f, 0.0f));
            meshBuilder.Normals.Add(normal);

            //we don't know how many verts the meshBuilder is up to, but we only care about the four we just added:
            int baseIndex = meshBuilder.Vertices.Count - 4;

            meshBuilder.AddTriangle(baseIndex, baseIndex + 1, baseIndex + 2);
            meshBuilder.AddTriangle(baseIndex, baseIndex + 2, baseIndex + 3);
        }
예제 #4
0
        /// <summary>
        /// Builds a grid using quads with shared vertices, and the origin in the bottom-left corner.
        /// </summary>
        public static void BuildSmoothGrid(this IMeshBuilder meshBuilder, float cellWidth, float cellLength, int columns, int rows, Func <int, int, float> heightFunc, Func <int, int, QuadCorners, Color> colorFunc = null)
        {
            if (colorFunc == null)
            {
                colorFunc = (i, j, quad) => Color.white;
            }

            int baseIndex = 0;

            for (int i = 0; i < rows; i++)
            {
                for (int j = 0; j < columns; j++)
                {
                    var x = cellWidth * j;
                    var z = cellLength * i;

                    var h0 = heightFunc(j, i);
                    var h1 = heightFunc(j, i + 1);
                    var h2 = heightFunc(j + 1, i + 1);
                    var h3 = heightFunc(j + 1, i);

                    QuadCorners quad;
                    quad.c0 = new Vector3(x, h0, z);
                    quad.c1 = new Vector3(x, h1, z + cellLength);
                    quad.c2 = new Vector3(x + cellWidth, h2, z + cellLength);
                    quad.c3 = new Vector3(x + cellWidth, h3, z);

                    var c = colorFunc(j, i, quad);

                    meshBuilder.Vertices.Add(quad.c0);
                    meshBuilder.Colors.Add(c);
                    meshBuilder.Vertices.Add(quad.c1);
                    meshBuilder.Colors.Add(c);
                    meshBuilder.Vertices.Add(quad.c2);
                    meshBuilder.Colors.Add(c);
                    meshBuilder.Vertices.Add(quad.c3);
                    meshBuilder.Colors.Add(c);

                    meshBuilder.Normals.Add(Vector3.up);
                    meshBuilder.Normals.Add(Vector3.up);
                    meshBuilder.Normals.Add(Vector3.up);
                    meshBuilder.Normals.Add(Vector3.up);

                    meshBuilder.AddTriangle(baseIndex, baseIndex + 1, baseIndex + 2);
                    meshBuilder.AddTriangle(baseIndex, baseIndex + 2, baseIndex + 3);

                    baseIndex += 4;
                }
            }
        }
예제 #5
0
        public static void BuildCylinder(this IMeshBuilder meshBuilder, int numSegments, int numLayers, float radius, float height)
        {
            var angleDelta  = Mathf.PI * 2f / numSegments;
            var layerHeight = height / numLayers;

            var bottom = new Vector3(0f, 0f, 0f);
            var top    = new Vector3(0f, height, 0f);

            meshBuilder.Vertices.Add(bottom);
            meshBuilder.Vertices.Add(top);

            for (int j = 0; j < numLayers; j++)
            {
                // The vertical position of the bottom of the current layer.
                var h = j * layerHeight;

                for (int i = 0; i <= numSegments; i++)
                {
                    var a = angleDelta * -i;

                    var p1 = new Vector3(Mathf.Cos(a) * radius, h, Mathf.Sin(a) * radius);
                    var p2 = p1 + Vector3.up * layerHeight;

                    meshBuilder.Vertices.Add(p1);
                    meshBuilder.Vertices.Add(p2);

                    var numVerts = meshBuilder.Vertices.Count;

                    if (i > 0)
                    {
                        // side
                        meshBuilder.AddTriangle(numVerts - 2, numVerts - 3, numVerts - 4);
                        meshBuilder.AddTriangle(numVerts - 2, numVerts - 1, numVerts - 3);

                        // bottom
                        if (j == 0)
                        {
                            meshBuilder.AddTriangle(numVerts - 4, 0, numVerts - 2);
                        }

                        // top
                        if (j == numLayers - 1)
                        {
                            meshBuilder.AddTriangle(numVerts - 1, 1, numVerts - 3);
                        }
                    }
                }
            }
        }
예제 #6
0
        /// <summary>
        /// Builds a single quad as part of a mesh grid.
        /// </summary>
        /// <param name="meshBuilder">The mesh builder currently being added to.</param>
        /// <param name="position">A position offset for the quad. Specifically the position of the corner vertex of the quad.</param>
        /// <param name="uv">The UV coordinates of the quad's corner vertex.</param>
        /// <param name="buildTriangles">Should triangles be built for this quad? This value should be false if this is the first quad in any row or collumn.</param>
        /// <param name="vertsPerRow">The number of vertices per row in this grid.</param>
        public static void BuildQuadForGrid(this IMeshBuilder meshBuilder, Vector3 position, Vector2 uv, bool buildTriangles, int vertsPerRow)
        {
            meshBuilder.Vertices.Add(position);
            meshBuilder.UVs.Add(uv);

            if (buildTriangles)
            {
                int baseIndex = meshBuilder.Vertices.Count - 1;

                int index0 = baseIndex;
                int index1 = baseIndex - 1;
                int index2 = baseIndex - vertsPerRow;
                int index3 = baseIndex - vertsPerRow - 1;

                meshBuilder.AddTriangle(index0, index2, index1);
                meshBuilder.AddTriangle(index2, index3, index1);
            }
        }
예제 #7
0
        public static void BuildQuad(this IMeshBuilder meshBuilder, int bottomIndex, int topIndex)
        {
            var bl = bottomIndex;
            var tl = topIndex;
            var tr = topIndex + 1;
            var br = bottomIndex + 1;

            Log.Trace("Building quad: verts=[{0},{1},{2},{3}], indices=[{4},{5},{6},{7}]",
                      meshBuilder.Vertices[bl],
                      meshBuilder.Vertices[tl],
                      meshBuilder.Vertices[tr],
                      meshBuilder.Vertices[br],
                      bl,
                      tl,
                      tr,
                      br);

            meshBuilder.AddTriangle(bl, tl, br);
            meshBuilder.AddTriangle(br, tl, tr);
        }
예제 #8
0
        public virtual void BuildMesh(IMeshBuilder meshBuilder, IStyleConfig styleConfig)
        {
            this.ApplyStyle(styleConfig);

            var baseIndex = meshBuilder.Vertices.Count;

            foreach (var face in this.Faces)
            {
                var numVerts = face.Corners.Count;

                for (int i = 0; i < face.Corners.Count; i++)
                {
                    var v  = face.Corners[i].Position;
                    var uv = face.UVs[i];

                    var worldPos = this.Transform.Position + (this.Transform.Rotation * Vector3.Scale(v, this.Transform.Scale));

                    meshBuilder.Vertices.Add(worldPos);
                    meshBuilder.UVs.Add(uv);
                    meshBuilder.Colors.Add(face.Color);
                }

                if (numVerts == 3)
                {
                    meshBuilder.AddTriangle(baseIndex, baseIndex + 1, baseIndex + 2);
                }
                else if (numVerts == 4)
                {
                    meshBuilder.AddTriangle(baseIndex, baseIndex + 1, baseIndex + 3);
                    meshBuilder.AddTriangle(baseIndex + 1, baseIndex + 2, baseIndex + 3);
                }
                else
                {
                    throw new InvalidOperationException(string.Format("Cannot build mesh for faces with {0} vertices", numVerts));
                }

                baseIndex = meshBuilder.Vertices.Count;
            }
        }
예제 #9
0
        /// <summary>
        /// Builds a single quad in the XZ plane, facing up the Y axis.
        /// </summary>
        /// <param name="meshBuilder">The mesh builder currently being added to.</param>
        /// <param name="offset">A position offset for the quad.</param>
        /// <param name="width">The width of the quad.</param>
        /// <param name="length">The length of the quad.</param>
        public static void BuildQuad(this IMeshBuilder meshBuilder, Vector3 offset, float width, float length)
        {
            meshBuilder.Vertices.Add(new Vector3(0.0f, 0.0f, 0.0f) + offset);
            meshBuilder.UVs.Add(new Vector2(0.0f, 0.0f));
            meshBuilder.Normals.Add(Vector3.up);

            meshBuilder.Vertices.Add(new Vector3(0.0f, 0.0f, length) + offset);
            meshBuilder.UVs.Add(new Vector2(0.0f, 1.0f));
            meshBuilder.Normals.Add(Vector3.up);

            meshBuilder.Vertices.Add(new Vector3(width, 0.0f, length) + offset);
            meshBuilder.UVs.Add(new Vector2(1.0f, 1.0f));
            meshBuilder.Normals.Add(Vector3.up);

            meshBuilder.Vertices.Add(new Vector3(width, 0.0f, 0.0f) + offset);
            meshBuilder.UVs.Add(new Vector2(1.0f, 0.0f));
            meshBuilder.Normals.Add(Vector3.up);

            //we don't know how many verts the meshBuilder is up to, but we only care about the four we just added:
            int baseIndex = meshBuilder.Vertices.Count - 4;

            meshBuilder.AddTriangle(baseIndex, baseIndex + 1, baseIndex + 2);
            meshBuilder.AddTriangle(baseIndex, baseIndex + 2, baseIndex + 3);
        }
예제 #10
0
        /// <summary>
        /// Builds a single triangle.
        /// </summary>
        /// <param name="meshBuilder">The mesh builder currently being added to.</param>
        /// <param name="corner0">The vertex position at index 0 of the triangle.</param>
        /// <param name="corner1">The vertex position at index 1 of the triangle.</param>
        /// <param name="corner2">The vertex position at index 2 of the triangle.</param>
        public static void BuildTriangle(this IMeshBuilder meshBuilder, Vector3 corner0, Vector3 corner1, Vector3 corner2)
        {
            Vector3 normal = Vector3.Cross((corner1 - corner0), (corner2 - corner0)).normalized;

            meshBuilder.Vertices.Add(corner0);
            meshBuilder.UVs.Add(new Vector2(0.0f, 0.0f));
            meshBuilder.Normals.Add(normal);

            meshBuilder.Vertices.Add(corner1);
            meshBuilder.UVs.Add(new Vector2(0.0f, 1.0f));
            meshBuilder.Normals.Add(normal);

            meshBuilder.Vertices.Add(corner2);
            meshBuilder.UVs.Add(new Vector2(1.0f, 1.0f));
            meshBuilder.Normals.Add(normal);

            int baseIndex = meshBuilder.Vertices.Count - 3;

            meshBuilder.AddTriangle(baseIndex, baseIndex + 1, baseIndex + 2);
        }
예제 #11
0
        public static void BuildIcosahedron(this IMeshBuilder meshBuilder, float radius = 1f)
        {
            // create 12 vertices of a icosahedron
            float t = (1f + Mathf.Sqrt(5f)) / 2f;

            meshBuilder.AddVertex(new Vector3(-1f, t, 0f).normalized *radius);
            meshBuilder.AddVertex(new Vector3(1f, t, 0f).normalized *radius);
            meshBuilder.AddVertex(new Vector3(-1f, -t, 0f).normalized *radius);
            meshBuilder.AddVertex(new Vector3(1f, -t, 0f).normalized *radius);

            meshBuilder.AddVertex(new Vector3(0f, -1f, t).normalized *radius);
            meshBuilder.AddVertex(new Vector3(0f, 1f, t).normalized *radius);
            meshBuilder.AddVertex(new Vector3(0f, -1f, -t).normalized *radius);
            meshBuilder.AddVertex(new Vector3(0f, 1f, -t).normalized *radius);

            meshBuilder.AddVertex(new Vector3(t, 0f, -1f).normalized *radius);
            meshBuilder.AddVertex(new Vector3(t, 0f, 1f).normalized *radius);
            meshBuilder.AddVertex(new Vector3(-t, 0f, -1f).normalized *radius);
            meshBuilder.AddVertex(new Vector3(-t, 0f, 1f).normalized *radius);

            // create 20 triangles of the icosahedron

            // 5 faces around point 0
            meshBuilder.AddTriangle(0, 11, 5);
            meshBuilder.AddTriangle(0, 5, 1);
            meshBuilder.AddTriangle(0, 1, 7);
            meshBuilder.AddTriangle(0, 7, 10);
            meshBuilder.AddTriangle(0, 10, 11);

            // 5 adjacent faces
            meshBuilder.AddTriangle(1, 5, 9);
            meshBuilder.AddTriangle(5, 11, 4);
            meshBuilder.AddTriangle(11, 10, 2);
            meshBuilder.AddTriangle(10, 7, 6);
            meshBuilder.AddTriangle(7, 1, 8);

            // 5 faces around point 3
            meshBuilder.AddTriangle(3, 9, 4);
            meshBuilder.AddTriangle(3, 4, 2);
            meshBuilder.AddTriangle(3, 2, 6);
            meshBuilder.AddTriangle(3, 6, 8);
            meshBuilder.AddTriangle(3, 8, 9);

            // 5 adjacent faces
            meshBuilder.AddTriangle(4, 9, 5);
            meshBuilder.AddTriangle(2, 4, 11);
            meshBuilder.AddTriangle(6, 2, 10);
            meshBuilder.AddTriangle(8, 6, 7);
            meshBuilder.AddTriangle(9, 8, 1);
        }
예제 #12
0
        public static void BuildIcoSphere(this IMeshBuilder meshBuilder, int recursionLevel = 3, float radius = 1f)
        {
            List <Vector3>         vertList = new List <Vector3>();
            Dictionary <long, int> middlePointIndexCache = new Dictionary <long, int>();

            // create 12 vertices of a icosahedron
            float t = (1f + Mathf.Sqrt(5f)) / 2f;

            vertList.Add(new Vector3(-1f, t, 0f).normalized *radius);
            vertList.Add(new Vector3(1f, t, 0f).normalized *radius);
            vertList.Add(new Vector3(-1f, -t, 0f).normalized *radius);
            vertList.Add(new Vector3(1f, -t, 0f).normalized *radius);

            vertList.Add(new Vector3(0f, -1f, t).normalized *radius);
            vertList.Add(new Vector3(0f, 1f, t).normalized *radius);
            vertList.Add(new Vector3(0f, -1f, -t).normalized *radius);
            vertList.Add(new Vector3(0f, 1f, -t).normalized *radius);

            vertList.Add(new Vector3(t, 0f, -1f).normalized *radius);
            vertList.Add(new Vector3(t, 0f, 1f).normalized *radius);
            vertList.Add(new Vector3(-t, 0f, -1f).normalized *radius);
            vertList.Add(new Vector3(-t, 0f, 1f).normalized *radius);

            // create 20 triangles of the icosahedron
            List <TriangleIndices> faces = new List <TriangleIndices>();

            // 5 faces around point 0
            faces.Add(new TriangleIndices(0, 11, 5));
            faces.Add(new TriangleIndices(0, 5, 1));
            faces.Add(new TriangleIndices(0, 1, 7));
            faces.Add(new TriangleIndices(0, 7, 10));
            faces.Add(new TriangleIndices(0, 10, 11));

            // 5 adjacent faces
            faces.Add(new TriangleIndices(1, 5, 9));
            faces.Add(new TriangleIndices(5, 11, 4));
            faces.Add(new TriangleIndices(11, 10, 2));
            faces.Add(new TriangleIndices(10, 7, 6));
            faces.Add(new TriangleIndices(7, 1, 8));

            // 5 faces around point 3
            faces.Add(new TriangleIndices(3, 9, 4));
            faces.Add(new TriangleIndices(3, 4, 2));
            faces.Add(new TriangleIndices(3, 2, 6));
            faces.Add(new TriangleIndices(3, 6, 8));
            faces.Add(new TriangleIndices(3, 8, 9));

            // 5 adjacent faces
            faces.Add(new TriangleIndices(4, 9, 5));
            faces.Add(new TriangleIndices(2, 4, 11));
            faces.Add(new TriangleIndices(6, 2, 10));
            faces.Add(new TriangleIndices(8, 6, 7));
            faces.Add(new TriangleIndices(9, 8, 1));

            // refine triangles
            for (int i = 0; i < recursionLevel; i++)
            {
                List <TriangleIndices> faces2 = new List <TriangleIndices>();
                foreach (var tri in faces)
                {
                    // replace triangle by 4 triangles
                    int a = getMiddlePoint(tri.v1, tri.v2, ref vertList, ref middlePointIndexCache, radius);
                    int b = getMiddlePoint(tri.v2, tri.v3, ref vertList, ref middlePointIndexCache, radius);
                    int c = getMiddlePoint(tri.v3, tri.v1, ref vertList, ref middlePointIndexCache, radius);

                    faces2.Add(new TriangleIndices(tri.v1, a, c));
                    faces2.Add(new TriangleIndices(tri.v2, b, a));
                    faces2.Add(new TriangleIndices(tri.v3, c, b));
                    faces2.Add(new TriangleIndices(a, b, c));
                }
                faces = faces2;
            }

            for (int i = 0; i < vertList.Count; i++)
            {
                meshBuilder.Vertices.Add(vertList[i]);
            }

            for (int i = 0; i < faces.Count; i++)
            {
                meshBuilder.AddTriangle(faces[i].v1, faces[i].v2, faces[i].v3);
            }

            for (int i = 0; i < vertList.Count; i++)
            {
                meshBuilder.Normals.Add(vertList[i].normalized);
                //            meshBuilder.UVs.Add(Vector2.zero);
                //            meshBuilder.Colors.Add(ColorHelper.RandomRGB());
            }
        }
예제 #13
0
        public unsafe void PolygonizeCell(float[] values, Vector3[] positions, float isoLevel, IMeshBuilder builder)
        {
            Profiler.BeginSample("cubeIndex");

            // Determine the index into the edge table which
            // tells us which vertices are inside of the surface
            var cubeIndex = 0;

            if (values[0] < isoLevel)
            {
                cubeIndex |= 1;
            }
            if (values[1] < isoLevel)
            {
                cubeIndex |= 2;
            }
            if (values[2] < isoLevel)
            {
                cubeIndex |= 4;
            }
            if (values[3] < isoLevel)
            {
                cubeIndex |= 8;
            }
            if (values[4] < isoLevel)
            {
                cubeIndex |= 16;
            }
            if (values[5] < isoLevel)
            {
                cubeIndex |= 32;
            }
            if (values[6] < isoLevel)
            {
                cubeIndex |= 64;
            }
            if (values[7] < isoLevel)
            {
                cubeIndex |= 128;
            }

            Profiler.EndSample();

            // Cube is entirely in/out of the surface
            if (EdgeTable[cubeIndex] == 0)
            {
                return;
            }

            Profiler.BeginSample("EdgeTable");

            var vertices = stackalloc Vector3[12];

            // Find the vertices where the surface intersects the cube
            if ((EdgeTable[cubeIndex] & 1) > 0)
            {
                vertices[0] = Interpolate(isoLevel, positions[0], positions[1], values[0], values[1]);
            }
            if ((EdgeTable[cubeIndex] & 2) > 0)
            {
                vertices[1] = Interpolate(isoLevel, positions[1], positions[2], values[1], values[2]);
            }
            if ((EdgeTable[cubeIndex] & 4) > 0)
            {
                vertices[2] = Interpolate(isoLevel, positions[2], positions[3], values[2], values[3]);
            }
            if ((EdgeTable[cubeIndex] & 8) > 0)
            {
                vertices[3] = Interpolate(isoLevel, positions[3], positions[0], values[3], values[0]);
            }
            if ((EdgeTable[cubeIndex] & 16) > 0)
            {
                vertices[4] = Interpolate(isoLevel, positions[4], positions[5], values[4], values[5]);
            }
            if ((EdgeTable[cubeIndex] & 32) > 0)
            {
                vertices[5] = Interpolate(isoLevel, positions[5], positions[6], values[5], values[6]);
            }
            if ((EdgeTable[cubeIndex] & 64) > 0)
            {
                vertices[6] = Interpolate(isoLevel, positions[6], positions[7], values[6], values[7]);
            }
            if ((EdgeTable[cubeIndex] & 128) > 0)
            {
                vertices[7] = Interpolate(isoLevel, positions[7], positions[4], values[7], values[4]);
            }
            if ((EdgeTable[cubeIndex] & 256) > 0)
            {
                vertices[8] = Interpolate(isoLevel, positions[0], positions[4], values[0], values[4]);
            }
            if ((EdgeTable[cubeIndex] & 512) > 0)
            {
                vertices[9] = Interpolate(isoLevel, positions[1], positions[5], values[1], values[5]);
            }
            if ((EdgeTable[cubeIndex] & 1024) > 0)
            {
                vertices[10] = Interpolate(isoLevel, positions[2], positions[6], values[2], values[6]);
            }
            if ((EdgeTable[cubeIndex] & 2048) > 0)
            {
                vertices[11] = Interpolate(isoLevel, positions[3], positions[7], values[3], values[7]);
            }

            Profiler.EndSample();

            Profiler.BeginSample("TriTable");
            /* Create the triangle */
            for (var i = 0; TriTable[cubeIndex][i] != -1; i += 3)
            {
                builder.AddTriangle(
                    vertices[TriTable[cubeIndex][i]],
                    vertices[TriTable[cubeIndex][i + 1]],
                    vertices[TriTable[cubeIndex][i + 2]]
                    );
            }

            Profiler.EndSample();
        }
예제 #14
0
        public static IMeshSelection ExtrudeEdge(
            this IMeshBuilder meshBuilder,
            IMeshSelection edge,
            Func <int, Vector3, Vector3> extrudeTranslationFunc)
        {
            Log.Trace("Will extrude edge {0}. Total vertices in mesh = {1}", edge, meshBuilder.Vertices.Count);

            var lowerEdge    = new MeshSelection(edge);
            var extrudedEdge = new MeshSelection();

            // Check if we're dealing with a closed selection loop.
            var isClosed = lowerEdge.IsClosed;

            if (isClosed)
            {
                Log.Trace("The edge has the same start and end point {0}", lowerEdge[0]);
            }

            // Extrude new vertices from the current source vertices.
            for (int i = 0; i < lowerEdge.Count; i++)
            {
                var extrudeIdx = lowerEdge[i];
                var p          = meshBuilder.Vertices[extrudeIdx];

                Log.Trace("extrudeIdx = {0}", extrudeIdx);
                // TODO: Need to skip duplicate indexes when the start/end range is wrapped.

                var translation  = extrudeTranslationFunc(i, p);
                var newVertexIdx = meshBuilder.AddVertex(p + translation);
                extrudedEdge.Add(newVertexIdx);

                // TODO: This currently assumes the normal won't be changed by the translation. Need fix
                // support rotation as well.
                meshBuilder.Normals.Add(meshBuilder.Normals[extrudeIdx]);
            }

            if (isClosed)
            {
                extrudedEdge.Add(extrudedEdge[0]);
            }

            Log.Trace("Building {0} quads", edge.Count);

            Assert.AreEqual(lowerEdge.Count, extrudedEdge.Count, "Number of extruded indices should match the number of lower indices");

            Log.Trace("lowerEdge = {0}", lowerEdge);
            Log.Trace("extrudedEdge = {0}", extrudedEdge);

            // Build quads between the start vertices and the extruded vertices, using the virtual
            // selection which includes the closing vertex index.
            for (int i = 0; i < lowerEdge.VirtualCount - 1; i++)
            {
                var bl = lowerEdge.GetAtVirtualIndex(i);
                var tl = extrudedEdge.GetAtVirtualIndex(i);
                var tr = extrudedEdge.GetAtVirtualIndex(i + 1);
                var br = lowerEdge.GetAtVirtualIndex(i + 1);

                Log.Trace("Building quad: verts=[{0},{1},{2},{3}], indices=[{4},{5},{6},{7}]",
                          meshBuilder.Vertices[bl],
                          meshBuilder.Vertices[tl],
                          meshBuilder.Vertices[tr],
                          meshBuilder.Vertices[br],
                          bl,
                          tl,
                          tr,
                          br);

                meshBuilder.AddTriangle(bl, tl, br);
                meshBuilder.AddTriangle(br, tl, tr);
            }

            return(extrudedEdge);
        }