コード例 #1
0
        /*private static ReuseCell getReuseCell(ReuseCell[, ,] cells, int lod, byte rDir, Vector3i pos)
        {
            int rx = rDir & 0x01;
            int rz = (rDir >> 1) & 0x01;
            int ry = (rDir >> 2) & 0x01;

            int dx = pos.X / lod - rx;
            int dy = pos.Y / lod - ry;
            int dz = pos.Z / lod - rz;

            ReuseCell ccc = cells[dx, dy, dz];
            return ccc;
        }*/
        internal static Vector3f InterpolateVoxelVector(long t, Vector3f P0, Vector3f P1)
        {
            long u = 0x0100 - t; //256 - t
            float s = 1.0f / 256.0f;
            Vector3f Q = P0 * t + P1 * u; //Density Interpolation
            Q *= s; // shift to shader !
            return Q;
        }
コード例 #2
0
 public Vector3f Max(Vector3f other)
 {
     return Max(this, other);
 }
コード例 #3
0
 public void Mul(Vector3f v)
 {
     this *= v;
 }
コード例 #4
0
 public void Div(Vector3f v)
 {
     this /= v;
 }
コード例 #5
0
 public bool Equals(Vector3f other)
 {
     return other.Y.Equals(Y) && other.Z.Equals(Z) && other.X.Equals(X);
 }
コード例 #6
0
        public static Vector3f Normalize(Vector3f v)
        {
            if (System.Math.Abs(v.MagnitudeSquare - 0) < float.Epsilon)
                return v;

            float inverse = 1 / v.Magnitude;
            return new Vector3f(
                v.X * inverse,
                v.Y * inverse,
                v.Z * inverse);
        }
コード例 #7
0
 public double Angle(Vector3f other)
 {
     return Angle(this, other);
 }
コード例 #8
0
 private static Vector3f ProjectNormal(Vector3f n, Vector3f delta)
 {
     //return Vector3f.Cross(n, delta);
     var mat = new Matrix3X3(
            1.0f - n.X * n.X, -n.X * n.Y, -n.X * n.Z,
            -n.X * n.Y, 1.0f - n.Y * n.Y, -n.Y * n.Z,
            -n.X * n.Z, -n.Y * n.Z, 1.0f - n.Z * n.Z);
     return mat * delta;
 }
コード例 #9
0
 public void AddVertex(Vector3f v, Vector3f normal)
 {
     vertices.Add(v);
     normals.Add(normal);
 }
コード例 #10
0
        private static Vector3f ComputeDelta(Vector3f v, int k, int s)
        {
            float p2k = (float)System.Math.Pow(2.0, k); // 1 << k would do the job much more efficient
            float wk = (float)System.Math.Pow(2.0, k - 2.0); // 1 << (k-2)
            Vector3f delta = Vector3f.Zero;

            if (k < 1)
            {
                return delta;
            }

            // x
            float p = v.X;
            float p2mk = (float)System.Math.Pow(2.0, -k);
            if (p < p2k)
            {
                // The vertex is inside the minimum cell.
                delta.X = (1.0f - p2mk * p) * wk;
            }
            else if (p > (p2k * (s - 1)))
            {
                // The vertex is inside the maximum cell.
                delta.X = ((p2k * s) - 1.0f - p) * wk;
            }

            // y
            p = v.Y;
            if (p < p2k)
            {
                // The vertex is inside the minimum cell.
                delta.Y = (1.0f - p2mk * p) * wk;
            }
            else if (p > (p2k * (s - 1)))
            {
                // The vertex is inside the maximum cell.
                delta.Y = ((p2k * s) - 1.0f - p) * wk;
            }

            // z
            p = v.Z;
            if (p < p2k)
            {
                // The vertex is inside the minimum cell.
                delta.Z = (1.0f - p2mk * p) * wk;
            }
            else if (p > (p2k * (s - 1)))
            {
                // The vertex is inside the maximum cell.
                delta.Z = ((p2k * s) - 1.0f - p) * wk;
            }

            return delta;
        }
コード例 #11
0
        private static Vector3f Interp(Vector3f v0, Vector3f v1, Vector3i p0, Vector3i p1, IVolumeData samples, byte lodIndex = 0)
        {
            sbyte s0 = samples[p0];
            sbyte s1 = samples[p1];

            int t = (s1 << 8) / (s1 - s0);
            int u = 0x0100 - t;

            if ((t & 0x00ff) == 0)
            {
                // The generated vertex lies at one of the corners so there
                // is no need to subdivide the interval.
                if (t == 0)
                {
                    return v1;
                }
                return v0;
            }
            else
            {
                for (int i = 0; i < lodIndex; ++i)
                {
                    Vector3f vm = (v0 + v1) / 2;
                    Vector3i pm = (p0 + p1) / 2;

                    sbyte sm = samples[pm];

                    // Determine which of the sub-intervals that contain
                    // the intersection with the isosurface.
                    if (Sign(s0) != Sign(sm))
                    {
                        v1 = vm;
                        p1 = pm;
                        s1 = sm;
                    }
                    else
                    {
                        v0 = vm;
                        p0 = pm;
                        s0 = sm;
                    }
                }
                t = (s1 << 8) / (s1 - s0);
                u = 0x0100 - t;

                return v0 * t * S + v1 * u * S;
            }
        }
コード例 #12
0
        public static int PolygonizeTransitionCell(Vector3f offset, Vector3i origin,
            Vector3i localX, Vector3i localY, Vector3i localZ,
            int x, int y, float cellSize,
            byte lodIndex, byte axis, byte directionMask,
            IVolumeData samples,
            ref IList<Vertex> verts, ref IList<int> indices,
            ref TransitionCache cache)
        {
            int lodStep = 1 << lodIndex;
            int sampleStep = 1 << (lodIndex - 1);
            int lodScale = 1 << lodIndex;
            int last = 16 * lodScale;

            byte near = 0;

            // Compute which of the six faces of the block that the vertex
            // is near. (near is defined as being in boundary cell.)
            for (int i = 0; i < 3; i++)
            {
                // Vertex close to negative face.
                if (origin[i] == 0) { near |= (byte)(1 << (i * 2 + 0)); }
                // Vertex close to positive face.
                if (origin[i] == last) { near |= (byte)(1 << (i * 2 + 1)); }
            }

            Vector3i[] coords =
                {
                    new Vector3i(0,0,0), new Vector3i(1,0,0), new Vector3i(2,0,0), // High-res lower row
                    new Vector3i(0,1,0), new Vector3i(1,1,0), new Vector3i(2,1,0), // High-res middle row
                    new Vector3i(0,2,0), new Vector3i(1,2,0), new Vector3i(2,2,0), // High-res upper row
                    new Vector3i(0,0,2), new Vector3i(2,0,2), // Low-res lower row
                    new Vector3i(0,2,2), new Vector3i(2,2,2)  // Low-res upper row
                };

            // TODO: Implement Matrix Math
            var mx = localX * sampleStep;
            var my = localY * sampleStep;
            var mz = localZ * sampleStep;

            Matrix3X3 basis = new Matrix3X3((Vector3f)mx, (Vector3f)my, (Vector3f)mz);

            Vector3i[] pos = {
                        origin + basis * coords[0x00], origin + basis * coords[0x01], origin + basis * coords[0x02],
                        origin + basis * coords[0x03], origin + basis * coords[0x04], origin + basis * coords[0x05],
                        origin + basis * coords[0x06], origin + basis * coords[0x07], origin + basis * coords[0x08],
                        origin + basis * coords[0x09], origin + basis * coords[0x0A],
                        origin + basis * coords[0x0B], origin + basis * coords[0x0C]
                };

            Vector3f[] normals = new Vector3f[13];

            for (int i = 0; i < 9; i++)
            {
                Vector3i p = pos[i];
                float nx = (samples[p + Vector3i.UnitX] - samples[p - Vector3i.UnitX]) * 0.5f;
                float ny = (samples[p + Vector3i.UnitY] - samples[p - Vector3i.UnitY]) * 0.5f;
                float nz = (samples[p + Vector3i.UnitZ] - samples[p - Vector3i.UnitZ]) * 0.5f;
                normals[i] = new Vector3f(nx, ny, nz);
                normals[i].Normalize();
            }

            normals[0x9] = normals[0];
            normals[0xA] = normals[2];
            normals[0xB] = normals[6];
            normals[0xC] = normals[8];

            Vector3i[] samplePos = {
                pos[0], pos[1], pos[2],
                pos[3], pos[4], pos[5],
                pos[6], pos[7], pos[8],
                pos[0], pos[2],
                pos[6], pos[8]
            };

            uint caseCode = (uint)(Sign(samples[pos[0]]) * 0x001 |
                                   Sign(samples[pos[1]]) * 0x002 |
                                   Sign(samples[pos[2]]) * 0x004 |
                                   Sign(samples[pos[5]]) * 0x008 |
                                   Sign(samples[pos[8]]) * 0x010 |
                                   Sign(samples[pos[7]]) * 0x020 |
                                   Sign(samples[pos[6]]) * 0x040 |
                                   Sign(samples[pos[3]]) * 0x080 |
                                   Sign(samples[pos[4]]) * 0x100);

            if (caseCode == 0 || caseCode == 511)
                return 0;

            cache[x, y].CaseIndex = (byte)caseCode;

            byte classIndex = Tables.TransitionCellClass[caseCode]; // Equivalence class index.
            var data = Tables.TransitionRegularCellData[classIndex & 0x7F];
            bool inverse = (classIndex & 128) != 0;
            int[] localVertexMapping = new int[12];

            int nv = (int)data.GetVertexCount();
            int nt = (int)data.GetTriangleCount();

            Debug.Assert(nv <= 12);
            var vert = new Vertex();

            for (int i = 0; i < nv; i++)
            {
                ushort edgeCode = Tables.TransitionVertexData[caseCode][i];
                byte v0 = HiNibble((byte)edgeCode);
                byte v1 = LoNibble((byte)edgeCode);
                bool lowside = (v0 > 8) && (v1 > 8);

                int d0 = samples[samplePos[v0]];
                int d1 = samples[samplePos[v1]];

                int t = (d1 << 8) / (d1 - d0);
                int u = 0x0100 - t;
                float t0 = t * S;
                float t1 = u * S;

                Vector3f n0 = normals[v0];
                Vector3f n1 = normals[v1];

                vert.Near = near;
                vert.Normal = n0 * t0 + n1 * t1;

                if ((t & 0x00ff) != 0)
                {
                    // Use the reuse information in transitionVertexData
                    byte dir = HiNibble((byte)(edgeCode >> 8));
                    byte idx = LoNibble((byte)(edgeCode >> 8));

                    bool present = (dir & directionMask) == dir;

                    if (present)
                    {
                        // The previous cell is available. Retrieve the cached cell
                        // from which to retrieve the reused vertex index from.
                        var prev = cache[x - (dir & 1), y - ((dir >> 1) & 1)];

                        if (prev.CaseIndex == 0 || prev.CaseIndex == 511)
                        {
                            // Previous cell does not contain any geometry.
                            localVertexMapping[i] = -1;
                        }
                        else
                        {
                            // Reuse the vertex index from the previous cell.
                            localVertexMapping[i] = prev.Verts[idx];
                        }
                    }
                    if (!present || localVertexMapping[i] < 0)
                    {
                        Vector3f p0 = (Vector3f)pos[v0];
                        Vector3f p1 = (Vector3f)pos[v1];

                        Vector3f pi = Interp(p0, p1, samplePos[v0], samplePos[v1], samples, lowside ? (byte)lodIndex : (byte)(lodIndex - 1));

                        if (lowside)
                        {
                            switch (axis)
                            {
                                case 0:
                                    pi.X = (float)origin.X;
                                    break;
                                case 1:
                                    pi.Y = (float)origin.Y;
                                    break;
                                case 2:
                                    pi.Z = (float)origin.Z;
                                    break;
                            }

                            Vector3f delta = ComputeDelta(pi, lodIndex, 16);
                            Vector3f proj = ProjectNormal(vert.Normal, delta);

                            vert.Primary = Unused;
                            vert.Secondary = offset + pi + proj;
                        }
                        else
                        {
                            vert.Near = 0;
                            vert.Primary = offset + pi;
                            vert.Secondary = Unused;
                        }

                        localVertexMapping[i] = verts.Count;
                        verts.Add(vert);

                        if ((dir & 8) != 0)
                        {
                            // The vertex can be reused.
                            cache[x, y].Verts[idx] = localVertexMapping[i];
                        }
                    }
                }
                else
                {
                    // Try to reuse corner vertex from a preceding cell.
                    // Use the reuse information in transitionCornerData.
                    byte v = t == 0 ? v1 : v0;
                    byte cornerData = Tables.TransitionCornerData[v];

                    byte dir = HiNibble(cornerData); // High nibble contains direction code.
                    byte idx = LoNibble((cornerData)); // Low nibble contains storage slot for vertex.
                    bool present = (dir & directionMask) == dir;

                    if (present)
                    {
                        // The previous cell is available. Retrieve the cached cell
                        // from which to retrieve the reused vertex index from.
                        var prev = cache[x - (dir & 1), y - ((dir >> 1) & 1)];

                        if (prev.CaseIndex == 0 || prev.CaseIndex == 511)
                        {
                            // Previous cell does not contain any geometry.
                            localVertexMapping[i] = -1;
                        }
                        else
                        {
                            // Reuse the vertex index from the previous cell.
                            localVertexMapping[i] = prev.Verts[idx];
                        }
                    }

                    if (!present || localVertexMapping[i] < 0)
                    {
                        // A vertex has to be created.
                        Vector3f pi = (Vector3f)pos[v];

                        if (v > 8)
                        {
                            // On low-resolution side.
                            // Necessary to translate the intersection point to the
                            // high-res side so that it is transformed the same way
                            // as the vertices in the regular cell.
                            switch (axis)
                            {
                                case 0:
                                    pi.X = (float)origin.X;
                                    break;
                                case 1:
                                    pi.Y = (float)origin.Y;
                                    break;
                                case 2:
                                    pi.Z = (float)origin.Z;
                                    break;
                            }

                            Vector3f delta = ComputeDelta(pi, lodIndex, 16);
                            Vector3f proj = ProjectNormal(vert.Normal, delta);

                            vert.Primary = Unused;
                            vert.Secondary = offset + pi + proj;
                        }
                        else
                        {
                            // On high-resolution side.
                            vert.Near = 0; // Vertices on high-res side are never moved.
                            vert.Primary = offset + pi;
                            vert.Secondary = Unused;
                        }
                        localVertexMapping[i] = verts.Count;
                        cache[x, y].Verts[idx] = localVertexMapping[i];
                        verts.Add(vert);
                    }
                }
            }

            for (long t = 0; t < nt; ++t)
            {
                if (inverse)
                {
                    indices.Add(localVertexMapping[data.Indizes()[t * 3 + 2]]);
                    indices.Add(localVertexMapping[data.Indizes()[t * 3 + 1]]);
                    indices.Add(localVertexMapping[data.Indizes()[t * 3 + 0]]);
                    //indices.push_back(localVertexMapping[ptr[2]]);
                    //indices.push_back(localVertexMapping[ptr[1]]);
                    //indices.push_back(localVertexMapping[ptr[0]]);
                }
                else
                {
                    indices.Add(localVertexMapping[data.Indizes()[t * 3 + 0]]);
                    indices.Add(localVertexMapping[data.Indizes()[t * 3 + 1]]);
                    indices.Add(localVertexMapping[data.Indizes()[t * 3 + 2]]);
                    // indices.push_back(localVertexMapping[ptr[0]]);
                    // indices.push_back(localVertexMapping[ptr[1]]);
                    // indices.push_back(localVertexMapping[ptr[2]]);
                }
            }

            return nt;
        }
コード例 #13
0
        public static int PolygonizeRegularCell(Vector3i min, Vector3f offset, Vector3i xyz,
            IVolumeData samples, byte lodIndex, float cellSize,
            ref IList<Vertex> verts, ref IList<int> indices, ref RegularCache cache)
        {
            int lodScale = 1 << lodIndex;
            int last = 15 * lodScale;
            byte directionMask = (byte)((xyz.X > 0 ? 1 : 0) | ((xyz.Y > 0 ? 1 : 0) << 1) | ((xyz.Z > 0 ? 1 : 0) << 2));
            byte near = 0;

            // Compute which of the six faces of the block that the vertex
            // is near. (near is defined as being in boundary cell.)
            for (int i = 0; i < 3; i++)
            {
                //Vertex close to negative face.
                if (min[i] == 0) { near |= (byte)(1 << (i * 2 + 0)); }
                //Vertex close to positive face.
                if (min[i] == last) { near |= (byte)(1 << (i * 2 + 1)); }
            }

            Vector3i[] cornerPositions = Tables.CornerIndex;
            for (int i = 0; i < cornerPositions.Length; i++)
            {
                cornerPositions[i] = min + cornerPositions[i] * lodScale;
            }

            //  new Vector3i[]
            //      {
            //          min + new Vector3i(0, 0, 0)*lodScale,
            //          min + new Vector3i(1, 0, 0)*lodScale,
            //          min + new Vector3i(0, 1, 0)*lodScale,
            //          min + new Vector3i(1, 1, 0)*lodScale,
            //
            //          min + new Vector3i(0, 0, 1)*lodScale,
            //          min + new Vector3i(1, 0, 1)*lodScale,
            //          min + new Vector3i(0, 1, 1)*lodScale,
            //          min + new Vector3i(1, 1, 1)*lodScale
            //      };

            Vector3i dif = cornerPositions[7] - cornerPositions[1];

            // Retrieve sample values for all the corners.
            sbyte[] cornerSamples =
                new sbyte[]
                    {
                        samples[cornerPositions[0]],
                        samples[cornerPositions[1]],
                        samples[cornerPositions[2]],
                        samples[cornerPositions[3]],
                        samples[cornerPositions[4]],
                        samples[cornerPositions[5]],
                        samples[cornerPositions[6]],
                        samples[cornerPositions[7]],
                    };

            Vector3f[] cornerNormals = new Vector3f[8];

            // Determine the index into the edge table which
            // tells us which vertices are inside of the surface
            uint caseCode = (uint)(((cornerSamples[0] >> 7) & 0x01)
                                 | ((cornerSamples[1] >> 6) & 0x02)
                                 | ((cornerSamples[2] >> 5) & 0x04)
                                 | ((cornerSamples[3] >> 4) & 0x08)
                                 | ((cornerSamples[4] >> 3) & 0x10)
                                 | ((cornerSamples[5] >> 2) & 0x20)
                                 | ((cornerSamples[6] >> 1) & 0x40)
                                 | (cornerSamples[7] & 0x80));

            cache[xyz].CaseIndex = (byte)caseCode;
            if ((caseCode ^ ((cornerSamples[7] >> 7) & 0xff)) == 0)
                return 0;

            // Compute the normals at the cell corners using central difference.
            for (int i = 0; i < 8; ++i)
            {
                var p = cornerPositions[i];
                float nx = (samples[p + Vector3i.UnitX] - samples[p - Vector3i.UnitX]) * 0.5f;
                float ny = (samples[p + Vector3i.UnitY] - samples[p - Vector3i.UnitY]) * 0.5f;
                float nz = (samples[p + Vector3i.UnitZ] - samples[p - Vector3i.UnitZ]) * 0.5f;
                cornerNormals[i] = new Vector3f(nx, ny, nz);
                cornerNormals[i].Normalize();
            }

            var c = Tables.RegularCellClass[caseCode];
            var data = Tables.RegularCellData[c];

            byte nt = (byte)data.GetTriangleCount();
            byte nv = (byte)data.GetVertexCount();

            int[] localVertexMapping = new int[12];

            var vert = new Vertex();
            vert.Near = near;
            // Generate all the vertex positions by interpolating along
            // each of the edges that intersect the isosurface.
            for (int i = 0; i < nv; i++)
            {
                ushort edgeCode = Tables.RegularVertexData[caseCode][i];
                byte v0 = HiNibble((byte)(edgeCode & 0xFF));
                byte v1 = LoNibble((byte)(edgeCode & 0xFF));

                Vector3i p0 = cornerPositions[v0];
                Vector3i p1 = cornerPositions[v1];
                Vector3f n0 = cornerNormals[v0];
                Vector3f n1 = cornerNormals[v1];

                int d0 = samples[p0];
                int d1 = samples[p1];

                Debug.Assert(v0 < v1);

                int t = (d1 << 8) / (d1 - d0);
                int u = 0x0100 - t;

                float t0 = t * S;
                float t1 = u * S;

                if ((t & 0x00ff) != 0)
                {
                    // Vertex lies in the interior of the edge.
                    byte dir = HiNibble((byte)(edgeCode >> 8));
                    byte idx = LoNibble((byte)(edgeCode >> 8));
                    bool present = (dir & directionMask) == dir;

                    if (present)
                    {
                        var prev = cache[xyz + PrevOffset(dir)];

                        // I don't think this can happen for non-corner vertices.
                        if (prev.CaseIndex == 0 || prev.CaseIndex == 255)
                        {
                            localVertexMapping[i] = -1;
                        }
                        else
                        {
                            localVertexMapping[i] = prev.Verts[idx];
                        }
                    }
                    if (!present || localVertexMapping[i] < 0)
                    {
                        localVertexMapping[i] = verts.Count;
                        Vector3f pi = Interp(p0, p1, p0, p1, samples, lodIndex);
                        vert.Primary = offset + pi;
                        vert.Normal = n0 * t0 + n1 * t1;

                        if (near > 0)
                        {
                            Vector3f delta = ComputeDelta(pi, lodIndex, 16);
                            vert.Secondary = vert.Primary + ProjectNormal(vert.Normal, delta);
                        }
                        else
                        {
                            // The vertex is not in a boundary cell, so the
                            // secondary position will never be used.
                            vert.Secondary = Unused; //vert.Primary;
                        }
                        verts.Add(vert);

                        if ((dir & 8) != 0)
                        {
                            // Store the generated vertex so that other cells can reuse it.
                            cache[xyz].Verts[idx] = localVertexMapping[i];
                        }
                    }
                }
                else if (t == 0 && v1 == 7)
                {
                    // This cell owns the vertex, so it should be created.
                    localVertexMapping[i] = verts.Count;
                    Vector3f pi = (Vector3f)p1 * t0 + (Vector3f)p1 * t1;

                    vert.Primary = offset + pi;
                    vert.Normal = n0 * t0 + n1 * t1;

                    if (near > 0)
                    {
                        Vector3f delta = ComputeDelta(pi, lodIndex, 16);
                        vert.Secondary = vert.Primary + ProjectNormal(vert.Normal, delta);
                    }
                    else
                    {
                        // The vertex is not in a boundary cell, so the secondary
                        // position will never be used.
                        vert.Secondary = Unused;
                    }
                    verts.Add(vert);
                    cache[xyz].Verts[0] = localVertexMapping[i];
                }
                else
                {
                    // A 3-bit direction code leading to the proper cell can easily be obtained by
                    // inverting the 3-bit corner index (bitwise, by exclusive ORing with the number 7).
                    // The corner index depends on the value of t, t = 0 means that we're at the higher
                    // numbered endpoint.
                    byte dir = t == 0 ? (byte)(v1 ^ 7) : (byte)(v0 ^ 7);
                    bool present = (dir & directionMask) == dir;

                    if (present)
                    {
                        var prev = cache[xyz + PrevOffset(dir)];

                        // The previous cell might not have any geometry, and we
                        // might therefore have to create a new vertex anyway.
                        if (prev.CaseIndex == 0 || prev.CaseIndex == 255)
                        {
                            localVertexMapping[i] = -1;
                        }
                        else
                        {
                            localVertexMapping[i] = prev.Verts[0];
                        }
                    }

                    if (!present || (localVertexMapping[i] < 0))
                    {
                        localVertexMapping[i] = verts.Count;

                        Vector3f pi = (Vector3f)p0 * t0 + (Vector3f)p1 * t1;
                        vert.Primary = offset + pi;
                        vert.Normal = n0 * t0 + n1 * t1;

                        if (near > 0)
                        {
                            Vector3f delta = ComputeDelta(pi, lodIndex, 16);
                            vert.Secondary = vert.Primary + ProjectNormal(vert.Normal, delta);
                        }
                        else
                        {
                            vert.Secondary = Unused;
                        }
                        verts.Add(vert);
                    }
                }
            }

            for (int t = 0; t < nt; t++)
            {
                for (int i = 0; i < 3; i++)
                {
                    indices.Add(localVertexMapping[data.Indizes()[t * 3 + i]]);
                }
            }

            return nt;
        }
コード例 #14
0
        internal void PolygonizeCell(Vector3i offsetPos, Vector3i pos, ref Mesh mesh, int lod)
        {
            Debug.Assert(lod >= 1, "Level of Detail must be greater than 1");
            offsetPos += pos * lod;

            byte directionMask = (byte)((pos.X > 0 ? 1 : 0) | ((pos.Z > 0 ? 1 : 0) << 1) | ((pos.Y > 0 ? 1 : 0) << 2));

            sbyte[] density = new sbyte[8];

            for (int i = 0; i < density.Length; i++)
            {
                density[i] = volume[offsetPos + Tables.CornerIndex[i] * lod];
            }

            byte caseCode = getCaseCode(density);
            if ((caseCode ^ ((density[7] >> 7) & 0xFF)) == 0) //for this cases there is no triangulation
                return;

            Vector3f[] cornerNormals = new Vector3f[8];
            for (int i = 0; i < 8; i++)
            {
                var p = offsetPos + Tables.CornerIndex[i] * lod;
                float nx = (volume[p + Vector3i.UnitX] - volume[p - Vector3i.UnitX]) * 0.5f;
                float ny = (volume[p + Vector3i.UnitY] - volume[p - Vector3i.UnitY]) * 0.5f;
                float nz = (volume[p + Vector3i.UnitZ] - volume[p - Vector3i.UnitZ]) * 0.5f;
                //cornerNormals[i] = new Vector3f(nx, ny, nz);

                cornerNormals[i].X = nx;
                cornerNormals[i].Y = ny;
                cornerNormals[i].Z = nz;
                cornerNormals[i].Normalize();
            }

            byte regularCellClass = Tables.RegularCellClass[caseCode];
            ushort[] vertexLocations = Tables.RegularVertexData[caseCode];

            Tables.RegularCell c = Tables.RegularCellData[regularCellClass];
            long vertexCount = c.GetVertexCount();
            long triangleCount = c.GetTriangleCount();
            byte[] indexOffset = c.Indizes(); //index offsets for current cell
            ushort[] mappedIndizes = new ushort[indexOffset.Length]; //array with real indizes for current cell

            for (int i = 0; i < vertexCount; i++)
            {
                byte edge = (byte)(vertexLocations[i] >> 8);
                byte reuseIndex = (byte)(edge & 0xF); //Vertex id which should be created or reused 1,2 or 3
                byte rDir = (byte)(edge >> 4); //the direction to go to reach a previous cell for reusing

                byte v1 = (byte)((vertexLocations[i]) & 0x0F); //Second Corner Index
                byte v0 = (byte)((vertexLocations[i] >> 4) & 0x0F); //First Corner Index

                sbyte d0 = density[v0];
                sbyte d1 = density[v1];

                //Vector3f n0 = cornerNormals[v0];
                //Vector3f n1 = cornerNormals[v1];

                Debug.Assert(v1 > v0);

                int t = (d1 << 8) / (d1 - d0);
                int u = 0x0100 - t;
                float t0 = t / 256f;
                float t1 = u / 256f;

                int index = -1;

                if (UseCache && v1 != 7 && (rDir & directionMask) == rDir)
                {
                    Debug.Assert(reuseIndex != 0);
                    ReuseCell cell = cache.GetReusedIndex(pos, rDir);
                    index = cell.Verts[reuseIndex];
                }

                if (index == -1)
                {
                    Vector3f normal = cornerNormals[v0] * t0 + cornerNormals[v1] * t1;
                    GenerateVertex(ref offsetPos, ref pos, mesh, lod, t, ref v0, ref v1, ref d0, ref d1, normal);
                    index = mesh.LatestAddedVertIndex();
                }

                if ((rDir & 8) != 0)
                {
                    cache.SetReusableIndex(pos, reuseIndex, mesh.LatestAddedVertIndex());
                }

                mappedIndizes[i] = (ushort)index;
            }

            for (int t = 0; t < triangleCount; t++)
            {
                for (int i = 0; i < 3; i++)
                {
                    mesh.AddIndex(mappedIndizes[c.Indizes()[t * 3 + i]]);
                }
            }
        }
コード例 #15
0
 public static Vector3f Max(Vector3f v1, Vector3f v2)
 {
     if (v1 >= v2) { return v1; }
     return v2;
 }
コード例 #16
0
 public static double Angle(Vector3f v1, Vector3f v2)
 {
     return
        (
       System.Math.Acos
       (
          Normalize(v1).Dot(Normalize(v2))
       )
        );
 }
コード例 #17
0
 public static Vector3f Min(Vector3f v1, Vector3f v2)
 {
     if (v1 <= v2) { return v1; }
     return v2;
 }
コード例 #18
0
 public static Vector3f Cross(Vector3f v1, Vector3f v2)
 {
     return
     (
        new Vector3f
        (
           v1.Y * v2.Z - v1.Z * v2.Y,
           v1.Z * v2.X - v1.X * v2.Z,
           v1.X * v2.Y - v1.Y * v2.X
        )
     );
 }
コード例 #19
0
 public void Add(Vector3f v)
 {
     this += v;
 }
コード例 #20
0
 public static float Distance(Vector3f v1, Vector3f v2)
 {
     return (float)System.Math.Sqrt(DistanceSquared(v1, v2));
 }
コード例 #21
0
 public float DistanceSquared(Vector3f v)
 {
     return DistanceSquared(this, v);
 }
コード例 #22
0
 public static float DistanceSquared(Vector3f v1, Vector3f v2)
 {
     return (v1.X - v2.X)*(v1.X - v2.X) +
            (v1.Y - v2.Y)*(v1.Y - v2.Y) +
            (v1.Z - v2.Z)*(v1.Z - v2.Z);
 }
コード例 #23
0
 public float Dot(Vector3f v)
 {
     return Dot(this, v);
 }
コード例 #24
0
 public static float Dot(Vector3f v1, Vector3f v2)
 {
     return
     (
        v1.X * v2.X +
        v1.Y * v2.Y +
        v1.Z * v2.Z
     );
 }
コード例 #25
0
 public Vector3f Lerp(Vector3f other, float control)
 {
     return Lerp(this, other, control);
 }
コード例 #26
0
 public static bool IsUnitVector(Vector3f v)
 {
     return v.MagnitudeSquare == 1;
 }
コード例 #27
0
 public Vector3f Min(Vector3f other)
 {
     return Min(this, other);
 }
コード例 #28
0
        public static Vector3f Lerp(Vector3f v1, Vector3f v2, float control)
        {
            if (control > 1 || control < 0)
            {
                // Error message includes information about the actual value of the
                // argument
                throw new ArgumentOutOfRangeException("control", "Must be between 0 and 1");
            }

            return
            (
               new Vector3f
               (
                   v1.X * (1 - control) + v2.X * control,
                   v1.Y * (1 - control) + v2.Y * control,
                   v1.Z * (1 - control) + v2.Z * control
                )
            );
        }
コード例 #29
0
 public void Sub(Vector3f v)
 {
     this -= v;
 }
コード例 #30
0
        private void GenerateVertex(ref Vector3i offsetPos, ref Vector3i pos, Mesh mesh, int lod, long t, ref byte v0, ref byte v1, ref sbyte d0, ref sbyte d1, Vector3f normal)
        {
            Vector3i iP0 = (offsetPos + Tables.CornerIndex[v0] * lod);
            Vector3f P0;// = new Vector3f(iP0.X, iP0.Y, iP0.Z);
            P0.X = iP0.X;
            P0.Y = iP0.Y;
            P0.Z = iP0.Z;

            Vector3i iP1 = (offsetPos + Tables.CornerIndex[v1] * lod);
            Vector3f P1;// = new Vector3f(iP1.X, iP1.Y, iP1.Z);
            P1.X = iP1.X;
            P1.Y = iP1.Y;
            P1.Z = iP1.Z;

            //EliminateLodPositionShift(lod, ref d0, ref d1, ref t, ref iP0, ref P0, ref iP1, ref P1);

            Vector3f Q = InterpolateVoxelVector(t, P0, P1);

            mesh.AddVertex(Q, normal);
        }