/// <summary>
        /// Returns the submesh for this face based on material info.
        /// </summary>
        /// <param name='f'>The face to find a submesh for.</param>
        public KeyValuePair <IntermediateMaterial, List <int> > FindOrCreateSubMesh(Face f)
        {
            ExternalReference externalRef = null;

            if (Header.Parent != null)
            {
                externalRef = Header.Parent as ExternalReference;
            }

            // Fetch palettes
            MaterialPalette mp = null;

            if (f.MaterialIndex != -1)
            {
                if (externalRef != null)
                {
                    externalRef.Header.MaterialPalettes.TryGetValue(f.MaterialIndex, out mp);
                }

                if (mp == null)
                {
                    Header.MaterialPalettes.TryGetValue(f.MaterialIndex, out mp);
                }

                if (mp == null)
                {
                    Log.WriteError("Could not find material palette: " + f.MaterialIndex);
                }
            }

            TexturePalette mainTex = null;

            if (f.TexturePattern != -1)
            {
                if (externalRef != null)
                {
                    externalRef.Header.TexturePalettes.TryGetValue(f.TexturePattern, out mainTex);
                }

                if (mainTex == null)
                {
                    Header.TexturePalettes.TryGetValue(f.TexturePattern, out mainTex);
                }

                if (mainTex == null)
                {
                    Log.WriteError("Could not find texture pattern: " + f.TexturePattern);
                }
            }

            TexturePalette detailTex = null;

            if (f.DetailTexturePattern != -1)
            {
                if (externalRef != null)
                {
                    externalRef.Header.TexturePalettes.TryGetValue(f.DetailTexturePattern, out detailTex);
                }

                if (mainTex == null)
                {
                    Header.TexturePalettes.TryGetValue(f.DetailTexturePattern, out detailTex);
                }

                if (mainTex == null)
                {
                    Log.WriteError("Could not find detail texture pattern: " + f.DetailTexturePattern);
                }
            }

            // Check locally
            foreach (KeyValuePair <IntermediateMaterial, List <int> > mesh in SubMeshes)
            {
                if (mesh.Key.Equals(mp, mainTex, detailTex, f.Transparency, f.LightMode))
                {
                    return(mesh);
                }
            }

            // Create a new submesh
            IntermediateMaterial im = Header.MaterialBank.FindOrCreateMaterial(f);
            KeyValuePair <IntermediateMaterial, List <int> > newMesh = new KeyValuePair <IntermediateMaterial, List <int> >(im, new List <int>());

            SubMeshes.Add(newMesh);
            return(newMesh);
        }
예제 #2
0
        public override IntermediateModel Process(IntermediateModelDef input, ContentProcessorContext context)
        {
            Scale = Scale == 0.0f ? 1.0f : Scale;

            model = new IntermediateModel();

            String prefix      = context.OutputDirectory;
            String wholeName   = context.OutputFilename;
            String partialName = wholeName.Substring(prefix.Length);
            String modelName   = partialName.Replace("\\\\", "\\");

            modelName = modelName.Replace(".xnb", "").Replace(".XNB", "");

            // Get the custom data associated with the model
            model.CustomData = ProcessCustomData(context);

            var scaleCustomData = model.CustomData["Scale"];

            if (scaleCustomData != null)
            {
                Scale = Convert.ToSingle(scaleCustomData.Value);
            }

            List <IntermediateModelMesh> imms = new List <IntermediateModelMesh>();

            for (int i = 0; i < input.ModelMeshes.Count; ++i)
            {
                var modelMesh = input.ModelMeshes[i];

                IntermediateModelMesh imm          = new IntermediateModelMesh();
                ModelMeshVertex[]     vertices     = new ModelMeshVertex[modelMesh.Vertices.Length];
                WeightedVertex[]      origVertices = new WeightedVertex[modelMesh.Vertices.Length];

                //DebugNow();

                for (int j = 0; j < modelMesh.Vertices.Length; ++j)
                {
                    if (input.HasSkinningData)
                    {
                        var intermediateWeightedVertex = input.WeightedVertices[modelMesh.Vertices[j].WeightedVertexIndex];
                        vertices[j].Position = Vector3.Transform(intermediateWeightedVertex.Position.ToVector3(), Matrix.CreateScale(Scale));

                        origVertices[j].Weight0           = new Core.Graphics.Primitives.BoneWeight();
                        origVertices[j].Weight0.BoneIndex = intermediateWeightedVertex.JointWeights[0].JointIndex;
                        origVertices[j].Weight0.Weight    = intermediateWeightedVertex.JointWeights[0].Weight;

                        origVertices[j].Weight1           = new Core.Graphics.Primitives.BoneWeight();
                        origVertices[j].Weight1.BoneIndex = intermediateWeightedVertex.JointWeights[1].JointIndex;
                        origVertices[j].Weight1.Weight    = intermediateWeightedVertex.JointWeights[1].Weight;

                        origVertices[j].Weight2           = new Core.Graphics.Primitives.BoneWeight();
                        origVertices[j].Weight2.BoneIndex = intermediateWeightedVertex.JointWeights[2].JointIndex;
                        origVertices[j].Weight2.Weight    = intermediateWeightedVertex.JointWeights[2].Weight;

                        origVertices[j].Weight3           = new Core.Graphics.Primitives.BoneWeight();
                        origVertices[j].Weight3.BoneIndex = intermediateWeightedVertex.JointWeights[3].JointIndex;
                        origVertices[j].Weight3.Weight    = intermediateWeightedVertex.JointWeights[3].Weight;
                    }
                    else
                    {
                        vertices[j].Position = Vector3.Transform(modelMesh.Vertices[j].Position.ToVector3(), Matrix.CreateScale(Scale));
                    }

                    vertices[j].Normal             = Vector3.TransformNormal(modelMesh.Vertices[j].Normal.ToVector3(), Matrix.CreateScale(Scale));
                    vertices[j].TextureCoordinate0 = modelMesh.Vertices[j].TextureCoordinate0.ToVector2();
                    vertices[j].Tangent            = modelMesh.Vertices[j].Tangent.ToVector3();
                    vertices[j].Binormal           = modelMesh.Vertices[j].Binormal.ToVector3();
                }

                OpaqueDataDictionary settings = new OpaqueDataDictionary();
                settings["GenerateMipmaps"] = true;

                IntermediateMaterial im = new IntermediateMaterial();
                im.Name          = modelMesh.Material.Name;
                im.DiffuseColor  = modelMesh.Material.DiffuseColor.ToVector3();
                im.SpecularColor = modelMesh.Material.SpecularColor.ToVector3();
                im.SpecularExp   = modelMesh.Material.CosinePower.AsSingle();
                im.Transparency  = modelMesh.Material.Transparency.AsSingle();
                im.UseAlpha      = modelMesh.Material.UseAlpha.AsBoolean();
                im.DrawBackfaces = modelMesh.Material.DrawBackfaces.AsBoolean();
                im.Reflectivity  = modelMesh.Material.Reflectivity.AsSingle();

                //DebugNow();

                im.DiffuseMapName = modelMesh.Material.DiffuseMapFilename.AsString();
                if (!String.IsNullOrEmpty(im.DiffuseMapName))
                {
                    //im.DiffuseMapReference = context.BuildAsset<TextureContent, TextureContent>(
                    //    new ExternalReference<TextureContent>(
                    //        Path.Combine(Path.GetDirectoryName(input.Path), im.DiffuseMapName)), "TextureProcessor", settings, null, null);
                }

                im.NormalMapName = modelMesh.Material.NormalMapFilename.AsString();
                if (!String.IsNullOrEmpty(im.NormalMapName))
                {
                    //im.BumpMapReference = context.BuildAsset<TextureContent, TextureContent>(
                    //    new ExternalReference<TextureContent>(
                    //        Path.Combine(Path.GetDirectoryName(input.Path), im.BumpMapName)), "TextureProcessor", settings, null, null);
                }

                im.SpecularMapName = modelMesh.Material.SpecularMapFilename.AsString();
                if (!String.IsNullOrEmpty(im.SpecularMapName))
                {
                    //im.SpecularMapReference = context.BuildAsset<TextureContent, TextureContent>(
                    //    new ExternalReference<TextureContent>(
                    //        Path.Combine(Path.GetDirectoryName(input.Path), im.SpecularMapName)), "TextureProcessor", settings, null, null);
                }

                imm.Indices = modelMesh.Indices.ToInt32Array();
                for (int k = 0; k <= imm.Indices.Length - 3; k += 3)
                {
                    var temp = imm.Indices[k];
                    imm.Indices[k]     = imm.Indices[k + 2];
                    imm.Indices[k + 2] = temp;
                }

                imm.Vertices         = vertices;
                imm.OriginalVertices = origVertices;
                imm.BoundingSphere   = BoundingSphere.CreateFromPoints(vertices.Select(v => v.Position));
                imm.BoundingBox      = BoundingBox.CreateFromPoints(vertices.Select(v => v.Position));
                imm.Material         = im;

                imms.Add(imm);
            }

            // Animation stuff
            List <Matrix>             bindPose          = new List <Matrix>();
            List <Matrix>             inverseBindPose   = new List <Matrix>();
            List <int>                skeletonHierarchy = new List <int>();
            IDictionary <string, int> boneMap           = new Dictionary <string, int>();
            IList <String>            boneNames         = new List <String>(input.BindPose.Count);

            for (int i = 0; i < input.BindPose.Count; boneNames.Add(String.Empty), ++i)
            {
                ;
            }

            //DebugNow();

            foreach (var joint in input.BindPose)
            {
                Matrix transform = Matrix.CreateFromQuaternion(joint.Rotation.ToQuaternion()) * joint.Position.ToTranslationMatrix();
                transform.Translation *= Scale;

                Matrix absoluteTransform = Matrix.CreateFromQuaternion(joint.AbsoluteRotation.ToQuaternion()) *
                                           joint.AbsolutePosition.ToTranslationMatrix();
                absoluteTransform.Translation *= Scale;

                bindPose.Add(transform);
                inverseBindPose.Add(Matrix.Invert(absoluteTransform));
                skeletonHierarchy.Add(joint.ParentIndex);
                boneNames[joint.Index] = joint.Name;
                boneMap.Add(joint.Name, joint.Index);
            }

            var animationClips = ProcessAnimations(input.AnimationKeyframes, input.BindPose, boneNames);
            var skinningData   = new SkinningData(bindPose, inverseBindPose, skeletonHierarchy, boneMap, boneNames, modelName);
            var animations     = PrepareAnimations(animationClips, skinningData, context);

            model.ModelMeshes    = imms.ToArray();
            model.AnimationMap   = animations;
            model.SkinningData   = skinningData;
            model.BoundingSphere = BoundingSphere.CreateFromPoints(imms.SelectMany(m => m.Vertices.Select(v => v.Position)));
            model.BoundingBox    = BoundingBox.CreateFromPoints(imms.SelectMany(m => m.Vertices.Select(v => v.Position)));

            return(model);
        }