public void Generate()
        {
            append_mesh();

            AxisAlignedBox3i bounds = Voxels.GridBounds;

            bounds.Max -= Vector3i.One;

            int[] vertices = new int[4];

            foreach (Vector3i nz in Voxels.NonZeros())
            {
                check_counts_or_append(6, 2);

                Box3d cube = Box3d.UnitZeroCentered;
                cube.Center = (Vector3d)nz;

                for (int fi = 0; fi < 6; ++fi)
                {
                    // checks dependent on neighbours
                    Index3i nbr = nz + gIndices.GridOffsets6[fi];
                    if (bounds.Contains(nbr))
                    {
                        if (SkipInteriorFaces && Voxels.Get(nbr))
                        {
                            continue;
                        }
                    }
                    else if (CapAtBoundary == false)
                    {
                        continue;
                    }


                    int           ni = gIndices.BoxFaceNormals[fi];
                    Vector3f      n  = (Vector3f)(Math.Sign(ni) * cube.Axis(Math.Abs(ni) - 1));
                    NewVertexInfo vi = new NewVertexInfo(Vector3d.Zero, n);
                    if (ColorSourceF != null)
                    {
                        vi.c      = ColorSourceF(nz);
                        vi.bHaveC = true;
                    }
                    for (int j = 0; j < 4; ++j)
                    {
                        vi.v        = cube.Corner(gIndices.BoxFaces[fi, j]);
                        vertices[j] = cur_mesh.AppendVertex(vi);
                    }

                    Index3i t0 = new Index3i(vertices[0], vertices[1], vertices[2], Clockwise);
                    Index3i t1 = new Index3i(vertices[0], vertices[2], vertices[3], Clockwise);
                    cur_mesh.AppendTriangle(t0);
                    cur_mesh.AppendTriangle(t1);
                }
            }
        }
Пример #2
0
        public override MeshGenerator Generate()
        {
            vertices  = new VectorArray3d((NoSharedVertices) ? (4 * 6) : 8);
            uv        = new VectorArray2f(vertices.Count);
            normals   = new VectorArray3f(vertices.Count);
            triangles = new IndexArray3i(2 * 6);

            if (NoSharedVertices == false)
            {
                for (int i = 0; i < 8; ++i)
                {
                    vertices[i] = Box.Corner(i);
                    normals[i]  = (Vector3f)(vertices[i] - Box.Center[i]).Normalized;
                    uv[i]       = Vector2f.Zero; // what to do for UVs in this case ?!?
                }
                int ti = 0;
                for (int fi = 0; fi < 6; ++fi)
                {
                    triangles.Set(ti++,
                                  gIndices.BoxFaces[fi, 0], gIndices.BoxFaces[fi, 1], gIndices.BoxFaces[fi, 2], Clockwise);
                    triangles.Set(ti++,
                                  gIndices.BoxFaces[fi, 0], gIndices.BoxFaces[fi, 2], gIndices.BoxFaces[fi, 3], Clockwise);
                }
            }
            else
            {
                int        ti        = 0;
                int        vi        = 0;
                Vector2f[] square_uv = new Vector2f[4] {
                    Vector2f.Zero, new Vector2f(1, 0), new Vector2f(1, 1), new Vector2f(0, 1)
                };
                for (int fi = 0; fi < 6; ++fi)
                {
                    int      v0 = vi++; vi += 3;
                    int      ni = gIndices.BoxFaceNormals[fi];
                    Vector3f n  = (Vector3f)(Math.Sign(ni) * Box.Axis(Math.Abs(ni) - 1));
                    for (int j = 0; j < 4; ++j)
                    {
                        vertices[v0 + j] = Box.Corner(gIndices.BoxFaces[fi, j]);
                        normals[v0 + j]  = n;
                        uv[v0 + j]       = square_uv[j];
                    }

                    triangles.Set(ti++, v0, v0 + 1, v0 + 2, Clockwise);
                    triangles.Set(ti++, v0, v0 + 2, v0 + 3, Clockwise);
                }
            }

            return(this);
        }
Пример #3
0
        public override MeshGenerator Generate()
        {
            int N = EdgeVertices;   int Nm2 = N - 2;
            int NT = N - 1;
            int N2 = N * N;

            vertices  = new VectorArray3d((NoSharedVertices) ? (N2 * 6) : (8 + Nm2 * 12 + Nm2 * Nm2 * 6));
            uv        = new VectorArray2f(vertices.Count);
            normals   = new VectorArray3f(vertices.Count);
            triangles = new IndexArray3i(2 * NT * NT * 6);
            groups    = new int[triangles.Count];

            Vector3d[] boxvertices = Box.ComputeVertices();

            int vi = 0;
            int ti = 0;

            if (NoSharedVertices)
            {
                for (int fi = 0; fi < 6; ++fi)
                {
                    // get corner vertices
                    Vector3d v00   = boxvertices[gIndices.BoxFaces[fi, 0]];
                    Vector3d v01   = boxvertices[gIndices.BoxFaces[fi, 1]];
                    Vector3d v11   = boxvertices[gIndices.BoxFaces[fi, 2]];
                    Vector3d v10   = boxvertices[gIndices.BoxFaces[fi, 3]];
                    Vector3f faceN = Math.Sign(gIndices.BoxFaceNormals[fi]) * (Vector3f)Box.Axis(Math.Abs(gIndices.BoxFaceNormals[fi]) - 1);

                    // add vertex rows
                    int start_vi = vi;
                    for (int yi = 0; yi < N; ++yi)
                    {
                        double ty = (double)yi / (double)(N - 1);
                        for (int xi = 0; xi < N; ++xi)
                        {
                            double tx = (double)xi / (double)(N - 1);
                            normals[vi]    = faceN;
                            uv[vi]         = new Vector2f(tx, ty);
                            vertices[vi++] = bilerp(ref v00, ref v01, ref v11, ref v10, tx, ty);
                        }
                    }

                    // add faces
                    for (int y0 = 0; y0 < NT; ++y0)
                    {
                        for (int x0 = 0; x0 < NT; ++x0)
                        {
                            int i00 = start_vi + y0 * N + x0;
                            int i10 = start_vi + (y0 + 1) * N + x0;
                            int i01 = i00 + 1, i11 = i10 + 1;

                            groups[ti] = fi;
                            triangles.Set(ti++, i00, i01, i11, Clockwise);
                            groups[ti] = fi;
                            triangles.Set(ti++, i00, i11, i10, Clockwise);
                        }
                    }
                }
            }
            else
            {
                // construct integer coordinates
                Vector3i[] intvertices = new Vector3i[boxvertices.Length];
                for (int k = 0; k < boxvertices.Length; ++k)
                {
                    Vector3d v = boxvertices[k] - Box.Center;
                    intvertices[k] = new Vector3i(
                        v.x < 0 ? 0 : N - 1,
                        v.y < 0 ? 0 : N - 1,
                        v.z < 0 ? 0 : N - 1);
                }
                int[] faceIndicesV = new int[N2];

                // add edge vertices and store in this map
                // todo: don't use a map (?)  how do we do that, though...
                //   - each index is in range [0,N). If we have (i,j,k), then for a given
                //     i, we have a finite number of j and k (< 2N?).
                //     make N array of 2N length, key on i, linear search for matching j/k?
                Dictionary <Vector3i, int> edgeVerts = new Dictionary <Vector3i, int>();
                for (int fi = 0; fi < 6; ++fi)
                {
                    // get corner vertices
                    int c00 = gIndices.BoxFaces[fi, 0], c01 = gIndices.BoxFaces[fi, 1],
                        c11 = gIndices.BoxFaces[fi, 2], c10 = gIndices.BoxFaces[fi, 3];
                    Vector3d v00 = boxvertices[c00];  Vector3i vi00 = intvertices[c00];
                    Vector3d v01 = boxvertices[c01];  Vector3i vi01 = intvertices[c01];
                    Vector3d v11 = boxvertices[c11];  Vector3i vi11 = intvertices[c11];
                    Vector3d v10 = boxvertices[c10];  Vector3i vi10 = intvertices[c10];

                    Action <Vector3d, Vector3d, Vector3i, Vector3i> do_edge = (a, b, ai, bi) => {
                        for (int i = 0; i < N; ++i)
                        {
                            double   t    = (double)i / (double)(N - 1);
                            Vector3i vidx = lerp(ref ai, ref bi, t);
                            if (edgeVerts.ContainsKey(vidx) == false)
                            {
                                Vector3d v = Vector3d.Lerp(ref a, ref b, t);
                                normals[vi]     = (Vector3f)v.Normalized;
                                uv[vi]          = Vector2f.Zero;
                                edgeVerts[vidx] = vi;
                                vertices[vi++]  = v;
                            }
                        }
                    };
                    do_edge(v00, v01, vi00, vi01);
                    do_edge(v01, v11, vi01, vi11);
                    do_edge(v11, v10, vi11, vi10);
                    do_edge(v10, v00, vi10, vi00);
                }


                // now generate faces
                for (int fi = 0; fi < 6; ++fi)
                {
                    // get corner vertices
                    int c00 = gIndices.BoxFaces[fi, 0], c01 = gIndices.BoxFaces[fi, 1],
                        c11 = gIndices.BoxFaces[fi, 2], c10 = gIndices.BoxFaces[fi, 3];
                    Vector3d v00 = boxvertices[c00]; Vector3i vi00 = intvertices[c00];
                    Vector3d v01 = boxvertices[c01]; Vector3i vi01 = intvertices[c01];
                    Vector3d v11 = boxvertices[c11]; Vector3i vi11 = intvertices[c11];
                    Vector3d v10 = boxvertices[c10]; Vector3i vi10 = intvertices[c10];
                    Vector3f faceN = Math.Sign(gIndices.BoxFaceNormals[fi]) * (Vector3f)Box.Axis(Math.Abs(gIndices.BoxFaceNormals[fi]) - 1);

                    // add vertex rows, using existing vertices if we have them in map
                    for (int yi = 0; yi < N; ++yi)
                    {
                        double ty = (double)yi / (double)(N - 1);
                        for (int xi = 0; xi < N; ++xi)
                        {
                            double   tx   = (double)xi / (double)(N - 1);
                            Vector3i vidx = bilerp(ref vi00, ref vi01, ref vi11, ref vi10, tx, ty);
                            int      use_vi;
                            if (edgeVerts.TryGetValue(vidx, out use_vi) == false)
                            {
                                Vector3d v = bilerp(ref v00, ref v01, ref v11, ref v10, tx, ty);
                                use_vi           = vi++;
                                normals[use_vi]  = faceN;
                                uv[use_vi]       = new Vector2f(tx, ty);
                                vertices[use_vi] = v;
                            }
                            faceIndicesV[yi * N + xi] = use_vi;
                        }
                    }

                    // add faces
                    for (int y0 = 0; y0 < NT; ++y0)
                    {
                        int y1 = y0 + 1;
                        for (int x0 = 0; x0 < NT; ++x0)
                        {
                            int x1  = x0 + 1;
                            int i00 = faceIndicesV[y0 * N + x0];
                            int i01 = faceIndicesV[y0 * N + x1];
                            int i11 = faceIndicesV[y1 * N + x1];
                            int i10 = faceIndicesV[y1 * N + x0];

                            groups[ti] = fi;
                            triangles.Set(ti++, i00, i01, i11, Clockwise);
                            groups[ti] = fi;
                            triangles.Set(ti++, i00, i11, i10, Clockwise);
                        }
                    }
                }
            }

            return(this);
        }
Пример #4
0
        // ported from WildMagic5 Wm5ContBox3.cpp::MergeBoxes
        public static Box3d Merge(ref Box3d box0, ref Box3d box1)
        {
            // Construct a box that contains the input boxes.
            var box = new Box3d();

            // The first guess at the box center.  This value will be updated later
            // after the input box vertices are projected onto axes determined by an
            // average of box axes.
            box.Center = 0.5 * (box0.Center + box1.Center);

            // A box's axes, when viewed as the columns of a matrix, form a rotation
            // matrix.  The input box axes are converted to quaternions.  The average
            // quaternion is computed, then normalized to unit length.  The result is
            // the slerp of the two input quaternions with t-value of 1/2.  The result
            // is converted back to a rotation matrix and its columns are selected as
            // the merged box axes.
            Quaterniond q0 = new Quaterniond(), q1 = new Quaterniond();
            var         rot0 = new Matrix3d(ref box0.AxisX, ref box0.AxisY, ref box0.AxisZ, false);

            q0.SetFromRotationMatrix(ref rot0);
            var rot1 = new Matrix3d(ref box1.AxisX, ref box1.AxisY, ref box1.AxisZ, false);

            q1.SetFromRotationMatrix(ref rot1);
            if (q0.Dot(q1) < 0)
            {
                q1 = -q1;
            }

            Quaterniond q         = q0 + q1;
            double      invLength = 1.0 / Math.Sqrt(q.Dot(q));

            q = q * invLength;
            Matrix3d q_mat = q.ToRotationMatrix();

            box.AxisX = q_mat.Column(0); box.AxisY = q_mat.Column(1); box.AxisZ = q_mat.Column(2);              //q.ToRotationMatrix(box.Axis);

            // Project the input box vertices onto the merged-box axes.  Each axis
            // D[i] containing the current center C has a minimum projected value
            // min[i] and a maximum projected value max[i].  The corresponding end
            // points on the axes are C+min[i]*D[i] and C+max[i]*D[i].  The point C
            // is not necessarily the midpoint for any of the intervals.  The actual
            // box center will be adjusted from C to a point C' that is the midpoint
            // of each interval,
            //   C' = C + sum_{i=0}^2 0.5*(min[i]+max[i])*D[i]
            // The box extents are
            //   e[i] = 0.5*(max[i]-min[i])

            int      i, j;
            double   dot;
            var      vertex = new Vector3d[8];
            Vector3d pmin   = Vector3d.Zero;
            Vector3d pmax   = Vector3d.Zero;

            box0.ComputeVertices(vertex);
            for (i = 0; i < 8; ++i)
            {
                Vector3d diff = vertex[i] - box.Center;
                for (j = 0; j < 3; ++j)
                {
                    dot = box.Axis(j).Dot(ref diff);
                    if (dot > pmax[j])
                    {
                        pmax[j] = dot;
                    }
                    else if (dot < pmin[j])
                    {
                        pmin[j] = dot;
                    }
                }
            }

            box1.ComputeVertices(vertex);
            for (i = 0; i < 8; ++i)
            {
                Vector3d diff = vertex[i] - box.Center;
                for (j = 0; j < 3; ++j)
                {
                    dot = box.Axis(j).Dot(ref diff);
                    if (dot > pmax[j])
                    {
                        pmax[j] = dot;
                    }
                    else if (dot < pmin[j])
                    {
                        pmin[j] = dot;
                    }
                }
            }

            // [min,max] is the axis-aligned box in the coordinate system of the
            // merged box axes.  Update the current box center to be the center of
            // the new box.  Compute the extents based on the new center.
            for (j = 0; j < 3; ++j)
            {
                box.Center   += (0.5 * (pmax[j] + pmin[j])) * box.Axis(j);
                box.Extent[j] = 0.5 * (pmax[j] - pmin[j]);
            }

            return(box);
        }