/// <summary> /// Parses a M2 file and creates the materials from it /// </summary> /// <param name="_M2File"></param> /// <returns></returns> public static Material[] ParseM2( FileInfo _M2File ) { string Text; using ( StreamReader R = _M2File.OpenText() ) Text = R.ReadToEnd(); List<Material> Result = new List<Material>(); int CurrentIndex = 0; while( true ) { // int MaterialStartIndex = Text.IndexOf( "material", CurrentIndex, StringComparison.CurrentCultureIgnoreCase ); int MaterialStartIndex = MatchWholeWord( Text, "material", CurrentIndex ); if ( MaterialStartIndex == -1 ) break; // Done! // Ensure it's at the beginning of a new line int PreviousEOLIndex = Text.LastIndexOf( '\n', MaterialStartIndex ); if ( PreviousEOLIndex == -1 ) PreviousEOLIndex = 0; // Assume it's the beginning of the file... if ( MaterialStartIndex - PreviousEOLIndex > 1 ) { // Either a comment or some unsupported "material" occurrence... string DEBUG = Text.Substring( MaterialStartIndex, Text.Length - MaterialStartIndex ); CurrentIndex = MaterialStartIndex+1; continue; } int NameStartIndex = MaterialStartIndex + "material".Length; if ( MaterialStartIndex >= Text.Length ) throw new Exception( "Unexpected end of file found after material declaration #" + Result.Count + " !" ); int OpeningBraceIndex = Text.IndexOf( '{', NameStartIndex ); if ( OpeningBraceIndex == -1 ) throw new Exception( "Opening brace not found after material declaration #" + Result.Count + " !" ); string MaterialName = Text.Substring( NameStartIndex, OpeningBraceIndex-NameStartIndex ); MaterialName = MaterialName.Trim(); if ( MaterialName == "" ) { // Simply skip that, must be something like "choubidou.material {" or the like... // throw new Exception( "Invalid material name!" ); CurrentIndex = OpeningBraceIndex; continue; } // Our new declaration starts here int MaterialDeclarationStartIndex = OpeningBraceIndex+1; int MaterialDeclarationEndIndex = IndexOfClosingBrace( Text, MaterialDeclarationStartIndex ); if ( MaterialDeclarationEndIndex == -1 ) throw new Exception( "Closing brace not found for material declaration \"" + MaterialName + "\"!" ); string MaterialDeclaration = Text.Substring( MaterialDeclarationStartIndex, MaterialDeclarationEndIndex-MaterialDeclarationStartIndex ); MaterialDeclaration += "\n"; // Add a mandatory EOL so parameters search is always successful! // Parse the declaration for parameters and texture names try { string DiffuseTextureName = ParseParameter( MaterialDeclaration, "diffuseMap", ".tga" ); string NormalTextureName = ParseParameter( MaterialDeclaration, "bumpmap", ".tga" ); string SpecularTextureName = ParseParameter( MaterialDeclaration, "specularMap", ".tga" ); // Create the new material Material M = new Material( _M2File, MaterialName, DiffuseTextureName, NormalTextureName, SpecularTextureName ); Result.Add( M ); } catch ( Exception _e ) { throw new Exception( "Error while parsing parameters for material \"" + MaterialName + "\"!", _e ); } // Go to the next material... CurrentIndex = MaterialDeclarationEndIndex; } return Result.ToArray(); }
/// <summary> /// Creates a box mesh /// </summary> /// <param name="_BBox">The mesh's box in local space</param> /// <param name="_Material">The material to use for the box</param> public void CreateBox( BoundingBox _BBox, Material _Material ) { m_OverrideMaterial = _Material; // Build vertices Point[] Vertices = new Point[8]; Vertices[0] = new Point( _BBox.m_Min.x + 0 * _BBox.DimX, _BBox.m_Min.y + 0 * _BBox.DimY, _BBox.m_Min.z + 0 * _BBox.DimZ ); Vertices[1] = new Point( _BBox.m_Min.x + 1 * _BBox.DimX, _BBox.m_Min.y + 0 * _BBox.DimY, _BBox.m_Min.z + 0 * _BBox.DimZ ); Vertices[2] = new Point( _BBox.m_Min.x + 1 * _BBox.DimX, _BBox.m_Min.y + 1 * _BBox.DimY, _BBox.m_Min.z + 0 * _BBox.DimZ ); Vertices[3] = new Point( _BBox.m_Min.x + 0 * _BBox.DimX, _BBox.m_Min.y + 1 * _BBox.DimY, _BBox.m_Min.z + 0 * _BBox.DimZ ); Vertices[4] = new Point( _BBox.m_Min.x + 0 * _BBox.DimX, _BBox.m_Min.y + 0 * _BBox.DimY, _BBox.m_Min.z + 1 * _BBox.DimZ ); Vertices[5] = new Point( _BBox.m_Min.x + 1 * _BBox.DimX, _BBox.m_Min.y + 0 * _BBox.DimY, _BBox.m_Min.z + 1 * _BBox.DimZ ); Vertices[6] = new Point( _BBox.m_Min.x + 1 * _BBox.DimX, _BBox.m_Min.y + 1 * _BBox.DimY, _BBox.m_Min.z + 1 * _BBox.DimZ ); Vertices[7] = new Point( _BBox.m_Min.x + 0 * _BBox.DimX, _BBox.m_Min.y + 1 * _BBox.DimY, _BBox.m_Min.z + 1 * _BBox.DimZ ); SetVertices( Vertices ); // Build faces FBXImporter.NodeMesh.Triangle[] Faces = new FBXImporter.NodeMesh.Triangle[2*6]; Faces[0] = new FBXImporter.NodeMesh.Triangle( 7, 4, 5, 0 ); // Front Faces[1] = new FBXImporter.NodeMesh.Triangle( 7, 5, 6, 1 ); Faces[2] = new FBXImporter.NodeMesh.Triangle( 6, 5, 1, 2 ); // Right Faces[3] = new FBXImporter.NodeMesh.Triangle( 6, 1, 2, 3 ); Faces[4] = new FBXImporter.NodeMesh.Triangle( 3, 7, 6, 4 ); // Top Faces[5] = new FBXImporter.NodeMesh.Triangle( 3, 6, 2, 5 ); Faces[6] = new FBXImporter.NodeMesh.Triangle( 3, 0, 4, 6 ); // Left Faces[7] = new FBXImporter.NodeMesh.Triangle( 3, 4, 7, 7 ); Faces[8] = new FBXImporter.NodeMesh.Triangle( 2, 1, 0, 8 ); // Back Faces[9] = new FBXImporter.NodeMesh.Triangle( 2, 0, 3, 9 ); Faces[10] = new FBXImporter.NodeMesh.Triangle( 4, 0, 1, 10 ); // Bottom Faces[11] = new FBXImporter.NodeMesh.Triangle( 4, 1, 5, 11 ); SetFaces( Faces ); // Build smoothing groups object[] SmoothingGroups = new object[] { 1, 1, 2, 2, 4, 4, 8, 8, 16, 16, 32, 32, 64, 64 }; FBXImporter.LayerElement Element = new FBXImporter.LayerElement( "Smg", FBXImporter.LayerElement.ELEMENT_TYPE.SMOOTHING, FBXImporter.LayerElement.MAPPING_TYPE.BY_TRIANGLE, 0 ); Element.SetArrayOfData( SmoothingGroups ); AddLayerElement( Element ); // Build UV set (compulsory otherwise TS can't be generated and an exception may occur) object[] UVs = new object[] { new Vector2D( 0.0f, 0.0f ), new Vector2D( 0.0f, 1.0f ), new Vector2D( 1.0f, 1.0f ), new Vector2D( 0.0f, 0.0f ), new Vector2D( 1.0f, 1.0f ), new Vector2D( 1.0f, 0.0f ), new Vector2D( 0.0f, 0.0f ), new Vector2D( 0.0f, 1.0f ), new Vector2D( 1.0f, 1.0f ), new Vector2D( 0.0f, 0.0f ), new Vector2D( 1.0f, 1.0f ), new Vector2D( 1.0f, 0.0f ), new Vector2D( 0.0f, 0.0f ), new Vector2D( 0.0f, 1.0f ), new Vector2D( 1.0f, 1.0f ), new Vector2D( 0.0f, 0.0f ), new Vector2D( 1.0f, 1.0f ), new Vector2D( 1.0f, 0.0f ), new Vector2D( 0.0f, 0.0f ), new Vector2D( 0.0f, 1.0f ), new Vector2D( 1.0f, 1.0f ), new Vector2D( 0.0f, 0.0f ), new Vector2D( 1.0f, 1.0f ), new Vector2D( 1.0f, 0.0f ), new Vector2D( 0.0f, 0.0f ), new Vector2D( 0.0f, 1.0f ), new Vector2D( 1.0f, 1.0f ), new Vector2D( 0.0f, 0.0f ), new Vector2D( 1.0f, 1.0f ), new Vector2D( 1.0f, 0.0f ), new Vector2D( 0.0f, 0.0f ), new Vector2D( 0.0f, 1.0f ), new Vector2D( 1.0f, 1.0f ), new Vector2D( 0.0f, 0.0f ), new Vector2D( 1.0f, 1.0f ), new Vector2D( 1.0f, 0.0f ), }; Element = new FBXImporter.LayerElement( "UVs", FBXImporter.LayerElement.ELEMENT_TYPE.UV, FBXImporter.LayerElement.MAPPING_TYPE.BY_TRIANGLE_VERTEX, 0 ); Element.SetArrayOfData( UVs ); AddLayerElement( Element ); // That's all, we don't build anything else as it will be done by the mesh consolidation... }