Example #1
0
    static void ReadData(StreamReader inputStream, ref Vector3[] vertices, ref Vector3[] normals, ref Color32[] colors32, ref Vector2[] uv, ref int[] triangles, Dictionary <string, int> propertyIndices)
    {
        int vertCounter = 0;
        int faceCounter = 0;

        while (!inputStream.EndOfStream)
        {
            string line = inputStream.ReadLine();
            if (line.StartsWith("comment"))                                                                     //log comments to console. might be useful. or not.
            {
                LogComment(line);
            }
            else
            {
                if (vertCounter < vertices.Length)
                {
                    VertexData data = ReadVertexDataFromLine(line, propertyIndices);
                    vertices[vertCounter] = new Vector3(data.x, data.y, data.z);
                    normals[vertCounter]  = new Vector3(data.nx, data.ny, data.nz);
                    colors32[vertCounter] = new Color32(data.r, data.g, data.b, (byte)255);
                    uv[vertCounter]       = new Vector2(data.u, data.v);
                    vertCounter++;
                }
                else
                {
                    string[] split = line.Split(' ');
                    int      numberOfVertsPerFace = int.Parse(split[0]);
                    if (numberOfVertsPerFace != 3)
                    {
                        throw new UnityException("The importer isn't built to handle faces with " + numberOfVertsPerFace + " vertices (only triangles are allowed)");
                    }
                    for (int i = 1; i <= 3; i++)
                    {
                        triangles[(3 * faceCounter) + i - 1] = int.Parse(split[i]);
                    }
                    faceCounter++;
                }
            }
        }
    }
Example #2
0
        protected override YAMLMappingNode ExportYAMLRoot()
        {
#warning TODO: provide for null values

            YAMLMappingNode node = base.ExportYAMLRoot();
            node.AddSerializedVersion(SerializedVersion);
            node.Add("m_SubMeshes", SubMeshes.ExportYAML());
            node.Add("m_Shapes", Shapes.ExportYAML());
            node.Add("m_BindPose", BindPoses.ExportYAML());
#warning ???
            node.Add("m_BoneNames", YAMLSequenceNode.Empty);
            node.Add("m_BoneNameHashes", BoneNameHashes.ExportYAML(false));
#warning ???
            node.Add("m_RootBoneName", YAMLScalarNode.Empty);
            node.Add("m_RootBoneNameHash", RootBoneNameHash);
            node.Add("m_MeshCompression", MeshCompression);
            node.Add("m_IsReadable", IsReadable);
            node.Add("m_KeepVertices", KeepVertices);
            node.Add("m_KeepIndices", KeepIndices);
            node.Add("m_IndexBuffer", IndexBuffer.ExportYAML());
            node.Add("m_Skin", Skin.ExportYAML());
            node.Add("m_VertexData", VertexData.ExportYAML());
            node.Add("m_CompressedMesh", CompressedMesh.ExportYAML());
            node.Add("m_LocalAABB", LocalAABB.ExportYAML());
            node.Add("m_MeshUsageFlags", MeshUsageFlags);
            if (IsReadCollision)
            {
                node.Add("m_BakedConvexCollisionMesh", CollisionData.BakedConvexCollisionMesh.ExportYAML());
                node.Add("m_BakedTriangleCollisionMesh", CollisionData.BakedTriangleCollisionMesh.ExportYAML());
            }
            else
            {
                node.Add("m_BakedConvexCollisionMesh", ArrayExtensions.EmptyBytes.ExportYAML());
                node.Add("m_BakedTriangleCollisionMesh", ArrayExtensions.EmptyBytes.ExportYAML());
            }
#warning ???
            node.Add("m_MeshOptimized", 0);

            return(node);
        }
        protected VertexData CreateVertexData()
        {
            var data = new VertexData();

            var triangleVertices = new[, ]
            {
                { 0.5f, 0.5f, 0.0f, /* Vertex Color: */ 1.0f, 0.0f, 0.0f },
                { -0.5f, 0.5f, 0.0f, /* Vertex Color: */ 0.0f, 1.0f, 0.0f },
                { 0.0f, -0.5f, 0.0f, /* Vertex Color: */ 0.0f, 0.0f, 1.0f },
            };

            DeviceSize memorySize = (ulong)(sizeof(float) * triangleVertices.Length);

            data.Buffer = CreateBuffer(memorySize, BufferUsageFlags.VertexBuffer);

            var memoryRequirements = device.GetBufferMemoryRequirements(data.Buffer);
            var memoryIndex        = FindMemoryIndex(MemoryPropertyFlags.HostVisible);
            var allocateInfo       = new MemoryAllocateInfo(memoryRequirements.Size, memoryIndex);

            data.DeviceMemory = BindBuffer(data.Buffer, allocateInfo);

            var mapped = device.MapMemory(data.DeviceMemory, 0, memorySize);

            VulkanUtils.Copy2DArray(triangleVertices, mapped, memorySize, memorySize);
            device.UnmapMemory(data.DeviceMemory);

            data.BindingDescriptions = new[]
            {
                new VertexInputBindingDescription(0, (uint)(sizeof(float) * triangleVertices.GetLength(1)), VertexInputRate.Vertex)
            };

            data.AttributeDescriptions = new[]
            {
                new VertexInputAttributeDescription(0, 0, Format.R32g32b32Sfloat, 0),
                new VertexInputAttributeDescription(1, 0, Format.R32g32b32Sfloat, sizeof(float) * 3)
            };

            return(data);
        }
Example #4
0
        protected override YAMLMappingNode ExportYAMLRoot(IAssetsExporter exporter)
        {
#warning TODO: values acording to read version (current 2017.3.0f3)
            YAMLMappingNode node = base.ExportYAMLRoot(exporter);
            node.AddSerializedVersion(GetSerializedVersion(exporter.Version));
            node.Add("m_SubMeshes", SubMeshes.ExportYAML(exporter));
            node.Add("m_Shapes", Shapes.ExportYAML(exporter));
            node.Add("m_BindPose", BindPoses.ExportYAML(exporter));
#warning ???
            node.Add("m_BoneNames", YAMLSequenceNode.Empty);
            node.Add("m_BoneNameHashes", IsReadBoneNameHashes(exporter.Version) ? BoneNameHashes.ExportYAML(false) : YAMLSequenceNode.Empty);
#warning ???
            node.Add("m_RootBoneName", YAMLScalarNode.Empty);
            node.Add("m_RootBoneNameHash", RootBoneNameHash);
            node.Add("m_MeshCompression", MeshCompression);
            node.Add("m_IsReadable", IsReadable);
            node.Add("m_KeepVertices", KeepVertices);
            node.Add("m_KeepIndices", KeepIndices);
            node.Add("m_IndexBuffer", IsReadIndexBuffer(exporter.Version) ? IndexBuffer.ExportYAML() : YAMLSequenceNode.Empty);
            node.Add("m_Skin", Skin.ExportYAML(exporter));
            node.Add("m_VertexData", VertexData.ExportYAML(exporter));
            node.Add("m_CompressedMesh", CompressedMesh.ExportYAML(exporter));
            node.Add("m_LocalAABB", LocalAABB.ExportYAML(exporter));
            node.Add("m_MeshUsageFlags", MeshUsageFlags);
            if (IsReadCollision(exporter.Version))
            {
                node.Add("m_BakedConvexCollisionMesh", CollisionData.BakedConvexCollisionMesh.ExportYAML());
                node.Add("m_BakedTriangleCollisionMesh", CollisionData.BakedTriangleCollisionMesh.ExportYAML());
            }
            else
            {
                node.Add("m_BakedConvexCollisionMesh", ArrayExtensions.EmptyBytes.ExportYAML());
                node.Add("m_BakedTriangleCollisionMesh", ArrayExtensions.EmptyBytes.ExportYAML());
            }
#warning ???
            node.Add("m_MeshOptimized", 0);

            return(node);
        }
Example #5
0
        private IGraph <T> BuildGraph(Vertex <T> vEnd, VertexData[] vTable)
        {
            /*
             * result <-- Instantiate a new graph instance
             * Add the End Vertex to the result
             * dataLast <-- vTable[Location of End]
             * previous <-- Previous of dataLast
             *
             * while previous is not null
             *  Add previous to result
             *  Add the edge from last and previous
             *
             *  dataLast <--vTable[Location of previous]
             *  previous <--previous of dataLast
             *
             * return result
             */

            IGraph <T> result = (IGraph <T>)GetType().Assembly.CreateInstance(this.GetType().FullName);

            result.AddVertex(vEnd.Data);

            VertexData dataLast = vTable[vEnd.Index];
            Vertex <T> prev     = dataLast.Previous;

            while (prev != null)
            {
                result.AddVertex(prev.Data);

                Edge <T> eEdge = GetEdge(prev.Data, dataLast.Vertex.Data);

                result.AddEdge(eEdge.From.Data, eEdge.To.Data, eEdge.Weight);

                dataLast = vTable[prev.Index];
                prev     = dataLast.Previous;
            }

            return(result);
        }
Example #6
0
        private static List <List <IntPoint> > CreatePolygons(IVertexSource a)
        {
            List <List <IntPoint> > allPolys    = new List <List <IntPoint> >();
            List <IntPoint>         currentPoly = null;
            VertexData last       = new VertexData();
            VertexData first      = new VertexData();
            bool       addedFirst = false;

            foreach (VertexData vertexData in a.Vertices())
            {
                if (vertexData.IsLineTo)
                {
                    if (!addedFirst)
                    {
                        currentPoly.Add(new IntPoint((long)(last.position.x * 1000), (long)(last.position.y * 1000)));
                        addedFirst = true;
                        first      = last;
                    }
                    currentPoly.Add(new IntPoint((long)(vertexData.position.x * 1000), (long)(vertexData.position.y * 1000)));
                    last = vertexData;
                }
                else
                {
                    addedFirst  = false;
                    currentPoly = new List <IntPoint>();
                    allPolys.Add(currentPoly);
                    if (vertexData.IsMoveTo)
                    {
                        last = vertexData;
                    }
                    else
                    {
                        last = first;
                    }
                }
            }

            return(allPolys);
        }
        public void Read(AssetStream stream)
        {
            Texture.Read(stream);
            if (IsReadAlphaTexture(stream.Version))
            {
                AlphaTexture.Read(stream);
            }

            if (IsReadVertices(stream.Version))
            {
                m_vertices = stream.ReadArray <SpriteVertex>();
                m_indices  = stream.ReadUInt16Array();
                stream.AlignStream(AlignType.Align4);
            }
            else
            {
                m_subMeshes   = stream.ReadArray <SubMesh>();
                m_indexBuffer = stream.ReadByteArray();
                stream.AlignStream(AlignType.Align4);

                VertexData.Read(stream);
            }

            TextureRect.Read(stream);
            TextureRectOffset.Read(stream);
            if (IsReadAtlasRectOffset(stream.Version))
            {
                AtlasRectOffset.Read(stream);
            }
            SettingsRaw = stream.ReadUInt32();
            if (IsReadUVTransform(stream.Version))
            {
                UVTransform.Read(stream);
            }
            if (IsReadDownscaleMultiplier(stream.Version))
            {
                DownscaleMultiplier = stream.ReadSingle();
            }
        }
Example #8
0
        void RenderTexturedQuad(CommandBuffer cmdBuffer, VertexData vertexData, ImageData imageData, PipelineLayout pipelineLayout, DescriptorSet descriptorSet, RenderPass renderPass, Pipeline pipeline, Framebuffer framebuffer, uint width, uint height)
        {
            var viewport = new Viewport(0, 0, width, height, 0, 1);

            cmdBuffer.SetViewport(0, new[] { viewport });

            var renderArea      = new Rect2D(new Offset2D(0, 0), new Extent2D(width, height));
            var renderPassBegin = new RenderPassBeginInfo(renderPass, framebuffer, renderArea, null);

            cmdBuffer.BeginRenderPass(renderPassBegin, SubpassContents.Inline);
            renderPassBegin.Dispose();

            cmdBuffer.BindDescriptorSets(PipelineBindPoint.Graphics, pipelineLayout, 0, new[] { descriptorSet }, null);

            cmdBuffer.BindPipeline(PipelineBindPoint.Graphics, pipeline);

            cmdBuffer.BindVertexBuffers(0, new[] { vertexData.Buffer }, new DeviceSize[] { 0 });
            cmdBuffer.BindIndexBuffer(vertexData.IndexBuffer, 0, IndexType.Uint32);
            cmdBuffer.DrawIndexed((uint)vertexData.Indicies.Length, 1, 0, 0, 1);

            cmdBuffer.EndRenderPass();
        }
Example #9
0
        void ShowFlatDependencies(VertexData vertex)
        {
            bool first    = true;
            var  flatDeps = GetAllDependencies(vertex);

            Console.WriteLine();

            foreach (var d in flatDeps)
            {
                var dSize = SpaceAnalyzer == null ? 0 : SpaceAnalyzer.GetSize(d.Item1);
                if (first)
                {
                    var sizeStr = dSize > 0 ? $" [size: {dSize}]" : "";
                    Console.WriteLine($"Distance | {d.Item1.value} [total deps: {flatDeps.Count}]{sizeStr}");
                    Line();
                    first = false;
                    continue;
                }
                var sizeStr2 = dSize > 0 ? $" [size: {dSize}]" : "";
                Console.WriteLine($"{string.Format ("{0,8}", d.Item2)} | {d.Item1.value}{d.Item1.DepsCount}{sizeStr2}");
            }
        }
Example #10
0
        public static List <List <IntPoint> > CreatePolygons(this IVertexSource sourcePath, double scaling = 1000)
        {
            List <List <IntPoint> > allPolys    = new List <List <IntPoint> >();
            List <IntPoint>         currentPoly = null;
            VertexData last       = new VertexData();
            VertexData first      = new VertexData();
            bool       addedFirst = false;

            foreach (VertexData vertexData in sourcePath.Vertices())
            {
                if (vertexData.IsLineTo)
                {
                    if (!addedFirst)
                    {
                        currentPoly.Add(new IntPoint((long)(last.position.X * scaling), (long)(last.position.Y * scaling)));
                        addedFirst = true;
                        first      = last;
                    }
                    currentPoly.Add(new IntPoint((long)(vertexData.position.X * scaling), (long)(vertexData.position.Y * scaling)));
                    last = vertexData;
                }
                else
                {
                    addedFirst  = false;
                    currentPoly = new List <IntPoint>();
                    allPolys.Add(currentPoly);
                    if (vertexData.IsMoveTo)
                    {
                        last = vertexData;
                    }
                    else
                    {
                        last = first;
                    }
                }
            }

            return(allPolys);
        }
            // Check equality on PositionIndex and ChannelData
            public bool ContentEquals(VertexData other)
            {
                if (PositionIndex != other.PositionIndex)
                {
                    return(false);
                }

                if (ChannelData.Length != other.ChannelData.Length)
                {
                    return(false);
                }

                for (var i = 0; i < ChannelData.Length; i++)
                {
                    if (!Equals(ChannelData[i], other.ChannelData[i]))
                    {
                        return(false);
                    }
                }

                return(true);
            }
Example #12
0
        public VertexData MakeFakeMesh(ref ElevationData evlData)
        {
            // Simple routine to convert or grid of float elevations into a format suitable for a quantized mesh of unsigned short ints

            VertexData vertices = new VertexData((uint)evlData.GridSize, (uint)evlData.GridSize);

            try
            {
                double ratio = 32767 / (double)(evlData.GridSize - 1);

                // data flows sw to se and up
                int m = 0;
                for (int y = 0; y < evlData.GridSize; y++)
                {
                    for (int x = 0; x < evlData.GridSize; x++)
                    {
                        try
                        {
                            // todo ratio is wrong
                            vertices.AddVertex(m, (ushort)(x * ratio), (ushort)(y * ratio),
                                               QuantizeHeight(evlData.MinimumHeight, evlData.MaximumHeight, evlData.Elev[m]));
                        }
                        catch (Exception ex1)
                        {
                            System.Diagnostics.Debug.WriteLine($"**** MakeFakeMesh Error *********:{ex1}");
                        }
                        m++;
                    }
                }
            }
            catch (Exception ex)
            {
#if DEBUG
                System.Diagnostics.Debug.WriteLine($"**** MakeFakeMesh Error *********:{ex}");
#endif
            }

            return(vertices);
        }
Example #13
0
        void RenderTriangle(CommandBuffer cmdBuffer, VertexData vertexData, RenderPass renderPass, Framebuffer framebuffer, Pipeline pipeline, uint width, uint height)
        {
            // Set the viewport
            var viewport = new Viewport(0, 0, width, height, 0, 0);

            cmdBuffer.SetViewport(0, new[] { viewport });

            var renderArea      = new Rect2D(new Offset2D(0, 0), new Extent2D(width, height));
            var renderPassBegin = new RenderPassBeginInfo(renderPass, framebuffer, renderArea, null);

            cmdBuffer.BeginRenderPass(renderPassBegin, SubpassContents.Inline);
            renderPassBegin.Dispose();

            cmdBuffer.BindPipeline(PipelineBindPoint.Graphics, pipeline);

            // Render the triangle
            cmdBuffer.BindVertexBuffers(0, new[] { vertexData.Buffer }, new DeviceSize[] { 0 });
            cmdBuffer.Draw(3, 1, 0, 0);

            // End the RenderPass
            cmdBuffer.EndRenderPass();
        }
Example #14
0
            public static void SetBoneInfo(ref VertexData target, int fieldIndex, byte boneIndex, float boneWeight)
            {
                Type type = typeof(VertexData);

                if (indexFieldInfos == null)
                {
                    indexFieldInfos  = new FieldInfo[16];
                    weightFieldInfos = new FieldInfo[16];

                    for (int i = 0; i < 16; ++i)
                    {
                        indexFieldInfos[i]  = type.GetField(string.Format("boneIndex{0}", i + 1));
                        weightFieldInfos[i] = type.GetField(string.Format("boneWeight{0}", i + 1));
                    }
                }

                object boxed = (object)target; // hello gc! :)

                indexFieldInfos[fieldIndex].SetValue(boxed, boneIndex);
                weightFieldInfos[fieldIndex].SetValue(boxed, boneWeight);
                target = (VertexData)boxed;
            }
Example #15
0
        protected void Initialize()
        {
            this.vertexDeclDirty       = true;
            this.buffersNeedRecreating = true;
            this.boundsDirty           = true;
            this.indexContentDirty     = true;
            this.boundingRadius        = 0.0f;

            vertexData = new VertexData();
            indexData  = new IndexData();

            otherTexCoordRange    = new float[2];
            otherTexCoordRange[0] = 0.0f;
            otherTexCoordRange[1] = 1.0f;

            SetupChainContainers();

            vertexData.vertexStart = 0;
            // index data set up later
            // set basic white material
            this.materialName = "BaseWhiteNoLighting";
        }
Example #16
0
 public void Add(VertexData[] intList)
 {
     faceMesh.AddItem(intList);
     for (int i = 0; i < intList.Length; i++)
     {
         var line = new VertexData[] { intList[i], intList[(i + 1) % intList.Length] };
         lineData.Add(new LineData(line[0], line[1]));
         if (!lineParentCounts.ContainsKey(line))
         {
             lineParentCounts.Add(line, 0);
         }
         lineParentCounts[line]++;
         lineMesh.AddItem(line);
         if (!pointParentCounts.ContainsKey(intList[i]))
         {
             pointParentCounts.Add(intList[i], 0);
         }
         pointParentCounts[intList[i]]++;
         pointMesh.AddItem(intList[i]);
     }
     RecalculateEverything();
 }
Example #17
0
        public void TestAlpha()
        {
            VertexData vertexData = new VertexData();

            vertexData.NumVertices = 3;

            IndexData indexData = new IndexData();

            indexData.AddTriangle(0, 1, 2);

            Mesh mesh = new Mesh(vertexData, indexData);

            mesh.SetVertexAlpha(0, 0.2f);
            mesh.SetVertexAlpha(1, 0.5f);
            mesh.SetVertexAlpha(2, 0.8f);

            float E = 0.02f;

            AssertAreEqualWithSmallError(mesh.GetVertexAlpha(0), 0.2f, "", E);
            AssertAreEqualWithSmallError(mesh.GetVertexAlpha(1), 0.5f, "", E);
            AssertAreEqualWithSmallError(mesh.GetVertexAlpha(2), 0.8f, "", E);
        }
Example #18
0
        public void TestGetBounds()
        {
            VertexData vertexData = new VertexData();

            vertexData.SetPoint(0, 10, 10);
            vertexData.SetPoint(1, 20, 10);
            vertexData.SetPoint(2, 10, 20);

            IndexData indexData = new IndexData();

            indexData.AddTriangle(0, 1, 2);

            Mesh      mesh     = new Mesh(vertexData, indexData);
            Rectangle expected = Rectangle.Create(10, 10, 10, 10);

            CompareRectangles(expected, mesh.Bounds);
            CompareRectangles(expected, mesh.GetBounds(mesh));

            mesh.Rotation = (float)Math.PI / 2.0f;
            expected.SetTo(-20, 10, 10, 10);
            CompareRectangles(expected, mesh.Bounds);
        }
Example #19
0
        public VTX1(EndianBinaryReader reader, int offset)
        {
            Attributes = new VertexData();

            reader.BaseStream.Seek(offset, System.IO.SeekOrigin.Begin);

            reader.SkipInt32();
            int vtx1Size = reader.ReadInt32();
            int attributeHeaderOffset = reader.ReadInt32();

            int[] attribDataOffsets = new int[13];

            for (int i = 0; i < 13; i++)
            {
                attribDataOffsets[i] = reader.ReadInt32();
            }

            GXVertexAttribute attrib = (GXVertexAttribute)reader.ReadInt32();

            while (attrib != GXVertexAttribute.Null)
            {
                GXComponentCount componentCount     = (GXComponentCount)reader.ReadInt32();
                GXDataType       componentType      = (GXDataType)reader.ReadInt32();
                byte             fractionalBitCount = reader.ReadByte();
                reader.Skip(3);
                long curPos = reader.BaseStream.Position;

                int attribDataSize = 0;
                int attribOffset   = GetAttributeDataOffset(attribDataOffsets, vtx1Size, attrib, out attribDataSize);
                int attribCount    = GetAttributeDataCount(attribDataSize, attrib, componentType, componentCount);
                Attributes.SetAttributeData(attrib, LoadAttributeData(reader, offset + attribOffset, attribCount, fractionalBitCount, attrib, componentType, componentCount));

                reader.BaseStream.Seek(curPos, System.IO.SeekOrigin.Begin);
                attrib = (GXVertexAttribute)reader.ReadInt32();
            }

            reader.BaseStream.Seek(offset + vtx1Size, System.IO.SeekOrigin.Begin);
        }
        public bool WorldDraw(WorldDraw wd)
        {
            if (_geometry is Rhino.Geometry.Mesh mesh)
            {
                var faces      = mesh.Faces.ToHost();
                var points     = new Point3dCollection(mesh.Vertices.ToHost());
                var vertexData = new VertexData();
                vertexData.SetNormalVectors(mesh.Normals.ToHost());
                bool hasVertColor = mesh.VertexColors.Count != 0;
                vertexData.SetTrueColors(hasVertColor ? mesh.VertexColors.ToHost() : null);
                wd.Geometry.Shell(points, faces, null, null, vertexData, false);
            }
            else if (_geometry is Rhino.Geometry.Curve curve)
            {
                double deviation = System.Math.Max(wd.Deviation(DeviationType.MaxDevForCurve, curve.PointAtStart.ToHost()), 0.01 * curve.GetLength());
                var    polyline  = curve.ToPolyline(10E+4 * Convert.VertexTolerance, Convert.AngleTolerance, deviation, 0.0);
                if (polyline != null)
                {
                    var giPoly = new Polyline();
                    giPoly.Points = new Point3dCollection(polyline.ToPolyline().ToArray().ToHost());
                    wd.Geometry.Polyline(giPoly);
                }
#if DEBUG
                else
                {
                    var tmpFile = new Rhino.FileIO.File3dm();
                    tmpFile.Objects.AddCurve(curve);
                    tmpFile.Write(System.IO.Path.Combine(System.IO.Path.GetTempPath(), "BricsCAD", "CurveFail.3dm"),
                                  new Rhino.FileIO.File3dmWriteOptions());
                }
#endif
            }
            else if (_geometry is Rhino.Geometry.Point)
            {
                return(false);
            }
            return(true);
        }
Example #21
0
        /** Sets up a VertexData instance with the correct positions for 4 vertices so that
         *  the texture can be mapped onto it unscaled. If the texture has a <code>frame</code>,
         *  the vertices will be offset accordingly.
         *
         *  @param vertexData  the VertexData instance to which the positions will be written.
         *  @param vertexID    the start position within the VertexData instance.
         *  @param bounds      useful only for textures with a frame. This will position the
         *                     vertices at the correct position within the given bounds,
         *                     distorted appropriately.
         */
        public void SetupVertexPositions(VertexData vertexData, int vertexId = 0,
                                         Rectangle bounds = null)
        {
            Rectangle frame  = Frame;
            float     width  = Width;
            float     height = Height;

            Rectangle sRectangle = Rectangle.Create();

            if (frame != null)
            {
                sRectangle.SetTo(-frame.X, -frame.Y, width, height);
            }
            else
            {
                sRectangle.SetTo(0, 0, width, height);
            }

            vertexData.SetPoint(vertexId, sRectangle.Left, sRectangle.Top);
            vertexData.SetPoint(vertexId + 1, sRectangle.Right, sRectangle.Top);
            vertexData.SetPoint(vertexId + 2, sRectangle.Left, sRectangle.Bottom);
            vertexData.SetPoint(vertexId + 3, sRectangle.Right, sRectangle.Bottom);

            if (bounds != null)
            {
                float scaleX = bounds.Width / FrameWidth;
                float scaleY = bounds.Height / FrameHeight;

                if (scaleX != 1.0 || scaleY != 1.0 || bounds.X != 0 || bounds.Y != 0)
                {
                    Matrix2D sMatrix = Matrix2D.Create();
                    sMatrix.Identity();
                    sMatrix.Scale(scaleX, scaleY);
                    sMatrix.Translate(bounds.X, bounds.Y);
                    vertexData.TransformVertices(sMatrix, vertexId, 4);
                }
            }
        }
Example #22
0
        // SGD :2013/6/18 15:02:51
        // 说明:顶点纹理坐标
        private unsafe void ReadTextureCoordData(uint vertexOffset, byte *vertexBuffer_Lock, uint vertexBuffer_VertexSize, VertexData vertexData)
        {
            VertexElement texElem = vertexData.vertexDeclaration.FindElementBySemantic(VertexElementSemantic.VES_TEXTURE_COORDINATES);
            float *       tReal;

            if (texElem == null)
            {
                for (uint i = 0; i < vertexData.vertexCount; i++)
                {
                    this._textureCroodnitas[vertexOffset + i] = new Vector2(0f, 0f);
                }
            }
            else
            {
                //byte* vextex = vertexBuffer_Lock;
                //for (uint i = 0; i < vertexData.vertexCount; i++) {
                //    texElem.BaseVertexPointerToElement(vextex, &tReal);
                //    this._textureCroodnitas[vertexOffset + i] = new Vector2(tReal[0], tReal[1]);
                //    vextex += vertexBuffer_VertexSize;
                //}
                //读取纹理坐标修正 2013/12/18
                VertexData vertex_data = vertexData;
                HardwareVertexBufferSharedPtr vbufPtr_tex = vertex_data.vertexBufferBinding.GetBuffer(texElem.Source);
                byte *vertex_tex = (byte *)vbufPtr_tex.Lock(HardwareBuffer.LockOptions.HBL_READ_ONLY);
                for (uint i = 0; i < vertex_data.vertexCount; ++i, /*vertex += vbufPtr.VertexSize,*/ vertex_tex += vbufPtr_tex.VertexSize)
                {
                    //posElem.BaseVertexPointerToElement(vertex, &pReal);
                    texElem.BaseVertexPointerToElement(vertex_tex, &tReal);
                    this._textureCroodnitas[vertexOffset + i] = new Vector2(tReal[0], tReal[1]);
                    vertex_tex += vertexBuffer_VertexSize;
                    //Vector3 pt = new Vector3(pReal[0], pReal[1], pReal[2]);
                    //vertices[current_offset + j] = (orientation * (pt * scale)) + position;
                    //tex_Cors[current_offset + j] = new Vector2(tReal[0], tReal[1]);
                }
                vbufPtr_tex.Unlock();
                vbufPtr_tex.Dispose();
            }
        }
Example #23
0
    private VertexData ShowVertexEditSceneUI(VertexData vertexData, int index)
    {
        Vector3 pos = handleTransform.TransformPoint(vertexData.GetPosition());

        Handles.color = Color.white;

        float size = HandleUtility.GetHandleSize(pos);

        Handles.Label(pos + 0.6f * size * Vector3.up, "" + index);

        if (Handles.Button(pos, handleRotation, 1.2f * size * handleSize, 1.2f * size * pickSize, Handles.DotCap))
        {
            vertexData.isEditMode = true;
            selectedVertexIndex   = index;
        }

        if (vertexData.isEditMode)
        {
            EditorGUI.BeginChangeCheck();

            pos = Handles.DoPositionHandle(pos, handleRotation);

            pos = handleTransform.InverseTransformPoint(pos);

            vertexData.positionX = pos.x;
            vertexData.positionY = pos.y;
            vertexData.positionZ = pos.z;

            if (EditorGUI.EndChangeCheck())
            {
                Undo.RecordObject(meshEditor, "Move vertex");
                EditorUtility.SetDirty(meshEditor);
            }
        }


        return(vertexData);
    }
Example #24
0
        // internal methods

        internal void SetTarget(Mesh target, VertexData vertexData = null, IndexData targetIndexData = null)
        {
            if (_target != target)
            {
                if (_target != null)
                {
                    _target.EnterFrame -= OnEnterFrame;
                }

                _target     = target;
                _vertexData = vertexData;
                _indexData  = targetIndexData;

                if (target != null)
                {
                    if (EnterFrame != null)
                    {
                        target.EnterFrame += OnEnterFrame;
                    }
                    OnTargetAssigned(target);
                }
            }
        }
Example #25
0
        /// <summary>
        /// Initializes a fragment filter with the specified number of passes and resolution.
        /// </summary>
        protected FragmentFilter(int numPasses = 1, float resolution = 1.0f)
        {
            NumPasses     = numPasses;
            Resolution    = resolution;
            Mode          = FragmentFilterMode.Replace;
            _passTextures = new List <Texture>(numPasses);
            _projMatrix   = Matrix.Create(0, 0, 0, 0, 0, 0);

            _vertexData = new VertexData(4, true);
            _vertexData.Vertices[1].TexCoords.X = 1.0f;
            _vertexData.Vertices[2].TexCoords.Y = 1.0f;
            _vertexData.Vertices[3].TexCoords.X = 1.0f;
            _vertexData.Vertices[3].TexCoords.Y = 1.0f;

            _indexData[0] = 0;
            _indexData[1] = 1;
            _indexData[2] = 2;
            _indexData[3] = 1;
            _indexData[4] = 3;
            _indexData[5] = 2;

            CreatePrograms();
        }
Example #26
0
        protected void InitImage(Texture texture)
        {
            if (texture == null)
            {
                throw new Exception("texture cannot be null!");
            }

            Rectangle frame  = texture.Frame;
            float     width  = (frame != null) ? frame.Width : texture.Width;
            float     height = (frame != null) ? frame.Height : texture.Height;
            bool      pma    = texture.PremultipliedAlpha;

            Init(width, height, 0xFFFFFF, pma);

            _vertexData.Vertices[1].TexCoords.X = 1.0f;
            _vertexData.Vertices[2].TexCoords.Y = 1.0f;
            _vertexData.Vertices[3].TexCoords.X = 1.0f;
            _vertexData.Vertices[3].TexCoords.Y = 1.0f;

            _texture                = texture;
            _vertexDataCache        = new VertexData(4, pma);
            _vertexDataCacheInvalid = true;
        }
Example #27
0
 public Vector2f[][] GenerateOutline(Version version)
 {
     if (IsReadVertices(version))
     {
         Vector2f[][] outline = new Vector2f[1][];
         outline[0] = new Vector2f[Vertices.Count];
         for (int i = 0; i < Vertices.Count; i++)
         {
             outline[0][i] = Vertices[i].Position.ToVector2();
         }
         return(outline);
     }
     else
     {
         List <Vector2f[]> outlines = new List <Vector2f[]>();
         foreach (SubMesh submesh in SubMeshes)
         {
             Vector3f[] vertices = VertexData.GenerateVertices(version, submesh);
             VerticesToOutline(outlines, vertices, submesh);
         }
         return(outlines.ToArray());
     }
 }
 public Vector2f[][] GenerateOutline(Version version)
 {
     if (HasVertices(version))
     {
         Vector2f[][] outline = new Vector2f[1][];
         outline[0] = new Vector2f[Vertices.Length];
         for (int i = 0; i < Vertices.Length; i++)
         {
             outline[0][i] = Vertices[i].Position.ToVector2();
         }
         return(outline);
     }
     else
     {
         List <Vector2f[]> outlines = new List <Vector2f[]>();
         for (int i = 0; i < SubMeshes.Length; i++)
         {
             Vector3f[] vertices = VertexData.GenerateVertices(version, ref SubMeshes[i]);
             VerticesToOutline(outlines, vertices, ref SubMeshes[i]);
         }
         return(outlines.ToArray());
     }
 }
Example #29
0
            public void SetData(VertexData v0, VertexData v1, VertexData v2)
            {
                Matrix4x4 matrix = new Matrix4x4();

                matrix.column_0 = v0.vertex;
                matrix.column_1 = v1.vertex;
                matrix.column_2 = v2.vertex;
                vertices        = matrix;

                matrix.column_0 = (Vector3)v0.uv;
                matrix.column_1 = (Vector3)v1.uv;
                matrix.column_2 = (Vector3)v2.uv;
                uvs             = matrix;

                matrix.column_0 = v0.normal;
                matrix.column_1 = v1.normal;
                matrix.column_2 = v2.normal;
                normals         = matrix;

                rawV0 = v0;
                rawV1 = v1;
                rawV2 = v2;
            }
        /// <inheritdoc />
        protected override void Initialize()
        {
            base.Initialize();

            // Matrix i,j -> path
            _data.Clear();

            // Prepare the matrix with initial costs
            // Walk each edge and add entry in cost dictionary
            foreach (TEdge edge in VisitedGraph.Edges)
            {
                SEquatableEdge <TVertex> ij = edge.ToVertexPair();
                double cost = _weights(edge);
                if (!_data.TryGetValue(ij, out VertexData data))
                {
                    _data[ij] = new VertexData(cost, edge);
                }
                else if (cost < data.Distance)
                {
                    _data[ij] = new VertexData(cost, edge);
                }
            }
        }
Example #31
0
 IEnumerable<VertexData> GetVertexIter()
 {
     VertexData vertexData = new VertexData();
     vertexData.command = VertexCmd.MoveTo;
     vertexData.x = originX + radiusX;
     vertexData.y = originY;
     yield return vertexData;
     double anglePerStep = MathHelper.Tau / (double)numSteps;
     double angle = 0;
     vertexData.command = VertexCmd.LineTo;
     if (m_cw)
     {
         for (int i = 1; i < numSteps; i++)
         {
             angle += anglePerStep;
             vertexData.x = originX + Math.Cos(MathHelper.Tau - angle) * radiusX;
             vertexData.y = originY + Math.Sin(MathHelper.Tau - angle) * radiusY;
             yield return vertexData;
         }
     }
     else
     {
         for (int i = 1; i < numSteps; i++)
         {
             angle += anglePerStep;
             vertexData.x = originX + Math.Cos(angle) * radiusX;
             vertexData.y = originY + Math.Sin(angle) * radiusY;
             yield return vertexData;
         }
     }
     vertexData.x = (int)EndVertexOrientation.CCW;
     vertexData.y = 0;
     vertexData.command = VertexCmd.CloseAndEndFigure;
     yield return vertexData;
     vertexData.command = VertexCmd.Stop;
     yield return vertexData;
 }
 public FVF_PositionNormalColored(VertexData data)
 {
     Position = data.Position.ToVector3();
     Normal = data.Normal.ToVector3();
     Color = (data.Color ?? System.Drawing.Color.White).ToArgb();
 }
Example #33
0
 static List<List<IntPoint>> CreatePolygons(VertexStoreSnap a)
 {
     List<List<IntPoint>> allPolys = new List<List<IntPoint>>();
     List<IntPoint> currentPoly = null;
     VertexData last = new VertexData();
     VertexData first = new VertexData();
     bool addedFirst = false;
     var snapIter = a.GetVertexSnapIter();
     double x, y;
     VertexCmd cmd = snapIter.GetNextVertex(out x, out y);
     do
     {
         if (cmd == VertexCmd.LineTo)
         {
             if (!addedFirst)
             {
                 currentPoly.Add(new IntPoint((long)(last.x * 1000), (long)(last.y * 1000)));
                 addedFirst = true;
                 first = last;
             }
             currentPoly.Add(new IntPoint((long)(x * 1000), (long)(y * 1000)));
             last = new VertexData(cmd, x, y);
         }
         else
         {
             addedFirst = false;
             currentPoly = new List<IntPoint>();
             allPolys.Add(currentPoly);
             if (cmd == VertexCmd.MoveTo)
             {
                 last = new VertexData(cmd, x, y);
             }
             else
             {
                 last = first;
             }
         }
         cmd = snapIter.GetNextVertex(out x, out y);
     } while (cmd != VertexCmd.Stop);
     return allPolys;
 }
 public FVF_PositionNormalTexturedColored(VertexData data)
 {
     Position = data.Position.ToVector3();
     Normal = data.Normal.ToVector3();
     Color = (data.Color ?? System.Drawing.Color.White).ToArgb();
     if (data.UV != null)
         UV = new Vector2(data.UV.U, data.UV.V);
     else
         UV = new Vector2();
 }
 public FVF_PositionNormal(VertexData data)
 {
     Position = data.Position.ToVector3();
     Normal = data.Normal.ToVector3();
 }
Example #36
0
        void CreateDecal()
        {
            Bounds bounds = Bounds.Cleared;
            foreach( Vertex vertex in vertices )
                bounds.Add( vertex.position );

            VertexData vertexData = new VertexData();
            IndexData indexData = new IndexData();

            //init vertexData
            VertexDeclaration declaration = vertexData.VertexDeclaration;
            declaration.AddElement( 0, 0, VertexElementType.Float3, VertexElementSemantic.Position );
            declaration.AddElement( 0, 12, VertexElementType.Float3, VertexElementSemantic.Normal );
            declaration.AddElement( 0, 24, VertexElementType.Float2,
                VertexElementSemantic.TextureCoordinates, 0 );
            declaration.AddElement( 0, 32, VertexElementType.Float3, VertexElementSemantic.Tangent );

            VertexBufferBinding bufferBinding = vertexData.VertexBufferBinding;
            HardwareVertexBuffer vertexBuffer = HardwareBufferManager.Instance.CreateVertexBuffer(
                44, vertices.Length, HardwareBuffer.Usage.StaticWriteOnly );
            bufferBinding.SetBinding( 0, vertexBuffer, true );
            vertexData.VertexCount = vertices.Length;

            //init indexData
            Trace.Assert( vertices.Length < 65536, "Decal: vertices.Length < 65536" );

            HardwareIndexBuffer indexBuffer = HardwareBufferManager.Instance.CreateIndexBuffer(
                HardwareIndexBuffer.IndexType._16Bit, indices.Length,
                HardwareBuffer.Usage.StaticWriteOnly );
            indexData.SetIndexBuffer( indexBuffer, true );
            indexData.IndexCount = indices.Length;

            //init material
            Material material = null;

            shaderBaseMaterial = HighLevelMaterialManager.Instance.
                GetMaterialByName( sourceMaterialName ) as ShaderBaseMaterial;
            //only default shader technique for ShaderBase material
            if( shaderBaseMaterial != null && !shaderBaseMaterial.IsDefaultTechniqueCreated() )
                shaderBaseMaterial = null;

            if( shaderBaseMaterial != null )
            {
                //ShaderBase material
                material = shaderBaseMaterial.BaseMaterial;
            }
            else
            {
                //standard material or fallback ShaderBase technique
                Material sourceMaterial = MaterialManager.Instance.GetByName( sourceMaterialName );
                if( sourceMaterial != null )
                {
                    //clone standard material
                    clonedStandardMaterial = MaterialManager.Instance.Clone( sourceMaterial,
                        MaterialManager.Instance.GetUniqueName( sourceMaterialName + "_Cloned" ) );
                    material = clonedStandardMaterial;
                }
            }

            staticMeshObject = SceneManager.Instance.CreateStaticMeshObject( bounds + Position,
                Position, Quat.Identity, new Vec3( 1, 1, 1 ), material, vertexData, indexData, true );
            staticMeshObject.AddToRenderQueue += StaticMeshObject_AddToRenderQueue;

            UpdateBuffers();
        }
 public FVF_PositionNormalTextured(VertexData data)
 {
     Position = data.Position.ToVector3();
     Normal = data.Normal.ToVector3();
     if (data.UV != null)
         UV = new Vector2(data.UV.U, data.UV.V);
     else
         UV = new Vector2();
 }
        private static bool SplitMeshUsingPlane(MeshData meshDataIn, FracturedObject fracturedComponent, SplitOptions splitOptions, Vector3 v3PlaneNormal, Vector3 v3PlaneRight, Vector3 v3PlanePoint, out List<MeshData> listMeshDatasPosOut, out List<MeshData> listMeshDatasNegOut, ProgressDelegate progress = null)
        {
            Plane planeSplit = new Plane(v3PlaneNormal, v3PlanePoint);

            listMeshDatasPosOut = new List<MeshData>();
            listMeshDatasNegOut = new List<MeshData>();

            // Check if the input object already has been split, to get its split closing submesh

            bool bNeedsNewSplitSubMesh = meshDataIn.nSplitCloseSubMesh == -1;
            int  nSplitCloseSubMesh    = meshDataIn.nSplitCloseSubMesh;

            // Here we are going to store our output vertex/index data

            int nCurrentVertexHash = meshDataIn.nCurrentVertexHash; // We will use this to identify vertices with same coordinates but different vertex data. They will share the same vertex hash

            List<VertexData>     listVertexDataPos   = new List<VertexData>();
            List<VertexData>     listVertexDataNeg   = new List<VertexData>();
            List<int>[]          alistIndicesPos     = new List<int>[meshDataIn.nSubMeshCount + (meshDataIn.nSplitCloseSubMesh == -1 ? 1 : 0)];
            List<int>[]          alistIndicesNeg     = new List<int>[meshDataIn.nSubMeshCount + (meshDataIn.nSplitCloseSubMesh == -1 ? 1 : 0)];
            MeshFaceConnectivity faceConnectivityPos = new MeshFaceConnectivity();
            MeshFaceConnectivity faceConnectivityNeg = new MeshFaceConnectivity();
            MeshDataConnectivity meshConnectivityPos = new MeshDataConnectivity();
            MeshDataConnectivity meshConnectivityNeg = new MeshDataConnectivity();

            listVertexDataPos.Capacity = meshDataIn.aVertexData.Length / 2;
            listVertexDataNeg.Capacity = meshDataIn.aVertexData.Length / 2;

            if(bNeedsNewSplitSubMesh)
            {
                // Make room for the split closing submesh

                nSplitCloseSubMesh = meshDataIn.nSubMeshCount;

                alistIndicesPos[nSplitCloseSubMesh] = new List<int>();
                alistIndicesNeg[nSplitCloseSubMesh] = new List<int>();
            }

            // Our vertices that form the clipped cap

            Dictionary<EdgeKeyByHash, int>     dicClipVerticesHash = new Dictionary<EdgeKeyByHash, int>    (new EdgeKeyByHash.EqualityComparer());
            Dictionary<EdgeKeyByHash, CapEdge> dicCapEdges         = new Dictionary<EdgeKeyByHash, CapEdge>(new EdgeKeyByHash.EqualityComparer());

            // A hash table with our clipped edges, to reuse clipped vertices

            Dictionary<EdgeKeyByIndex, ClippedEdge> dicClippedEdgesPos = new Dictionary<EdgeKeyByIndex, ClippedEdge>(new EdgeKeyByIndex.EqualityComparer());
            Dictionary<EdgeKeyByIndex, ClippedEdge> dicClippedEdgesNeg = new Dictionary<EdgeKeyByIndex, ClippedEdge>(new EdgeKeyByIndex.EqualityComparer());

            int nClippedCacheHits   = 0;
            int nClippedCacheMisses = 0;

            // A hash table with the remapped indices, to reuse non-clipped vertices

            Dictionary<int, int> dicRemappedIndicesPos = new Dictionary<int, int>();
            Dictionary<int, int> dicRemappedIndicesNeg = new Dictionary<int, int>();

            for(int nSubMesh = 0; nSubMesh < meshDataIn.nSubMeshCount; nSubMesh++)
            {
                // Index list

                alistIndicesPos[nSubMesh] = new List<int>();
                alistIndicesNeg[nSubMesh] = new List<int>();
                List<int> listIndicesPos = alistIndicesPos[nSubMesh];
                List<int> listIndicesNeg = alistIndicesNeg[nSubMesh];

                alistIndicesPos[nSubMesh].Capacity = meshDataIn.aaIndices[nSubMesh].Length / 2;
                alistIndicesNeg[nSubMesh].Capacity = meshDataIn.aaIndices[nSubMesh].Length / 2;

                // A reference to the output arrays/lists (it will be switching between positive/negative side along the algorithm)

                List<VertexData>     plistVertexData    = listVertexDataPos;
                List<int>            plistObjectIndices = listIndicesPos;
                MeshFaceConnectivity pFaceConnectivity  = faceConnectivityPos;
                MeshDataConnectivity pMeshConnectivity  = meshConnectivityPos;

                Dictionary<EdgeKeyByIndex, ClippedEdge> pdicClippedEdges    = dicClippedEdgesPos;
                Dictionary<int, int>                    pdicRemappedIndices = dicRemappedIndicesPos;

                // Iterate through all submesh faces:

                for(int i = 0; i < meshDataIn.aaIndices[nSubMesh].Length / 3; i++)
	            {
                    plistVertexData     = listVertexDataPos;
                    plistObjectIndices  = listIndicesPos;
                    pFaceConnectivity   = faceConnectivityPos;
                    pMeshConnectivity   = meshConnectivityPos;
                    pdicClippedEdges    = dicClippedEdgesPos;
                    pdicRemappedIndices = dicRemappedIndicesPos;

		            int nIndex1 = meshDataIn.aaIndices[nSubMesh][i * 3 + 0];
		            int nIndex2 = meshDataIn.aaIndices[nSubMesh][i * 3 + 1];
		            int nIndex3 = meshDataIn.aaIndices[nSubMesh][i * 3 + 2];

                    int nHashV1 = meshDataIn.aVertexData[nIndex1].nVertexHash;
                    int nHashV2 = meshDataIn.aVertexData[nIndex2].nVertexHash;
                    int nHashV3 = meshDataIn.aVertexData[nIndex3].nVertexHash;

		            Vector3 v1 = meshDataIn.aVertexData[nIndex1].v3Vertex;
		            Vector3 v2 = meshDataIn.aVertexData[nIndex2].v3Vertex;
		            Vector3 v3 = meshDataIn.aVertexData[nIndex3].v3Vertex;

                    // Classify vertices depending on the side of the plane they lay on, then clip if necessary.

		            float fSide1 = v1.x * planeSplit.normal.x + v1.y * planeSplit.normal.y + v1.z * planeSplit.normal.z + planeSplit.distance;
		            float fSide2 = v2.x * planeSplit.normal.x + v2.y * planeSplit.normal.y + v2.z * planeSplit.normal.z + planeSplit.distance;
		            float fSide3 = v3.x * planeSplit.normal.x + v3.y * planeSplit.normal.y + v3.z * planeSplit.normal.z + planeSplit.distance;

                    bool  bForceSameSide  = false;
                    int   nAlmostInPlane  = 0;
                    bool  bAlmostInPlane1 = false;
                    bool  bAlmostInPlane2 = false;
                    bool  bAlmostInPlane3 = false;
                    float fFurthest       = 0.0f;

                    if(Mathf.Abs(fSide1) < UltimateFracturing.Parameters.EPSILONDISTANCEPLANE) { bAlmostInPlane1 = true; nAlmostInPlane++; }
                    if(Mathf.Abs(fSide2) < UltimateFracturing.Parameters.EPSILONDISTANCEPLANE) { bAlmostInPlane2 = true; nAlmostInPlane++; }
                    if(Mathf.Abs(fSide3) < UltimateFracturing.Parameters.EPSILONDISTANCEPLANE) { bAlmostInPlane3 = true; nAlmostInPlane++; }

                    if(Mathf.Abs(fSide1) > Mathf.Abs(fFurthest)) fFurthest = fSide1;
                    if(Mathf.Abs(fSide2) > Mathf.Abs(fFurthest)) fFurthest = fSide2;
                    if(Mathf.Abs(fSide3) > Mathf.Abs(fFurthest)) fFurthest = fSide3;

                    if(nAlmostInPlane == 1)
                    {
                        // Look if the other two vertices are on the same side. If so, we'll skip the clipping too.
                        if(bAlmostInPlane1 && (fSide2 * fSide3 > 0.0f)) bForceSameSide = true;
                        if(bAlmostInPlane2 && (fSide1 * fSide3 > 0.0f)) bForceSameSide = true;
                        if(bAlmostInPlane3 && (fSide1 * fSide2 > 0.0f)) bForceSameSide = true;
                    }
                    else if(nAlmostInPlane > 1)
                    {
                        bForceSameSide = true;

                        if(nAlmostInPlane == 3)
                        {
                            // Coplanar
                            continue;
                        }
                    }

		            if((fSide1 * fSide2 > 0.0f && fSide2 * fSide3 > 0.0f) || bForceSameSide)
		            {
			            // All on the same side, no clipping needed

			            if(fFurthest < 0.0f)
			            {
				            plistVertexData     = listVertexDataNeg;
				            plistObjectIndices  = listIndicesNeg;
                            pFaceConnectivity   = faceConnectivityNeg;
                            pMeshConnectivity   = meshConnectivityNeg;
                            pdicClippedEdges    = dicClippedEdgesNeg;
                            pdicRemappedIndices = dicRemappedIndicesNeg;
			            }

                        int nNewIndex1 = -1;
                        int nNewIndex2 = -1;
                        int nNewIndex3 = -1;

                        // Find vertices in remapped indices list and add vertex data if not present

                        if(pdicRemappedIndices.ContainsKey(nIndex1))
                        {
                            nNewIndex1 = pdicRemappedIndices[nIndex1];
                        }
                        if(nNewIndex1 == -1)
                        {
                            nNewIndex1 = plistVertexData.Count;
                            plistVertexData.Add(meshDataIn.aVertexData[nIndex1].Copy());
                            pdicRemappedIndices[nIndex1] = nNewIndex1;
                        }

                        if(pdicRemappedIndices.ContainsKey(nIndex2))
                        {
                            nNewIndex2 = pdicRemappedIndices[nIndex2];
                        }
                        if(nNewIndex2 == -1)
                        {
                            nNewIndex2 = plistVertexData.Count;
                            plistVertexData.Add(meshDataIn.aVertexData[nIndex2].Copy());
                            pdicRemappedIndices[nIndex2] = nNewIndex2;
                        }

                        if(pdicRemappedIndices.ContainsKey(nIndex3))
                        {
                            nNewIndex3 = pdicRemappedIndices[nIndex3];
                        }
                        if(nNewIndex3 == -1)
                        {
                            nNewIndex3 = plistVertexData.Count;
                            plistVertexData.Add(meshDataIn.aVertexData[nIndex3].Copy());
                            pdicRemappedIndices[nIndex3] = nNewIndex3;
                        }

                        // Add triangle indices

                        if(fracturedComponent.GenerateChunkConnectionInfo && splitOptions.bForceNoChunkConnectionInfo == false)
                        {
                            pMeshConnectivity.NotifyNewClippedFace(meshDataIn, nSubMesh, i, nSubMesh, plistObjectIndices.Count / 3);
                        }

                        plistObjectIndices.Add(nNewIndex1);
                        plistObjectIndices.Add(nNewIndex2);
                        plistObjectIndices.Add(nNewIndex3);

                        if(fracturedComponent.GenerateIslands && splitOptions.bForceNoIslandGeneration == false)
                        {
                            pFaceConnectivity.AddEdge(nSubMesh, v1, v2, nHashV1, nHashV2, nNewIndex1, nNewIndex2);
                            pFaceConnectivity.AddEdge(nSubMesh, v2, v3, nHashV2, nHashV3, nNewIndex2, nNewIndex3);
                            pFaceConnectivity.AddEdge(nSubMesh, v3, v1, nHashV3, nHashV1, nNewIndex3, nNewIndex1);
                        }

                        // Add cap edges only if an edge is lying on the plane

                        if(nAlmostInPlane == 2)
                        {
                            if(fFurthest > 0.0f)
                            {
                                if(bAlmostInPlane1 && bAlmostInPlane2 && splitOptions.bForceNoCap == false) AddCapEdge(dicCapEdges, nHashV1, nHashV2, v1, v2);
                                if(bAlmostInPlane2 && bAlmostInPlane3 && splitOptions.bForceNoCap == false) AddCapEdge(dicCapEdges, nHashV2, nHashV3, v2, v3);
                                if(bAlmostInPlane3 && bAlmostInPlane1 && splitOptions.bForceNoCap == false) AddCapEdge(dicCapEdges, nHashV3, nHashV1, v3, v1);
                            }
                            else
                            {
                                if(bAlmostInPlane1 && bAlmostInPlane2 && splitOptions.bForceNoCap == false) AddCapEdge(dicCapEdges, nHashV2, nHashV1, v2, v1);
                                if(bAlmostInPlane2 && bAlmostInPlane3 && splitOptions.bForceNoCap == false) AddCapEdge(dicCapEdges, nHashV3, nHashV2, v3, v2);
                                if(bAlmostInPlane3 && bAlmostInPlane1 && splitOptions.bForceNoCap == false) AddCapEdge(dicCapEdges, nHashV1, nHashV3, v1, v3);
                            }
                        }
		            }
                    else if(nAlmostInPlane == 1)
                    {
                        // Special treatment clipping for one vertex laying on the clipping plane and the other 2 on different sides

                        int  nNewIndex1 = -1;
                        int  nNewIndex2 = -1;
                        int  nNewIndex3 = -1;
                        int  nNewIndex4 = -1;
                        int  nHashV4    = -1;
                        bool bEdge      = false;

                        EdgeKeyByIndex clippedEdgeKey;

                        if(bAlmostInPlane1)
                        {
                            // v1 almost on the clipping plane

					        if(fSide2 < 0.0f)
					        {
						        plistVertexData     = listVertexDataNeg;
						        plistObjectIndices  = listIndicesNeg;
                                pFaceConnectivity   = faceConnectivityNeg;
                                pMeshConnectivity   = meshConnectivityNeg;
                                pdicClippedEdges    = dicClippedEdgesNeg;
                                pdicRemappedIndices = dicRemappedIndicesNeg;
					        }

                            clippedEdgeKey = new EdgeKeyByIndex(nIndex2, nIndex3);

                            if(pdicClippedEdges.ContainsKey(clippedEdgeKey))
                            {
                                nClippedCacheHits++;
                                bEdge = true;
                                nNewIndex2 = pdicClippedEdges[clippedEdgeKey].GetFirstIndex(nIndex2);
                                nNewIndex4 = pdicClippedEdges[clippedEdgeKey].nClippedIndex;
                            }
                            else
                            {
                                nClippedCacheMisses++;
                                if(pdicRemappedIndices.ContainsKey(nIndex2)) nNewIndex2 = pdicRemappedIndices[nIndex2];
                            }

                            // Clip if not present in clipped edge list

                            EdgeKeyByHash clippedEdgeKeyHash = new EdgeKeyByHash(nHashV2, nHashV3);

                            if(dicClipVerticesHash.ContainsKey(clippedEdgeKeyHash))
                            {
                                nHashV4 = dicClipVerticesHash[clippedEdgeKeyHash];
                            }
                            else
                            {
                                nHashV4 = nCurrentVertexHash++;
                                dicClipVerticesHash.Add(clippedEdgeKeyHash, nHashV4);
                            }

                            VertexData vd4 = new VertexData(nHashV4);

                            if(bEdge == false)
                            {
                                if(VertexData.ClipAgainstPlane(meshDataIn.aVertexData, nIndex2, nIndex3, v2, v3, planeSplit, ref vd4) == false)
                                {
                                    return false;
                                }
                            }

                            // Add geometry of one side

                            // Add vertex data for all data not present in remapped list

                            if(nNewIndex1 == -1)
                            {
                                if(pdicRemappedIndices.ContainsKey(nIndex1))
                                {
                                    nNewIndex1 = pdicRemappedIndices[nIndex1];
                                }
                            }
                            if(nNewIndex1 == -1)
                            {
                                nNewIndex1 = plistVertexData.Count;
                                plistVertexData.Add(meshDataIn.aVertexData[nIndex1].Copy());
                                pdicRemappedIndices[nIndex1] = nNewIndex1;
                            }

                            if(nNewIndex2 == -1)
                            {
                                nNewIndex2 = plistVertexData.Count;
                                plistVertexData.Add(meshDataIn.aVertexData[nIndex2].Copy());
                                pdicRemappedIndices[nIndex2] = nNewIndex2;
                            }

                            if(nNewIndex4 == -1)
                            {
                                nNewIndex4 = plistVertexData.Count;
                                plistVertexData.Add(vd4);
                            }

                            if(fracturedComponent.GenerateChunkConnectionInfo && splitOptions.bForceNoChunkConnectionInfo == false)
                            {
                                pMeshConnectivity.NotifyNewClippedFace(meshDataIn, nSubMesh, i, nSubMesh, plistObjectIndices.Count / 3);
                            }

                            plistObjectIndices.Add(nNewIndex1);
                            plistObjectIndices.Add(nNewIndex2);
                            plistObjectIndices.Add(nNewIndex4);

                            Vector3 v4 = plistVertexData[nNewIndex4].v3Vertex;

                            if(fracturedComponent.GenerateIslands && splitOptions.bForceNoIslandGeneration == false)
                            {
                                pFaceConnectivity.AddEdge(nSubMesh, v1, v2, nHashV1, nHashV2, nNewIndex1, nNewIndex2);
                                pFaceConnectivity.AddEdge(nSubMesh, v2, v4, nHashV2, nHashV4, nNewIndex2, nNewIndex4);
                                pFaceConnectivity.AddEdge(nSubMesh, v4, v1, nHashV4, nHashV1, nNewIndex4, nNewIndex1);
                            }

                            // Update cap edges and cache

                            if(plistVertexData == listVertexDataPos && splitOptions.bForceNoCap == false) AddCapEdge(dicCapEdges, nHashV4, nHashV1, plistVertexData[nNewIndex4].v3Vertex, plistVertexData[nNewIndex1].v3Vertex);

                            if(bEdge == false) pdicClippedEdges.Add(clippedEdgeKey, new ClippedEdge(nIndex2, nIndex3, nNewIndex2, nNewIndex3, nNewIndex4));

                            // Add geometry of other side

					        if(fSide3 < 0.0f)
					        {
						        plistVertexData     = listVertexDataNeg;
                                plistObjectIndices  = listIndicesNeg;
                                pFaceConnectivity   = faceConnectivityNeg;
                                pMeshConnectivity   = meshConnectivityNeg;
                                pdicClippedEdges    = dicClippedEdgesNeg;
                                pdicRemappedIndices = dicRemappedIndicesNeg;
					        }
					        else
					        {
						        plistVertexData     = listVertexDataPos;
						        plistObjectIndices  = listIndicesPos;
                                pFaceConnectivity   = faceConnectivityPos;
                                pMeshConnectivity   = meshConnectivityPos;
                                pdicClippedEdges    = dicClippedEdgesPos;
                                pdicRemappedIndices = dicRemappedIndicesPos;
					        }

                            nNewIndex1 = -1;
                            nNewIndex2 = -1;
                            nNewIndex3 = -1;
                            nNewIndex4 = -1;
                            bEdge      = false;

                            // Find edges in cache

                            if(pdicClippedEdges.ContainsKey(clippedEdgeKey))
                            {
                                nClippedCacheHits++;
                                bEdge      = true;
                                nNewIndex3 = pdicClippedEdges[clippedEdgeKey].GetSecondIndex(nIndex3);
                                nNewIndex4 = pdicClippedEdges[clippedEdgeKey].nClippedIndex;
                            }
                            else
                            {
                                nClippedCacheMisses++;
                                if(pdicRemappedIndices.ContainsKey(nIndex3)) nNewIndex3 = pdicRemappedIndices[nIndex3];
                            }

                            // Add vertex data for all data not present in remapped list

                            if(nNewIndex1 == -1)
                            {
                                if(pdicRemappedIndices.ContainsKey(nIndex1))
                                {
                                    nNewIndex1 = pdicRemappedIndices[nIndex1];
                                }
                            }
                            if(nNewIndex1 == -1)
                            {
                                nNewIndex1 = plistVertexData.Count;
                                plistVertexData.Add(meshDataIn.aVertexData[nIndex1].Copy());
                                pdicRemappedIndices[nIndex1] = nNewIndex1;
                            }

                            if(nNewIndex3 == -1)
                            {
                                nNewIndex3 = plistVertexData.Count;
                                plistVertexData.Add(meshDataIn.aVertexData[nIndex3].Copy());
                                pdicRemappedIndices[nIndex3] = nNewIndex3;
                            }

                            if(nNewIndex4 == -1)
                            {
                                nNewIndex4 = plistVertexData.Count;
                                plistVertexData.Add(vd4);
                            }

                            if(fracturedComponent.GenerateChunkConnectionInfo && splitOptions.bForceNoChunkConnectionInfo == false)
                            {
                                pMeshConnectivity.NotifyNewClippedFace(meshDataIn, nSubMesh, i, nSubMesh, plistObjectIndices.Count / 3);
                            }

                            plistObjectIndices.Add(nNewIndex1);
                            plistObjectIndices.Add(nNewIndex4);
                            plistObjectIndices.Add(nNewIndex3);

                            if(fracturedComponent.GenerateIslands && splitOptions.bForceNoIslandGeneration == false)
                            {
                                pFaceConnectivity.AddEdge(nSubMesh, v1, v4, nHashV1, nHashV4, nNewIndex1, nNewIndex4);
                                pFaceConnectivity.AddEdge(nSubMesh, v4, v3, nHashV4, nHashV3, nNewIndex4, nNewIndex3);
                                pFaceConnectivity.AddEdge(nSubMesh, v3, v1, nHashV3, nHashV1, nNewIndex3, nNewIndex1);
                            }

                            // Update cap edges and cache

                            if(plistVertexData == listVertexDataPos && splitOptions.bForceNoCap == false) AddCapEdge(dicCapEdges, nHashV1, nHashV4, plistVertexData[nNewIndex1].v3Vertex, plistVertexData[nNewIndex4].v3Vertex);

                            if(bEdge == false) pdicClippedEdges.Add(clippedEdgeKey, new ClippedEdge(nIndex2, nIndex3, nNewIndex2, nNewIndex3, nNewIndex4));
                        }
                        else if(bAlmostInPlane2)
                        {
                            // v2 almost on the clipping plane

					        if(fSide3 < 0.0f)
					        {
						        plistVertexData     = listVertexDataNeg;
						        plistObjectIndices  = listIndicesNeg;
                                pFaceConnectivity   = faceConnectivityNeg;
                                pMeshConnectivity   = meshConnectivityNeg;
                                pdicClippedEdges    = dicClippedEdgesNeg;
                                pdicRemappedIndices = dicRemappedIndicesNeg;
					        }

                            clippedEdgeKey = new EdgeKeyByIndex(nIndex3, nIndex1);

                            if(pdicClippedEdges.ContainsKey(clippedEdgeKey))
                            {
                                nClippedCacheHits++;
                                bEdge      = true;
                                nNewIndex3 = pdicClippedEdges[clippedEdgeKey].GetFirstIndex(nIndex3);
                                nNewIndex4 = pdicClippedEdges[clippedEdgeKey].nClippedIndex;
                            }
                            else
                            {
                                nClippedCacheMisses++;
                                if(pdicRemappedIndices.ContainsKey(nIndex3)) nNewIndex3 = pdicRemappedIndices[nIndex3];
                            }

                            // Clip if not present in clipped edge list

                            EdgeKeyByHash clippedEdgeKeyHash = new EdgeKeyByHash(nHashV3, nHashV1);

                            if(dicClipVerticesHash.ContainsKey(clippedEdgeKeyHash))
                            {
                                nHashV4 = dicClipVerticesHash[clippedEdgeKeyHash];
                            }
                            else
                            {
                                nHashV4 = nCurrentVertexHash++;
                                dicClipVerticesHash.Add(clippedEdgeKeyHash, nHashV4);
                            }

                            VertexData vd4 = new VertexData(nHashV4);

                            if(bEdge == false)
                            {
                                if(VertexData.ClipAgainstPlane(meshDataIn.aVertexData, nIndex3, nIndex1, v3, v1, planeSplit, ref vd4) == false)
                                {
                                    return false;
                                }
                            }

                            // Add geometry of one side

                            // Add vertex data for all data not present in remapped list

                            if(nNewIndex2 == -1)
                            {
                                if(pdicRemappedIndices.ContainsKey(nIndex2))
                                {
                                    nNewIndex2 = pdicRemappedIndices[nIndex2];
                                }
                            }
                            if(nNewIndex2 == -1)
                            {
                                nNewIndex2 = plistVertexData.Count;
                                plistVertexData.Add(meshDataIn.aVertexData[nIndex2].Copy());
                                pdicRemappedIndices[nIndex2] = nNewIndex2;
                            }

                            if(nNewIndex3 == -1)
                            {
                                nNewIndex3 = plistVertexData.Count;
                                plistVertexData.Add(meshDataIn.aVertexData[nIndex3].Copy());
                                pdicRemappedIndices[nIndex3] = nNewIndex3;
                            }

                            if(nNewIndex4 == -1)
                            {
                                nNewIndex4 = plistVertexData.Count;
                                plistVertexData.Add(vd4);
                            }

                            if(fracturedComponent.GenerateChunkConnectionInfo && splitOptions.bForceNoChunkConnectionInfo == false)
                            {
                                pMeshConnectivity.NotifyNewClippedFace(meshDataIn, nSubMesh, i, nSubMesh, plistObjectIndices.Count / 3);
                            }

                            plistObjectIndices.Add(nNewIndex2);
                            plistObjectIndices.Add(nNewIndex3);
                            plistObjectIndices.Add(nNewIndex4);

                            Vector3 v4 = plistVertexData[nNewIndex4].v3Vertex;

                            if(fracturedComponent.GenerateIslands && splitOptions.bForceNoIslandGeneration == false)
                            {
                                pFaceConnectivity.AddEdge(nSubMesh, v2, v3, nHashV2, nHashV3, nNewIndex2, nNewIndex3);
                                pFaceConnectivity.AddEdge(nSubMesh, v3, v4, nHashV3, nHashV4, nNewIndex3, nNewIndex4);
                                pFaceConnectivity.AddEdge(nSubMesh, v4, v2, nHashV4, nHashV2, nNewIndex4, nNewIndex2);
                            }

                            // Update cap edges and cache

                            if(plistVertexData == listVertexDataPos && splitOptions.bForceNoCap == false) AddCapEdge(dicCapEdges, nHashV4, nHashV2, plistVertexData[nNewIndex4].v3Vertex, plistVertexData[nNewIndex2].v3Vertex);

                            if(bEdge == false) pdicClippedEdges.Add(clippedEdgeKey, new ClippedEdge(nIndex3, nIndex1, nNewIndex3, nNewIndex1, nNewIndex4));

                            // Add geometry of other side

					        if(fSide1 < 0.0f)
					        {
						        plistVertexData     = listVertexDataNeg;
                                plistObjectIndices  = listIndicesNeg;
                                pFaceConnectivity   = faceConnectivityNeg;
                                pMeshConnectivity   = meshConnectivityNeg;
                                pdicClippedEdges    = dicClippedEdgesNeg;
                                pdicRemappedIndices = dicRemappedIndicesNeg;
					        }
					        else
					        {
						        plistVertexData     = listVertexDataPos;
						        plistObjectIndices  = listIndicesPos;
                                pFaceConnectivity   = faceConnectivityPos;
                                pMeshConnectivity   = meshConnectivityPos;
                                pdicClippedEdges    = dicClippedEdgesPos;
                                pdicRemappedIndices = dicRemappedIndicesPos;
					        }

                            nNewIndex1 = -1;
                            nNewIndex2 = -1;
                            nNewIndex4 = -1;
                            bEdge      = false;

                            // Find edges in cache

                            if(pdicClippedEdges.ContainsKey(clippedEdgeKey))
                            {
                                nClippedCacheHits++;
                                bEdge      = true;
                                nNewIndex1 = pdicClippedEdges[clippedEdgeKey].GetSecondIndex(nIndex1);
                                nNewIndex4 = pdicClippedEdges[clippedEdgeKey].nClippedIndex;
                            }
                            else
                            {
                                nClippedCacheMisses++;
                                if(pdicRemappedIndices.ContainsKey(nIndex1)) nNewIndex1 = pdicRemappedIndices[nIndex1];
                            }

                            // Add vertex data for all data not present in remapped list

                            if(nNewIndex1 == -1)
                            {
                                nNewIndex1 = plistVertexData.Count;
                                plistVertexData.Add(meshDataIn.aVertexData[nIndex1].Copy());
                                pdicRemappedIndices[nIndex1] = nNewIndex1;
                            }

                            if(nNewIndex2 == -1)
                            {
                                if(pdicRemappedIndices.ContainsKey(nIndex2))
                                {
                                    nNewIndex2 = pdicRemappedIndices[nIndex2];
                                }
                            }
                            if(nNewIndex2 == -1)
                            {
                                nNewIndex2 = plistVertexData.Count;
                                plistVertexData.Add(meshDataIn.aVertexData[nIndex2].Copy());
                                pdicRemappedIndices[nIndex2] = nNewIndex2;
                            }

                            if(nNewIndex4 == -1)
                            {
                                nNewIndex4 = plistVertexData.Count;
                                plistVertexData.Add(vd4);
                            }

                            if(fracturedComponent.GenerateChunkConnectionInfo && splitOptions.bForceNoChunkConnectionInfo == false)
                            {
                                pMeshConnectivity.NotifyNewClippedFace(meshDataIn, nSubMesh, i, nSubMesh, plistObjectIndices.Count / 3);
                            }

                            plistObjectIndices.Add(nNewIndex2);
                            plistObjectIndices.Add(nNewIndex4);
                            plistObjectIndices.Add(nNewIndex1);

                            if(fracturedComponent.GenerateIslands && splitOptions.bForceNoIslandGeneration == false)
                            {
                                pFaceConnectivity.AddEdge(nSubMesh, v2, v4, nHashV2, nHashV4, nNewIndex2, nNewIndex4);
                                pFaceConnectivity.AddEdge(nSubMesh, v4, v1, nHashV4, nHashV1, nNewIndex4, nNewIndex1);
                                pFaceConnectivity.AddEdge(nSubMesh, v1, v2, nHashV1, nHashV2, nNewIndex1, nNewIndex2);
                            }

                            // Update cap edges and cache

                            if(plistVertexData == listVertexDataPos && splitOptions.bForceNoCap == false) AddCapEdge(dicCapEdges, nHashV2, nHashV4, plistVertexData[nNewIndex2].v3Vertex, plistVertexData[nNewIndex4].v3Vertex);

                            if(bEdge == false) pdicClippedEdges.Add(clippedEdgeKey, new ClippedEdge(nIndex3, nIndex1, nNewIndex3, nNewIndex1, nNewIndex4));
                        }
                        else if(bAlmostInPlane3)
                        {
                            // v3 almost on the clipping plane

					        if(fSide1 < 0.0f)
					        {
						        plistVertexData     = listVertexDataNeg;
						        plistObjectIndices  = listIndicesNeg;
                                pFaceConnectivity   = faceConnectivityNeg;
                                pMeshConnectivity   = meshConnectivityNeg;
                                pdicClippedEdges    = dicClippedEdgesNeg;
                                pdicRemappedIndices = dicRemappedIndicesNeg;
					        }

                            clippedEdgeKey = new EdgeKeyByIndex(nIndex1, nIndex2);

                            if(pdicClippedEdges.ContainsKey(clippedEdgeKey))
                            {
                                nClippedCacheHits++;
                                bEdge      = true;
                                nNewIndex1 = pdicClippedEdges[clippedEdgeKey].GetFirstIndex(nIndex1);
                                nNewIndex4 = pdicClippedEdges[clippedEdgeKey].nClippedIndex;
                            }
                            else
                            {
                                nClippedCacheMisses++;
                                if(pdicRemappedIndices.ContainsKey(nIndex1)) nNewIndex1 = pdicRemappedIndices[nIndex1];
                            }

                            // Clip if not present in clipped edge list

                            EdgeKeyByHash clippedEdgeKeyHash = new EdgeKeyByHash(nHashV1, nHashV2);

                            if(dicClipVerticesHash.ContainsKey(clippedEdgeKeyHash))
                            {
                                nHashV4 = dicClipVerticesHash[clippedEdgeKeyHash];
                            }
                            else
                            {
                                nHashV4 = nCurrentVertexHash++;
                                dicClipVerticesHash.Add(clippedEdgeKeyHash, nHashV4);
                            }

                            VertexData vd4 = new VertexData(nHashV4);

                            if(bEdge == false)
                            {
                                if(VertexData.ClipAgainstPlane(meshDataIn.aVertexData, nIndex1, nIndex2, v1, v2, planeSplit, ref vd4) == false)
                                {
                                    return false;
                                }
                            }

                            // Add geometry of one side

                            // Add vertex data for all data not present in remapped list

                            if(nNewIndex1 == -1)
                            {
                                nNewIndex1 = plistVertexData.Count;
                                plistVertexData.Add(meshDataIn.aVertexData[nIndex1].Copy());
                                pdicRemappedIndices[nIndex1] = nNewIndex1;
                            }

                            if(nNewIndex3 == -1)
                            {
                                if(pdicRemappedIndices.ContainsKey(nIndex3))
                                {
                                    nNewIndex3 = pdicRemappedIndices[nIndex3];
                                }
                            }
                            if(nNewIndex3 == -1)
                            {
                                nNewIndex3 = plistVertexData.Count;
                                plistVertexData.Add(meshDataIn.aVertexData[nIndex3].Copy());
                                pdicRemappedIndices[nIndex3] = nNewIndex3;
                            }

                            if(nNewIndex4 == -1)
                            {
                                nNewIndex4 = plistVertexData.Count;
                                plistVertexData.Add(vd4);
                            }

                            if(fracturedComponent.GenerateChunkConnectionInfo && splitOptions.bForceNoChunkConnectionInfo == false)
                            {
                                pMeshConnectivity.NotifyNewClippedFace(meshDataIn, nSubMesh, i, nSubMesh, plistObjectIndices.Count / 3);
                            }

                            plistObjectIndices.Add(nNewIndex1);
                            plistObjectIndices.Add(nNewIndex4);
                            plistObjectIndices.Add(nNewIndex3);

                            Vector3 v4 = plistVertexData[nNewIndex4].v3Vertex;

                            if(fracturedComponent.GenerateIslands && splitOptions.bForceNoIslandGeneration == false)
                            {
                                pFaceConnectivity.AddEdge(nSubMesh, v1, v4, nHashV1, nHashV4, nNewIndex1, nNewIndex4);
                                pFaceConnectivity.AddEdge(nSubMesh, v4, v3, nHashV4, nHashV3, nNewIndex4, nNewIndex3);
                                pFaceConnectivity.AddEdge(nSubMesh, v3, v1, nHashV3, nHashV1, nNewIndex3, nNewIndex1);
                            }

                            // Update cap edges and cache

                            if(plistVertexData == listVertexDataPos && splitOptions.bForceNoCap == false) AddCapEdge(dicCapEdges, nHashV4, nHashV3, plistVertexData[nNewIndex4].v3Vertex, plistVertexData[nNewIndex3].v3Vertex);

                            if(bEdge == false) pdicClippedEdges.Add(clippedEdgeKey, new ClippedEdge(nIndex1, nIndex2, nNewIndex1, nNewIndex2, nNewIndex4));

                            // Add geometry of other side

					        if(fSide2 < 0.0f)
					        {
						        plistVertexData     = listVertexDataNeg;
                                plistObjectIndices  = listIndicesNeg;
                                pFaceConnectivity   = faceConnectivityNeg;
                                pMeshConnectivity   = meshConnectivityNeg;
                                pdicClippedEdges    = dicClippedEdgesNeg;
                                pdicRemappedIndices = dicRemappedIndicesNeg;
					        }
					        else
					        {
						        plistVertexData     = listVertexDataPos;
						        plistObjectIndices  = listIndicesPos;
                                pFaceConnectivity   = faceConnectivityPos;
                                pMeshConnectivity   = meshConnectivityPos;
                                pdicClippedEdges    = dicClippedEdgesPos;
                                pdicRemappedIndices = dicRemappedIndicesPos;
					        }

                            nNewIndex2 = -1;
                            nNewIndex3 = -1;
                            nNewIndex4 = -1;
                            bEdge      = false;

                            // Find edges in cache

                            if(pdicClippedEdges.ContainsKey(clippedEdgeKey))
                            {
                                nClippedCacheHits++;
                                bEdge      = true;
                                nNewIndex2 = pdicClippedEdges[clippedEdgeKey].GetSecondIndex(nIndex2);
                                nNewIndex4 = pdicClippedEdges[clippedEdgeKey].nClippedIndex;
                            }
                            else
                            {
                                nClippedCacheMisses++;
                                if(pdicRemappedIndices.ContainsKey(nIndex2)) nNewIndex2 = pdicRemappedIndices[nIndex2];
                            }

                            // Add vertex data for all data not present in remapped list

                            if(nNewIndex2 == -1)
                            {
                                nNewIndex2 = plistVertexData.Count;
                                plistVertexData.Add(meshDataIn.aVertexData[nIndex2].Copy());
                                pdicRemappedIndices[nIndex2] = nNewIndex2;
                            }

                            if(nNewIndex3 == -1)
                            {
                                if(pdicRemappedIndices.ContainsKey(nIndex3))
                                {
                                    nNewIndex3 = pdicRemappedIndices[nIndex3];
                                }
                            }
                            if(nNewIndex3 == -1)
                            {
                                nNewIndex3 = plistVertexData.Count;
                                plistVertexData.Add(meshDataIn.aVertexData[nIndex3].Copy());
                                pdicRemappedIndices[nIndex3] = nNewIndex3;
                            }

                            if(nNewIndex4 == -1)
                            {
                                nNewIndex4 = plistVertexData.Count;
                                plistVertexData.Add(vd4);
                            }

                            if(fracturedComponent.GenerateChunkConnectionInfo && splitOptions.bForceNoChunkConnectionInfo == false)
                            {
                                pMeshConnectivity.NotifyNewClippedFace(meshDataIn, nSubMesh, i, nSubMesh, plistObjectIndices.Count / 3);
                            }

                            plistObjectIndices.Add(nNewIndex2);
                            plistObjectIndices.Add(nNewIndex3);
                            plistObjectIndices.Add(nNewIndex4);

                            if(fracturedComponent.GenerateIslands && splitOptions.bForceNoIslandGeneration == false)
                            {
                                pFaceConnectivity.AddEdge(nSubMesh, v2, v3, nHashV2, nHashV3, nNewIndex2, nNewIndex3);
                                pFaceConnectivity.AddEdge(nSubMesh, v3, v4, nHashV3, nHashV4, nNewIndex3, nNewIndex4);
                                pFaceConnectivity.AddEdge(nSubMesh, v4, v2, nHashV4, nHashV2, nNewIndex4, nNewIndex2);
                            }

                            // Update cap edges and cache

                            if(plistVertexData == listVertexDataPos && splitOptions.bForceNoCap == false) AddCapEdge(dicCapEdges, nHashV3, nHashV4, plistVertexData[nNewIndex3].v3Vertex, plistVertexData[nNewIndex4].v3Vertex);

                            if(bEdge == false) pdicClippedEdges.Add(clippedEdgeKey, new ClippedEdge(nIndex1, nIndex2, nNewIndex1, nNewIndex2, nNewIndex4));
                        }
                    }
		            else
		            {
			            if(fSide1 * fSide2 < 0.0f)
			            {
				            // v1 and v2 on different sides

				            if(fSide2 * fSide3 < 0.0f)
				            {
					            // ... and v3 on same side as v1

					            if(fSide1 < 0.0f)
					            {
						            plistVertexData     = listVertexDataNeg;
						            plistObjectIndices  = listIndicesNeg;
                                    pFaceConnectivity   = faceConnectivityNeg;
                                    pMeshConnectivity   = meshConnectivityNeg;
                                    pdicClippedEdges    = dicClippedEdgesNeg;
                                    pdicRemappedIndices = dicRemappedIndicesNeg;
					            }

                                int  nNewIndex1 = -1;
                                int  nNewIndex2 = -1;
                                int  nNewIndex3 = -1;
                                int  nNewIndex4 = -1;
                                int  nNewIndex5 = -1;
                                int  nHashV4    = -1;
                                int  nHashV5    = -1;
                                bool bEdgeKey1  = false;
                                bool bEdgeKey2  = false;

                                EdgeKeyByIndex edgeKey1 = new EdgeKeyByIndex(nIndex1, nIndex2);
                                EdgeKeyByIndex edgeKey2 = new EdgeKeyByIndex(nIndex2, nIndex3);

                                // Find edges in cache

                                if(pdicClippedEdges.ContainsKey(edgeKey1))
                                {
                                    nClippedCacheHits++;
                                    bEdgeKey1  = true;
                                    nNewIndex1 = pdicClippedEdges[edgeKey1].GetFirstIndex(nIndex1);
                                    nNewIndex4 = pdicClippedEdges[edgeKey1].nClippedIndex;
                                }
                                else
                                {
                                    nClippedCacheMisses++;
                                    if(pdicRemappedIndices.ContainsKey(nIndex1)) nNewIndex1 = pdicRemappedIndices[nIndex1];
                                }

                                if(pdicClippedEdges.ContainsKey(edgeKey2))
                                {
                                    nClippedCacheHits++;
                                    bEdgeKey2  = true;
                                    nNewIndex3 = pdicClippedEdges[edgeKey2].GetSecondIndex(nIndex3);
                                    nNewIndex5 = pdicClippedEdges[edgeKey2].nClippedIndex;
                                }
                                else
                                {
                                    nClippedCacheMisses++;
                                    if(pdicRemappedIndices.ContainsKey(nIndex3)) nNewIndex3 = pdicRemappedIndices[nIndex3];
                                }

                                // Clip if not present in clipped edge list

                                EdgeKeyByHash clippedEdgeKeyHash = new EdgeKeyByHash(nHashV1, nHashV2);

                                if(dicClipVerticesHash.ContainsKey(clippedEdgeKeyHash))
                                {
                                    nHashV4 = dicClipVerticesHash[clippedEdgeKeyHash];
                                }
                                else
                                {
                                    nHashV4 = nCurrentVertexHash++;
                                    dicClipVerticesHash.Add(clippedEdgeKeyHash, nHashV4);
                                }

                                clippedEdgeKeyHash = new EdgeKeyByHash(nHashV2, nHashV3);

                                if(dicClipVerticesHash.ContainsKey(clippedEdgeKeyHash))
                                {
                                    nHashV5 = dicClipVerticesHash[clippedEdgeKeyHash];
                                }
                                else
                                {
                                    nHashV5 = nCurrentVertexHash++;
                                    dicClipVerticesHash.Add(clippedEdgeKeyHash, nHashV5);
                                }

                                VertexData vd4 = new VertexData(nHashV4), vd5 = new VertexData(nHashV5);

                                if(bEdgeKey1 == false)
                                {
                                    if(VertexData.ClipAgainstPlane(meshDataIn.aVertexData, nIndex1, nIndex2, v1, v2, planeSplit, ref vd4) == false)
                                    {
                                        return false;
                                    }
                                }

                                if(bEdgeKey2 == false)
                                {
                                    if(VertexData.ClipAgainstPlane(meshDataIn.aVertexData, nIndex2, nIndex3, v2, v3, planeSplit, ref vd5) == false)
                                    {
                                        return false;
                                    }
                                }

					            // Add geometry of one side

                                // Add vertex data for all data not present in remapped list

                                if(nNewIndex1 == -1)
                                {
                                    nNewIndex1 = plistVertexData.Count;
                                    plistVertexData.Add(meshDataIn.aVertexData[nIndex1].Copy());
                                    pdicRemappedIndices[nIndex1] = nNewIndex1;
                                }

                                if(nNewIndex3 == -1)
                                {
                                    nNewIndex3 = plistVertexData.Count;
                                    plistVertexData.Add(meshDataIn.aVertexData[nIndex3].Copy());
                                    pdicRemappedIndices[nIndex3] = nNewIndex3;
                                }

                                if(nNewIndex4 == -1)
                                {
                                    nNewIndex4 = plistVertexData.Count;
                                    plistVertexData.Add(vd4);
                                }

                                if(nNewIndex5 == -1)
                                {
                                    nNewIndex5 = plistVertexData.Count;
                                    plistVertexData.Add(vd5);
                                }

                                if(fracturedComponent.GenerateChunkConnectionInfo && splitOptions.bForceNoChunkConnectionInfo == false)
                                {
                                    pMeshConnectivity.NotifyNewClippedFace(meshDataIn, nSubMesh, i, nSubMesh, plistObjectIndices.Count / 3);
                                }

                                plistObjectIndices.Add(nNewIndex1);
                                plistObjectIndices.Add(nNewIndex4);
                                plistObjectIndices.Add(nNewIndex5);

                                if(fracturedComponent.GenerateChunkConnectionInfo && splitOptions.bForceNoChunkConnectionInfo == false)
                                {
                                    pMeshConnectivity.NotifyNewClippedFace(meshDataIn, nSubMesh, i, nSubMesh, plistObjectIndices.Count / 3);
                                }

                                plistObjectIndices.Add(nNewIndex1);
                                plistObjectIndices.Add(nNewIndex5);
                                plistObjectIndices.Add(nNewIndex3);

                                Vector3 v4 = plistVertexData[nNewIndex4].v3Vertex;
                                Vector3 v5 = plistVertexData[nNewIndex5].v3Vertex;

                                if(fracturedComponent.GenerateIslands && splitOptions.bForceNoIslandGeneration == false)
                                {
                                    pFaceConnectivity.AddEdge(nSubMesh, v1, v4, nHashV1, nHashV4, nNewIndex1, nNewIndex4);
                                    pFaceConnectivity.AddEdge(nSubMesh, v4, v5, nHashV4, nHashV5, nNewIndex4, nNewIndex5);
                                    pFaceConnectivity.AddEdge(nSubMesh, v5, v1, nHashV5, nHashV1, nNewIndex5, nNewIndex1);
                                    pFaceConnectivity.AddEdge(nSubMesh, v1, v5, nHashV1, nHashV5, nNewIndex1, nNewIndex5);
                                    pFaceConnectivity.AddEdge(nSubMesh, v5, v3, nHashV5, nHashV3, nNewIndex5, nNewIndex3);
                                    pFaceConnectivity.AddEdge(nSubMesh, v3, v1, nHashV3, nHashV1, nNewIndex3, nNewIndex1);
                                }

                                // Update cap edges and cache

                                if(plistVertexData == listVertexDataPos && splitOptions.bForceNoCap == false) AddCapEdge(dicCapEdges, nHashV4, nHashV5, plistVertexData[nNewIndex4].v3Vertex, plistVertexData[nNewIndex5].v3Vertex);

                                if(pdicClippedEdges.ContainsKey(edgeKey1) == false) pdicClippedEdges.Add(edgeKey1, new ClippedEdge(nIndex1, nIndex2, nNewIndex1, nNewIndex2, nNewIndex4));
                                if(pdicClippedEdges.ContainsKey(edgeKey2) == false) pdicClippedEdges.Add(edgeKey2, new ClippedEdge(nIndex2, nIndex3, nNewIndex2, nNewIndex3, nNewIndex5));

                                // Add geometry of other side

					            if(fSide2 < 0.0f)
					            {
						            plistVertexData     = listVertexDataNeg;
                                    plistObjectIndices  = listIndicesNeg;
                                    pFaceConnectivity   = faceConnectivityNeg;
                                    pMeshConnectivity   = meshConnectivityNeg;
                                    pdicClippedEdges    = dicClippedEdgesNeg;
                                    pdicRemappedIndices = dicRemappedIndicesNeg;
					            }
					            else
					            {
						            plistVertexData     = listVertexDataPos;
						            plistObjectIndices  = listIndicesPos;
                                    pFaceConnectivity   = faceConnectivityPos;
                                    pMeshConnectivity   = meshConnectivityPos;
                                    pdicClippedEdges    = dicClippedEdgesPos;
                                    pdicRemappedIndices = dicRemappedIndicesPos;
					            }

                                nNewIndex1 = -1;
                                nNewIndex2 = -1;
                                nNewIndex3 = -1;
                                nNewIndex4 = -1;
                                nNewIndex5 = -1;
                                bEdgeKey1  = false;
                                bEdgeKey2  = false;

                                // Find edges in cache

                                if(pdicClippedEdges.ContainsKey(edgeKey1))
                                {
                                    nClippedCacheHits++;
                                    bEdgeKey1  = true;
                                    nNewIndex2 = pdicClippedEdges[edgeKey1].GetSecondIndex(nIndex2);
                                    nNewIndex4 = pdicClippedEdges[edgeKey1].nClippedIndex;
                                }
                                else
                                {
                                    nClippedCacheMisses++;
                                    if(pdicRemappedIndices.ContainsKey(nIndex2)) nNewIndex2 = pdicRemappedIndices[nIndex2];
                                }

                                if(pdicClippedEdges.ContainsKey(edgeKey2))
                                {
                                    nClippedCacheHits++;
                                    bEdgeKey2  = true;
                                    nNewIndex2 = pdicClippedEdges[edgeKey2].GetFirstIndex(nIndex2);
                                    nNewIndex5 = pdicClippedEdges[edgeKey2].nClippedIndex;
                                }
                                else
                                {
                                    nClippedCacheMisses++;
                                    if(pdicRemappedIndices.ContainsKey(nIndex2)) nNewIndex2 = pdicRemappedIndices[nIndex2];
                                }

                                // Add vertex data for all data not present in remapped list

                                if(nNewIndex2 == -1)
                                {
                                    nNewIndex2 = plistVertexData.Count;
                                    plistVertexData.Add(meshDataIn.aVertexData[nIndex2].Copy());
                                    pdicRemappedIndices[nIndex2] = nNewIndex2;
                                }

                                if(nNewIndex4 == -1)
                                {
                                    nNewIndex4 = plistVertexData.Count;
                                    plistVertexData.Add(vd4);
                                }

                                if(nNewIndex5 == -1)
                                {
                                    nNewIndex5 = plistVertexData.Count;
                                    plistVertexData.Add(vd5);
                                }

                                if(fracturedComponent.GenerateChunkConnectionInfo && splitOptions.bForceNoChunkConnectionInfo == false)
                                {
                                    pMeshConnectivity.NotifyNewClippedFace(meshDataIn, nSubMesh, i, nSubMesh, plistObjectIndices.Count / 3);
                                }

                                plistObjectIndices.Add(nNewIndex4);
                                plistObjectIndices.Add(nNewIndex2);
                                plistObjectIndices.Add(nNewIndex5);

                                if(fracturedComponent.GenerateIslands && splitOptions.bForceNoIslandGeneration == false)
                                {
                                    pFaceConnectivity.AddEdge(nSubMesh, v4, v2, nHashV4, nHashV2, nNewIndex4, nNewIndex2);
                                    pFaceConnectivity.AddEdge(nSubMesh, v2, v5, nHashV2, nHashV5, nNewIndex2, nNewIndex5);
                                    pFaceConnectivity.AddEdge(nSubMesh, v5, v4, nHashV5, nHashV4, nNewIndex5, nNewIndex4);
                                }

                                // Update cap edges and cache

                                if(plistVertexData == listVertexDataPos && splitOptions.bForceNoCap == false) AddCapEdge(dicCapEdges, nHashV5, nHashV4, plistVertexData[nNewIndex5].v3Vertex, plistVertexData[nNewIndex4].v3Vertex);

                                if(pdicClippedEdges.ContainsKey(edgeKey1) == false) pdicClippedEdges.Add(edgeKey1, new ClippedEdge(nIndex1, nIndex2, nNewIndex1, nNewIndex2, nNewIndex4));
                                if(pdicClippedEdges.ContainsKey(edgeKey2) == false) pdicClippedEdges.Add(edgeKey2, new ClippedEdge(nIndex2, nIndex3, nNewIndex2, nNewIndex3, nNewIndex5));
				            }
				            else
				            {
					            // ... and v3 on same side as v2

					            if(fSide1 < 0.0f)
					            {
						            plistVertexData     = listVertexDataNeg;
						            plistObjectIndices  = listIndicesNeg;
                                    pFaceConnectivity   = faceConnectivityNeg;
                                    pMeshConnectivity   = meshConnectivityNeg;
                                    pdicClippedEdges    = dicClippedEdgesNeg;
                                    pdicRemappedIndices = dicRemappedIndicesNeg;
					            }

                                int  nNewIndex1 = -1;
                                int  nNewIndex2 = -1;
                                int  nNewIndex3 = -1;
                                int  nNewIndex4 = -1;
                                int  nNewIndex5 = -1;
                                int  nHashV4    = -1;
                                int  nHashV5    = -1;
                                bool bEdgeKey1  = false;
                                bool bEdgeKey3  = false;

                                EdgeKeyByIndex edgeKey1 = new EdgeKeyByIndex(nIndex1, nIndex2);
                                EdgeKeyByIndex edgeKey3 = new EdgeKeyByIndex(nIndex1, nIndex3);

                                // Find edges in cache

                                if(pdicClippedEdges.ContainsKey(edgeKey1))
                                {
                                    nClippedCacheHits++;
                                    bEdgeKey1  = true;
                                    nNewIndex1 = pdicClippedEdges[edgeKey1].GetFirstIndex(nIndex1);
                                    nNewIndex4 = pdicClippedEdges[edgeKey1].nClippedIndex;
                                }
                                else
                                {
                                    nClippedCacheMisses++;
                                    if(pdicRemappedIndices.ContainsKey(nIndex1)) nNewIndex1 = pdicRemappedIndices[nIndex1];
                                }

                                if(pdicClippedEdges.ContainsKey(edgeKey3))
                                {
                                    nClippedCacheHits++;
                                    bEdgeKey3  = true;
                                    nNewIndex1 = pdicClippedEdges[edgeKey3].GetFirstIndex(nIndex1);
                                    nNewIndex5 = pdicClippedEdges[edgeKey3].nClippedIndex;
                                }
                                else
                                {
                                    nClippedCacheMisses++;
                                    if(pdicRemappedIndices.ContainsKey(nIndex1)) nNewIndex1 = pdicRemappedIndices[nIndex1];
                                }

                                // Clip if not present in clipped edge list

                                EdgeKeyByHash clippedEdgeKeyHash = new EdgeKeyByHash(nHashV1, nHashV2);

                                if(dicClipVerticesHash.ContainsKey(clippedEdgeKeyHash))
                                {
                                    nHashV4 = dicClipVerticesHash[clippedEdgeKeyHash];
                                }
                                else
                                {
                                    nHashV4 = nCurrentVertexHash++;
                                    dicClipVerticesHash.Add(clippedEdgeKeyHash, nHashV4);
                                }

                                clippedEdgeKeyHash = new EdgeKeyByHash(nHashV1, nHashV3);

                                if(dicClipVerticesHash.ContainsKey(clippedEdgeKeyHash))
                                {
                                    nHashV5 = dicClipVerticesHash[clippedEdgeKeyHash];
                                }
                                else
                                {
                                    nHashV5 = nCurrentVertexHash++;
                                    dicClipVerticesHash.Add(clippedEdgeKeyHash, nHashV5);
                                }

                                VertexData vd4 = new VertexData(nHashV4), vd5 = new VertexData(nHashV5);

                                if(bEdgeKey1 == false)
                                {
                                    if(VertexData.ClipAgainstPlane(meshDataIn.aVertexData, nIndex1, nIndex2, v1, v2, planeSplit, ref vd4) == false)
                                    {
                                        return false;
                                    }
                                }

                                if(bEdgeKey3 == false)
                                {
                                    if(VertexData.ClipAgainstPlane(meshDataIn.aVertexData, nIndex1, nIndex3, v1, v3, planeSplit, ref vd5) == false)
                                    {
                                        return false;
                                    }
                                }

					            // Add geometry of one side

                                // Add vertex data for all data not present in remapped list

                                if(nNewIndex1 == -1)
                                {
                                    nNewIndex1 = plistVertexData.Count;
                                    plistVertexData.Add(meshDataIn.aVertexData[nIndex1].Copy());
                                    pdicRemappedIndices[nIndex1] = nNewIndex1;
                                }

                                if(nNewIndex4 == -1)
                                {
                                    nNewIndex4 = plistVertexData.Count;
                                    plistVertexData.Add(vd4);
                                }

                                if(nNewIndex5 == -1)
                                {
                                    nNewIndex5 = plistVertexData.Count;
                                    plistVertexData.Add(vd5);
                                }

                                if(fracturedComponent.GenerateChunkConnectionInfo && splitOptions.bForceNoChunkConnectionInfo == false)
                                {
                                    pMeshConnectivity.NotifyNewClippedFace(meshDataIn, nSubMesh, i, nSubMesh, plistObjectIndices.Count / 3);
                                }

                                plistObjectIndices.Add(nNewIndex1);
                                plistObjectIndices.Add(nNewIndex4);
                                plistObjectIndices.Add(nNewIndex5);

                                Vector3 v4 = plistVertexData[nNewIndex4].v3Vertex;
                                Vector3 v5 = plistVertexData[nNewIndex5].v3Vertex;

                                if(fracturedComponent.GenerateIslands && splitOptions.bForceNoIslandGeneration == false)
                                {
                                    pFaceConnectivity.AddEdge(nSubMesh, v1, v4, nHashV1, nHashV4, nNewIndex1, nNewIndex4);
                                    pFaceConnectivity.AddEdge(nSubMesh, v4, v5, nHashV4, nHashV5, nNewIndex4, nNewIndex5);
                                    pFaceConnectivity.AddEdge(nSubMesh, v5, v1, nHashV5, nHashV1, nNewIndex5, nNewIndex1);
                                }

                                // Update cap edges and cache

                                if(plistVertexData == listVertexDataPos && splitOptions.bForceNoCap == false) AddCapEdge(dicCapEdges, nHashV4, nHashV5, plistVertexData[nNewIndex4].v3Vertex, plistVertexData[nNewIndex5].v3Vertex);

                                if(pdicClippedEdges.ContainsKey(edgeKey1) == false) pdicClippedEdges.Add(edgeKey1, new ClippedEdge(nIndex1, nIndex2, nNewIndex1, nNewIndex2, nNewIndex4));
                                if(pdicClippedEdges.ContainsKey(edgeKey3) == false) pdicClippedEdges.Add(edgeKey3, new ClippedEdge(nIndex1, nIndex3, nNewIndex1, nNewIndex3, nNewIndex5));

                                // Add geometry of other side

					            if(fSide2 < 0.0f)
					            {
						            plistVertexData     = listVertexDataNeg;
                                    plistObjectIndices  = listIndicesNeg;
                                    pFaceConnectivity   = faceConnectivityNeg;
                                    pMeshConnectivity   = meshConnectivityNeg;
                                    pdicClippedEdges    = dicClippedEdgesNeg;
                                    pdicRemappedIndices = dicRemappedIndicesNeg;
					            }
					            else
					            {
						            plistVertexData     = listVertexDataPos;
						            plistObjectIndices  = listIndicesPos;
                                    pFaceConnectivity   = faceConnectivityPos;
                                    pMeshConnectivity   = meshConnectivityPos;
                                    pdicClippedEdges    = dicClippedEdgesPos;
                                    pdicRemappedIndices = dicRemappedIndicesPos;
					            }

                                nNewIndex1 = -1;
                                nNewIndex2 = -1;
                                nNewIndex3 = -1;
                                nNewIndex4 = -1;
                                nNewIndex5 = -1;
                                bEdgeKey1  = false;
                                bEdgeKey3  = false;

                                // Find edges in cache

                                if(pdicClippedEdges.ContainsKey(edgeKey1))
                                {
                                    nClippedCacheHits++;
                                    bEdgeKey1  = true;
                                    nNewIndex2 = pdicClippedEdges[edgeKey1].GetSecondIndex(nIndex2);
                                    nNewIndex4 = pdicClippedEdges[edgeKey1].nClippedIndex;
                                }
                                else
                                {
                                    nClippedCacheMisses++;
                                    if(pdicRemappedIndices.ContainsKey(nIndex2)) nNewIndex2 = pdicRemappedIndices[nIndex2];
                                }

                                if(pdicClippedEdges.ContainsKey(edgeKey3))
                                {
                                    nClippedCacheHits++;
                                    bEdgeKey3  = true;
                                    nNewIndex3 = pdicClippedEdges[edgeKey3].GetSecondIndex(nIndex3);
                                    nNewIndex5 = pdicClippedEdges[edgeKey3].nClippedIndex;
                                }
                                else
                                {
                                    nClippedCacheMisses++;
                                    if(pdicRemappedIndices.ContainsKey(nIndex3)) nNewIndex3 = pdicRemappedIndices[nIndex3];
                                }

                                // Add vertex data for all data not present in remapped list

                                if(nNewIndex2 == -1)
                                {
                                    nNewIndex2 = plistVertexData.Count;
                                    plistVertexData.Add(meshDataIn.aVertexData[nIndex2].Copy());
                                    pdicRemappedIndices[nIndex2] = nNewIndex2;
                                }

                                if(nNewIndex3 == -1)
                                {
                                    nNewIndex3 = plistVertexData.Count;
                                    plistVertexData.Add(meshDataIn.aVertexData[nIndex3].Copy());
                                    pdicRemappedIndices[nIndex3] = nNewIndex3;
                                }

                                if(nNewIndex4 == -1)
                                {
                                    nNewIndex4 = plistVertexData.Count;
                                    plistVertexData.Add(vd4);
                                }

                                if(nNewIndex5 == -1)
                                {
                                    nNewIndex5 = plistVertexData.Count;
                                    plistVertexData.Add(vd5);
                                }

                                if(fracturedComponent.GenerateChunkConnectionInfo && splitOptions.bForceNoChunkConnectionInfo == false)
                                {
                                    pMeshConnectivity.NotifyNewClippedFace(meshDataIn, nSubMesh, i, nSubMesh, plistObjectIndices.Count / 3);
                                }

                                plistObjectIndices.Add(nNewIndex4);
                                plistObjectIndices.Add(nNewIndex2);
                                plistObjectIndices.Add(nNewIndex3);

                                if(fracturedComponent.GenerateChunkConnectionInfo && splitOptions.bForceNoChunkConnectionInfo == false)
                                {
                                    pMeshConnectivity.NotifyNewClippedFace(meshDataIn, nSubMesh, i, nSubMesh, plistObjectIndices.Count / 3);
                                }

                                plistObjectIndices.Add(nNewIndex4);
                                plistObjectIndices.Add(nNewIndex3);
                                plistObjectIndices.Add(nNewIndex5);

                                if(fracturedComponent.GenerateIslands && splitOptions.bForceNoIslandGeneration == false)
                                {
                                    pFaceConnectivity.AddEdge(nSubMesh, v4, v2, nHashV4, nHashV2, nNewIndex4, nNewIndex2);
                                    pFaceConnectivity.AddEdge(nSubMesh, v2, v3, nHashV2, nHashV3, nNewIndex2, nNewIndex3);
                                    pFaceConnectivity.AddEdge(nSubMesh, v3, v4, nHashV3, nHashV4, nNewIndex3, nNewIndex4);
                                    pFaceConnectivity.AddEdge(nSubMesh, v4, v3, nHashV4, nHashV3, nNewIndex4, nNewIndex3);
                                    pFaceConnectivity.AddEdge(nSubMesh, v3, v5, nHashV3, nHashV5, nNewIndex3, nNewIndex5);
                                    pFaceConnectivity.AddEdge(nSubMesh, v5, v4, nHashV5, nHashV4, nNewIndex5, nNewIndex4);
                                }

                                // Update cap edges and cache

                                if(plistVertexData == listVertexDataPos && splitOptions.bForceNoCap == false) AddCapEdge(dicCapEdges, nHashV5, nHashV4, plistVertexData[nNewIndex5].v3Vertex, plistVertexData[nNewIndex4].v3Vertex);

                                if(pdicClippedEdges.ContainsKey(edgeKey1) == false) pdicClippedEdges.Add(edgeKey1, new ClippedEdge(nIndex1, nIndex2, nNewIndex1, nNewIndex2, nNewIndex4));
                                if(pdicClippedEdges.ContainsKey(edgeKey3) == false) pdicClippedEdges.Add(edgeKey3, new ClippedEdge(nIndex1, nIndex3, nNewIndex1, nNewIndex3, nNewIndex5));
				            }
			            }
			            else if(fSide2 * fSide3 < 0.0f)
			            {
				            // v1 and v2 on same side, and v3 on different side

					        if(fSide1 < 0.0f)
					        {
						        plistVertexData     = listVertexDataNeg;
						        plistObjectIndices  = listIndicesNeg;
                                pFaceConnectivity   = faceConnectivityNeg;
                                pMeshConnectivity   = meshConnectivityNeg;
                                pdicClippedEdges    = dicClippedEdgesNeg;
                                pdicRemappedIndices = dicRemappedIndicesNeg;
					        }

                            int  nNewIndex1 = -1;
                            int  nNewIndex2 = -1;
                            int  nNewIndex3 = -1;
                            int  nNewIndex4 = -1;
                            int  nNewIndex5 = -1;
                            int  nHashV4    = -1;
                            int  nHashV5    = -1;
                            bool bEdgeKey2  = false;
                            bool bEdgeKey3  = false;

                            EdgeKeyByIndex edgeKey2 = new EdgeKeyByIndex(nIndex2, nIndex3);
                            EdgeKeyByIndex edgeKey3 = new EdgeKeyByIndex(nIndex1, nIndex3);

                            // Find edges in cache

                            if(pdicClippedEdges.ContainsKey(edgeKey2))
                            {
                                nClippedCacheHits++;
                                bEdgeKey2  = true;
                                nNewIndex2 = pdicClippedEdges[edgeKey2].GetFirstIndex(nIndex2);
                                nNewIndex5 = pdicClippedEdges[edgeKey2].nClippedIndex;
                            }
                            else
                            {
                                nClippedCacheMisses++;
                                if(pdicRemappedIndices.ContainsKey(nIndex2)) nNewIndex2 = pdicRemappedIndices[nIndex2];
                            }

                            if(pdicClippedEdges.ContainsKey(edgeKey3))
                            {
                                nClippedCacheHits++;
                                bEdgeKey3  = true;
                                nNewIndex1 = pdicClippedEdges[edgeKey3].GetFirstIndex(nIndex1);
                                nNewIndex4 = pdicClippedEdges[edgeKey3].nClippedIndex;
                            }
                            else
                            {
                                nClippedCacheMisses++;
                                if(pdicRemappedIndices.ContainsKey(nIndex1)) nNewIndex1 = pdicRemappedIndices[nIndex1];
                            }

                            // Clip if not present in clipped edge list

                            EdgeKeyByHash clippedEdgeKeyHash = new EdgeKeyByHash(nHashV1, nHashV3);

                            if(dicClipVerticesHash.ContainsKey(clippedEdgeKeyHash))
                            {
                                nHashV4 = dicClipVerticesHash[clippedEdgeKeyHash];
                            }
                            else
                            {
                                nHashV4 = nCurrentVertexHash++;
                                dicClipVerticesHash.Add(clippedEdgeKeyHash, nHashV4);
                            }

                            clippedEdgeKeyHash = new EdgeKeyByHash(nHashV2, nHashV3);

                            if(dicClipVerticesHash.ContainsKey(clippedEdgeKeyHash))
                            {
                                nHashV5 = dicClipVerticesHash[clippedEdgeKeyHash];
                            }
                            else
                            {
                                nHashV5 = nCurrentVertexHash++;
                                dicClipVerticesHash.Add(clippedEdgeKeyHash, nHashV5);
                            }

                            VertexData vd4 = new VertexData(nHashV4), vd5 = new VertexData(nHashV5);

                            if(bEdgeKey2 == false)
                            {
                                if(VertexData.ClipAgainstPlane(meshDataIn.aVertexData, nIndex2, nIndex3, v2, v3, planeSplit, ref vd5) == false)
                                {
                                    return false;
                                }
                            }

                            if(bEdgeKey3 == false)
                            {
                                if(VertexData.ClipAgainstPlane(meshDataIn.aVertexData, nIndex1, nIndex3, v1, v3, planeSplit, ref vd4) == false)
                                {
                                    return false;
                                }
                            }

					        // Add geometry of one side

                            // Add vertex data for all data not present in remapped list

                            if(nNewIndex1 == -1)
                            {
                                nNewIndex1 = plistVertexData.Count;
                                plistVertexData.Add(meshDataIn.aVertexData[nIndex1].Copy());
                                pdicRemappedIndices[nIndex1] = nNewIndex1;
                            }

                            if(nNewIndex2 == -1)
                            {
                                nNewIndex2 = plistVertexData.Count;
                                plistVertexData.Add(meshDataIn.aVertexData[nIndex2].Copy());
                                pdicRemappedIndices[nIndex2] = nNewIndex2;
                            }

                            if(nNewIndex4 == -1)
                            {
                                nNewIndex4 = plistVertexData.Count;
                                plistVertexData.Add(vd4);
                            }

                            if(nNewIndex5 == -1)
                            {
                                nNewIndex5 = plistVertexData.Count;
                                plistVertexData.Add(vd5);
                            }

                            if(fracturedComponent.GenerateChunkConnectionInfo && splitOptions.bForceNoChunkConnectionInfo == false)
                            {
                                pMeshConnectivity.NotifyNewClippedFace(meshDataIn, nSubMesh, i, nSubMesh, plistObjectIndices.Count / 3);
                            }

                            plistObjectIndices.Add(nNewIndex2);
                            plistObjectIndices.Add(nNewIndex5);
                            plistObjectIndices.Add(nNewIndex4);

                            if(fracturedComponent.GenerateChunkConnectionInfo && splitOptions.bForceNoChunkConnectionInfo == false)
                            {
                                pMeshConnectivity.NotifyNewClippedFace(meshDataIn, nSubMesh, i, nSubMesh, plistObjectIndices.Count / 3);
                            }

                            plistObjectIndices.Add(nNewIndex2);
                            plistObjectIndices.Add(nNewIndex4);
                            plistObjectIndices.Add(nNewIndex1);

                            Vector3 v4 = plistVertexData[nNewIndex4].v3Vertex;
                            Vector3 v5 = plistVertexData[nNewIndex5].v3Vertex;

                            if(fracturedComponent.GenerateIslands && splitOptions.bForceNoIslandGeneration == false)
                            {
                                pFaceConnectivity.AddEdge(nSubMesh, v2, v5, nHashV2, nHashV5, nNewIndex2, nNewIndex5);
                                pFaceConnectivity.AddEdge(nSubMesh, v5, v4, nHashV5, nHashV4, nNewIndex5, nNewIndex4);
                                pFaceConnectivity.AddEdge(nSubMesh, v4, v2, nHashV4, nHashV2, nNewIndex4, nNewIndex2);
                                pFaceConnectivity.AddEdge(nSubMesh, v2, v4, nHashV2, nHashV4, nNewIndex2, nNewIndex4);
                                pFaceConnectivity.AddEdge(nSubMesh, v4, v1, nHashV4, nHashV1, nNewIndex4, nNewIndex1);
                                pFaceConnectivity.AddEdge(nSubMesh, v1, v2, nHashV1, nHashV2, nNewIndex1, nNewIndex2);
                            }

                            // Update cap edges and cache

                            if(plistVertexData == listVertexDataPos && splitOptions.bForceNoCap == false) AddCapEdge(dicCapEdges, nHashV5, nHashV4, plistVertexData[nNewIndex5].v3Vertex, plistVertexData[nNewIndex4].v3Vertex);

                            if(pdicClippedEdges.ContainsKey(edgeKey2) == false) pdicClippedEdges.Add(edgeKey2, new ClippedEdge(nIndex2, nIndex3, nNewIndex2, nNewIndex3, nNewIndex5));
                            if(pdicClippedEdges.ContainsKey(edgeKey3) == false) pdicClippedEdges.Add(edgeKey3, new ClippedEdge(nIndex1, nIndex3, nNewIndex1, nNewIndex3, nNewIndex4));

                            // Add geometry of other side

					        if(fSide3 < 0.0f)
					        {
						        plistVertexData     = listVertexDataNeg;
                                plistObjectIndices  = listIndicesNeg;
                                pFaceConnectivity   = faceConnectivityNeg;
                                pMeshConnectivity   = meshConnectivityNeg;
                                pdicClippedEdges    = dicClippedEdgesNeg;
                                pdicRemappedIndices = dicRemappedIndicesNeg;
					        }
					        else
					        {
						        plistVertexData     = listVertexDataPos;
						        plistObjectIndices  = listIndicesPos;
                                pFaceConnectivity   = faceConnectivityPos;
                                pMeshConnectivity   = meshConnectivityPos;
                                pdicClippedEdges    = dicClippedEdgesPos;
                                pdicRemappedIndices = dicRemappedIndicesPos;
					        }

                            nNewIndex1 = -1;
                            nNewIndex2 = -1;
                            nNewIndex3 = -1;
                            nNewIndex4 = -1;
                            nNewIndex5 = -1;
                            bEdgeKey2  = false;
                            bEdgeKey3  = false;

                            // Find edges in cache

                            if(pdicClippedEdges.ContainsKey(edgeKey2))
                            {
                                nClippedCacheHits++;
                                bEdgeKey2  = true;
                                nNewIndex3 = pdicClippedEdges[edgeKey2].GetSecondIndex(nIndex3);
                                nNewIndex5 = pdicClippedEdges[edgeKey2].nClippedIndex;
                            }
                            else
                            {
                                nClippedCacheMisses++;
                                if(pdicRemappedIndices.ContainsKey(nIndex3)) nNewIndex3 = pdicRemappedIndices[nIndex3];
                            }

                            if(pdicClippedEdges.ContainsKey(edgeKey3))
                            {
                                nClippedCacheHits++;
                                bEdgeKey3  = true;
                                nNewIndex3 = pdicClippedEdges[edgeKey3].GetSecondIndex(nIndex3);
                                nNewIndex4 = pdicClippedEdges[edgeKey3].nClippedIndex;
                            }
                            else
                            {
                                nClippedCacheMisses++;
                                if(pdicRemappedIndices.ContainsKey(nIndex3)) nNewIndex3 = pdicRemappedIndices[nIndex3];
                            }

                            // Add vertex data for all data not present in remapped list

                            if(nNewIndex3 == -1)
                            {
                                nNewIndex3 = plistVertexData.Count;
                                plistVertexData.Add(meshDataIn.aVertexData[nIndex3].Copy());
                                pdicRemappedIndices[nIndex3] = nNewIndex3;
                            }

                            if(nNewIndex4 == -1)
                            {
                                nNewIndex4 = plistVertexData.Count;
                                plistVertexData.Add(vd4);
                            }

                            if(nNewIndex5 == -1)
                            {
                                nNewIndex5 = plistVertexData.Count;
                                plistVertexData.Add(vd5);
                            }

                            if(fracturedComponent.GenerateChunkConnectionInfo && splitOptions.bForceNoChunkConnectionInfo == false)
                            {
                                pMeshConnectivity.NotifyNewClippedFace(meshDataIn, nSubMesh, i, nSubMesh, plistObjectIndices.Count / 3);
                            }

                            plistObjectIndices.Add(nNewIndex5);
                            plistObjectIndices.Add(nNewIndex3);
                            plistObjectIndices.Add(nNewIndex4);

                            if(fracturedComponent.GenerateIslands && splitOptions.bForceNoIslandGeneration == false)
                            {
                                pFaceConnectivity.AddEdge(nSubMesh, v5, v3, nHashV5, nHashV3, nNewIndex5, nNewIndex3);
                                pFaceConnectivity.AddEdge(nSubMesh, v3, v4, nHashV3, nHashV4, nNewIndex3, nNewIndex4);
                                pFaceConnectivity.AddEdge(nSubMesh, v4, v5, nHashV4, nHashV5, nNewIndex4, nNewIndex5);
                            }

                            // Update cap edges and cache

                            if(plistVertexData == listVertexDataPos && splitOptions.bForceNoCap == false) AddCapEdge(dicCapEdges, nHashV4, nHashV5, plistVertexData[nNewIndex4].v3Vertex, plistVertexData[nNewIndex5].v3Vertex);

                            if(pdicClippedEdges.ContainsKey(edgeKey2) == false) pdicClippedEdges.Add(edgeKey2, new ClippedEdge(nIndex2, nIndex3, nNewIndex2, nNewIndex3, nNewIndex5));
                            if(pdicClippedEdges.ContainsKey(edgeKey3) == false) pdicClippedEdges.Add(edgeKey3, new ClippedEdge(nIndex1, nIndex3, nNewIndex1, nNewIndex3, nNewIndex4));
			            }
		            }
	            }
            }

//          Debug.Log("Clipped cache hits " + nClippedCacheHits + " clipped cache misses " + nClippedCacheMisses);

            // Compute transforms

            Vector3 v3CenterPos = Vector3.zero;

            if(listVertexDataPos.Count > 0)
            {
                Vector3 v3Min = Vector3.zero, v3Max = Vector3.zero;
                MeshData.ComputeMinMax(listVertexDataPos, ref v3Min, ref v3Max);
                v3CenterPos = (v3Min + v3Max) * 0.5f;
            }

            Matrix4x4 mtxToLocalPos = Matrix4x4.TRS(v3CenterPos, meshDataIn.qRotation, meshDataIn.v3Scale).inverse;

            if(splitOptions.bVerticesAreLocal)
            {
                mtxToLocalPos = Matrix4x4.TRS(v3CenterPos, Quaternion.identity, Vector3.one).inverse;
            }

            Vector3 v3CenterNeg = Vector3.zero;

            if(listVertexDataNeg.Count > 0)
            {
                Vector3 v3Min = Vector3.zero, v3Max = Vector3.zero;
                MeshData.ComputeMinMax(listVertexDataNeg, ref v3Min, ref v3Max);
                v3CenterNeg = (v3Min + v3Max) * 0.5f;
            }

            Matrix4x4 mtxToLocalNeg = Matrix4x4.TRS(v3CenterNeg, meshDataIn.qRotation, meshDataIn.v3Scale).inverse;

            if(splitOptions.bVerticesAreLocal)
            {
                mtxToLocalNeg = Matrix4x4.TRS(v3CenterNeg, Quaternion.identity, Vector3.one).inverse;
            }

            // Resolve cap outline and add its geometry

            List<List<Vector3>> listlistResolvedCapVertices   = new List<List<Vector3>>();
            List<List<int>>     listlistResolvedCapHashValues = new List<List<int>>();

            bool bNeedsConnectivityPostprocess = false;

            Matrix4x4 mtxPlane = Matrix4x4.TRS(v3PlanePoint, Quaternion.LookRotation(Vector3.Cross(v3PlaneNormal, v3PlaneRight), v3PlaneNormal), Vector3.one);

            if(dicCapEdges.Count > 0 && splitOptions.bForceNoCap == false)
            {
                if(ResolveCap(dicCapEdges, listlistResolvedCapVertices, listlistResolvedCapHashValues, fracturedComponent))
	            {
                    if(listlistResolvedCapVertices.Count > 1)
                    {
                        // There's more than one closed cap. We need to postprocess the mesh because there may be more than one object on a side of the plane as a result of the clipping.
                        bNeedsConnectivityPostprocess = (fracturedComponent.GenerateIslands && (splitOptions.bForceNoIslandGeneration == false)) ? true : false;
                    }

                    TriangulateConstrainedDelaunay( listlistResolvedCapVertices, listlistResolvedCapHashValues, splitOptions.bForceCapVertexSoup, fracturedComponent, bNeedsConnectivityPostprocess, faceConnectivityPos, faceConnectivityNeg,
                                                    meshConnectivityPos, meshConnectivityNeg, splitOptions.nForceMeshConnectivityHash, nSplitCloseSubMesh,
                                                    mtxPlane, mtxToLocalPos, mtxToLocalNeg, v3CenterPos, v3CenterNeg,
                                                    alistIndicesPos, listVertexDataPos, alistIndicesNeg, listVertexDataNeg);
                }
                else
                {
                    if(fracturedComponent.Verbose) Debug.LogWarning("Error resolving cap");
                }
            }

            // Postprocess if necessary
            if(bNeedsConnectivityPostprocess)
            {
                // Search for multiple objects inside each meshes

                List<MeshData> listIslandsPos = MeshData.PostProcessConnectivity(meshDataIn, faceConnectivityPos, meshConnectivityPos, alistIndicesPos, listVertexDataPos, nSplitCloseSubMesh, nCurrentVertexHash, false);
                List<MeshData> listIslandsNeg = new List<MeshData>();

                if(splitOptions.bIgnoreNegativeSide == false)
                {
                    listIslandsNeg = MeshData.PostProcessConnectivity(meshDataIn, faceConnectivityNeg, meshConnectivityNeg, alistIndicesNeg, listVertexDataNeg, nSplitCloseSubMesh, nCurrentVertexHash, false);
                }

                // Sometimes we are feed a mesh with multiple islands as input. If this is the case, compute connectivity between islands at this point.

                List<MeshData> listTotalIslands = new List<MeshData>();
                listTotalIslands.AddRange(listIslandsPos);
                listTotalIslands.AddRange(listIslandsNeg);

                if(fracturedComponent.GenerateChunkConnectionInfo && splitOptions.bForceNoIslandConnectionInfo == false)
                {
                    for(int i = 0; i < listTotalIslands.Count; i++)
                    {
                        if(progress != null && listTotalIslands.Count > 10 && splitOptions.bForceNoProgressInfo == false)
                        {
                            progress("Fracturing", "Processing island connectivity...", i / (float)listTotalIslands.Count);
                            if(Fracturer.IsFracturingCancelled()) return false;
                        }

                        for(int j = 0; j < listTotalIslands.Count; j++)
                        {
                            if(i != j)
                            {
                                ComputeIslandsMeshDataConnectivity(fracturedComponent, splitOptions.bVerticesAreLocal, listTotalIslands[i], listTotalIslands[j]);
                            }
                        }
                    }
                }

                listMeshDatasPosOut.AddRange(listIslandsPos);
                listMeshDatasNegOut.AddRange(listIslandsNeg);
            }
            else
            {
                // Create new MeshDatas

                if(listVertexDataPos.Count > 0 && alistIndicesPos.Length > 0)
                {
                    MeshData newMeshData = new MeshData(meshDataIn.aMaterials, alistIndicesPos, listVertexDataPos, nSplitCloseSubMesh, v3CenterPos, meshDataIn.qRotation, meshDataIn.v3Scale, mtxToLocalPos, false, false);
                    newMeshData.meshDataConnectivity = meshConnectivityPos;
                    newMeshData.nCurrentVertexHash   = nCurrentVertexHash;
                    listMeshDatasPosOut.Add(newMeshData);
                }

                if(listVertexDataNeg.Count > 0 && alistIndicesNeg.Length > 0 && splitOptions.bIgnoreNegativeSide == false)
                {
                    MeshData newMeshData = new MeshData(meshDataIn.aMaterials, alistIndicesNeg, listVertexDataNeg, nSplitCloseSubMesh, v3CenterNeg, meshDataIn.qRotation, meshDataIn.v3Scale, mtxToLocalNeg, false, false);
                    newMeshData.meshDataConnectivity = meshConnectivityNeg;
                    newMeshData.nCurrentVertexHash   = nCurrentVertexHash;
                    listMeshDatasNegOut.Add(newMeshData);
                }
            }

            return true;
        }
        //增加读取纹理坐标
        private unsafe uint ReadVertexData(uint vertexOffset, VertexData vertexData) {
            VertexElement posElem = vertexData.vertexDeclaration.FindElementBySemantic(VertexElementSemantic.VES_POSITION);
            HardwareVertexBufferSharedPtr vertexBuffer = vertexData.vertexBufferBinding.GetBuffer(posElem.Source);
            byte* vertexMemory = (byte*)vertexBuffer.Lock(HardwareBuffer.LockOptions.HBL_READ_ONLY);
            float* pElem;
            bool needrecomputeVertex = false;
            if (this._quaoffset != Quaternion.IDENTITY || this._posoffset != Vector3.ZERO) {
                needrecomputeVertex = true;
            }
            //texture          
            if (_readTextureCoordinate) {
                ReadTextureCoordData(vertexOffset, vertexMemory, vertexBuffer.VertexSize, vertexData);
            }

            if (needrecomputeVertex) {
                for (uint i = 0; i < vertexData.vertexCount; i++) {
                    posElem.BaseVertexPointerToElement(vertexMemory, &pElem);
                    Vector3 point = new Vector3(pElem[0], pElem[1], pElem[2]);
                    // vertices[current_offset + j] = (orientation * (pt * scale)) + position;
                    _vertices[vertexOffset] = GetVextexTrans(point, this._quaoffset, this._scale, this._posoffset); //point * this.scale;
                    vertexMemory += vertexBuffer.VertexSize;
                    vertexOffset++;
                }
            }
            else {
                for (uint i = 0; i < vertexData.vertexCount; i++) {
                    posElem.BaseVertexPointerToElement(vertexMemory, &pElem);
                    Vector3 point = new Vector3(pElem[0], pElem[1], pElem[2]);
                    _vertices[vertexOffset] = point * this._scale;
                    vertexMemory += vertexBuffer.VertexSize;
                    vertexOffset++;
                }
            }

            vertexBuffer.Unlock();
            // SGD :2013/6/8 13:43:51
            // 说明:销毁指针引用 防止.NET回收
            vertexBuffer.Dispose();
            return vertexOffset;
        }
Example #40
0
            public void Add(string name, Texture2D texture, int tiles_x, int tiles_y)
            {
                int tile_width = (int)FMath.Round((float)texture.Width / (float)tiles_x);
                int tile_height = (int)FMath.Round((float)texture.Height / (float)tiles_y);
                tile_width /= ScaleDivisor;
                tile_height /= ScaleDivisor;
                tile_width = System.Math.Max(1, tile_width);
                tile_height = System.Math.Max(1, tile_height);

                ColorBuffer color_buffer = new ColorBuffer(tile_width, tile_height, PixelFormat.Rgba);
                FrameBuffer frame_buffer = new FrameBuffer();
                frame_buffer.SetColorTarget(color_buffer);

                FrameBuffer old_frame_buffer = Director.Instance.GL.Context.GetFrameBuffer();
                Director.Instance.GL.Context.SetFrameBuffer(frame_buffer);

                ShaderProgram.SetAttributeBinding(0, "iPosition");
                ShaderProgram.SetAttributeBinding(1, "iUV");

                texture.SetWrap(TextureWrapMode.ClampToEdge);
                texture.SetFilter(TextureFilterMode.Linear);

                Director.Instance.GL.Context.SetTexture(0, texture);

                Director.Instance.GL.Context.SetVertexBuffer(0, VertexBuffer);
                Director.Instance.GL.Context.SetShaderProgram(ShaderProgram);

                ImageRect old_scissor = Director.Instance.GL.Context.GetScissor();
                ImageRect old_viewport = Director.Instance.GL.Context.GetViewport();

                Director.Instance.GL.Context.SetScissor(0, 0, tile_width, tile_height);
                Director.Instance.GL.Context.SetViewport(0, 0, tile_width, tile_height);

                Entry entry = new Entry();
                entry.TilesX = tiles_x;
                entry.TilesY = tiles_y;
                entry.TileWidth = tile_width;
                entry.TileHeight = tile_height;
                entry.Data = new List<List<byte>>();
                for (int i = 0; i < tiles_y * tiles_x; ++i)
                    entry.Data.Add(new List<byte>());

                Vector2 uv_step = new Vector2(1.0f, 1.0f) / new Vector2(tiles_x, tiles_y);
                for (int y = 0; y < tiles_y; y++)
                {
                    for (int x = 0; x < tiles_x; x++)
                    {
                        float uv_x0 = uv_step.X * (x + 0);
                        float uv_x1 = uv_step.X * (x + 1);
                        float uv_y0 = uv_step.Y * (tiles_y - 1 - y + 0);
                        float uv_y1 = uv_step.Y * (tiles_y - 1 - y + 1);

                        VertexDataArray[0] = new VertexData() { position = new Vector2(-1.0f, -1.0f), uv = new Vector2(uv_x0, uv_y1) };
                        VertexDataArray[1] = new VertexData() { position = new Vector2(-1.0f, +1.0f), uv = new Vector2(uv_x0, uv_y0) };
                        VertexDataArray[2] = new VertexData() { position = new Vector2(+1.0f, +1.0f), uv = new Vector2(uv_x1, uv_y0) };
                        VertexDataArray[3] = new VertexData() { position = new Vector2(+1.0f, -1.0f), uv = new Vector2(uv_x1, uv_y1) };
                        VertexBuffer.SetIndices(IndexDataArray, 0, 0, 4);
                        VertexBuffer.SetVertices(VertexDataArray, 0, 0, 4);
                        Director.Instance.GL.Context.SetVertexBuffer(0, VertexBuffer);

                        Director.Instance.GL.Context.DrawArrays(DrawMode.TriangleFan, 0, 4);

                        byte[] data = new byte[tile_width * tile_height * 4];

                        // DEBUG: fill with visible memory pattern
                        //for (int i = 0; i< tile_width * tile_height * 4; ++i)
                            //data[i] = (byte)(i % (tile_width / 4));

                        Director.Instance.GL.Context.ReadPixels(data, PixelFormat.Rgba, 0, 0, tile_width, tile_height);

                        List<byte> output = entry.Data[tiles_x * y + x];
                        for (int i = 0; i < tile_width * tile_height * 4; ++i)
                            output.Add(data[i]);
                    }
                }

                Director.Instance.GL.Context.SetVertexBuffer(0, null);
                Director.Instance.GL.Context.SetShaderProgram(null);
                Director.Instance.GL.Context.SetFrameBuffer(old_frame_buffer);
                Director.Instance.GL.Context.SetScissor(old_scissor);
                Director.Instance.GL.Context.SetViewport(old_viewport);

                TileData[name] = entry;
            }
        // SGD :2013/6/18 15:02:51
        // 说明:顶点纹理坐标
        private unsafe void ReadTextureCoordData(uint vertexOffset, byte* vertexBuffer_Lock, uint vertexBuffer_VertexSize, VertexData vertexData) {
            VertexElement texElem = vertexData.vertexDeclaration.FindElementBySemantic(VertexElementSemantic.VES_TEXTURE_COORDINATES);
            float* tReal;
            if (texElem == null) {
                for (uint i = 0; i < vertexData.vertexCount; i++) {
                    this._textureCroodnitas[vertexOffset + i] = new Vector2(0f, 0f);
                }
            }
            else {
                //byte* vextex = vertexBuffer_Lock;
                //for (uint i = 0; i < vertexData.vertexCount; i++) {
                //    texElem.BaseVertexPointerToElement(vextex, &tReal);
                //    this._textureCroodnitas[vertexOffset + i] = new Vector2(tReal[0], tReal[1]);
                //    vextex += vertexBuffer_VertexSize;
                //}
                //读取纹理坐标修正 2013/12/18
                 VertexData vertex_data=vertexData;
                HardwareVertexBufferSharedPtr vbufPtr_tex = vertex_data.vertexBufferBinding.GetBuffer(texElem.Source);
                byte* vertex_tex = (byte*)vbufPtr_tex.Lock(HardwareBuffer.LockOptions.HBL_READ_ONLY);
                for (uint i = 0; i < vertex_data.vertexCount; ++i, /*vertex += vbufPtr.VertexSize,*/ vertex_tex += vbufPtr_tex.VertexSize) {
                    //posElem.BaseVertexPointerToElement(vertex, &pReal);
                    texElem.BaseVertexPointerToElement(vertex_tex, &tReal);
                    this._textureCroodnitas[vertexOffset + i] = new Vector2(tReal[0], tReal[1]);
                    vertex_tex += vertexBuffer_VertexSize;
                    //Vector3 pt = new Vector3(pReal[0], pReal[1], pReal[2]);
                    //vertices[current_offset + j] = (orientation * (pt * scale)) + position;
                    //tex_Cors[current_offset + j] = new Vector2(tReal[0], tReal[1]);
                }
                vbufPtr_tex.Unlock();
                vbufPtr_tex.Dispose();
            }

        }
Example #42
0
    // Assumes file has everything right, else get bad results and/or an exception is thrown
    // Assumes read pointer is at the line after "coord Coordinate { point ["
    /// <summary>
    /// Reads in all the vertices and indices of the figure being loaded.
    /// </summary>
    private void ReadVertsForShapeInVRML()
    {
        List<Vector3> verts = new List<Vector3>();
          List<Vector3> colors = new List<Vector3>();
          List<ushort> vertIndices = new List<ushort>();
          List<ushort> colorIndices = new List<ushort>();

          ReadVectListFromVMRL(verts);
          LookForInVMRL("coordIndex [");
          ReadIndicesListFromVRML(vertIndices);

          LookForInVMRL("color Color { color [");
          ReadVectListFromVMRL(colors);
          LookForInVMRL("colorIndex [");
          ReadIndicesListFromVRML(colorIndices);

          for (int i = 0; i < vertIndices.Count; i++)
          {
         VertexData v = new VertexData(verts[vertIndices[i]], colors[colorIndices[i]]);
         vertList.Add(v);
          }

          CalculateNormals();
    }
Example #43
0
            private unsafe uint ReadVertexData(uint vertexOffset, VertexData vertexData)
            {
                VertexElement posElem = vertexData.vertexDeclaration.FindElementBySemantic(VertexElementSemantic.VES_POSITION);
                HardwareVertexBufferSharedPtr vertexBuffer = vertexData.vertexBufferBinding.GetBuffer(posElem.Source);
                byte* vertexMemory = (byte*)vertexBuffer.Lock(HardwareBuffer.LockOptions.HBL_READ_ONLY);
                float* pElem;

                for (uint i = 0; i < vertexData.vertexCount; i++)
                {
                    posElem.BaseVertexPointerToElement(vertexMemory, &pElem);

                    Mogre.Vector3 point = new Mogre.Vector3(pElem[0], pElem[1], pElem[2]);
                    vertices[vertexOffset] = point * this.scale;
                    vertexMemory += vertexBuffer.VertexSize;
                    vertexOffset++;
                }

                vertexBuffer.Unlock();
                return vertexOffset;
            }
Example #44
0
        private void CreateBuffers(ushort[] indices, short[] vertices)
        {
            var numIndices = (uint)indices.Length;
            var numVertices = (uint)vertices.Length;

            _vertexDeclaration = HardwareBufferManager.Singleton.CreateVertexDeclaration();
            _vertexDeclaration.AddElement(0, 0, VertexElementType.VET_SHORT2, VertexElementSemantic.VES_POSITION);
            _ib = HardwareBufferManager.Singleton.CreateIndexBuffer(HardwareIndexBuffer.IndexType.IT_16BIT, numIndices, HardwareBuffer.Usage.HBU_STATIC_WRITE_ONLY);
            _vb = HardwareBufferManager.Singleton.CreateVertexBuffer(_vertexDeclaration.GetVertexSize(0), numVertices, HardwareBuffer.Usage.HBU_STATIC_WRITE_ONLY, false);

            unsafe
            {
                fixed (ushort* x = indices)
                    _ib.WriteData(0, numIndices * sizeof(ushort), x, true);

                fixed (short* x = vertices)
                    _vb.WriteData(0, numVertices * sizeof(ushort), x, true);
            }

            var binding = new VertexBufferBinding();
            binding.SetBinding(0, _vb);

            VertexData = new VertexData(_vertexDeclaration, binding);
            VertexData.vertexCount = numVertices;
            VertexData.vertexStart = 0;

            IndexData = new IndexData();
            IndexData.indexBuffer = _ib;
            IndexData.indexCount = numIndices;
            IndexData.indexStart = 0;
        }
Example #45
0
        public IEnumerable<VertexData> GetVertexIter()
        {
            VertexData vertexData = new VertexData();
            vertexData.command = VertexCmd.MoveTo;
            vertexData.position = m_points[0];
            yield return vertexData;
            vertexData.command = VertexCmd.LineTo;
            for (int i = 1; i < m_points.Count; i++)
            {
                vertexData.position = m_points[i];
                yield return vertexData;
            }

            vertexData.command = VertexCmd.Stop;
            vertexData.position = new Vector2();
            yield return vertexData;
        }
Example #46
0
    /// <summary>
    /// Calculates the normal vectors based on each set of three vertices.
    /// Creates a "flat-shaded", or "boxy" style when given to the shader program.
    /// </summary>
    private void CalculateNormals()
    {
        // This will be completed in a future program
          // I will explain then why we don't want to use the normals the Wings3d exports.
          // This assumes that Wings3d exports faces in CC order.

          // After we cover this, you should be able to write this in a small number of lines using Vector3 operations.
          // Hint:  Loop through, processing 3 verts at a time.
          // Note that in C#, you can't do: vertList[i + 2].Normal = normal;
          // You need to do something like: vertList[i + 2] = new VertexData(vertList[i + 2].Position, vertList[i + 2].Color, normal);
          for (int i = 0; i < vertList.Count; i += 3)
          {
         Vector3 normal = Vector3.Cross(vertList[i + 1].Position - vertList[i].Position, vertList[i + 2].Position - vertList[i].Position);
         normal = Vector3.Normalize(normal);
         vertList[i] = new VertexData(vertList[i].Position, vertList[i].Color, normal);
         vertList[i + 1] = new VertexData(vertList[i + 1].Position, vertList[i + 1].Color, normal);
         vertList[i + 2] = new VertexData(vertList[i + 2].Position, vertList[i + 2].Color, normal);
          }
    }
Example #47
0
		VertexData CreateVertexData( Vec3[] vertices )
		{
			VertexData vertexData = new VertexData();

			VertexDeclaration declaration = vertexData.VertexDeclaration;
			declaration.AddElement( 0, 0, VertexElementType.Float3, VertexElementSemantic.Position );

			VertexBufferBinding bufferBinding = vertexData.VertexBufferBinding;
			HardwareVertexBuffer vertexBuffer = HardwareBufferManager.Instance.CreateVertexBuffer(
				12, vertices.Length, HardwareBuffer.Usage.StaticWriteOnly );
			bufferBinding.SetBinding( 0, vertexBuffer, true );
			vertexData.VertexCount = vertices.Length;

			unsafe
			{
				Vec3* buffer = (Vec3*)vertexBuffer.Lock( HardwareBuffer.LockOptions.Normal ).ToPointer();
				foreach( Vec3 position in vertices )
				{
					*buffer = position;
					buffer++;
				}
				vertexBuffer.Unlock();
			}

			return vertexData;
		}
Example #48
0
            public void TestOffscreen(string name, Texture2D texture)
            {
                const int Width = 32;
                const int Height = 32;

                ImageRect old_scissor = Director.Instance.GL.Context.GetScissor();
                ImageRect old_viewport = Director.Instance.GL.Context.GetViewport();
                FrameBuffer old_frame_buffer = Director.Instance.GL.Context.GetFrameBuffer();

                ColorBuffer color_buffer = new ColorBuffer(Width, Height, PixelFormat.Rgba);
                FrameBuffer frame_buffer = new FrameBuffer();
                frame_buffer.SetColorTarget(color_buffer);

                System.Console.WriteLine("SetFrameBuffer(): enter");
                Director.Instance.GL.Context.SetFrameBuffer(frame_buffer);
                System.Console.WriteLine("SetFrameBuffer(): exit");

                ShaderProgram.SetAttributeBinding(0, "iPosition");
                ShaderProgram.SetAttributeBinding(1, "iUV");

                texture.SetWrap(TextureWrapMode.ClampToEdge);
                texture.SetFilter(TextureFilterMode.Linear);

                Director.Instance.GL.Context.SetTexture(0, texture);
                Director.Instance.GL.Context.SetVertexBuffer(0, VertexBuffer);
                Director.Instance.GL.Context.SetShaderProgram(ShaderProgram);
                Director.Instance.GL.Context.SetScissor(0, 0, Width, Height);
                Director.Instance.GL.Context.SetViewport(0, 0, Width, Height);

                float uv_x0 = 0.0f;
                float uv_x1 = 1.0f;
                float uv_y0 = 0.0f;
                float uv_y1 = 1.0f;

                VertexDataArray[0] = new VertexData() { position = new Vector2(-1.0f, -1.0f), uv = new Vector2(uv_x0, uv_y1) };
                VertexDataArray[1] = new VertexData() { position = new Vector2(-1.0f, +1.0f), uv = new Vector2(uv_x0, uv_y0) };
                VertexDataArray[2] = new VertexData() { position = new Vector2(+1.0f, +1.0f), uv = new Vector2(uv_x1, uv_y0) };
                VertexDataArray[3] = new VertexData() { position = new Vector2(+1.0f, -1.0f), uv = new Vector2(uv_x1, uv_y1) };

                VertexBuffer.SetIndices(IndexDataArray, 0, 0, 4);
                VertexBuffer.SetVertices(VertexDataArray, 0, 0, 4);

                Director.Instance.GL.Context.SetVertexBuffer(0, VertexBuffer);

                Director.Instance.GL.Context.DrawArrays(DrawMode.TriangleFan, 0, 4);

                int count = Width * Height * 4;
                byte[] data = new byte[count];

                System.Console.WriteLine("ReadPixels(): enter");
                Director.Instance.GL.Context.ReadPixels(data, PixelFormat.Rgba, 0, 0, Width, Height);
                System.Console.WriteLine("ReadPixels(): exit");

                int nonzero = 0;
                int nonclear = 0;
                for (int i = 0; i < count; ++i)
                {
                    if (data[i] != 0)
                        nonzero++;
                    if (data[i] != 0xfe)
                        nonclear++;

                    System.Console.Write("{0} ", data[i]);
                    if (i % Width == 0)
                        System.Console.WriteLine("");
                }

                System.Console.WriteLine("");
                System.Console.WriteLine("nonzero: {0}, nonclear: {1}", nonzero, nonclear);

                Director.Instance.GL.Context.SetVertexBuffer(0, null);
                Director.Instance.GL.Context.SetShaderProgram(null);
                Director.Instance.GL.Context.SetFrameBuffer(old_frame_buffer);
                Director.Instance.GL.Context.SetScissor(old_scissor);
                Director.Instance.GL.Context.SetViewport(old_viewport);

                System.Console.WriteLine("SwapBuffers(): enter");
                Director.Instance.GL.Context.SwapBuffers();
                System.Console.WriteLine("SwapBuffers(): exit");
                Thread.Sleep(250);
            }
        /// <summary>
        /// Returns ready to display render information for a sidepart of this wall.
        /// Note: Z component is the height.
        /// </summary>
        /// <param name="PartType">Which part (upper, middle, lower)</param>
        /// <param name="IsLeftSide">Left or Right side</param>
        /// <param name="TexWidth">Texture width</param>
        /// <param name="TexHeight">Texture height</param>
        /// <param name="TexShrink">Texture shrink</param>
        /// <param name="Scale">Additional scale for vertices</param>
        /// <returns></returns>
        public VertexData GetVertexData(WallPartType PartType, bool IsLeftSide, int TexWidth, int TexHeight, int TexShrink, Real Scale = 1.0f)
        {
            VertexData RI = new VertexData();
            bool drawTopDown = true;
            RooSideDefFlags flags;
            int xoffset = 0;
            int yoffset = 0;

            // fill vars based on left or right side
            if (!IsLeftSide)
            {
                RI.P0.X = P1.X;
                RI.P3.X = P2.X;
                RI.P1.X = P1.X;
                RI.P2.X = P2.X;

                RI.P0.Y = P1.Y;
                RI.P3.Y = P2.Y;
                RI.P1.Y = P1.Y;
                RI.P2.Y = P2.Y;

                flags = RightSide.Flags;
                xoffset = RightXOffset;
                yoffset = RightYOffset;

                switch (PartType)
                {
                    case WallPartType.Upper:
                        RI.P0.Z = z3;
                        RI.P3.Z = zz3;
                        RI.P1.Z = z2;
                        RI.P2.Z = zz2;
                        drawTopDown = !RightSide.Flags.IsAboveBottomUp;
                        break;

                    case WallPartType.Middle:
                        RI.P0.Z = z2;
                        RI.P3.Z = zz2;
                        RI.P1.Z = z1;
                        RI.P2.Z = zz1;
                        drawTopDown = RightSide.Flags.IsNormalTopDown;
                        break;

                    case WallPartType.Lower:
                        if (BowtieFlags.IsBelowPos || BowtieFlags.IsBelowNeg)
                        {
                            RI.P0.Z = z1Neg;
                            RI.P3.Z = zz1Neg;
                        }
                        else
                        {
                            RI.P0.Z = z1;
                            RI.P3.Z = zz1;
                        }

                        RI.P1.Z = z0;
                        RI.P2.Z = zz0;
                        drawTopDown = RightSide.Flags.IsBelowTopDown;
                        break;
                }
            }
            else
            {
                RI.P0.X = P2.X;
                RI.P3.X = P1.X;
                RI.P1.X = P2.X;
                RI.P2.X = P1.X;

                RI.P0.Y = P2.Y;
                RI.P3.Y = P1.Y;
                RI.P1.Y = P2.Y;
                RI.P2.Y = P1.Y;

                flags = LeftSide.Flags;
                xoffset = LeftXOffset;
                yoffset = LeftYOffset;

                switch (PartType)
                {
                    case WallPartType.Upper:
                        RI.P0.Z = zz3;
                        RI.P3.Z = z3;
                        RI.P1.Z = zz2;
                        RI.P2.Z = z2;
                        drawTopDown = !LeftSide.Flags.IsAboveBottomUp;
                        break;

                    case WallPartType.Middle:
                        RI.P0.Z = zz2;
                        RI.P3.Z = z2;
                        RI.P1.Z = zz1;
                        RI.P2.Z = z1;
                        drawTopDown = LeftSide.Flags.IsNormalTopDown;
                        break;

                    case WallPartType.Lower:
                        RI.P0.Z = zz1;
                        RI.P3.Z = z1;
                        RI.P1.Z = zz0;
                        RI.P2.Z = z0;
                        drawTopDown = LeftSide.Flags.IsBelowTopDown;
                        break;
                }
            }

            // scales
            Real invWidth = 1.0f / (Real)TexWidth;
            Real invHeight = 1.0f / (Real)TexHeight;
            Real invWidthFudge = 1.0f / (Real)(TexWidth << 4);
            Real invHeightFudge = 1.0f / (Real)(TexHeight << 4);

            // Start with UV calculation, see d3drender.c ---
            Real u1 = (Real)xoffset * (Real)TexShrink * invHeight;
            Real u2 = u1 + (ClientLength * (Real)TexShrink * invHeight);

            // set U
            RI.UV0.X = u1;
            RI.UV1.X = u1;
            RI.UV3.X = u2;
            RI.UV2.X = u2;

            // calculate V
            int bottom, top;
            if (!drawTopDown)
            {
                if (RI.P1.Z == RI.P2.Z)
                    bottom = (int)RI.P1.Z;
                else
                {
                    bottom = (int)MathUtil.Min(RI.P1.Z, RI.P2.Z);
                    bottom = bottom & ~(GeometryConstants.FINENESS - 1);
                }

                if (RI.P0.Z == RI.P3.Z)
                    top = (int)RI.P0.Z;
                else
                {
                    top = (int)MathUtil.Max(RI.P0.Z, RI.P3.Z);
                    top = (top + GeometryConstants.FINENESS - 1) & ~(GeometryConstants.FINENESS - 1);
                }

                if (RI.P1.Z == RI.P2.Z)
                {
                    RI.UV1.Y = 1.0f - ((Real)yoffset * (Real)TexShrink * invWidth);
                    RI.UV2.Y = 1.0f - ((Real)yoffset * (Real)TexShrink * invWidth);
                }
                else
                {
                    RI.UV1.Y = 1.0f - ((Real)yoffset * (Real)TexShrink * invWidth);
                    RI.UV2.Y = 1.0f - ((Real)yoffset * (Real)TexShrink * invWidth);
                    RI.UV1.Y -= ((Real)RI.P1.Z - bottom) * (Real)TexShrink * invWidthFudge;
                    RI.UV2.Y -= ((Real)RI.P2.Z - bottom) * (Real)TexShrink * invWidthFudge;
                }

                RI.UV0.Y = RI.UV1.Y - ((Real)(RI.P0.Z - RI.P1.Z) * (Real)TexShrink * invWidthFudge);
                RI.UV3.Y = RI.UV2.Y - ((Real)(RI.P3.Z - RI.P2.Z) * (Real)TexShrink * invWidthFudge);
            }

            // else, need to place tex origin at top left
            else
            {
                if (RI.P0.Z == RI.P3.Z)
                    top = (int)RI.P0.Z;
                else
                {
                    top = (int)MathUtil.Max(RI.P0.Z, RI.P3.Z);
                    top = (top + GeometryConstants.FINENESS - 1) & ~(GeometryConstants.FINENESS - 1);
                }

                if (RI.P1.Z == RI.P2.Z)
                    bottom = (int)RI.P1.Z;
                else
                {
                    bottom = (int)MathUtil.Min(RI.P1.Z, RI.P2.Z);
                    bottom = bottom & ~(GeometryConstants.FINENESS - 1);
                }

                if (RI.P0.Z == RI.P3.Z)
                {
                    RI.UV0.Y = 0.0f;
                    RI.UV3.Y = 0.0f;
                }
                else
                {
                    RI.UV0.Y = ((Real)top - RI.P0.Z) * (Real)TexShrink * invWidthFudge;
                    RI.UV3.Y = ((Real)top - RI.P3.Z) * (Real)TexShrink * invWidthFudge;
                }

                RI.UV0.Y -= ((Real)(yoffset * TexShrink) * invWidth);
                RI.UV3.Y -= ((Real)(yoffset * TexShrink) * invWidth);

                RI.UV1.Y = RI.UV0.Y + ((RI.P0.Z - RI.P1.Z) * (Real)TexShrink * invWidthFudge);
                RI.UV2.Y = RI.UV3.Y + ((RI.P3.Z - RI.P2.Z) * (Real)TexShrink * invWidthFudge);
            }

            // backwards
            if (flags.IsBackwards)
            {
                Real temp;

                temp = RI.UV3.X;
                RI.UV3.X = RI.UV0.X;
                RI.UV0.X = temp;

                temp = RI.UV2.X;
                RI.UV2.X = RI.UV1.X;
                RI.UV1.X = temp;
            }

            // no vtile
            // seems to apply only to middle parts, at least for bottom it creates strange holes
            if (flags.IsNoVTile && PartType == WallPartType.Middle)
            {
                if (RI.UV0.Y < 0.0f)
                {
                    Real tex, wall, ratio, temp;

                    tex = RI.UV1.Y - RI.UV0.Y;
                    if (tex == 0)
                        tex = 1.0f;
                    temp = -RI.UV0.Y;
                    ratio = temp / tex;

                    wall = RI.P0.Z - RI.P1.Z;
                    temp = wall * ratio;
                    RI.P0.Z -= temp;
                    RI.UV0.Y = 0.0f;
                }
                if (RI.UV3.Y < 0.0f)
                {
                    Real tex, wall, ratio, temp;

                    tex = RI.UV2.Y - RI.UV3.Y;
                    if (tex == 0)
                        tex = 1.0f;
                    temp = -RI.UV3.Y;
                    ratio = temp / tex;

                    wall = RI.P3.Z - RI.P2.Z;
                    temp = wall * ratio;
                    RI.P3.Z -= temp;
                    RI.UV3.Y = 0.0f;
                }

                RI.P1.Z -= 16.0f;
                RI.P2.Z -= 16.0f;
            }

            RI.UV0.Y += 1.0f / TexWidth;
            RI.UV3.Y += 1.0f / TexWidth;
            RI.UV1.Y -= 1.0f / TexWidth;
            RI.UV2.Y -= 1.0f / TexWidth;

            // scale by user scale
            RI.P0 *= Scale;
            RI.P3 *= Scale;
            RI.P1 *= Scale;
            RI.P2 *= Scale;

            // calculate the normal
            V3 P0P1 = (RI.P1 - RI.P0);
            V3 P0P2 = (RI.P2 - RI.P0);
            RI.Normal = P0P1.CrossProduct(P0P2);
            RI.Normal.Normalize();
            RI.Normal = -RI.Normal;
            return RI;
        }
Example #50
0
        private Mesh GenerateDummyMesh(MeshBinding meshBinding)
        {
            var vertexData = new VertexData();
            vertexData.VertexComponentNames = meshBinding.Mesh.PrimaryVertexData.VertexComponentNames
                .Select(name => new GrannyString(name.String)).ToList();
            vertexData.Vertices = new List<Vertex>();
            var dummyVertex = Helpers.CreateInstance(meshBinding.Mesh.VertexFormat) as Vertex;
            vertexData.Vertices.Add(dummyVertex);
            Root.VertexDatas.Add(vertexData);

            var topology = new TriTopology();
            topology.Groups = new List<TriTopologyGroup>();
            var group = new TriTopologyGroup();
            group.MaterialIndex = 0;
            group.TriCount = 0;
            group.TriFirst = 0;
            topology.Groups.Add(group);

            topology.Indices = new List<int>();
            Root.TriTopologies.Add(topology);

            var mesh = new Mesh();
            mesh.Name = meshBinding.Mesh.Name;
            mesh.VertexFormat = meshBinding.Mesh.VertexFormat;
            mesh.PrimaryTopology = topology;
            mesh.PrimaryVertexData = vertexData;
            if (meshBinding.Mesh.BoneBindings != null)
            {
                mesh.BoneBindings = new List<BoneBinding>();
                ConformMeshBoneBindings(mesh, meshBinding.Mesh);
            }

            return mesh;
        }
Example #51
0
        static void Triangulate(    List<Vector3> listVertices, List<int> listIndices, FracturedObject fracturedComponent, List<List<Vector3>> listlistPointsConstrainedDelaunay, List<List<int>> listlistHashValuesConstrainedDelaunay,
                                    bool bConnectivityPostprocess, MeshFaceConnectivity faceConnectivityPos, MeshFaceConnectivity faceConnectivityNeg, MeshDataConnectivity meshConnectivityPos, MeshDataConnectivity meshConnectivityNeg, int nForceMeshConnectivityHash,
                                    int nSplitCloseSubMesh, Matrix4x4 mtxPlane, Matrix4x4 mtxToLocalPos, Matrix4x4 mtxToLocalNeg, Vector3 v3CenterPos, Vector3 v3CenterNeg,
                                    List<int>[] aListIndicesPosInOut, List<VertexData> listVertexDataPosInOut, List<int>[] aListIndicesNegInOut, List<VertexData> listVertexDataNegInOut)
        {
            int nPositiveSideIndexStart = listVertexDataPosInOut.Count;
		    int nNegativeSideIndexStart = listVertexDataNegInOut.Count;

            if(listVertexDataPosInOut.Count < 1 || listVertexDataNegInOut.Count < 1)
            {
                return;
            }

            // Add vertex data

            VertexData[] aVtxDataCapPos = new VertexData[listVertices.Count];
            VertexData[] aVtxDataCapNeg = new VertexData[listVertices.Count];

            Vector3 v3PlaneNormal = mtxPlane.MultiplyVector(Vector3.up);

            float fReversedCapNormals = fracturedComponent.InvertCapNormals ? -1.0f : 1.0f;

            Vector3 v3CapNormalLocalPos = mtxToLocalPos.MultiplyVector(-v3PlaneNormal * fReversedCapNormals);
            Vector3 v3CapNormalLocalNeg = mtxToLocalNeg.MultiplyVector( v3PlaneNormal * fReversedCapNormals);

            Vector3 v3TangentPos = Vector3.right;
            v3TangentPos = mtxPlane.MultiplyVector(v3TangentPos);
            v3TangentPos = mtxToLocalPos.MultiplyVector(v3TangentPos);

            Vector3 v3TangentNeg = Vector3.right;
            v3TangentNeg = mtxPlane.MultiplyVector(v3TangentNeg);
            v3TangentNeg = mtxToLocalNeg.MultiplyVector(v3TangentNeg);

            Matrix4x4 mtxPlaneInverse = mtxPlane.inverse;

            Color32 colWhite  = new Color32(255, 255, 255, 255);
            Vector3 v2Mapping = Vector2.zero;

            for(int i = 0; i < listVertices.Count; i++)
            {
                Vector3 v3Local   = mtxPlaneInverse.MultiplyPoint3x4(listVertices[i]);
                v2Mapping.x = v3Local.x * fracturedComponent.SplitMappingTileU;
                v2Mapping.y = v3Local.z * fracturedComponent.SplitMappingTileV;

                int nVertexHash = ComputeVertexHash(listVertices[i], listlistPointsConstrainedDelaunay, listlistHashValuesConstrainedDelaunay);

                aVtxDataCapPos[i] = new VertexData(nVertexHash, listVertices[i], v3CapNormalLocalPos, v3TangentPos, colWhite, v2Mapping, v2Mapping, true, true, listVertexDataPosInOut[0].bHasColor32, listVertexDataPosInOut[0].bHasMapping1, listVertexDataPosInOut[0].bHasMapping2);
                aVtxDataCapNeg[i] = new VertexData(nVertexHash, listVertices[i], v3CapNormalLocalNeg, v3TangentNeg, colWhite, v2Mapping, v2Mapping, true, true, listVertexDataNegInOut[0].bHasColor32, listVertexDataNegInOut[0].bHasMapping1, listVertexDataNegInOut[0].bHasMapping2);
            }

            listVertexDataPosInOut.AddRange(aVtxDataCapPos);
            listVertexDataNegInOut.AddRange(aVtxDataCapNeg);

            // Add indices

            for(int i = 0; i < listIndices.Count / 3; i++)
		    {
                int nTriangleA = listIndices[i * 3 + 0];
                int nTriangleB = listIndices[i * 3 + 1];
                int nTriangleC = listIndices[i * 3 + 2];

                int nHashPosA  = listVertexDataPosInOut[nPositiveSideIndexStart + nTriangleA].nVertexHash;
                int nHashPosB  = listVertexDataPosInOut[nPositiveSideIndexStart + nTriangleB].nVertexHash;
                int nHashPosC  = listVertexDataPosInOut[nPositiveSideIndexStart + nTriangleC].nVertexHash;

                int nHashNegA  = listVertexDataNegInOut[nNegativeSideIndexStart + nTriangleA].nVertexHash;
                int nHashNegB  = listVertexDataNegInOut[nNegativeSideIndexStart + nTriangleB].nVertexHash;
                int nHashNegC  = listVertexDataNegInOut[nNegativeSideIndexStart + nTriangleC].nVertexHash;

                if(nHashPosA != -1 && nHashPosB != -1 && nHashPosC != -1 && nHashNegA != -1 && nHashNegB != -1 && nHashNegC != -1)
                {
                    int nMeshConnectivityHash = nForceMeshConnectivityHash == -1 ? MeshDataConnectivity.GetNewHash() : nForceMeshConnectivityHash; // New hash value to identify the 2 shared faces

                    if(fracturedComponent.GenerateChunkConnectionInfo)
                    {
                        meshConnectivityPos.NotifyNewCapFace(nMeshConnectivityHash, nSplitCloseSubMesh, aListIndicesPosInOut[nSplitCloseSubMesh].Count / 3);
                    }

                    aListIndicesPosInOut[nSplitCloseSubMesh].Add(nPositiveSideIndexStart + nTriangleA);
			        aListIndicesPosInOut[nSplitCloseSubMesh].Add(nPositiveSideIndexStart + nTriangleB);
			        aListIndicesPosInOut[nSplitCloseSubMesh].Add(nPositiveSideIndexStart + nTriangleC);

                    if(bConnectivityPostprocess)
                    {
                        faceConnectivityPos.AddEdge(nSplitCloseSubMesh, listVertices[nTriangleA], listVertices[nTriangleB], nHashPosA, nHashPosB, nPositiveSideIndexStart + nTriangleA, nPositiveSideIndexStart + nTriangleB);
                        faceConnectivityPos.AddEdge(nSplitCloseSubMesh, listVertices[nTriangleB], listVertices[nTriangleC], nHashPosB, nHashPosC, nPositiveSideIndexStart + nTriangleB, nPositiveSideIndexStart + nTriangleC);
                        faceConnectivityPos.AddEdge(nSplitCloseSubMesh, listVertices[nTriangleC], listVertices[nTriangleA], nHashPosC, nHashPosA, nPositiveSideIndexStart + nTriangleC, nPositiveSideIndexStart + nTriangleA);
                    }

                    if(fracturedComponent.GenerateChunkConnectionInfo)
                    {
                        meshConnectivityNeg.NotifyNewCapFace(nMeshConnectivityHash, nSplitCloseSubMesh, aListIndicesNegInOut[nSplitCloseSubMesh].Count / 3);
                    }

			        aListIndicesNegInOut[nSplitCloseSubMesh].Add(nNegativeSideIndexStart + nTriangleA);
			        aListIndicesNegInOut[nSplitCloseSubMesh].Add(nNegativeSideIndexStart + nTriangleC);
			        aListIndicesNegInOut[nSplitCloseSubMesh].Add(nNegativeSideIndexStart + nTriangleB);

                    if(bConnectivityPostprocess)
                    {
                        faceConnectivityNeg.AddEdge(nSplitCloseSubMesh, listVertices[nTriangleA], listVertices[nTriangleC], nHashNegA, nHashNegC, nNegativeSideIndexStart + nTriangleA, nNegativeSideIndexStart + nTriangleC);
                        faceConnectivityNeg.AddEdge(nSplitCloseSubMesh, listVertices[nTriangleC], listVertices[nTriangleB], nHashNegC, nHashNegB, nNegativeSideIndexStart + nTriangleC, nNegativeSideIndexStart + nTriangleB);
                        faceConnectivityNeg.AddEdge(nSplitCloseSubMesh, listVertices[nTriangleB], listVertices[nTriangleA], nHashNegB, nHashNegA, nNegativeSideIndexStart + nTriangleB, nNegativeSideIndexStart + nTriangleA);
                    }
                }
            }
        }
Example #52
0
        public IEnumerable<VertexData> GetVertexIter()
        {
            // go to the start
            if (UseStartEndLimit)
            {
                //---------------------------------------------------------
                VertexData vertexData = new VertexData();
                vertexData.command = VertexCmd.MoveTo;
                vertexData.x = startX;
                vertexData.y = startY;
                yield return vertexData;
                //---------------------------------------------------------
                double angle = startAngle;
                vertexData.command = VertexCmd.LineTo;
                //calculate nsteps
                int n = 0;
                while (n < calculateNSteps - 1)
                {
                    angle += flatenDeltaAngle;
                    vertexData.x = originX + Math.Cos(angle) * radiusX;
                    vertexData.y = originY + Math.Sin(angle) * radiusY;
                    yield return vertexData;
                    n++;
                }

                //while ((angle < endAngle - flatenDeltaAngle / 4) == (((int)ArcDirection.CounterClockWise) == 1))
                //{
                //    angle += flatenDeltaAngle;
                //    vertexData.x = originX + Math.Cos(angle) * radiusX;
                //    vertexData.y = originY + Math.Sin(angle) * radiusY;

                //    yield return vertexData;
                //}
                //---------------------------------------------------------
                vertexData.x = endX;
                vertexData.y = endY;
                yield return vertexData;
                vertexData.command = VertexCmd.Stop;
                yield return vertexData;
            }
            else
            {
                VertexData vertexData = new VertexData();
                vertexData.command = VertexCmd.MoveTo;
                vertexData.x = originX + Math.Cos(startAngle) * radiusX;
                vertexData.y = originY + Math.Sin(startAngle) * radiusY;
                yield return vertexData;
                //---------------------------------------------------------
                double angle = startAngle;
                vertexData.command = VertexCmd.LineTo;
                while ((angle < endAngle - flatenDeltaAngle / 4) == (((int)ArcDirection.CounterClockWise) == 1))
                {
                    angle += flatenDeltaAngle;
                    vertexData.x = originX + Math.Cos(angle) * radiusX;
                    vertexData.y = originY + Math.Sin(angle) * radiusY;
                    yield return vertexData;
                }
                //---------------------------------------------------------
                vertexData.x = originX + Math.Cos(endAngle) * radiusX;
                vertexData.y = originY + Math.Sin(endAngle) * radiusY;
                yield return vertexData;
                vertexData.command = VertexCmd.Stop;
                yield return vertexData;
            }
        }