#region License // Copyright 2016 Kastellanos Nikolaos // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #endregion using System; using System.Collections.Generic; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Content.Pipeline; using Microsoft.Xna.Framework.Content.Pipeline.Processors; using Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler; using nkast.Aether.Content.Pipeline.Graphics; namespace nkast.Aether.Content.Pipeline.Serialization { [ContentTypeWriter] class DynamicModelWriter : ContentTypeWriter { /// /// Write a Model xnb, compatible with the XNB Container Format. /// protected override void Write(ContentWriter output, DynamicModelContent model) { WriteBones(output, model.Bones); WriteMeshes(output, model, model.Meshes); WriteBoneReference(output, model.Bones.Count, model.Source.Root); output.WriteObject(model.Source.Tag); return; } private void WriteBones(ContentWriter output, ModelBoneContentCollection bones) { int bonesCount = bones.Count; output.Write((UInt32)bonesCount); foreach (ModelBoneContent bone in bones) { output.WriteObject(bone.Name); output.Write(bone.Transform); } foreach (ModelBoneContent bone in bones) { WriteBoneReference(output, bonesCount, bone.Parent); output.Write((uint)bone.Children.Count); foreach (ModelBoneContent child in bone.Children) WriteBoneReference(output, bonesCount, child); } return; } // The BoneReference type varies in size depending on the number of bones in the model. // If bone count is less than 255 this value is serialized as a Byte, otherwise it is UInt32. // If the reference value is zero the bone is null, otherwise (bone reference - 1) is an index into the model bone list. private void WriteBoneReference(ContentWriter output, int bonesCount, ModelBoneContent bone) { if (bone == null) output.Write((byte)0); else if (bonesCount < 255) output.Write((byte)(bone.Index + 1)); else output.Write((UInt32)(bone.Index + 1)); } private void WriteMeshes(ContentWriter output, DynamicModelContent model, List meshes) { output.Write((UInt32)meshes.Count); int bonesCount = model.Bones.Count; foreach (DynamicModelMeshContent mesh in meshes) { output.WriteObject(mesh.Name); WriteBoneReference(output, bonesCount, mesh.ParentBone); WriteBoundingSphere(output, mesh.BoundingSphere); output.WriteObject(mesh.Tag); WriteParts(output, model, mesh.MeshParts); } return; } private void WriteBoundingSphere(ContentWriter output, BoundingSphere value) { output.Write(value.Center); output.Write(value.Radius); } private void WriteParts(ContentWriter output, DynamicModelContent model, List parts) { output.Write((UInt32)parts.Count); foreach (DynamicModelMeshPartContent part in parts) { output.Write((UInt32)part.VertexOffset); output.Write((UInt32)part.NumVertices); output.Write((UInt32)part.StartIndex); output.Write((UInt32)part.PrimitiveCount); output.WriteObject(part.Tag); output.WriteSharedResource(part.VertexBuffer); output.WriteSharedResource(part.IndexBuffer); output.WriteSharedResource(part.Material); } return; } public override string GetRuntimeType(TargetPlatform targetPlatform) { return "Microsoft.Xna.Framework.Graphics.Model"; } public override string GetRuntimeReader(TargetPlatform targetPlatform) { return "Microsoft.Xna.Framework.Content.ModelReader, Microsoft.Xna.Framework.Graphics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553"; } } }