예제 #1
0
        public void InitializeFromApply(DMesh3 mesh, IEnumerable <int> triangles)
        {
            initialize_buffers(mesh);
            bool has_groups = mesh.HasTriangleGroups;

            foreach (int tid in triangles)
            {
                if (!mesh.IsTriangle(tid))
                {
                    continue;
                }

                Index3i tv = mesh.GetTriangle(tid);
                bool    va = save_vertex(mesh, tv.a);
                bool    vb = save_vertex(mesh, tv.b);
                bool    vc = save_vertex(mesh, tv.c);

                Index4i tri = new Index4i(tv.a, tv.b, tv.c,
                                          has_groups ? mesh.GetTriangleGroup(tid) : DMesh3.InvalidID);
                RemovedT.Add(tid);
                Triangles.Add(tri);

                MeshResult result = mesh.RemoveTriangle(tid, true, false);
                if (result != MeshResult.Ok)
                {
                    throw new Exception("RemoveTrianglesMeshChange.Initialize: exception in RemoveTriangle(" + tid.ToString() + "): " + result.ToString());
                }
                Util.gDevAssert(mesh.IsVertex(tv.a) == va && mesh.IsVertex(tv.b) == vb && mesh.IsVertex(tv.c) == vc);
            }
        }
예제 #2
0
        public int AppendTriangle(int i, int j, int k, int g = -1)
        {
            int ti = Triangles.Length / 3;

            if (HasTriangleGroups)
            {
                FaceGroups.Add((g == -1) ? 0 : g);
            }
            Triangles.Add(i); Triangles.Add(j); Triangles.Add(k);
            return(ti);
        }
예제 #3
0
        public int AppendQuad(int i, int j, int k, int l, int g = -1)
        {
            int qi = Quads.Length / 4;

            if (HasFaceGroups)
            {
                FaceGroups.Add((g == -1) ? 0 : g);
            }
            Quads.Add(i); Quads.Add(j); Quads.Add(k); Quads.Add(l);
            return(qi);
        }
예제 #4
0
        public void InitializeFromExisting(DMesh3 mesh, IEnumerable <int> added_v, IEnumerable <int> added_t)
        {
            initialize_buffers(mesh);
            bool has_groups = mesh.HasTriangleGroups;

            if (added_v != null)
            {
                foreach (int vid in added_v)
                {
                    Util.gDevAssert(mesh.IsVertex(vid));
                    append_vertex(mesh, vid);
                }
            }

            foreach (int tid in added_t)
            {
                Util.gDevAssert(mesh.IsTriangle(tid));

                Index3i tv  = mesh.GetTriangle(tid);
                Index4i tri = new Index4i(tv.a, tv.b, tv.c,
                                          has_groups ? mesh.GetTriangleGroup(tid) : DMesh3.InvalidID);
                AddedT.Add(tid);
                Triangles.Add(tri);
            }
        }
예제 #5
0
        bool save_vertex(DMesh3 mesh, int vid, bool force = false)
        {
            if (force || mesh.VerticesRefCounts.refCount(vid) == 2)
            {
                RemovedV.Add(vid);
                Positions.Add(mesh.GetVertex(vid));
                if (Normals != null)
                {
                    Normals.Add(mesh.GetVertexNormal(vid));
                }

                if (Colors != null)
                {
                    Colors.Add(mesh.GetVertexColor(vid));
                }

                if (UVs != null)
                {
                    UVs.Add(mesh.GetVertexUV(vid));
                }

                return(false);
            }
            return(true);
        }
예제 #6
0
        public int AppendUV(Vector2f uv)
        {
            int id = UVs.Length;

            UVs.Add(uv);
            return(id);
        }
예제 #7
0
        public IOReadResult Read(BinaryReader reader, ReadOptions options, IMeshBuilder builder)
        {
            if (options.CustomFlags != null)
            {
                ParseArguments(options.CustomFlags);
            }

            /*byte[] header = */
            reader.ReadBytes(80);
            int totalTris = reader.ReadInt32();

            Objects = new List <STLSolid>();
            Objects.Add(new STLSolid());

            int    tri_size = 50;               // bytes
            IntPtr bufptr   = Marshal.AllocHGlobal(tri_size);
            var    tmp      = new stl_triangle();
            Type   tri_type = tmp.GetType();

            var tri_attribs = new DVector <short>();

            try
            {
                for (int i = 0; i < totalTris; ++i)
                {
                    byte[] tri_bytes = reader.ReadBytes(50);
                    if (tri_bytes.Length < 50)
                    {
                        break;
                    }

                    Marshal.Copy(tri_bytes, 0, bufptr, tri_size);
                    var tri = (stl_triangle)Marshal.PtrToStructure(bufptr, tri_type);

                    append_vertex(tri.ax, tri.ay, tri.az);
                    append_vertex(tri.bx, tri.by, tri.bz);
                    append_vertex(tri.cx, tri.cy, tri.cz);
                    tri_attribs.Add(tri.attrib);
                }
            }
            catch (Exception e)
            {
                return(new IOReadResult(IOCode.GenericReaderError, "exception: " + e.Message));
            }

            Marshal.FreeHGlobal(bufptr);

            if (Objects.Count == 1)
            {
                Objects[0].TriAttribs = tri_attribs;
            }

            foreach (STLSolid solid in Objects)
            {
                BuildMesh(solid, builder);
            }

            return(new IOReadResult(IOCode.Ok, ""));
        }
예제 #8
0
        public PackedSparseMatrix Square()
        {
            if (Rows.Length != Columns)
            {
                throw new Exception("PackedSparseMatrix.Square: matrix is not square!");
            }

            int N = Columns;

            var entries      = new DVector <matrix_entry>();
            var entries_lock = new SpinLock();

            gParallel.BlockStartEnd(0, N - 1, (r_start, r_end) =>
            {
                for (int r1i = r_start; r1i <= r_end; r1i++)
                {
                    // determine which entries of squared matrix might be nonzeros
                    var nbrs = new HashSet <int>();
                    nbrs.Add(r1i);
                    PackedSparseMatrix.nonzero[] row = Rows[r1i];
                    for (int k = 0; k < row.Length; ++k)
                    {
                        if (row[k].j > r1i)
                        {
                            nbrs.Add(row[k].j);
                        }

                        PackedSparseMatrix.nonzero[] row2 = Rows[row[k].j];
                        for (int j = 0; j < row2.Length; ++j)
                        {
                            if (row2[j].j > r1i)                                 // only compute lower-triangular entries
                            {
                                nbrs.Add(row2[j].j);
                            }
                        }
                    }

                    // compute them!
                    foreach (int c2i in nbrs)
                    {
                        double v = DotRowColumn(r1i, c2i, this);
                        if (Math.Abs(v) > MathUtil.ZeroTolerance)
                        {
                            bool taken = false;
                            entries_lock.Enter(ref taken);
                            entries.Add(new matrix_entry()
                            {
                                r = r1i, c = c2i, value = v
                            });
                            entries_lock.Exit();
                        }
                    }
                }
            });

            var R = new PackedSparseMatrix(entries, N, N, true);

            return(R);
        }
예제 #9
0
        /// <summary>
        /// insert val into list at list_index.
        /// </summary>
        public void Insert(int list_index, int val)
        {
            int block_ptr = list_heads[list_index];

            if (block_ptr == Null)
            {
                block_ptr = allocate_block();
                block_store[block_ptr] = 0;
                list_heads[list_index] = block_ptr;
            }

            int N = block_store[block_ptr];

            if (N < BLOCKSIZE)
            {
                block_store[block_ptr + N + 1] = val;
            }
            else
            {
                // spill to linked list
                int cur_head = block_store[block_ptr + BLOCK_LIST_OFFSET];

                if (free_head_ptr == Null)
                {
                    // allocate new linkedlist node
                    int new_ptr = linked_store.size;
                    linked_store.Add(val);
                    linked_store.Add(cur_head);
                    block_store[block_ptr + BLOCK_LIST_OFFSET] = new_ptr;
                }
                else
                {
                    // pull from free list
                    int free_ptr = free_head_ptr;
                    free_head_ptr              = linked_store[free_ptr + 1];
                    linked_store[free_ptr]     = val;
                    linked_store[free_ptr + 1] = cur_head;
                    block_store[block_ptr + BLOCK_LIST_OFFSET] = free_ptr;
                }
            }

            // count new element
            block_store[block_ptr] += 1;
        }
예제 #10
0
        /*
         * Construction
         */
        public int AppendVertex(double x, double y, double z)
        {
            int i = Vertices.Length / 3;

            if (HasVertexNormals)
            {
                Normals.Add(0); Normals.Add(1); Normals.Add(0);
            }
            if (HasVertexColors)
            {
                Colors.Add(1); Colors.Add(1); Colors.Add(1);
            }
            if (HasVertexUVs)
            {
                UVs.Add(0); UVs.Add(0);
            }
            Vertices.Add(x); Vertices.Add(y); Vertices.Add(z);
            return(i);
        }
예제 #11
0
 public T Allocate()
 {
     if (Free.size > 0)
     {
         T allocated = Free[Free.size - 1];
         Free.pop_back();
         return(allocated);
     }
     else
     {
         T newval = new T();
         Allocated.Add(newval);
         return(newval);
     }
 }
예제 #12
0
        // Appends a box that contains free triangles in one-ring of vertex vid.
        // If tri count is < spill threshold, push onto spill list instead.
        // Returns # of free tris found.
        int add_one_ring_box(int vid, byte[] used_triangles, int[] temp_tris,
                             ref int iBoxCur, ref int iIndicesCur,
                             DVector <int> spill, int nSpillThresh)
        {
            // collect free triangles
            int num_free = 0;

            foreach (int tid in mesh.VtxTrianglesItr(vid))
            {
                if (used_triangles[tid] == 0)
                {
                    temp_tris[num_free++] = tid;
                }
            }

            // none free, get out
            if (num_free == 0)
            {
                return(0);
            }

            // if we only had a couple free triangles, wait and see if
            // they get picked up by another vert
            if (num_free < nSpillThresh)
            {
                spill.Add(vid);
                return(num_free);
            }

            // append new box
            AxisAlignedBox3f box = AxisAlignedBox3f.Empty;
            int iBox             = iBoxCur++;

            box_to_index.insert(iIndicesCur, iBox);

            index_list.insert(num_free, iIndicesCur++);
            for (int i = 0; i < num_free; ++i)
            {
                index_list.insert(temp_tris[i], iIndicesCur++);
                used_triangles[temp_tris[i]]++;     // incrementing for sanity check below, just need to set to 1
                box.Contain(mesh.GetTriBounds(temp_tris[i]));
            }

            box_centers.insert(box.Center, iBox);
            box_extents.insert(box.Extents, iBox);
            return(num_free);
        }
예제 #13
0
 void append_vertex(DMesh3 mesh, int vid)
 {
     AddedV.Add(vid);
     Positions.Add(mesh.GetVertex(vid));
     if (Normals != null)
     {
         Normals.Add(mesh.GetVertexNormal(vid));
     }
     if (Colors != null)
     {
         Colors.Add(mesh.GetVertexColor(vid));
     }
     if (UVs != null)
     {
         UVs.Add(mesh.GetVertexUV(vid));
     }
 }
예제 #14
0
        // todo:
        //   remove
        //   clear


        public void rebuild_free_list()
        {
            free_indices = new DVector <int>();
            used_count   = 0;

            int N = ref_counts.Length;

            for (int i = 0; i < N; ++i)
            {
                if (ref_counts[i] > 0)
                {
                    used_count++;
                }
                else
                {
                    free_indices.Add(i);
                }
            }
        }
예제 #15
0
        public static PackedSparseMatrix FromDense(DenseMatrix m, bool bSymmetric)
        {
            var nonzeros = new DVector <matrix_entry>();

            for (int r = 0; r < m.Rows; ++r)
            {
                int nStop = (bSymmetric) ? r + 1 : m.Columns;
                for (int c = 0; c < nStop; ++c)
                {
                    if (m[r, c] != 0)
                    {
                        nonzeros.Add(new matrix_entry()
                        {
                            r = r, c = c, value = m[r, c]
                        });
                    }
                }
            }
            return(new PackedSparseMatrix(nonzeros, m.Rows, m.Columns, bSymmetric));
        }
예제 #16
0
        public int AppendNewVertex(DMesh3 mesh, int vid)
        {
            int idx = ModifiedV.Length;

            ModifiedV.Add(vid);
            OldPositions.Add(mesh.GetVertex(vid));
            NewPositions.Add(OldPositions[idx]);
            if (NewNormals != null)
            {
                OldNormals.Add(mesh.GetVertexNormal(vid));
                NewNormals.Add(OldNormals[idx]);
            }
            if (NewColors != null)
            {
                OldColors.Add(mesh.GetVertexColor(vid));
                NewColors.Add(OldColors[idx]);
            }
            if (NewUVs != null)
            {
                OldUVs.Add(mesh.GetVertexUV(vid));
                NewUVs.Add(OldUVs[idx]);
            }
            return(idx);
        }
예제 #17
0
        // strategy here is:
        //  1) partition triangles by vertex one-rings into leaf boxes
        //      1a) first pass where we skip one-rings that have < 3 free tris
        //      1b) second pass where we handle any missed tris
        //  2) sequentially combine N leaf boxes into (N/2 + N%2) layer 2 boxes
        //  3) repeat until layer K has only 1 box, which is root of tree
        void build_by_one_rings(ClusterPolicy ePolicy)
        {
            box_to_index = new DVector <int>();
            box_centers  = new DVector <Vector3f>();
            box_extents  = new DVector <Vector3f>();
            int iBoxCur = 0;

            index_list = new DVector <int>();
            int iIndicesCur = 0;

            // replace w/ BitArray ?
            byte[] used_triangles = new byte[mesh.MaxTriangleID];
            Array.Clear(used_triangles, 0, used_triangles.Length);

            // temporary buffer
            int nMaxEdgeCount = mesh.GetMaxVtxEdgeCount();

            int[] temp_tris = new int[2 * nMaxEdgeCount];

            // first pass: cluster by one-ring, but if # of free tris
            //  in a ring is small (< 3), push onto spill list to try again,
            //  because those tris might be picked up by a bigger cluster
            DVector <int> spill = new DVector <int>();

            foreach (int vid in mesh.VertexIndices())
            {
                int tCount = add_one_ring_box(vid, used_triangles, temp_tris,
                                              ref iBoxCur, ref iIndicesCur, spill, 3);
                if (tCount < 3)
                {
                    spill.Add(vid);
                }
            }

            // second pass: check any spill vertices. Most are probably gone
            // now, but a few stray triangles might still exist
            int N = spill.Length;

            for (int si = 0; si < N; ++si)
            {
                int vid = spill[si];
                add_one_ring_box(vid, used_triangles, temp_tris,
                                 ref iBoxCur, ref iIndicesCur, null, 0);
            }


            // [RMS] test code to make sure each triangle is in exactly one list
            //foreach ( int tid in mesh.TriangleIndices() ) {
            //    int n = used_triangles[tid];
            //    if (n != 1)
            //        Util.gBreakToDebugger();
            //}

            // keep track of where triangle lists end
            triangles_end = iIndicesCur;

            // this defines ClusterPolicy.Default
            //ClusterFunctionType clusterF = cluster_boxes;
            //ClusterFunctionType clusterF = cluster_boxes_matrix;
            ClusterFunctionType clusterF = cluster_boxes_nearsearch;

            if (ePolicy == ClusterPolicy.Fastest)
            {
                clusterF = cluster_boxes;
            }
            else if (ePolicy == ClusterPolicy.MinimalVolume)
            {
                clusterF = cluster_boxes_matrix;
            }
            else if (ePolicy == ClusterPolicy.FastVolumeMetric)
            {
                clusterF = cluster_boxes_nearsearch;
            }

            // ok, now repeatedly cluster current layer of N boxes into N/2 + N%2 boxes,
            // until we hit a 1-box layer, which is root of the tree
            int nPrevEnd   = iBoxCur;
            int nLayerSize = clusterF(0, iBoxCur, ref iBoxCur, ref iIndicesCur);
            int iStart     = nPrevEnd;
            int iCount     = iBoxCur - nPrevEnd;

            while (nLayerSize > 1)
            {
                nPrevEnd   = iBoxCur;
                nLayerSize = clusterF(iStart, iCount, ref iBoxCur, ref iIndicesCur);
                iStart     = nPrevEnd;
                iCount     = iBoxCur - nPrevEnd;
            }

            root_index = iBoxCur - 1;
        }
예제 #18
0
        private void append_face(string[] tokens, OBJMaterial activeMaterial, int nActiveGroup)
        {
            int nMode = 0;

            if (tokens[1].IndexOf("//") != -1)
            {
                nMode = 1;
            }
            else if (tokens[1].IndexOf('/') != -1)
            {
                nMode = 2;
            }

            var t = new Triangle();

            t.clear();
            for (int ti = 0; ti < tokens.Length - 1; ++ti)
            {
                int j = (ti < 3) ? ti : 2;
                if (ti >= 3)
                {
                    t.move_vertex(2, 1);
                }

                // parse next vertex
                if (nMode == 0)
                {
                    // "f v1 v2 v3"
                    t.set_vertex(j, parse_v(tokens[ti + 1]));
                }
                else if (nMode == 1)
                {
                    // "f v1//vn1 v2//vn2 v3//vn3"
                    string[] parts = tokens[ti + 1].Split(this.splitDoubleSlash, StringSplitOptions.RemoveEmptyEntries);
                    t.set_vertex(j, parse_v(parts[0]), parse_n(parts[1]));
                }
                else if (nMode == 2)
                {
                    string[] parts = tokens[ti + 1].Split(this.splitSlash, StringSplitOptions.RemoveEmptyEntries);
                    if (parts.Length == 2)
                    {
                        // "f v1/vt1 v2/vt2 v3/vt3"
                        t.set_vertex(j, parse_v(parts[0]), -1, parse_u(parts[1]));
                    }
                    else if (parts.Length == 3)
                    {
                        // "f v1/vt1/vn1 v2/vt2/vn2 v3/vt3/vn3"
                        t.set_vertex(j, parse_v(parts[0]), parse_n(parts[2]), parse_u(parts[1]));
                    }
                    else
                    {
                        emit_warning("parse_triangle unexpected face component " + tokens[j]);
                    }
                }


                // do append
                if (ti >= 2)
                {
                    if (activeMaterial != null)
                    {
                        t.nMaterialID = activeMaterial.id;
                        UsedMaterials[activeMaterial.id] = activeMaterial.name;
                    }
                    t.nGroupID = nActiveGroup;
                    vTriangles.Add(t);
                    if (t.is_complex())
                    {
                        HasComplexVertices = true;
                    }
                }
            }
        }
예제 #19
0
 public void Return(T obj)
 {
     Free.Add(obj);
 }
예제 #20
0
        public IOReadResult ParseInput(TextReader reader, ReadOptions options)
        {
            vPositions = new DVector <double>();
            vNormals   = new DVector <float>();
            vUVs       = new DVector <float>();
            vColors    = new DVector <float>();
            vTriangles = new DVector <Triangle>();

            bool        bVerticesHaveColors = false;
            int         nMaxUVLength        = 0;
            OBJMaterial activeMaterial      = null;

            var GroupNames    = new Dictionary <string, int>();
            int nGroupCounter = 0;
            int nActiveGroup  = Triangle.InvalidGroupID;

            int nLines = 0;

            while (reader.Peek() >= 0)
            {
                string line = reader.ReadLine();
                nLines++;
                string[] tokens = line.Split((char[])null, StringSplitOptions.RemoveEmptyEntries);
                if (tokens.Length == 0)
                {
                    continue;
                }

                // [RMS] this will hang VS on large models...
                //if (nWarningLevel >= 2)
                //    emit_warning("Parsing line " + line);
                try
                {
                    if (tokens[0][0] == 'v')
                    {
                        if (tokens[0].Length == 1)
                        {
                            if (tokens.Length == 7)
                            {
                                vPositions.Add(Double.Parse(tokens[1]));
                                vPositions.Add(Double.Parse(tokens[2]));
                                vPositions.Add(Double.Parse(tokens[3]));

                                vColors.Add(float.Parse(tokens[4]));
                                vColors.Add(float.Parse(tokens[5]));
                                vColors.Add(float.Parse(tokens[6]));
                                bVerticesHaveColors = true;
                            }
                            else if (tokens.Length >= 4)
                            {
                                vPositions.Add(Double.Parse(tokens[1]));
                                vPositions.Add(Double.Parse(tokens[2]));
                                vPositions.Add(Double.Parse(tokens[3]));
                            }
                            if (tokens.Length != 4 && tokens.Length != 7)
                            {
                                emit_warning("[OBJReader] vertex has unknown format: " + line);
                            }
                        }
                        else if (tokens[0][1] == 'n')
                        {
                            if (tokens.Length >= 4)
                            {
                                vNormals.Add(float.Parse(tokens[1]));
                                vNormals.Add(float.Parse(tokens[2]));
                                vNormals.Add(float.Parse(tokens[3]));
                            }
                            if (tokens.Length != 4)
                            {
                                emit_warning("[OBJReader] normal has more than 3 coordinates: " + line);
                            }
                        }
                        else if (tokens[0][1] == 't')
                        {
                            if (tokens.Length >= 3)
                            {
                                vUVs.Add(float.Parse(tokens[1]));
                                vUVs.Add(float.Parse(tokens[2]));
                                nMaxUVLength = Math.Max(nMaxUVLength, tokens.Length);
                            }
                            if (tokens.Length != 3)
                            {
                                emit_warning("[OBJReader] UV has unknown format: " + line);
                            }
                        }
                    }
                    else if (tokens[0][0] == 'f')
                    {
                        if (tokens.Length < 4)
                        {
                            emit_warning("[OBJReader] degenerate face specified : " + line);
                        }
                        else if (tokens.Length == 4)
                        {
                            var tri = new Triangle();
                            parse_triangle(tokens, ref tri);

                            tri.nGroupID = nActiveGroup;

                            if (activeMaterial != null)
                            {
                                tri.nMaterialID = activeMaterial.id;
                                UsedMaterials[activeMaterial.id] = activeMaterial.name;
                            }

                            vTriangles.Add(tri);
                            if (tri.is_complex())
                            {
                                HasComplexVertices = true;
                            }
                        }
                        else
                        {
                            append_face(tokens, activeMaterial, nActiveGroup);
                        }
                    }
                    else if (tokens[0][0] == 'g')
                    {
                        string sGroupName = (tokens.Length == 2) ? tokens[1] : line.Substring(line.IndexOf(tokens[1]));
                        if (GroupNames.ContainsKey(sGroupName))
                        {
                            nActiveGroup = GroupNames[sGroupName];
                        }
                        else
                        {
                            nActiveGroup           = nGroupCounter;
                            GroupNames[sGroupName] = nGroupCounter++;
                        }
                    }
                    else if (tokens[0][0] == 'o')
                    {
                        // TODO multi-object support
                    }
                    else if (tokens[0] == "mtllib" && options.ReadMaterials)
                    {
                        if (MTLFileSearchPaths.Count == 0)
                        {
                            emit_warning("Materials requested but Material Search Paths not initialized!");
                        }

                        string sMTLPathString = (tokens.Length == 2) ? tokens[1] :
                                                line.Substring(line.IndexOf(tokens[1]));
                        string sFile = FindMTLFile(sMTLPathString);
                        if (sFile != null)
                        {
                            IOReadResult result = ReadMaterials(sFile);
                            if (result.code != IOCode.Ok)
                            {
                                emit_warning("error parsing " + sFile + " : " + result.message);
                            }
                        }
                        else
                        {
                            emit_warning("material file " + sMTLPathString + " could not be found in material search paths");
                        }
                    }
                    else if (tokens[0] == "usemtl" && options.ReadMaterials)
                    {
                        activeMaterial = find_material(tokens[1]);
                    }
                }
                catch (Exception e)
                {
                    emit_warning("error parsing line " + nLines.ToString() + ": " + line + ", exception " + e.Message);
                }
            }

            m_bOBJHasPerVertexColors = bVerticesHaveColors;
            m_bOBJHasTriangleGroups  = (nActiveGroup != Triangle.InvalidGroupID);
            m_nSetInvalidGroupsTo    = nGroupCounter++;
            m_nUVComponents          = nMaxUVLength;

            return(new IOReadResult(IOCode.Ok, ""));
        }