Exemple #1
0
        public static CarveMesh PerformCSG(double[] firstVerts, int[] firstFaceIndices, int[] firstFaceSizes,
                                           double[] secondVerts, int[] secondFaceIndices, int[] secondFaceSizes,
                                           CSGOperations operation)
        {
            CarveMesh finalResult = null;

            unsafe
            {
                InteropMesh a = new InteropMesh();
                InteropMesh b = new InteropMesh();

                InteropMesh *result;

                fixed(double *aVerts = &firstVerts[0], bVerts = &secondVerts[0])
                {
                    fixed(int *aFaces = &firstFaceIndices[0], bFaces = &secondFaceIndices[0])
                    {
                        fixed(int *aFSizes = &firstFaceSizes[0], bFSizes = &secondFaceSizes[0])
                        {
                            a.numVertices    = firstVerts.Length;
                            a.numFaceIndices = firstFaceIndices.Length;
                            a.vertices       = aVerts;
                            a.faceIndices    = aFaces;
                            a.faceSizes      = aFSizes;
                            a.numFaces       = firstFaceSizes.Length;

                            b.numVertices    = secondVerts.Length;
                            b.numFaceIndices = secondFaceIndices.Length;
                            b.vertices       = bVerts;
                            b.faceIndices    = bFaces;
                            b.faceSizes      = bFSizes;
                            b.numFaces       = secondFaceSizes.Length;

                            try
                            {
                                result = performCSG(&a, &b, operation);
                            }

                            catch (SEHException ex)
                            {
                                ArgumentException e = new ArgumentException("Carve has thrown an error. Possible reason is corrupt or self-intersecting meshes", ex);
                                throw e;
                            }
                        }
                    }
                }

                if (result->numVertices == 0)
                {
                    freeMesh(result);
                    return(null);
                }


                finalResult = new CarveMesh();

                finalResult.Vertices    = new double[result->numVertices];
                finalResult.FaceIndices = new int[result->numFaceIndices];
                finalResult.FaceSizes   = new int[result->numFaces];

                if (result->numVertices > 0)
                {
                    Parallel.For(0, finalResult.Vertices.Length, i =>
                    {
                        finalResult.Vertices[i] = result->vertices[i];
                    });
                }

                if (result->numFaceIndices > 0)
                {
                    Parallel.For(0, finalResult.FaceIndices.Length, i =>
                    {
                        finalResult.FaceIndices[i] = result->faceIndices[i];
                    });
                }

                if (result->numFaces > 0)
                {
                    Parallel.For(0, finalResult.FaceSizes.Length, i =>
                    {
                        finalResult.FaceSizes[i] = result->faceSizes[i];
                    });
                }

                freeMesh(result);
            }   // end-unsafe

            return(finalResult);
        }
Exemple #2
0
        public static TetgenMesh Tetrahedralize(double[] vertList, int[] faceIndexList, int[] faceSizesList, TetgenBehaviour beh)
        {
            TetgenMesh finalResult = null;

            unsafe
            {
                InteropMesh  a      = new InteropMesh();
                InteropMesh *result = null;

                fixed(double *aVerts = &vertList[0])
                {
                    fixed(int *aFaces = &faceIndexList[0])
                    {
                        fixed(int *aFSizes = &faceSizesList[0])
                        {
                            a.numVertices    = vertList.Length / 3;
                            a.numFaceIndices = faceIndexList.Length;
                            a.vertices       = aVerts;
                            a.faceIndices    = aFaces;
                            a.faceSizes      = aFSizes;
                            a.numFaces       = faceSizesList.Length;

                            System.Console.WriteLine(string.Format("Num verts: {0}", a.numVertices));
                            System.Console.WriteLine(string.Format("Num face indices: {0}", a.numFaceIndices));
                            System.Console.WriteLine(string.Format("Num faces: {0}", a.numFaces));

                            TetgenBehaviourUnsafe bu = new TetgenBehaviourUnsafe();

                            bu.plc              = beh.plc;
                            bu.quality          = beh.quality;
                            bu.optlevel         = beh.optlevel;
                            bu.optmaxdihedral   = beh.optmaxdihedral;
                            bu.optminslidihed   = beh.optminslidihed;
                            bu.optminsmtdihed   = beh.optminsmtdihed;
                            bu.coarsen          = beh.coarsen;
                            bu.maxvolume        = beh.maxvolume;
                            bu.minratio         = beh.minratio;
                            bu.mindihedral      = beh.mindihedral;
                            bu.insertaddpoints  = beh.insertaddpoints;
                            bu.refine           = beh.refine;
                            bu.supsteiner_level = beh.supsteiner_level;


                            //try
                            //{
                            result = performTetgen(&a, &bu);
                            //}

                            //catch (SEHException ex)
                            //{
                            //    System.Console.WriteLine(ex.Message);
                            //    System.Console.WriteLine(ex.StackTrace);
                            //    System.Console.ReadLine();

                            //ArgumentException e = new ArgumentException("Tetgen has thrown an error. Possible reason is corrupt or self-intersecting meshes", ex);
                            //throw e;
                            //}
                        }
                    }
                }

                if (result == null)
                {
                    System.Console.WriteLine("Result is null.");
                    return(null);
                }

                if (result->numVertices == 0)
                {
                    freeMesh(result);
                    return(null);
                }
                finalResult = new TetgenMesh();

                finalResult.Vertices     = new double[result->numVertices * 3];
                finalResult.FaceIndices  = new int[result->numFaceIndices];
                finalResult.FaceSizes    = new int[result->numFaces];
                finalResult.TetraIndices = new int[result->numTetra * 4];
                finalResult.EdgeIndices  = new int[result->numEdges * 2];

                if (result->numVertices > 0)
                {
                    Parallel.For(0, finalResult.Vertices.Length, i =>
                    {
                        finalResult.Vertices[i] = result->vertices[i];
                    });
                }

                if (result->numFaceIndices > 0)
                {
                    Parallel.For(0, finalResult.FaceIndices.Length, i =>
                    {
                        finalResult.FaceIndices[i] = result->faceIndices[i];
                    });
                }

                if (result->numFaces > 0)
                {
                    Parallel.For(0, finalResult.FaceSizes.Length, i =>
                    {
                        finalResult.FaceSizes[i] = result->faceSizes[i];
                    });
                }

                if (result->numTetra > 0)
                {
                    Parallel.For(0, finalResult.TetraIndices.Length, i =>
                    {
                        finalResult.TetraIndices[i] = result->tetra[i];
                    });
                }

                if (result->numEdges > 0)
                {
                    Parallel.For(0, finalResult.EdgeIndices.Length, i =>
                    {
                        finalResult.EdgeIndices[i] = result->edges[i];
                    });
                }

                //freeMesh(result);
            }   // end-unsafe

            return(finalResult);
        }
Exemple #3
0
 private static unsafe extern InteropMesh *performCSG(ref InteropMesh a, ref InteropMesh b, CSGOperations op);
Exemple #4
0
        /// <summary>
        /// Performs the specified operation on the provided meshes.
        /// </summary>
        /// <param name="first">The first mesh</param>
        /// <param name="second">The second mesh</param>
        /// <param name="operation">The mesh opration to perform on the two meshes</param>
        /// <returns>A triangular mesh resulting from performing the specified operation. If the resulting mesh is empty, will return null.</returns>
        public static Mesh3 PerformCSG(Mesh3 first, Mesh3 second, CSGOperations operation)
        {
            Mesh3 finalResult = null;

            unsafe
            {
                InteropMesh a            = new InteropMesh();
                InteropMesh b            = new InteropMesh();
                Vector3[]   aTransformed = first.GetTransformedVertices();
                Vector3[]   bTransformed = second.GetTransformedVertices();

                InteropMesh *result;

                fixed(Vector3 *aVerts = &aTransformed[0], bVerts = &bTransformed[0])
                {
                    fixed(int *aTris = &first.TriangleIndices[0], bTris = &second.TriangleIndices[0])
                    {
                        a.vertsArrayLength = first.Vertices.Length * 3;
                        a.triArrayLength   = first.TriangleIndices.Length;
                        a.vertices         = (double *)aVerts;
                        a.triangleIndices  = aTris;

                        b.vertsArrayLength = second.Vertices.Length * 3;
                        b.triArrayLength   = second.TriangleIndices.Length;
                        b.vertices         = (double *)bVerts;
                        b.triangleIndices  = bTris;

                        try
                        {
                            result = performCSG(ref a, ref b, operation);
                        }
                        catch (SEHException ex)
                        {
                            ArgumentException e = new ArgumentException("Carve has thrown an error. Possible reason is corrupt or self-intersecting meshes", ex);
                            throw e;
                        }
                    }
                }

                if (result->vertsArrayLength == 0)
                {
                    freeMesh(result);
                    return(null);
                }

                Vector3[] vertices        = new Vector3[result->vertsArrayLength / 3];
                int[]     triangleIndices = new int[result->triArrayLength];

                // Copy the results back in parallel
                Parallel.For(0, vertices.Length, i =>
                {
                    vertices[i] = new Vector3(result->vertices[3 * i], result->vertices[3 * i + 1], result->vertices[3 * i + 2]);
                });

                Parallel.For(0, triangleIndices.Length, i =>
                {
                    triangleIndices[i] = result->triangleIndices[i];
                });

                // If none of the vertices had colors, return whatever we have
                if (!first.HasColours && !second.HasColours)
                {
                    finalResult = new Mesh3(vertices, triangleIndices);
                    freeMesh(result);
                }
                else // Assign colors to the resulting mesh
                {
                    uint[] colors   = new uint[vertices.Length];
                    uint   grayCode = 4286611584; // The uint value of the color gray (representing no color)

                    // Assign the default gray to all vertices
                    Parallel.For(0, colors.Length, i =>
                    {
                        colors[i] = grayCode;
                    });

                    #region Worst practices of parallel coding

                    /**
                     * The procedure for color matching is creating a map of (vertex=>color) and then
                     * comparing all vertices of the resulting mesh (in parallel) with this map and
                     * assigning colors as necessary
                     */
                    if (first.HasColours)
                    {
                        ConcurrentDictionary <Vector3, uint> firstMap = new ConcurrentDictionary <Vector3, uint>();

                        // Create vertex to color map
                        Parallel.For(0, aTransformed.Length, i =>
                        {
                            firstMap[aTransformed[i]] = first.VertexColours[i];
                        });

                        // Assign colors
                        Parallel.For(0, vertices.Length, i =>
                        {
                            if (firstMap.ContainsKey(vertices[i]))
                            {
                                colors[i] = firstMap[vertices[i]];
                            }
                        });
                    }

                    if (second.HasColours)
                    {
                        ConcurrentDictionary <Vector3, uint> secondMap = new ConcurrentDictionary <Vector3, uint>();

                        Parallel.For(0, bTransformed.Length, i =>
                        {
                            secondMap[bTransformed[i]] = second.VertexColours[i];
                        });

                        Parallel.For(0, vertices.Length, i =>
                        {
                            if (secondMap.ContainsKey(vertices[i]))
                            {
                                colors[i] = secondMap[vertices[i]];
                            }
                        });
                    }
                    #endregion

                    finalResult = new Mesh3(vertices, triangleIndices, colors);
                }
            } // end-unsafe

            Matrix3 transform = first.Transform.Invert();
            finalResult = new Mesh3(finalResult.Vertices.Select(x => transform.Transform(x - first.Position)).ToArray(),
                                    finalResult.TriangleIndices, finalResult.VertexColours);
            finalResult.Position  = first.Position;
            finalResult.Transform = first.Transform;
            return(finalResult);
        }
Exemple #5
0
        /// <summary>
        /// Performs the specified operation on the provided meshes.
        /// </summary>
        /// <param name="first">The first mesh</param>
        /// <param name="second">The second mesh</param>
        /// <param name="operation">The mesh opration to perform on the two meshes</param>
        /// <returns>A triangular mesh resulting from performing the specified operation. If the resulting mesh is empty, will return null.</returns>
        public static Tuple <int[], double[]> PerformCSG(int[] t1, int[] t2, double[] v1, double[] v2, CSGOperations operation)
        {
            Tuple <int[], double[]> finalResult = null;

            unsafe
            {
                InteropMesh a = new InteropMesh();
                InteropMesh b = new InteropMesh();

                InteropMesh *result;


                fixed(double *aVerts = &v1[0], bVerts = &v2[0])
                {
                    fixed(int *aTris = &t1[0], bTris = &t2[0])
                    {
                        a.vertsArrayLength = v1.Length;
                        a.triArrayLength   = t1.Length;
                        a.vertices         = (double *)aVerts;
                        a.triangleIndices  = aTris;

                        b.vertsArrayLength = v2.Length;
                        b.triArrayLength   = t2.Length;
                        b.vertices         = (double *)bVerts;
                        b.triangleIndices  = bTris;
                    }
                }

                try
                {
                    result = performCSG(ref a, ref b, operation);
                }
                catch (SEHException ex)
                {
                    ArgumentException e = new ArgumentException("Carve has thrown an error. Possible reason is corrupt or self-intersecting meshes", ex);

                    throw e;
                }
                if (result->vertsArrayLength == 0)
                {
                    freeMesh(result);
                    return(null);
                }

                double[] vertices        = new double[result->vertsArrayLength];
                int[]    triangleIndices = new int[result->triArrayLength];

                // Copy the results back in parallel
                for (int i = 0; i < vertices.Length; i++)
                {
                    vertices[i] = result->vertices[i];
                }

                for (int i = 0; i < triangleIndices.Length; i++)
                {
                    triangleIndices[i] = result->triangleIndices[i];
                }


                finalResult = Tuple.Create(triangleIndices, vertices);
                freeMesh(result);
            }   // end-unsafe

            return(finalResult);
        }