コード例 #1
0
ファイル: SceneLoader.cs プロジェクト: vr3d/GodComplex
        protected bool  CreateTextureParameter(FBXImporter.Material _Material, string _PropertyName, Scene.Materials.MaterialParameters _MaterialParameters, string _ParameterName, string _OpacityPropertyName)
        {
            FBXImporter.ObjectProperty Property = _Material.FindProperty(_PropertyName);
            if (Property == null)
            {
                return(false);                  // No such property...
            }
            if (Property.Textures.Length == 0)
            {
                return(false);                  // That property has no texture...
            }
            // Check for opacity
            string OpacityTextureRelativeFileName = null;

            if (_OpacityPropertyName != null)
            {
                FBXImporter.ObjectProperty OpacityProperty = _Material.FindProperty(_OpacityPropertyName);
                if (OpacityProperty != null && OpacityProperty.Textures.Length != 0)
                {
                    OpacityTextureRelativeFileName = OpacityProperty.Textures[0].RelativeFileName;
                }
            }

            // Create the parameter with that texture
            Scene.Materials.Texture2D Tex = m_Scene.CreateTexture(Property.Textures[0].RelativeFileName, OpacityTextureRelativeFileName, Property.Textures[0].UseMipMap);
            _MaterialParameters.CreateParameter(_ParameterName, Scene.Materials.MaterialParameters.PARAMETER_TYPE.TEXTURE2D).AsTexture2D.Value = Tex;

            return(true);
        }
コード例 #2
0
ファイル: SceneLoader.cs プロジェクト: vr3d/GodComplex
 /// <summary>
 /// Creates a texture parameter from a material property that contains a texture (e.g. DiffuseColor, SpecularColor, etc.)
 /// </summary>
 /// <param name="_Material"></param>
 /// <param name="_PropertyName"></param>
 /// <param name="_MaterialParameters"></param>
 /// <param name="_ParameterName"></param>
 /// <returns>True if a texture is available</returns>
 protected bool  CreateTextureParameter(FBXImporter.Material _Material, string _PropertyName, Scene.Materials.MaterialParameters _MaterialParameters, string _ParameterName)
 {
     return(CreateTextureParameter(_Material, _PropertyName, _MaterialParameters, _ParameterName, null));
 }
コード例 #3
0
ファイル: SceneLoader.cs プロジェクト: vr3d/GodComplex
        /// <summary>
        /// Attempts to map FBX materials to render techniques
        /// </summary>
        /// <param name="_Materials">The list of materials to process</param>
        protected void  ProcessMaterials(FBXImporter.Material[] _Materials)
        {
            m_Material2Parameters.Clear();

            foreach (FBXImporter.Material Mat in _Materials)
            {
                Scene.Materials.MaterialParameters MatParams = null;

// DEBUG
// if ( Mat.Name == "sp_00_svod" )
//  MatParams = null;
// DEBUG

                if (m_MaterialsDatabase != null)
                {                       // Handle the special case of scenes that were exported as OBJ format and whos material informations lie in the diffuse color "texture"
                    FBXImporter.ObjectProperty DiffuseColorProperty = Mat.FindProperty("DiffuseColor");
                    if (DiffuseColorProperty != null && DiffuseColorProperty.Textures.Length > 0)
                    {
                        string PseudoTextureName = DiffuseColorProperty.Textures[0].AbsoluteFileName;                           // Actually a material name!
                        MaterialsDatabase.Material MatOverride = m_MaterialsDatabase.FindByName(PseudoTextureName);
                        if (MatOverride != null)
                        {                               // Replace this material's textures by the actual material's textures (does it make sense? ^^)
                            if (MatOverride.TextureDiffuse != null)
                            {
                                FBXImporter.ObjectProperty TextureProperty = Mat.FindProperty("DiffuseColor");
                                if (TextureProperty != null)
                                {
                                    TextureProperty.Textures = new FBXImporter.Texture[] { new FBXImporter.Texture(Mat.ParentScene, MatOverride.TextureDiffuse, MatOverride.TextureDiffuse, MatOverride.TextureDiffuse) };
                                }
                            }
                            if (MatOverride.TextureNormal != null)
                            {
                                FBXImporter.ObjectProperty TextureProperty = Mat.FindProperty("NormalMap");
                                if (TextureProperty != null)
                                {
                                    TextureProperty.Textures = new FBXImporter.Texture[] { new FBXImporter.Texture(Mat.ParentScene, MatOverride.TextureNormal, MatOverride.TextureNormal, MatOverride.TextureNormal) };
                                }
                            }
                            if (MatOverride.TextureSpecular != null)
                            {
                                FBXImporter.ObjectProperty TextureProperty = Mat.FindProperty("SpecularColor");
                                if (TextureProperty != null)
                                {
                                    TextureProperty.Textures = new FBXImporter.Texture[] { new FBXImporter.Texture(Mat.ParentScene, MatOverride.TextureSpecular, MatOverride.TextureSpecular, MatOverride.TextureSpecular) };
                                }
                            }
                        }
                    }
                }

                // Specialize the material
                if (Mat is FBXImporter.MaterialHardwareShader)
                {
                    FBXImporter.MaterialHardwareShader HardwareMaterial = Mat as FBXImporter.MaterialHardwareShader;

                    MatParams = m_Scene.CreateMaterialParameters(Mat.Name, HardwareMaterial.RelativeURL);

                    foreach (FBXImporter.MaterialHardwareShader.TableEntry Entry in HardwareMaterial.ShaderEntries)
                    {
                        switch (Entry.TypeName)
                        {
                        case "Boolean":
                            MatParams.CreateParameter(Entry.Name, Scene.Materials.MaterialParameters.PARAMETER_TYPE.BOOL).AsBool.Value = (bool)Entry.Value;
                            break;

                        case "Integer":
                            MatParams.CreateParameter(Entry.Name, Scene.Materials.MaterialParameters.PARAMETER_TYPE.INT).AsInt.Value = (int)Entry.Value;
                            break;

                        case "Float":
                            MatParams.CreateParameter(Entry.Name, Scene.Materials.MaterialParameters.PARAMETER_TYPE.FLOAT).AsFloat.Value = (float)Entry.Value;
                            break;

                        case "Float2":
                            MatParams.CreateParameter(Entry.Name, Scene.Materials.MaterialParameters.PARAMETER_TYPE.FLOAT2).AsFloat2.Value = Entry.Value as Vector2D;
                            break;

                        case "Float3":
                            MatParams.CreateParameter(Entry.Name, Scene.Materials.MaterialParameters.PARAMETER_TYPE.FLOAT3).AsFloat3.Value = Entry.Value as Vector;
                            break;

                        case "Float4":
                            MatParams.CreateParameter(Entry.Name, Scene.Materials.MaterialParameters.PARAMETER_TYPE.FLOAT4).AsFloat4.Value = Entry.Value as Vector4D;
                            break;

                        case "Matrix":
                            MatParams.CreateParameter(Entry.Name, Scene.Materials.MaterialParameters.PARAMETER_TYPE.MATRIX4).AsMatrix4.Value = Entry.Value as Matrix4x4;
                            break;

                        case "Texture":
                            CreateTextureParameter(Mat, Entry.Name, MatParams, Entry.Name);
                            break;
                        }
                    }

                    m_Material2Parameters[Mat] = MatParams;
                    continue;
                }

                FBXImporter.Material SpecificMaterial = null;

                if (Mat is FBXImporter.MaterialPhong)
                {
                    SpecificMaterial = Mat as FBXImporter.MaterialPhong;
                    MatParams        = m_Scene.CreateMaterialParameters(Mat.Name, "Phong");
                }
                else if (Mat is FBXImporter.MaterialLambert)
                {
                    SpecificMaterial = Mat as FBXImporter.MaterialLambert;
                    MatParams        = m_Scene.CreateMaterialParameters(Mat.Name, "Lambert");
                }
                else
                {
                    continue;                           // Unrecognized hence unsupported material type...
                }
//              // Lambert parameters
//              MatParams.CreateParameter( "AmbientColor", Scene.Materials.MaterialParameters.PARAMETER_TYPE.FLOAT3 ).AsFloat3.Value = SpecificMaterial.AmbientColor;
//              CreateTextureParameter( Mat, "AmbientColor", MatParams, "AmbientTexture" );
//              MatParams.CreateParameter( "AmbientFactor", Scene.Materials.MaterialParameters.PARAMETER_TYPE.FLOAT ).AsFloat.Value = SpecificMaterial.AmbientFactor;
//
//              MatParams.CreateParameter( "DiffuseColor", Scene.Materials.MaterialParameters.PARAMETER_TYPE.FLOAT3 ).AsFloat3.Value = SpecificMaterial.DiffuseColor;
//              MatParams.CreateParameter( "DiffuseFactor", Scene.Materials.MaterialParameters.PARAMETER_TYPE.FLOAT ).AsFloat.Value = SpecificMaterial.DiffuseFactor;
//              bool	bHasDiffuseTexture = CreateTextureParameter( Mat, "DiffuseColor", MatParams, "DiffuseTexture", "TransparentColor" );
//              MatParams.CreateParameter( "HasDiffuseTexture", Scene.Materials.MaterialParameters.PARAMETER_TYPE.BOOL ).AsBool.Value = bHasDiffuseTexture;
//
//              MatParams.CreateParameter( "EmissiveColor", Scene.Materials.MaterialParameters.PARAMETER_TYPE.FLOAT3 ).AsFloat3.Value = SpecificMaterial.EmissiveColor;
//              MatParams.CreateParameter( "EmissiveFactor", Scene.Materials.MaterialParameters.PARAMETER_TYPE.FLOAT ).AsFloat.Value = SpecificMaterial.EmissiveFactor;
//              CreateTextureParameter( Mat, "EmissiveColor", MatParams, "EmissiveTexture" );
//
//              FBXImporter.ObjectProperty	OpacityProp = SpecificMaterial.FindProperty( "Opacity" );
//              float	fOpacity = OpacityProp != null ? (float) OpacityProp.Value : 1.0f;
//              MatParams.CreateParameter( "Opacity", Scene.Materials.MaterialParameters.PARAMETER_TYPE.FLOAT ).AsFloat.Value = fOpacity;
// //				MatParams.IsOpaque = fOpacity >= 1.0f;
//
//              bool	bHasNormalTexture = CreateTextureParameter( Mat, "Bump", MatParams, "NormalTexture" );
//              MatParams.CreateParameter( "HasNormalTexture", Scene.Materials.MaterialParameters.PARAMETER_TYPE.BOOL ).AsBool.Value = bHasNormalTexture;


                // Lambert parameters
                MatParams.CreateParameter("AmbientColor", Scene.Materials.MaterialParameters.PARAMETER_TYPE.FLOAT3).AsFloat3.Value = SpecificMaterial.FindProperty("AmbientColor").AsVector3;
                CreateTextureParameter(Mat, "AmbientColor", MatParams, "AmbientTexture");
                MatParams.CreateParameter("AmbientFactor", Scene.Materials.MaterialParameters.PARAMETER_TYPE.FLOAT).AsFloat.Value = SpecificMaterial.FindProperty("AmbientFactor").AsFloat;

                MatParams.CreateParameter("DiffuseColor", Scene.Materials.MaterialParameters.PARAMETER_TYPE.FLOAT3).AsFloat3.Value = SpecificMaterial.FindProperty("DiffuseColor").AsVector3;
                MatParams.CreateParameter("DiffuseFactor", Scene.Materials.MaterialParameters.PARAMETER_TYPE.FLOAT).AsFloat.Value  = SpecificMaterial.FindProperty("DiffuseFactor").AsFloat;
                bool bHasDiffuseTexture = CreateTextureParameter(Mat, "DiffuseColor", MatParams, "DiffuseTexture", "TransparentColor");
                MatParams.CreateParameter("HasDiffuseTexture", Scene.Materials.MaterialParameters.PARAMETER_TYPE.BOOL).AsBool.Value = bHasDiffuseTexture;

                MatParams.CreateParameter("EmissiveColor", Scene.Materials.MaterialParameters.PARAMETER_TYPE.FLOAT3).AsFloat3.Value = SpecificMaterial.FindProperty("EmissiveColor").AsVector3;
                MatParams.CreateParameter("EmissiveFactor", Scene.Materials.MaterialParameters.PARAMETER_TYPE.FLOAT).AsFloat.Value  = SpecificMaterial.FindProperty("EmissiveFactor").AsFloat;
                bool bHasEmissiveTexture = CreateTextureParameter(Mat, "EmissiveColor", MatParams, "EmissiveTexture");

                float fOpacity = SpecificMaterial.FindProperty("Opacity").AsFloat;
                MatParams.CreateParameter("Opacity", Scene.Materials.MaterialParameters.PARAMETER_TYPE.FLOAT).AsFloat.Value = fOpacity;
//					MatParams.IsOpaque = fOpacity >= 1.0f;

                bool bHasNormalTexture = false;
                if (Mat.FindProperty("Bump").Textures.Length > 0)
                {
                    bHasNormalTexture = CreateTextureParameter(Mat, "Bump", MatParams, "NormalTexture");
                }
                else if (Mat.FindProperty("NormalMap").Textures.Length > 0)
                {
                    bHasNormalTexture = CreateTextureParameter(Mat, "NormalMap", MatParams, "NormalTexture");
                }
                MatParams.CreateParameter("HasNormalTexture", Scene.Materials.MaterialParameters.PARAMETER_TYPE.BOOL).AsBool.Value = bHasNormalTexture;


                // Phong parameters
                try
                {
                    MatParams.CreateParameter("ReflectionColor", Scene.Materials.MaterialParameters.PARAMETER_TYPE.FLOAT3).AsFloat3.Value = SpecificMaterial.FindProperty("ReflectionColor").AsVector3;
                    CreateTextureParameter(Mat, "ReflectionColor", MatParams, "ReflectionTexture");
                    MatParams.CreateParameter("ReflectionFactor", Scene.Materials.MaterialParameters.PARAMETER_TYPE.FLOAT).AsFloat.Value = SpecificMaterial.FindProperty("ReflectionFactor").AsFloat;

                    MatParams.CreateParameter("Shininess", Scene.Materials.MaterialParameters.PARAMETER_TYPE.FLOAT).AsFloat.Value       = SpecificMaterial.FindProperty("Shininess").AsFloat;
                    MatParams.CreateParameter("SpecularColor", Scene.Materials.MaterialParameters.PARAMETER_TYPE.FLOAT3).AsFloat3.Value = SpecificMaterial.FindProperty("SpecularColor").AsVector3;
                    MatParams.CreateParameter("SpecularFactor", Scene.Materials.MaterialParameters.PARAMETER_TYPE.FLOAT).AsFloat.Value  = SpecificMaterial.FindProperty("SpecularFactor").AsFloat;
                    bool bHasSpecularTexture = CreateTextureParameter(Mat, "SpecularColor", MatParams, "SpecularTexture");
                    MatParams.CreateParameter("HasSpecularTexture", Scene.Materials.MaterialParameters.PARAMETER_TYPE.BOOL).AsBool.Value = bHasSpecularTexture;
                }
                catch (Exception)
                {
                }

                // Register the material
                m_Material2Parameters[Mat] = MatParams;
            }
        }
コード例 #4
0
ファイル: SceneLoader.cs プロジェクト: vr3d/GodComplex
        /// <summary>
        /// Optimizes the existing meshes and build the primitives necessary for runtime display
        /// This will attempt to compact identical meshes and also consolidate mesh primitives
        /// </summary>
        protected void  BuildConsolidatedMeshes()
        {
            // 1] Retrieve all existing meshes and compact identical instances
            List <LoaderTempMesh> CompactedMeshes = new List <LoaderTempMesh>();

            foreach (LoaderTempMesh M in m_TempMesh2FinalMesh.Keys)
            {
                // Check the existing meshes to see if they might be a master to this mesh
                if (m_bCompactIdenticalMeshes)
                {
                    foreach (LoaderTempMesh MasterMesh in CompactedMeshes)
                    {
                        if (M.MergeWithMasterMesh(MasterMesh))
                        {
                            break;                              // We found this mesh's master!
                        }
                    }
                }
                CompactedMeshes.Add(M);
            }

            // 2] Consolidate master meshes
//			WMath.Global.PushEpsilon( 1e-3f );	// Use this new epsilon for float comparisons in the Math library...

            foreach (LoaderTempMesh M in CompactedMeshes)
            {
                M.PerformConsolidation();
            }

//			WMath.Global.PopEpsilon();

            // 3] Rebuild slave meshes from consolidated meshes
            foreach (LoaderTempMesh M in CompactedMeshes)
            {
                M.RebuildFromMasterMesh();
            }


            // 4] Convert the mesh into a clean consolidated mesh
            PrimitiveBuilder Builder = new PrimitiveBuilder();
            foreach (LoaderTempMesh M in CompactedMeshes)
            {
                Scene.Nodes.Mesh TargetMesh = m_TempMesh2FinalMesh[M];

                // Setup basic mesh infos
                TargetMesh.BBox = M.BoundingBox;

                // I know it's a bit of a lousy approximation for the b-sphere but we can always refine it later...
                TargetMesh.BSphere = new BoundingSphere(M.BoundingBox.Center, 0.5f * M.BoundingBox.Dim.Magnitude());

                // Build primitives
                int PrimitiveIndex = 0;
                foreach (LoaderTempMesh.Primitive P in M.ConsolidatedPrimitives)
                {
                    if (P.Material == null)
                    {
                        throw new Exception("Primitive \"" + P.Name + "\" has no assigned material!");
                    }

                    Scene.Materials.MaterialParameters MatParams = m_Material2Parameters[P.Material];

//                  if ( !m_Material2Technique.ContainsKey( P.Material ) )
//                      continue;	// Un-supported...

                    // Create the temporary builder that will handle the primitive conversion
                    Builder.CreatePrimitive(P, TargetMesh, M.Name + "." + PrimitiveIndex++, MatParams);
                }
            }
        }
コード例 #5
0
        public Scene.Nodes.Mesh.Primitive       CreatePrimitive(LoaderTempMesh.Primitive _SourcePrimitive, Scene.Nodes.Mesh _ParentMesh, string _Name, Scene.Materials.MaterialParameters _MatParams)
        {
            m_SourcePrimitive = _SourcePrimitive;

            Scene.Nodes.Mesh.Primitive Target = _ParentMesh.AddPrimitive(_Name, _MatParams, _SourcePrimitive.VerticesCount, _SourcePrimitive.FacesCount);

            // Build the primitive's triangles
            for (int FaceIndex = 0; FaceIndex < _SourcePrimitive.FacesCount; FaceIndex++)
            {
                Target.Faces[FaceIndex].V0 = _SourcePrimitive.Faces[FaceIndex].V0.m_Index;
                Target.Faces[FaceIndex].V1 = _SourcePrimitive.Faces[FaceIndex].V1.m_Index;
                Target.Faces[FaceIndex].V2 = _SourcePrimitive.Faces[FaceIndex].V2.m_Index;
            }

            // Build the primitive's vertex streams
            int[] StreamIndices = new int[8];
            foreach (LoaderTempMesh.Primitive.VertexStream Stream in m_SourcePrimitive.VertexStreams)
            {
                Scene.Nodes.Mesh.Primitive.VertexStream.USAGE      Usage     = Scene.Nodes.Mesh.Primitive.VertexStream.USAGE.UNKNOWN;
                Scene.Nodes.Mesh.Primitive.VertexStream.FIELD_TYPE FieldType = Scene.Nodes.Mesh.Primitive.VertexStream.FIELD_TYPE.UNKNOWN;
                object Content = null;

                switch (Stream.StreamType)
                {
                case LoaderTempMesh.VERTEX_INFO_TYPE.POSITION:
                {
                    Usage     = Scene.Nodes.Mesh.Primitive.VertexStream.USAGE.POSITION;
                    FieldType = Scene.Nodes.Mesh.Primitive.VertexStream.FIELD_TYPE.FLOAT3;
                    Vector[] T = new Vector[_SourcePrimitive.VerticesCount];
                    Content = T;
                    for (int i = 0; i < _SourcePrimitive.VerticesCount; i++)
                    {
                        T[i] = (Vector)(Stream.Stream[i] as WMath.Point);
                    }
                }
                break;

                case LoaderTempMesh.VERTEX_INFO_TYPE.NORMAL:
                {
                    Usage     = Scene.Nodes.Mesh.Primitive.VertexStream.USAGE.NORMAL;
                    FieldType = Scene.Nodes.Mesh.Primitive.VertexStream.FIELD_TYPE.FLOAT3;
                    Vector[] T = new Vector[_SourcePrimitive.VerticesCount];
                    Content = T;
                    for (int i = 0; i < _SourcePrimitive.VerticesCount; i++)
                    {
                        T[i] = Stream.Stream[i] as WMath.Vector;
                    }
                }
                break;

                case LoaderTempMesh.VERTEX_INFO_TYPE.TANGENT:
                {
                    Usage     = Scene.Nodes.Mesh.Primitive.VertexStream.USAGE.TANGENT;
                    FieldType = Scene.Nodes.Mesh.Primitive.VertexStream.FIELD_TYPE.FLOAT3;
                    Vector[] T = new Vector[_SourcePrimitive.VerticesCount];
                    Content = T;
                    for (int i = 0; i < _SourcePrimitive.VerticesCount; i++)
                    {
                        T[i] = Stream.Stream[i] as WMath.Vector;
                    }
                }
                break;

                case LoaderTempMesh.VERTEX_INFO_TYPE.BINORMAL:
                {
                    Usage     = Scene.Nodes.Mesh.Primitive.VertexStream.USAGE.BITANGENT;
                    FieldType = Scene.Nodes.Mesh.Primitive.VertexStream.FIELD_TYPE.FLOAT3;
                    Vector[] T = new Vector[_SourcePrimitive.VerticesCount];
                    Content = T;
                    for (int i = 0; i < _SourcePrimitive.VerticesCount; i++)
                    {
                        T[i] = Stream.Stream[i] as WMath.Vector;
                    }
                }
                break;

                case LoaderTempMesh.VERTEX_INFO_TYPE.TEXCOORD1D:
                {
                    Usage     = Scene.Nodes.Mesh.Primitive.VertexStream.USAGE.TEXCOORDS;
                    FieldType = Scene.Nodes.Mesh.Primitive.VertexStream.FIELD_TYPE.FLOAT;
                    float[] T = new float[_SourcePrimitive.VerticesCount];
                    Content = T;
                    for (int i = 0; i < _SourcePrimitive.VerticesCount; i++)
                    {
                        T[i] = (float)Stream.Stream[i];
                    }
                }
                break;

                case LoaderTempMesh.VERTEX_INFO_TYPE.TEXCOORD2D:
                {
                    Usage     = Scene.Nodes.Mesh.Primitive.VertexStream.USAGE.TEXCOORDS;
                    FieldType = Scene.Nodes.Mesh.Primitive.VertexStream.FIELD_TYPE.FLOAT2;
                    Vector2D[] T = new Vector2D[_SourcePrimitive.VerticesCount];
                    Content = T;
                    for (int i = 0; i < _SourcePrimitive.VerticesCount; i++)
                    {
                        T[i]   = Stream.Stream[i] as WMath.Vector2D;
                        T[i].Y = 1.0f - T[i].Y;                                         // Here we must complement the V coordinate as MAX has the bad habit of inverting the Y axis of images!
                    }
                }
                break;

                case LoaderTempMesh.VERTEX_INFO_TYPE.TEXCOORD3D:
                {
                    Usage     = Scene.Nodes.Mesh.Primitive.VertexStream.USAGE.TEXCOORDS;
                    FieldType = Scene.Nodes.Mesh.Primitive.VertexStream.FIELD_TYPE.FLOAT3;
                    Vector[] T = new Vector[_SourcePrimitive.VerticesCount];
                    Content = T;
                    for (int i = 0; i < _SourcePrimitive.VerticesCount; i++)
                    {
                        T[i]   = Stream.Stream[i] as WMath.Vector;
                        T[i].Y = 1.0f - T[i].Y;                                         // Here we must complement the V coordinate as MAX has the bad habit of inverting the Y axis of images!
                    }
                }
                break;

                case LoaderTempMesh.VERTEX_INFO_TYPE.COLOR_HDR:
                {
                    Usage     = Scene.Nodes.Mesh.Primitive.VertexStream.USAGE.COLOR_HDR;
                    FieldType = Scene.Nodes.Mesh.Primitive.VertexStream.FIELD_TYPE.FLOAT4;
                    Vector4D[] T = new Vector4D[_SourcePrimitive.VerticesCount];
                    Content = T;
                    for (int i = 0; i < _SourcePrimitive.VerticesCount; i++)
                    {
                        T[i] = Stream.Stream[i] as WMath.Vector4D;
                    }
                }
                break;
                }

                if (Usage == Scene.Nodes.Mesh.Primitive.VertexStream.USAGE.UNKNOWN ||
                    FieldType == Scene.Nodes.Mesh.Primitive.VertexStream.FIELD_TYPE.UNKNOWN)
                {
                    continue;                           // Unsupported... Should we throw?
                }
                if (Content == null)
                {
                    throw new Exception("Invalid content!");
                }

                int StreamIndexIndex = (int)Usage - 1;                          // Skip UNKNOWN usage and use the value as "stream type"
                int StreamIndex      = StreamIndices[StreamIndexIndex];
                StreamIndices[StreamIndexIndex]++;                              // Increase stream index

                Target.AddVertexStream(Usage, FieldType, StreamIndex, Content);

                StreamIndex++;
            }

            return(Target);
        }