/// <summary> /// Load an FBX file from a file on disk. /// </summary> /// <param name="filename"> /// The filename of the FBX file to load. /// </param> /// <param name="additionalAnimationFiles"> /// A dictionary mapping of animation names to filenames for additional FBX files to load. /// </param> /// <returns> /// The loaded <see cref="IModel"/>. /// </returns> public IModel Load(string filename, Dictionary <string, string> additionalAnimationFiles) { this.LoadAssimpLibrary(); // Import the scene via AssImp. var importer = new AssimpContext(); const PostProcessSteps ProcessFlags = 0 | PostProcessSteps.FlipUVs | PostProcessSteps.FlipWindingOrder ; var scene = importer.ImportFile(filename, ProcessFlags); VertexPositionNormalTextureBlendable[] vertexes; int[] indices; IModelBone boneHierarchy; if (scene.MeshCount >= 1) { var boneWeightingMap = this.BuildBoneWeightingMap(scene); boneHierarchy = this.ImportBoneHierarchy(scene.RootNode, scene.Meshes[0]); vertexes = this.ImportVertexes(scene, boneWeightingMap); indices = this.ImportIndices(scene); } else { boneHierarchy = this.ImportBoneHierarchy(scene.RootNode, null); vertexes = new VertexPositionNormalTextureBlendable[0]; indices = new int[0]; } // Create the list of animations, including the null animation. var animations = new List <IAnimation>(); // Import the basic animation. if (scene.AnimationCount > 0) { animations.AddRange( scene.Animations.Select( assimpAnimation => this.ImportAnimation(assimpAnimation.Name, assimpAnimation))); } // For each additional animation file, import that and add the animation to the existing scene. animations.AddRange( from kv in additionalAnimationFiles let animationImporter = new AssimpContext() let additionalScene = animationImporter.ImportFile(kv.Value, ProcessFlags) where additionalScene.AnimationCount == 1 select this.ImportAnimation(kv.Key, additionalScene.Animations[0])); // Return the resulting model. return(new Model( new AnimationCollection(animations), boneHierarchy, vertexes, indices)); }
/// <summary> /// Initializes a new instance of the <see cref="Model"/> class. /// </summary> /// <param name="availableAnimations"> /// The available animations. /// </param> /// <param name="rootBone"> /// The root bone, or null if there's no skeletal information. /// </param> /// <param name="vertexes"> /// The vertexes associated with this model. /// </param> /// <param name="indices"> /// The indices associated with the model. /// </param> public Model( IAnimationCollection availableAnimations, IModelBone rootBone, VertexPositionNormalTextureBlendable[] vertexes, int[] indices) { this.AvailableAnimations = availableAnimations; this.Root = rootBone; this.Vertexes = vertexes; this.Indices = indices; if (this.Root != null) { this.m_FlattenedBones = this.Root.Flatten(); this.Bones = this.m_FlattenedBones.ToDictionary(k => k.Name, v => v); } }
/// <summary> /// Indicates whether this instance and a specified object are equal. /// </summary> /// <param name="other"> /// The object to compare this instance to. /// </param> /// <returns> /// Whether or not this instance is equal to the specified object. /// </returns> public bool Equals(VertexPositionNormalTextureBlendable other) { return(this.Position.Equals(other.Position) && this.Normal.Equals(other.Normal) && this.TextureCoordinate.Equals(other.TextureCoordinate) && this.BoneWeights.Equals(other.BoneWeights) && this.BoneIndices.Equals(other.BoneIndices)); }
/// <summary> /// Indicates whether this instance and a specified object are equal. /// </summary> /// <param name="other"> /// The object to compare this instance to. /// </param> /// <returns> /// Whether or not this instance is equal to the specified object. /// </returns> public bool Equals(VertexPositionNormalTextureBlendable other) { return this.Position.Equals(other.Position) && this.Normal.Equals(other.Normal) && this.TextureCoordinate.Equals(other.TextureCoordinate) && this.BoneWeights.Equals(other.BoneWeights) && this.BoneIndices.Equals(other.BoneIndices); }