コード例 #1
0
        /// <summary>
        /// This is the routine to convert the input node to polygon faces.
        /// </summary>
        /// <param name="nodeHandle"> Input the node by handle. </param>
        /// <param name="convertToTri"> Input whether to convert to a poly object first. </param>
        /// <param name="addShell"> Input whether to add the shell modifier when finished converting to face. </param>
        /// <param name="shell"> Input the shell thickness amount. </param>
        /// <param name="addEditMesh"> Input whether to add the Edit Mesh modifier when finished converting to face. </param>
        /// <param name="collapseNode"> Input whether to collapse the node afterwards. </param>
        /// <param name="centerPivot"> Input whether to center the pivot on each new face. </param>
        /// <returns> Returns 1 if successful or -1 if not. </returns>
        static public int ConvertToPolygonFaces(uint nodeHandle,
                                                bool convertToPoly = true, // C# now supports default parameters
                                                bool addShell      = true,
                                                float shell        = 0.1f,
                                                bool addEditMesh   = true,
                                                bool collapseNode  = true,
                                                bool centerPivot   = true)
        {
            try
            {
                IGlobal      global = Autodesk.Max.GlobalInterface.Instance;
                IInterface14 ip     = global.COREInterface14;

                IINode node = ip.GetINodeByHandle(nodeHandle);
                if (node == null)
                {
                    return(-1);
                }

                // Get it's current object state. If a modifier has been applied, for example,
                // it is going to return the OS of the mesh in it's current form in the timeline.
                IObjectState os = node.ObjectRef.Eval(ip.Time);

                // Now grab the object itself.
                IObject objOriginal = os.Obj;

                IPolyObject polyObject = objOriginal as IPolyObject;

                IClass_ID   cid     = global.Class_ID.Create((uint)BuiltInClassIDA.POLYOBJ_CLASS_ID, 0);
                IPolyObject polyObj = ip.CreateInstance(SClass_ID.Geomobject, cid as IClass_ID) as IPolyObject;

                if (polyObject == null && convertToPoly)
                {
                    if (objOriginal.CanConvertToType(global.TriObjectClassID) == 1)
                    {
                        objOriginal = objOriginal.ConvertToType(ip.Time, global.TriObjectClassID);
                    }
                    else
                    {
                        return(-1);
                    }
                    ITriObject triOriginal = objOriginal as ITriObject;
                    polyObj.Mesh.AddTri(triOriginal.Mesh);
                    polyObj.Mesh.FillInMesh();
                    polyObj.Mesh.EliminateBadVerts(0);
                    polyObj.Mesh.MakePolyMesh(0, true);
                }
                else if (polyObject == null)
                {
                    polyObj = polyObject;
                }
                else
                {
                    return(-1);
                }

                IMatrix3    mat              = node.GetNodeTM(0, null);
                IPoint3     ptOffsetPos      = node.ObjOffsetPos;
                IQuat       quatOffsetRot    = node.ObjOffsetRot;
                IScaleValue scaleOffsetScale = node.ObjOffsetScale;

                // We can grab the faces as a List and iterate them in .NET API.

                int nNumFaces = polyObj.Mesh.FNum;
                if (m_bUsingProgress)
                {
                    m_ctrlProgress.PB_ProgressMaxNum = nNumFaces;
                }

                ADN_UserBreakCheck checkUserBreak = new ADN_UserBreakCheck();

                for (int i = 0; i < nNumFaces; i++)
                {
                    if (checkUserBreak.Check() == true)
                    {
                        return(-1);
                    }
                    if (m_bUsingProgress)
                    {
                        m_ctrlProgress.PB_ProgressCurrNum = i;
                    }

                    // Create a new poly object for each new face.
                    object objectNewFace = ip.CreateInstance(SClass_ID.Geomobject, cid as IClass_ID);

                    // Create a new node to hold it in the scene.
                    IObject objNewFace = (IObject)objectNewFace;
                    IINode  n          = global.COREInterface.CreateObjectNode(objNewFace);

                    // Name it and ensure it is unique...
                    string newname = "ADN-Sample-Face";
                    ip.MakeNameUnique(ref newname);
                    n.Name = newname;

                    // Based on what we created above, we can safely cast it to TriObject
                    IPolyObject polyNewFace = objNewFace as IPolyObject;

                    // Setup the new poly object with 1 face, and the vertex count from the original object's face we are processing
                    polyNewFace.Mesh.SetNumFaces(1);
                    polyNewFace.Mesh.SetMapNum(2);
                    IMNFace f = polyObj.Mesh.F(i);

                    polyNewFace.Mesh.F(0).Assign(f);

                    IMNFace fnew = polyNewFace.Mesh.F(0);

                    IList <int> vtx = f.Vtx;

                    polyNewFace.Mesh.SetNumVerts(vtx.Count);
                    for (int k = 0; k < vtx.Count; k++)
                    {
                        int     nvindex = vtx[k];
                        IMNVert vert    = polyObj.Mesh.V(nvindex);
                        Debug.Print("\nVertex = " + k + ", " + nvindex);
                        polyNewFace.Mesh.V(k).Assign(vert);
                        fnew.Vtx[k] = k;
                    }


                    int     nedge = nedge = polyNewFace.Mesh.SimpleNewEdge(0, 1);
                    IMNEdge edge  = polyNewFace.Mesh.E(nedge);
                    edge.Track = -1;
                    edge.F1    = 0;
                    edge.F2    = -1;
                    polyNewFace.Mesh.SetEdgeVis(nedge, true);

                    nedge      = polyNewFace.Mesh.SimpleNewEdge(1, 2);
                    edge       = polyNewFace.Mesh.E(nedge);
                    edge.Track = -1;
                    edge.F1    = 0;
                    edge.F2    = -1;
                    polyNewFace.Mesh.SetEdgeVis(nedge, true);

                    nedge      = polyNewFace.Mesh.SimpleNewEdge(2, 3);
                    edge       = polyNewFace.Mesh.E(nedge);
                    edge.Track = -1;
                    edge.F1    = 0;
                    edge.F2    = -1;
                    polyNewFace.Mesh.SetEdgeVis(nedge, true);

                    nedge      = polyNewFace.Mesh.SimpleNewEdge(3, 0);
                    edge       = polyNewFace.Mesh.E(nedge);
                    edge.Track = -1;
                    edge.F1    = 0;
                    edge.F2    = -1;
                    polyNewFace.Mesh.SetEdgeVis(nedge, true);

                    polyNewFace.Mesh.FillInMesh();
                    // make it update.
                    polyNewFace.Mesh.InvalidateGeomCache();

                    if (addShell)
                    {
                        AddOsmShell(n.Handle, shell);
                    }

                    if (addEditMesh)
                    {
                        AddOsmEditMesh(n.Handle);
                    }

                    if (collapseNode)
                    {
                        ip.CollapseNode(n, true);
                    }

                    // update transform to match object being exploded.
                    n.SetNodeTM(0, mat);
                    n.ObjOffsetPos   = ptOffsetPos;
                    n.ObjOffsetRot   = quatOffsetRot;
                    n.ObjOffsetScale = scaleOffsetScale;
                    n.ObjOffsetPos   = ptOffsetPos;
                    if (centerPivot)
                    {
                        n.CenterPivot(0, false);
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.Print(ex.Message);
                return(-1);
            }

            return(1);
        }
コード例 #2
0
ファイル: ObjectMethods.cs プロジェクト: yuan505/Explode
        internal static unsafe void ExplodeNode(BaseNode baseNode, IPoint3 moveValue, ushort matID)
        {
            //A node is a part of an IIINode, it's a matID part of the real IINode
            var node = baseNode.INode;

            var world = node.GetObjTMAfterWSM(0, null);
            var local = world;

            if (!node.IsRootNode)
            {
                IMatrix3 m3Parent = node.ParentNode.GetObjTMAfterWSM(0, null);
                local = world.Multiply(m_Global.Inverse(m3Parent));
            }

            //We basically need to keep all the verts - but this could be millions, or we could keep an ID
            //IINode inode = baseNode.Node;

            //string sKey = matID.ToString();
            //string sMoveValue = string.Format("[{0};{1};{2}]", moveValue.X, moveValue.Y, moveValue.Z);

            //inode.SetUserPropString(ref sKey, ref sMoveValue);
            //---------------------------------------------------------------------------------------------

            if (baseNode.Mesh.TriMesh != null) //mesh
            {
                var           mesh                  = baseNode.Mesh.TriMesh;
                BitArray      facesPerID            = baseNode.GetMaterialBitArray(matID);
                HashSet <int> uniqueVertexIndexList = new HashSet <int>();

                //loop through the bitarray to see which faces are set. For the set faces, save the verts
                for (int i = 0; i < facesPerID.Count; i++)
                {
                    if (facesPerID[i])
                    {
                        //This should be a singular face that has the defined ID
                        IFace face = mesh.Faces[i];

                        IntPtr vertsIndices = face.AllVerts;

                        uint *dwordVertIndices = (uint *)vertsIndices.ToPointer();

                        for (int j = 0; j < 3; j++)
                        {
                            var vertexIndex = (int)dwordVertIndices[j];
                            uniqueVertexIndexList.Add(vertexIndex);
                        }
                    }
                }
                foreach (var vertexIndex in uniqueVertexIndexList)
                {
                    var localPos = mesh.GetVert(vertexIndex);
                    var finalPos = CalculateWorldPosVerts(localPos, moveValue, local);

                    mesh.SetVert(vertexIndex, finalPos);
                }
            }

            else //poly
            {
                var mesh = baseNode.Mesh.PolyMesh;

                //Get the bitArray for each ID
                BitArray      facesPerID            = baseNode.GetMaterialBitArray(matID);
                HashSet <int> uniqueVertexIndexList = new HashSet <int>();

                //loop through the bitarray to see which faces are set. For the set faces, save the verts
                for (int i = 0; i < facesPerID.Count; i++)
                {
                    if (facesPerID[i])
                    {
                        //This should be a singular face that has the defined ID
                        IMNFace     face        = mesh.F(i);
                        IList <int> vertIndices = face.Vtx;

                        foreach (var vertexIndex in vertIndices)
                        {
                            uniqueVertexIndexList.Add(vertexIndex);
                        }
                    }
                }
                foreach (var vertexIndex in uniqueVertexIndexList)
                {
                    var localPos = mesh.P(vertexIndex);
                    var finalPos = CalculateWorldPosVerts(localPos, moveValue, local);
                    mesh.V(vertexIndex).P = finalPos;
                }
            }
        }
コード例 #3
0
ファイル: ObjectMethods.cs プロジェクト: yuan505/Explode
        public static unsafe void BuildBoundingBox(ParentNode parentNode, ushort matID)
        {
            var node = parentNode.INode;

            var world = node.GetObjTMAfterWSM(0, null);
            var local = world;

            if (!node.IsRootNode)
            {
                IMatrix3 m3Parent = node.ParentNode.GetObjTMAfterWSM(0, null);
                local = world.Multiply(m_Global.Inverse(m3Parent));
            }

            if (parentNode.Mesh.TriMesh != null) //mesh
            {
                var mesh = parentNode.Mesh.TriMesh;

                BitArray facesPerID = parentNode.GetMaterialBitArray(matID);

                float?xMaxValue = null, xMinValue = null;
                float?yMaxValue = null, yMinValue = null;
                float?zMaxValue = null, zMinValue = null;

                IPoint3 maxValues, minValues;

                //loop through the bitarray to see which faces are set. For the set faces, save the verts
                for (int i = 0; i < facesPerID.Count; i++)
                {
                    if (facesPerID[i])
                    {
                        //This should be a singular face that has the defined ID
                        IFace face = mesh.Faces[i];

                        IntPtr vertsIndices = face.AllVerts;

                        uint *dwordVertIndices = (uint *)vertsIndices.ToPointer();

                        for (int j = 0; j < 3; j++)
                        {
                            var vertexIndex = (int)dwordVertIndices[j];

                            //Maybe don't hold giant lists of vertex indices - just do it while we loop over them all
                            //TODO very important check if this is necessary
                            //parentNode.MaterialIDVertexList.Add(vertexIndex);

                            var pos = mesh.GetVert(vertexIndex);
                            pos = local.PointTransform(pos);

                            FindMaxMinValues(ref xMaxValue, ref xMinValue,
                                             ref yMaxValue, ref yMinValue,
                                             ref zMaxValue, ref zMinValue, pos);
                        }
                    }
                }

                maxValues = m_Global.Point3.Create(xMaxValue.Value, yMaxValue.Value, zMaxValue.Value);
                minValues = m_Global.Point3.Create(xMinValue.Value, yMinValue.Value, zMinValue.Value);

                var bb = new BoundingBox(maxValues, minValues);

                parentNode.SetBoundingBox(matID, bb);
            }
            else
            {
                var mesh = parentNode.Mesh.PolyMesh;

                //Get the bitArray for each ID
                BitArray facesPerID = parentNode.GetMaterialBitArray(matID);

                float?xMaxValue = null, xMinValue = null;
                float?yMaxValue = null, yMinValue = null;
                float?zMaxValue = null, zMinValue = null;

                IPoint3 maxValues, minValues;

                //loop through the bitarray to see which faces are set. For the set faces, save the verts
                for (int i = 0; i < facesPerID.Count; i++)
                {
                    if (facesPerID[i])
                    {
                        //This should be a singular face that has the defined ID
                        IMNFace     face        = mesh.F(i);
                        IList <int> vertIndices = face.Vtx;

                        foreach (var vertexIndex in vertIndices)
                        {
                            //parentNode.MaterialIDVertexList.Add(vertexIndex);

                            var pos = mesh.P(vertexIndex);
                            pos = local.PointTransform(pos);

                            FindMaxMinValues(ref xMaxValue, ref xMinValue,
                                             ref yMaxValue, ref yMinValue,
                                             ref zMaxValue, ref zMinValue, pos);
                        }
                    }
                }

                maxValues = m_Global.Point3.Create(xMaxValue.Value, yMaxValue.Value, zMaxValue.Value);
                minValues = m_Global.Point3.Create(xMinValue.Value, yMinValue.Value, zMinValue.Value);

                var bb = new BoundingBox(maxValues, minValues);

                parentNode.SetBoundingBox(matID, bb);
            }
        }
コード例 #4
0
ファイル: ObjectMethods.cs プロジェクト: yuan505/Explode
        public static BaseNode CreateNode(IINode iNode, bool isPolyObject, bool isParentNode)
        {
            //We need to create our 'RealBaseNode'
            BaseNode tempBaseNode;

            if (isParentNode)
            {
                tempBaseNode = new ParentNode(iNode, isPolyObject);
            }
            else
            {
                tempBaseNode = new ChildNode(iNode, isPolyObject);
            }

            IObject baseObjectRef = iNode.ObjectRef.FindBaseObject();

            if (!isPolyObject)
            {
                //Cast base object to triObject because we know it's a triObject
                ITriObject triObj = baseObjectRef as ITriObject;
                if (triObj == null)
                {
                    return(null);                //if for some reason the cast failed, return
                }
                IMesh triMesh = triObj.Mesh;

                var numFaces = triMesh.NumFaces;

                DebugMethods.Log(isParentNode? String.Format("ParentNode num face {0}", numFaces) : String.Format("ChildNode num face {0}", numFaces));

                //Build FaceID Dictionary.
                for (int index = 0; index < numFaces; index++)
                {
                    IFace  face  = triMesh.Faces[index];
                    ushort matID = face.MatID;

                    if (tempBaseNode.DoesKeyExist(matID))
                    {
                        tempBaseNode.SetMaterialIDBit(matID, index);
                    }
                    else
                    {
                        tempBaseNode.CreateNewMaterialBitArray(matID, index, numFaces);
                    }
                }
            }
            else
            {
                IPolyObject polyObj = baseObjectRef as IPolyObject;
                if (polyObj == null)
                {
                    return(null);                 //if for some reason the cast failed, return
                }
                IMNMesh polyMesh = polyObj.Mesh;

                var numFaces = polyMesh.FNum;

                DebugMethods.Log(isParentNode ? String.Format("ParentNode num face {0}", numFaces) : String.Format("ChildNode num face {0}", numFaces));

                //Build FaceID Dictionary.
                for (int index = 0; index < numFaces; index++)
                {
                    IMNFace face  = polyMesh.F(index);
                    ushort  matID = face.Material;

                    if (tempBaseNode.DoesKeyExist(matID))
                    {
                        //Same material ID, just set the bit
                        //tempBaseNode.GetMaterialBitArray(matID).Set(index, true);
                        tempBaseNode.SetMaterialIDBit(matID, index);
                    }
                    else
                    {
                        tempBaseNode.CreateNewMaterialBitArray(matID, index, numFaces);
                    }
                }
            }
            //We should have a 'RealBaseNode' with a filled up dictionary full of IDs & faces!
            //Maybe there is some weird object with 0 faces?
            if (tempBaseNode.GetMaterialIDCount() == 0)
            {
                return(null);
            }

            return(tempBaseNode);
        }
コード例 #5
0
ファイル: ObjectMethods.cs プロジェクト: yuan505/Explode
        public static ushort?UpdateFaceDictionary(BaseNode node)
        {
            var triMesh  = node.Mesh.TriMesh;
            var polyMesh = node.Mesh.PolyMesh;

            var faceCountPerID = new Dictionary <ushort, int>();

            //Get numFaces of each ID
            foreach (var ids in node.GetUsedMaterialIDsArray())
            {
                faceCountPerID.Add(ids, GetCardinality(node.GetMaterialBitArray(ids)));
            }

            //clear the materialFaceDictionary
            node.ClearMaterialBitArray();

            if (node.Mesh.TriMesh != null)
            {
                var numFaces   = triMesh.NumFaces;
                var parentNode = node as ParentNode;

                //Build FaceID Dictionary.
                for (int index = 0; index < numFaces; index++)
                {
                    IFace  face  = triMesh.Faces[index];
                    ushort matID = face.MatID;

                    //This means it's a child node
                    if (parentNode == null)
                    {
                        UpdateNode(node, matID, index, numFaces);
                    }
                    //So it's a parentNode, but we don't want to update delete material IDs so check if that's not true
                    else if (!parentNode.IsMatIDDeleted(matID))
                    {
                        UpdateNode(node, matID, index, numFaces);
                    }
                }
            }
            else
            {
                var numFaces   = polyMesh.FNum;
                var parentNode = node as ParentNode;

                //Build FaceID Dictionary.
                for (int index = 0; index < numFaces; index++)
                {
                    IMNFace face  = polyMesh.F(index);
                    ushort  matID = face.Material;

                    if (parentNode == null)
                    {
                        UpdateNode(node, matID, index, numFaces);
                    }
                    else if (!parentNode.IsMatIDDeleted(matID))
                    {
                        UpdateNode(node, matID, index, numFaces);
                    }
                }
            }

            foreach (var ids in node.GetUsedMaterialIDsArray())
            {
                int numFaces;
                if (!faceCountPerID.TryGetValue(ids, out numFaces))
                {
                    continue;
                }
                if (numFaces != GetCardinality(node.GetMaterialBitArray(ids)))
                {
                    return(ids);
                }
            }

            return(null);
        }