/// <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... }
/// <summary> /// This builds the mesh primitives that we'll be able to use at runtime /// </summary> public void BuildPrimitives() { // if ( m_Owner.GenerateTriangleStrips ) // throw new Exception( "Triangle Strips are not supported yet!" ); // Setup the comparison flags used for consolidation ConsolidatedVertex.ms_CompareSmoothingGroups = m_Owner.ConsolidateSplitBySMG; ConsolidatedVertex.VertexInfo.ms_CompareUVs = m_Owner.ConsolidateSplitByUV; ConsolidatedVertex.VertexInfo.ms_CompareColors = m_Owner.ConsolidateSplitByColor; ////////////////////////////////////////////////////////////////////////// // Reset X-Form if ( m_Pivot != null ) { Point[] NewVertices = new Point[m_Vertices.Length]; for ( int VertexIndex=0; VertexIndex < m_Vertices.Length; VertexIndex++ ) NewVertices[VertexIndex] = m_Vertices[VertexIndex] * m_Pivot; m_Vertices = NewVertices; } ////////////////////////////////////////////////////////////////////////// // Build the original list of consolidated faces List<ConsolidatedFace> Faces = new List<ConsolidatedFace>(); foreach ( FBXImporter.NodeMesh.Triangle T in m_Faces ) { ConsolidatedFace NewFace = new ConsolidatedFace(); NewFace.Index = Faces.Count; NewFace.VertexIndex0 = T.Vertex0; NewFace.VertexIndex1 = T.Vertex1; NewFace.VertexIndex2 = T.Vertex2; Faces.Add( NewFace ); } ////////////////////////////////////////////////////////////////////////// // Attempt to retrieve smoothing groups & materials data foreach ( FBXImporter.LayerElement Element in m_LayerElements ) { if ( Element.ElementType == FBXImporter.LayerElement.ELEMENT_TYPE.MATERIAL ) { if ( m_OverrideMaterial != null ) continue; // Ignore specific material if we have an override... // Retrieve the array of data object[] Data = Element.ToArray(); switch ( Element.MappingType ) { case FBXImporter.LayerElement.MAPPING_TYPE.BY_TRIANGLE: for ( int FaceIndex=0; FaceIndex < Faces.Count; FaceIndex++ ) Faces[FaceIndex].Material = (FBXImporter.Material) Data[FaceIndex]; break; case FBXImporter.LayerElement.MAPPING_TYPE.ALL_SAME: { FBXImporter.Material Mat = (FBXImporter.Material) Data[0]; foreach ( ConsolidatedFace F in Faces ) F.Material = Mat; break; } default: throw new Exception( "Found a layer element of type \"MATERIAL\" with unsupported \"" + Element.MappingType + "\" mapping type!\r\n(Only BY_POLYGON & ALL_SAME mapping modes are supported!)" ); } } else if ( Element.ElementType == FBXImporter.LayerElement.ELEMENT_TYPE.SMOOTHING ) { // Retrieve the array of data object[] Data = Element.ToArray(); switch ( Element.MappingType ) { case FBXImporter.LayerElement.MAPPING_TYPE.BY_TRIANGLE: for ( int FaceIndex=0; FaceIndex < Faces.Count; FaceIndex++ ) Faces[FaceIndex].SmoothingGroups = (int) Data[FaceIndex]; break; case FBXImporter.LayerElement.MAPPING_TYPE.ALL_SAME: { int SMG = (int) Data[0]; foreach ( ConsolidatedFace F in Faces ) F.SmoothingGroups = SMG; break; } case FBXImporter.LayerElement.MAPPING_TYPE.BY_EDGE: { break; } default: throw new Exception( "Found a layer element of type \"SMOOTHING\" with unsupported \"" + Element.MappingType + "\" mapping type!\r\n(Only BY_POLYGON & ALL_SAME mapping modes are supported!)" ); } } } ////////////////////////////////////////////////////////////////////////// // Check if we have tangent space information TANGENT_SPACE_AVAILABILITY TSAvailability = TANGENT_SPACE_AVAILABILITY.NOTHING; foreach ( FBXImporter.LayerElement Element in m_LayerElements ) switch ( Element.ElementType ) { case FBXImporter.LayerElement.ELEMENT_TYPE.UV: TSAvailability |= TANGENT_SPACE_AVAILABILITY.UVs; break; case FBXImporter.LayerElement.ELEMENT_TYPE.NORMAL: TSAvailability |= TANGENT_SPACE_AVAILABILITY.NORMAL; break; case FBXImporter.LayerElement.ELEMENT_TYPE.TANGENT: TSAvailability |= TANGENT_SPACE_AVAILABILITY.TANGENT; break; case FBXImporter.LayerElement.ELEMENT_TYPE.BINORMAL: TSAvailability |= TANGENT_SPACE_AVAILABILITY.BINORMAL; break; } if ( TSAvailability == TANGENT_SPACE_AVAILABILITY.NOTHING ) { // Can't generate ! switch ( m_Owner.NoTangentSpaceAction ) { case SceneLoader.NO_TANGENT_SPACE_ACTION.THROW: throw new Exception( "Can't generate Tangent Space because there is no texture coordinates!" ); case SceneLoader.NO_TANGENT_SPACE_ACTION.SKIP: return; } } ////////////////////////////////////////////////////////////////////////// // Build dummy layer elements for position, normal, tangent & binormal streams of data // m_LayerElementPosition = new FBXImporter.LayerElement( "Position", FBXImporter.LayerElement.ELEMENT_TYPE.POSITION, FBXImporter.LayerElement.MAPPING_TYPE.BY_CONTROL_POINT, 0 ); m_LayerElementPosition.SetArrayOfData( m_Vertices ); m_LayerElements.Insert( 0, m_LayerElementPosition ); // Make it first layer! m_LayerElementNormal = null; m_LayerElementTangent = null; m_LayerElementBiNormal = null; foreach ( FBXImporter.LayerElement LE in m_LayerElements ) { if ( m_LayerElementNormal == null && LE.ElementType == FBXImporter.LayerElement.ELEMENT_TYPE.NORMAL ) { // Re-use the normals element m_LayerElementNormal = LE; m_LayerElementNormal.MappingType = LE.MappingType;// FBXImporter.LayerElement.MAPPING_TYPE.BY_TRIANGLE_VERTEX; m_LayerElementNormal.ReferenceType = LE.ReferenceType;// FBXImporter.LayerElement.REFERENCE_TYPE.DIRECT; } else if ( m_LayerElementTangent == null && LE.ElementType == FBXImporter.LayerElement.ELEMENT_TYPE.TANGENT ) { // Re-use the tangents element m_LayerElementTangent = LE; m_LayerElementTangent.MappingType = LE.MappingType;// FBXImporter.LayerElement.MAPPING_TYPE.BY_TRIANGLE_VERTEX; m_LayerElementTangent.ReferenceType = LE.ReferenceType;//FBXImporter.LayerElement.REFERENCE_TYPE.DIRECT; } else if ( m_LayerElementBiNormal == null && LE.ElementType == FBXImporter.LayerElement.ELEMENT_TYPE.BINORMAL ) { // Re-use the binormals element m_LayerElementBiNormal = LE; m_LayerElementBiNormal.MappingType = LE.MappingType;// FBXImporter.LayerElement.MAPPING_TYPE.BY_TRIANGLE_VERTEX; m_LayerElementBiNormal.ReferenceType = LE.ReferenceType;//FBXImporter.LayerElement.REFERENCE_TYPE.DIRECT; } } if ( m_LayerElementNormal == null ) { // Create a new normals element that we'll need to generate m_LayerElementNormal = new FBXImporter.LayerElement( "Normal", FBXImporter.LayerElement.ELEMENT_TYPE.NORMAL, FBXImporter.LayerElement.MAPPING_TYPE.BY_TRIANGLE_VERTEX, 0 ); m_LayerElements.Add( m_LayerElementNormal ); } if ( m_Owner.GenerateTangentSpace && m_LayerElementTangent == null ) { // Create a new tangents element that we'll need to generate m_LayerElementTangent = new FBXImporter.LayerElement( "Tangent", FBXImporter.LayerElement.ELEMENT_TYPE.TANGENT, FBXImporter.LayerElement.MAPPING_TYPE.BY_TRIANGLE_VERTEX, 0 ); m_LayerElements.Add( m_LayerElementTangent ); } if ( m_Owner.GenerateTangentSpace && m_LayerElementBiNormal == null ) { // Create a new binormals element that we'll need to generate m_LayerElementBiNormal = new FBXImporter.LayerElement( "BiNormal", FBXImporter.LayerElement.ELEMENT_TYPE.BINORMAL, FBXImporter.LayerElement.MAPPING_TYPE.BY_TRIANGLE_VERTEX, 0 ); m_LayerElements.Add( m_LayerElementBiNormal ); } ////////////////////////////////////////////////////////////////////////// // Generate missing data BuildTangentSpace( Faces, TSAvailability, m_Owner.GenerateTangentSpace ); ////////////////////////////////////////////////////////////////////////// // Build primitives based on referenced materials m_Primitives.Clear(); Dictionary<FBXImporter.Material,Primitive> Material2Primitive = new Dictionary<FBXImporter.Material,Primitive>(); Primitive DefaultPrimitive = null; for ( int FaceIndex=0; FaceIndex < Faces.Count; FaceIndex++ ) { ConsolidatedFace F = Faces[FaceIndex]; Primitive P = null; if ( F.Material == null ) { // Default material if ( DefaultPrimitive == null ) { // Create the default primitive DefaultPrimitive = new Primitive( this, m_Owner, this.m_Name + "_Primitive" + m_Primitives.Count, null ); DefaultPrimitive.OverrideMaterial = m_OverrideMaterial; // Setup the optional override material m_Primitives.Add( DefaultPrimitive ); } P = DefaultPrimitive; } else if ( !Material2Primitive.ContainsKey( F.Material ) ) { // New primitive! P = new Primitive( this, m_Owner, this.m_Name + "_Primitive" + m_Primitives.Count, F.Material ); m_Primitives.Add( P ); Material2Primitive[F.Material] = P; } else P = Material2Primitive[F.Material]; P.AddFace( F ); } }