예제 #1
0
        static int TriangleCompareFunction(TriangleGraph elementA, TriangleGraph elementB, int axis)
        {
            float valueA = (axis == 0) ? elementA.Centroid.X : (axis == 1) ? elementA.Centroid.Y : elementA.Centroid.Z;

            float valueB = (axis == 0) ? elementB.Centroid.X : (axis == 1) ? elementB.Centroid.Y : elementB.Centroid.Z;

            if (valueA < valueB)
                return -1;
            if (valueA > valueB)
                return 1;

            return 0;
        }
예제 #2
0
        public void GenerateGeometry(ref byte[] DensityField, byte IsoValue, int DensityFieldWidth, int DensityFieldHeight, int DensityFieldDepth, int Width, int Height, int Depth, int xOrigin, int yOrigin, int zOrigin, Vector3 ratio, Matrix transform)
        {
            DestroyBuffers();

            List<VertexPN> _vertices = new List<VertexPN>();
            List<ushort> _indices = new List<ushort>();
            SortedList<int, ushort> _edgeToIndices = new SortedList<int, ushort>();
            collisionGraph.Clear();

            int width = DensityFieldWidth;
            int sliceArea = width * DensityFieldHeight;

            byte[] DensityCache = new byte[8];
            Vector3[] VectorCache = new Vector3[8];
            for (int z = zOrigin; z < zOrigin + Depth; z++)
            {
                for (int y = yOrigin; y < yOrigin + Height; y++)
                {

                    int dIdx = z * sliceArea + y * width + xOrigin;

                    VectorCache[0] = new Vector3(xOrigin, y, z) * ratio - Vector3.One;
                    VectorCache[3] = new Vector3(xOrigin, y + 1, z) * ratio - Vector3.One;
                    VectorCache[4] = new Vector3(xOrigin, y, z + 1) * ratio - Vector3.One;
                    VectorCache[7] = new Vector3(xOrigin, y + 1, z + 1) * ratio - Vector3.One;
                    DensityCache[0] = DensityField[dIdx];
                    DensityCache[3] = DensityField[dIdx + width];
                    DensityCache[4] = DensityField[dIdx + sliceArea];
                    DensityCache[7] = DensityField[dIdx + sliceArea + width];

                    for (int x = xOrigin + 1; x <= xOrigin + Width; x++)
                    {
                        dIdx = z * sliceArea + y * width + x;

                        VectorCache[1] = new Vector3(x, y, z) * ratio - Vector3.One;
                        VectorCache[2] = new Vector3(x, y + 1, z) * ratio - Vector3.One;
                        VectorCache[5] = new Vector3(x, y, z + 1) * ratio - Vector3.One;
                        VectorCache[6] = new Vector3(x, y + 1, z + 1) * ratio - Vector3.One;
                        DensityCache[1] = DensityField[dIdx];
                        DensityCache[2] = DensityField[dIdx + width];
                        DensityCache[5] = DensityField[dIdx + sliceArea];
                        DensityCache[6] = DensityField[dIdx + sliceArea + width];
                        /*
                           Determine the index into the edge table which
                           tells us which vertices are inside of the surface
                        */
                        int cubeindex = 0;
                        if (DensityCache[0] > IsoValue) cubeindex |= 1;
                        if (DensityCache[1] > IsoValue) cubeindex |= 2;
                        if (DensityCache[2] > IsoValue) cubeindex |= 4;
                        if (DensityCache[3] > IsoValue) cubeindex |= 8;
                        if (DensityCache[4] > IsoValue) cubeindex |= 16;
                        if (DensityCache[5] > IsoValue) cubeindex |= 32;
                        if (DensityCache[6] > IsoValue) cubeindex |= 64;
                        if (DensityCache[7] > IsoValue) cubeindex |= 128;

                        /* Cube is entirely in/out of the surface */
                        if (cubeindex != 0 && cubeindex != 255)
                        {
                            /*0-r
                            1-r+x
                            2-r+x+y
                            3-r+y
                            4-r+z
                            5-r+x+z
                            6-r+x+y+z
                            7-r+y+z
                            */
                            //Now lets generate some normal vectors!
                            Vector3[] NormalCache = new Vector3[8];
                            NormalCache[0] = ComputeNormal(ref DensityField, DensityFieldWidth, DensityFieldHeight, DensityFieldDepth, x - 1, y, z);
                            NormalCache[1] = ComputeNormal(ref DensityField, DensityFieldWidth, DensityFieldHeight, DensityFieldDepth, x, y, z);
                            NormalCache[2] = ComputeNormal(ref DensityField, DensityFieldWidth, DensityFieldHeight, DensityFieldDepth, x, y + 1, z);
                            NormalCache[3] = ComputeNormal(ref DensityField, DensityFieldWidth, DensityFieldHeight, DensityFieldDepth, x - 1, y + 1, z);
                            NormalCache[4] = ComputeNormal(ref DensityField, DensityFieldWidth, DensityFieldHeight, DensityFieldDepth, x - 1, y, z + 1);
                            NormalCache[5] = ComputeNormal(ref DensityField, DensityFieldWidth, DensityFieldHeight, DensityFieldDepth, x, y, z + 1);
                            NormalCache[6] = ComputeNormal(ref DensityField, DensityFieldWidth, DensityFieldHeight, DensityFieldDepth, x, y + 1, z + 1);
                            NormalCache[7] = ComputeNormal(ref DensityField, DensityFieldWidth, DensityFieldHeight, DensityFieldDepth, x - 1, y + 1, z + 1);
                            for (int i = 0; VoxelHelper.NewTriangleTable2[cubeindex, i] != -1; i += 3)
                            {
                                int[] edgeIndices = new int[3];
                                for (int j = 0; j < 3; j++)
                                {
                                    int idx = GetEdgeId(DensityFieldWidth, DensityFieldHeight, x, y, z, VoxelHelper.NewTriangleTable2[cubeindex, i + j]);
                                    edgeIndices[j] = idx;
                                    if(!collisionGraph.ContainsKey(idx))
                                        collisionGraph.Add(idx, new List<TriangleGraph>());
                                    if (!_edgeToIndices.ContainsKey(idx))
                                    {
                                        _edgeToIndices.Add(idx, (ushort)_vertices.Count);

                                        _vertices.Add(GenerateVertex(VoxelHelper.NewTriangleTable2[cubeindex, i + j], VectorCache, NormalCache, DensityCache, IsoValue));
                                    }
                                    _indices.Add(_edgeToIndices[idx]);
                                }
                                ushort id0 = _indices[_indices.Count - 3];
                                ushort id1 = _indices[_indices.Count - 2];
                                ushort id2 = _indices[_indices.Count - 1];
                                Vector3 v0 = Vector3.Transform(_vertices[id0].Position, transform);
                                Vector3 v1 = Vector3.Transform(_vertices[id1].Position, transform);
                                Vector3 v2 = Vector3.Transform(_vertices[id2].Position, transform);
                                TriangleGraph graph = new TriangleGraph(id0, id1, id2, v0, v1, v2);
                                for (int j = 0; j < edgeIndices.Length; j++)
                                    collisionGraph[edgeIndices[j]].Add(graph);

                                PrimitiveCount++;
                            }
                        }
                        //Swap our caches
                        VectorCache[0] = VectorCache[1];
                        VectorCache[3] = VectorCache[2];
                        VectorCache[4] = VectorCache[5];
                        VectorCache[7] = VectorCache[6];
                        DensityCache[0] = DensityCache[1];
                        DensityCache[3] = DensityCache[2];
                        DensityCache[4] = DensityCache[5];
                        DensityCache[7] = DensityCache[6];
                    }
                }
            }

            verts = _vertices.ToArray();
            ib = _indices.ToArray();
            if (verts.Length > 0)
            {
                renderElement.VertexCount = verts.Length;
                renderElement.VertexBuffer = new VertexBuffer(GFX.Device, verts.Length * VertexPN.SizeInBytes, BufferUsage.WriteOnly);
                renderElement.VertexBuffer.SetData<VertexPN>(verts);
            }
            if (ib.Length > 0)
            {
                renderElement.IndexBuffer = new IndexBuffer(GFX.Device, ib.Length * sizeof(ushort), BufferUsage.WriteOnly, IndexElementSize.SixteenBits);
                renderElement.IndexBuffer.SetData<ushort>(ib);
                renderElement.PrimitiveCount = PrimitiveCount;
            }

            collisionTree = new KDTree<TriangleGraph>(TriangleCompareFunction);
            for (int i = 0; i < collisionGraph.Values.Count; i++)
            {
                List<TriangleGraph> entries = collisionGraph.Values[i];
                collisionTree.AddElementRange(entries.ToArray(), false);
            }
            collisionTree.BuildTree();

            CanRender = (PrimitiveCount > 0);
        }
예제 #3
0
        static int CompareCollisionNodesKD(TriangleGraph nodeA, TriangleGraph nodeB, int axis)
        {
            float nodeAValue = (axis == 0) ? nodeA.Centroid.X : (axis == 1) ? nodeA.Centroid.Y : nodeA.Centroid.Z;

            float nodeBValue = (axis == 0) ? nodeB.Centroid.X : (axis == 1) ? nodeB.Centroid.Y : nodeB.Centroid.Z;

            if (nodeAValue < nodeBValue)
                return -1;
            if (nodeAValue > nodeBValue)
                return 1;

            return 0;
        }