Exemplo n.º 1
0
		/// <summary>
		/// Add vertex and index sets of a mesh to the builder.
		/// </summary>
		/// <param name="mesh">The mesh object.</param>
		/// <param name="lodIndex">The LOD level to be processed.</param>
		public void AddObject( Mesh mesh, int lodIndex )
		{
			if ( mesh == null )
				throw new ArgumentNullException();

			//mesh.AddVertexAndIndexSets(this, lodIndex);

			//NOTE: The Mesh.AddVertexAndIndexSets() assumes there weren't any vertex data added to the builder yet.
			//For this class I decided to break that assumption, thus using following replacement for the commented call.
			//I guess rarely, but still you might want to add vertex/index sets of several objects to one builder.
			//Maybe AddVertexAndIndexSets could be removed and this method utilized back in Mesh.

			//TODO: find out whether custom index buffer needs to be created in cases (like in the AddObject(IRenderable)).
			//Borrilis, do you know?

			int vertexSetCount = vertexDataList.Count;
			int indexOfSharedVertexSet = vertexSetCount;

			if ( mesh.SharedVertexData != null )
			{
				AddVertexData( mesh.SharedVertexData );
				vertexSetCount++;
			}

			// Prepare the builder using the submesh information
			for ( int i = 0; i < mesh.SubMeshCount; i++ )
			{
				SubMesh sm = mesh.GetSubMesh( i );

				if ( sm.useSharedVertices )
				{
					// Use shared vertex data
					if ( lodIndex == 0 )
					{
						AddIndexData( sm.IndexData, indexOfSharedVertexSet,
						sm.OperationType );
					}
					else
					{
						AddIndexData( sm.LodFaceList[ lodIndex - 1 ],
						indexOfSharedVertexSet, sm.OperationType );
					}
				}
				else
				{
					// own vertex data, add it and reference it directly
					AddVertexData( sm.VertexData );

					if ( lodIndex == 0 )
					{
						// base index data
						AddIndexData( sm.IndexData, vertexSetCount++,
						sm.OperationType );
					}
					else
					{
						// LOD index data
						AddIndexData( sm.LodFaceList[ lodIndex - 1 ],
						vertexSetCount++, sm.OperationType );
					}
				}
			}
		}
        public static Mesh CopyMesh(Mesh mesh)
        {
            Mesh newMesh = new Mesh(mesh.Name);
            if (mesh.Skeleton != null)
                newMesh.NotifySkeleton(mesh.Skeleton);
            newMesh.SetVertexBufferPolicy(mesh.VertexBufferUsage, mesh.UseVertexShadowBuffer);
            newMesh.SetIndexBufferPolicy(mesh.IndexBufferUsage, mesh.UseIndexShadowBuffer);

            // this sets bounding radius as well
            newMesh.BoundingBox = mesh.BoundingBox;

            MeshUtility meshUtility = new MeshUtility();
            for (int i = 0; i < mesh.SubMeshCount; ++i)
                meshUtility.AddSubmeshData(mesh.GetSubMesh(i));

            // This should be done after we finish with the lod stuff
            newMesh.AutoBuildEdgeLists = true;
            newMesh.BuildEdgeList();

            foreach (AttachmentPoint ap in mesh.AttachmentPoints)
                newMesh.AttachmentPoints.Add(new AttachmentPoint(ap));

            for (int i = 0; i < mesh.SubMeshCount; ++i) {
                SubMesh srcSubMesh = mesh.GetSubMesh(i);
                SubMesh dstSubMesh = newMesh.CreateSubMesh(srcSubMesh.Name);
                CopySubMesh(dstSubMesh, srcSubMesh, meshUtility.subMeshDataMap[srcSubMesh.Name]);
            }

            if (mesh.SharedVertexData != null) {
                newMesh.SharedVertexData = new VertexData();
                CopyVertexData(newMesh.SharedVertexData, mesh.SharedVertexData, meshUtility.sharedSubMeshData.VertexIdMap);
                CopyBoneAssignments(newMesh, mesh, meshUtility.sharedSubMeshData.VertexIdMap);
            }
            // newMesh.CompileBoneAssignments();

            return newMesh;
        }
        public static void ExtractCollisionShapes( Mesh mesh, string path )
        {
            PhysicsData physicsData = null;
            List<string> deleteEm = new List<string>();
            int count = mesh.SubMeshCount;

            for( int i = 0; i < count; i++ )
            {
                SubMesh subMesh = mesh.GetSubMesh( i );
                CollisionShape shape = null;
                string targetName = null;
                bool cv = String.Compare( subMesh.Name.Substring( 0, 5 ), "mvcv_", false ) == 0;
                bool rg = String.Compare( subMesh.Name.Substring( 0, 5 ), "mvrg_", false ) == 0;
                int firstIndex = 0;
                if( cv )
                    firstIndex = 5;
                else if( rg )
                {
                    string rest = subMesh.Name.Substring( 5 );
                    firstIndex = rest.IndexOf( "_" ) + 1 + 5;
                }
                if( cv || rg )
                {
                    // It's probably a collision volume - - check the
                    // shape type to make sure
                    if( String.Compare( subMesh.Name.Substring( firstIndex, 4 ), "obb_", false ) == 0 )
                    {
                        shape = ExtractBox( subMesh );
                    }
                    else if( String.Compare( subMesh.Name.Substring( firstIndex, 5 ), "aabb_", false ) == 0 )
                    {
                        shape = ExtractBox( subMesh );
                    }
                    else if( String.Compare( subMesh.Name.Substring( firstIndex, 7 ), "sphere_", false ) == 0 )
                    {
                        shape = ExtractSphere( subMesh );
                    }
                    else if( String.Compare( subMesh.Name.Substring( firstIndex, 8 ), "capsule_", false ) == 0 )
                    {
                        shape = ExtractCapsule( subMesh );
                    }
                    if( shape != null )
                        targetName = GetTargetSubmesh( mesh, subMesh.Name );
                }
                if( shape != null )
                {
                    deleteEm.Add( subMesh.Name );
                    if( physicsData == null )
                        physicsData = new PhysicsData();
                    physicsData.AddCollisionShape( targetName, shape );
                }
            }
            for( int i = 0; i < deleteEm.Count; i++ )
            {
                mesh.RemoveSubMesh( deleteEm[ i ] );
            }
            if( physicsData != null )
            {
                PhysicsSerializer serializer = new PhysicsSerializer();
                serializer.ExportPhysics( physicsData, path + ".physics" );
            }

            if( DoLog )
                CloseLog();
        }
        // This attempts to parse a CV name and get the name of a matching submesh
        // defined in the Axiom mesh.  This is tailored to ideosyncrasities in how
        // the 3dsMax COLLADA exporter mangles names.  I'm not sure exactly what it
        // does, but it has something to do with inserting a suffix like '-lib' at
        // or near the end of the CV mesh name.
        //
        // Return a target submesh name, or String.Empty if either we cannot parse
        // the name satisfactorily, or the target is not found.
        private static string GetTargetSubmeshMaxStyle( Mesh mesh, string collisionSubmesh )
        {
            const string mesh_pattern = "(.*)-(lib|obj|mesh)\\.([0-9]+)";
            const string cv_prefix = "mvcv_(obb|aabb|sphere|capsule)_";

            Regex mvcv_regex = new Regex( cv_prefix + mesh_pattern );
            Match mvcvMatch = mvcv_regex.Match( collisionSubmesh );

            if( !mvcvMatch.Success || mvcvMatch.Groups.Count < 3 )
            {
                if( DoLog )
                {
                    Log( string.Format( "Unexpected collision volume name: {0}", collisionSubmesh ) );
                }
                return String.Empty;
            }

            string mvcv_target = mvcvMatch.Groups[ 2 ].Value;

            for( int i = 0; i < mesh.SubMeshCount; ++i )
            {
                string submeshName = mesh.GetSubMesh( i ).Name;

                // strip off the -obj.0 part
                Regex submesh_regex = new Regex( mesh_pattern );
                Match submeshMatch = submesh_regex.Match( submeshName );

                if( !submeshMatch.Success || submeshMatch.Groups.Count < 2 )
                {
                    continue;
                }

                string shortName = submeshMatch.Groups[ 1 ].Value;
                if( mvcv_target.StartsWith( shortName, StringComparison.CurrentCultureIgnoreCase ) )
                {
                    return submeshName;
                }
            }

            if( DoLog )
            {
                Log( string.Format( "Failed to find target submesh for {0}", collisionSubmesh ) );
            }

            return String.Empty;
        }
        // Look for a target submesh assuming that the COLLADA exporter did not
        // do any special name mangling.  I've tested this against files emitted
        // from Maya; I expect it will work for DAE files from other sources, too,
        // such as Blender or XSI.  Time will tell...
        private static string GetTargetSubmeshGeneralStyle( Mesh mesh, string collisionSubmesh )
        {
            string targetName = String.Empty;

            CvNameParser parser =  new CvNameParser();

            parser.AnalyzeName( collisionSubmesh );

            if( parser.IsValid )
            {
                // Form the target name as the first submesh name and see if
                // there is actually matching submesh.
                string candidate = parser.Target + ".0";

                for( int i = 0; i < mesh.SubMeshCount; i++ )
                {
                    if( mesh.GetSubMesh( i ).Name.Equals( candidate ) )
                    {
                        targetName = candidate;
                        break;
                    }
                }
            }

            return targetName;
        }