/// <summary> /// Builds a consolidated vertex /// </summary> /// <param name="_Face">The face referencing this vertex</param> /// <param name="_FaceVertexIndex">The index of the vertex in that face</param> /// <param name="_VertexIndex">The index of the vertex to build</param> /// <returns></returns> protected ConsolidatedVertex BuildConsolidatedVertex( ConsolidatedFace _Face, int _FaceVertexIndex, int _VertexIndex ) { ConsolidatedVertex Result = new ConsolidatedVertex(); // Setup its smoothing group Result.m_SmoothingGroups = _Face.SmoothingGroups; // Setup informations for ( int LayerElementIndex=0; LayerElementIndex < m_CollapsedLayerElements.Length; LayerElementIndex++ ) { FBXImporter.LayerElement Element = m_CollapsedLayerElements[LayerElementIndex]; LoaderTempMesh OwnerMesh = m_CollapsedLayerElementMeshes[LayerElementIndex]; if ( Element.MappingType != FBXImporter.LayerElement.MAPPING_TYPE.BY_EDGE ) { // Translate information VERTEX_INFO_TYPE InfoType = VERTEX_INFO_TYPE.UNKNOWN; switch ( Element.ElementType ) { case FBXImporter.LayerElement.ELEMENT_TYPE.POSITION: InfoType = VERTEX_INFO_TYPE.POSITION; break; case FBXImporter.LayerElement.ELEMENT_TYPE.NORMAL: InfoType = VERTEX_INFO_TYPE.NORMAL; break; case FBXImporter.LayerElement.ELEMENT_TYPE.BINORMAL: InfoType = VERTEX_INFO_TYPE.BINORMAL; break; case FBXImporter.LayerElement.ELEMENT_TYPE.TANGENT: InfoType = VERTEX_INFO_TYPE.TANGENT; break; case FBXImporter.LayerElement.ELEMENT_TYPE.UV: InfoType = VERTEX_INFO_TYPE.TEXCOORD2D; break; case FBXImporter.LayerElement.ELEMENT_TYPE.VERTEX_COLOR: InfoType = VERTEX_INFO_TYPE.COLOR_HDR; break; } if ( InfoType == VERTEX_INFO_TYPE.UNKNOWN ) continue; // Not supported... // Fill the info ConsolidatedVertex.VertexInfo Info = new ConsolidatedVertex.VertexInfo(); Info.m_Owner = OwnerMesh; Info.m_SourceLayerElement = Element; Info.m_Type = InfoType; Info.m_Index = Element.Index; object[] Data = Element.ToArray(); switch ( Element.MappingType ) { case FBXImporter.LayerElement.MAPPING_TYPE.BY_CONTROL_POINT: Info.m_Value = Data[_VertexIndex]; break; case FBXImporter.LayerElement.MAPPING_TYPE.BY_TRIANGLE: Info.m_Value = Data[_Face.Index]; break; case FBXImporter.LayerElement.MAPPING_TYPE.BY_TRIANGLE_VERTEX: Info.m_Value = Data[3*_Face.Index + _FaceVertexIndex]; break; case FBXImporter.LayerElement.MAPPING_TYPE.ALL_SAME: Info.m_Value = Data[0]; break; } Result.m_Infos.Add( Info ); // Special treatment for position, normal, tangent & binormal... switch ( InfoType ) { case VERTEX_INFO_TYPE.POSITION: Result.m_PositionInfo = Info; break; case VERTEX_INFO_TYPE.NORMAL: Result.m_NormalInfo = Info; break; case VERTEX_INFO_TYPE.TANGENT: Result.m_TangentInfo = Info; break; case VERTEX_INFO_TYPE.BINORMAL: Result.m_BinormalInfo = Info; break; } } } return Result; }
public float m_Weight = 0.0f; // The weight of this face (in our case, the angle of the face at the given vertex) #endregion Fields #region Constructors public SharedFace( ConsolidatedFace _Face, Point _V0, Point _V1, Point _V2 ) { m_Face = _Face; // Retrieve the angle formed by the 2 vectors and use it as weight for this face's influence Vector D0 = (_V1 - _V0).Normalize(); Vector D1 = (_V2 - _V0).Normalize(); float fDot = D0 | D1; m_Weight = (float) Math.Acos( fDot ); if ( float.IsNaN( m_Weight ) ) m_Weight = 0.0f; // Occurs when D0 & D1 are very very small or really close to each other (usually, degenerate faces so it's okay if we skip them anyway) }
/// <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 ); } }
public void AddFace( ConsolidatedFace _Face ) { m_Faces.Add( _Face ); }