public HeightMapInfoContent(ModelContent model, MeshContent terrainMesh, float terrainScale, int terrainWidth, int terrainLength)
        {
            Model = model;
            if (terrainMesh == null)
            {
                throw new ArgumentNullException("terrainMesh");
            }

            if (terrainWidth <= 0)
            {
                throw new ArgumentOutOfRangeException("terrainWidth");
            }
            if (terrainLength <= 0)
            {
                throw new ArgumentOutOfRangeException("terrainLength");
            }

            TerrainScale = terrainScale;
            Height       = new float[terrainWidth, terrainLength];
            Normals      = new Vector3[terrainWidth, terrainLength];
            GeometryContent item = terrainMesh.Geometry[0];

            for (int i = 0; i < item.Vertices.VertexCount; i++)
            {
                Vector3 vector3 = item.Vertices.Positions[i];
                Vector3 item1   = (Vector3)item.Vertices.Channels[VertexChannelNames.Normal()][i];
                int     x       = (int)(vector3.X / terrainScale + (terrainWidth - 1) / 2f);
                int     z       = (int)(vector3.Z / terrainScale + (terrainLength - 1) / 2f);
                Height[x, z]  = vector3.Y;
                Normals[x, z] = item1;
            }
        }
Example #2
0
        public static bool NeedsSplitting(MeshContent mesh, int maxBones)
        {
            SortedDictionary <string, object> skinnedBones = new SortedDictionary <string, object>();

            foreach (GeometryContent geom in mesh.Geometry)
            {
                VertexChannel <BoneWeightCollection> weightChannel = null;
                foreach (VertexChannel channel in geom.Vertices.Channels)
                {
                    if (channel.Name == VertexChannelNames.Weights())
                    {
                        weightChannel = (VertexChannel <BoneWeightCollection>)channel;
                        break;
                    }
                }
                if (weightChannel != null)
                {
                    foreach (BoneWeightCollection weights in weightChannel)
                    {
                        foreach (BoneWeight weight in weights)
                        {
                            if (!skinnedBones.ContainsKey(weight.BoneName))
                            {
                                skinnedBones.Add(weight.BoneName, null);
                            }
                        }
                    }
                }
            }
            return(skinnedBones.Keys.Count > maxBones);
        }
        /// <summary>
        /// Make sure all of the geometry contains a vertex color channel.
        /// </summary>
        /// <param name="mesh"></param>
        private static void EnsureVertexColors(MeshContent mesh)
        {
            foreach (GeometryContent meshPart in mesh.Geometry)
            {
                //if ((meshPart.Name != null) && !meshPart.Name.StartsWith("SCP_"))
                {
                    bool foundColor = false;
                    foreach (VertexChannel channel in meshPart.Vertices.Channels)
                    {
                        if (channel.Name == VertexChannelNames.Color(0))
                        {
                            foundColor = true;
                            break;
                        }
                    }
                    if (!foundColor)
                    {
                        int       cnt    = meshPart.Vertices.VertexCount;
                        Vector4[] colors = new Vector4[cnt];
                        for (int i = 0; i < cnt; ++i)
                        {
                            colors[i] = Vector4.One;
                        }

                        meshPart.Vertices.Channels.Add <Vector4>(
                            VertexChannelNames.Color(0).ToString(), colors);
                    }
                }
            }
        }
        private static void ColorMaterials(MeshContent mesh)
        {
            foreach (GeometryContent meshPart in mesh.Geometry)
            {
                Vector4 constColor = MatColor(meshPart);

                bool foundColor = false;
                foreach (VertexChannel channel in meshPart.Vertices.Channels)
                {
                    if (channel.Name == VertexChannelNames.Color(0))
                    {
                        foundColor = true;
                        VertexChannel <Vector4> colorChannel = (VertexChannel <Vector4>)channel;
                        for (int i = 0; i < colorChannel.Count; ++i)
                        {
                            colorChannel[i] = constColor;
                        }
                    }
                }
                if (!foundColor)
                {
                    int       cnt    = meshPart.Vertices.VertexCount;
                    Vector4[] colors = new Vector4[cnt];
                    for (int i = 0; i < cnt; ++i)
                    {
                        colors[i] = constColor;
                    }

                    meshPart.Vertices.Channels.Add <Vector4>(
                        VertexChannelNames.Color(0).ToString(), colors);
                }
            }
        }
        private static bool MeshHasSkinning(MeshContent mesh)
        {
            bool flag;
            bool flag1;
            IEnumerator <GeometryContent> enumerator = mesh.Geometry.GetEnumerator();

            try {
                do
                {
                    flag1 = enumerator.MoveNext();
                    if (flag1)
                    {
                        GeometryContent current = enumerator.Current;
                        flag1 = current.Vertices.Channels.Contains(VertexChannelNames.Weights());
                    }
                    else
                    {
                        flag = true;
                        return(flag);
                    }
                }while (flag1);
                flag = false;
                return(flag);
            } finally {
                flag1 = enumerator == null;
                if (!flag1)
                {
                    enumerator.Dispose();
                }
            }
            flag = true;
            return(flag);
        }
Example #6
0
        static void ProcessWeightsChannel(GeometryContent geometry, int vertexChannelIndex, SerializableSkeleton skeleton)
        {
            Dictionary <string, int> boneIndices = skeleton.boneIndexByName;

            // convert all of our bone weights into the correct indices and weight values
            VertexChannel <BoneWeightCollection> inputWeights = geometry.Vertices.Channels[vertexChannelIndex] as VertexChannel <BoneWeightCollection>;

            Vector4[] outputIndices = new Vector4[inputWeights.Count];
            Vector4[] outputWeights = new Vector4[inputWeights.Count];
            for (int i = 0; i < inputWeights.Count; i++)
            {
                ConvertWeights(inputWeights[i], boneIndices, outputIndices, outputWeights, i, geometry);
            }

            // create our new channel names
            int    usageIndex  = VertexChannelNames.DecodeUsageIndex(inputWeights.Name);
            string indicesName = VertexChannelNames.EncodeName(Microsoft.Xna.Framework.Graphics.VertexElementUsage.BlendIndices, usageIndex);
            string weightsName = VertexChannelNames.EncodeName(Microsoft.Xna.Framework.Graphics.VertexElementUsage.BlendWeight, usageIndex);

            // add in the index and weight channels
            geometry.Vertices.Channels.Insert(vertexChannelIndex + 1, indicesName, outputIndices);
            geometry.Vertices.Channels.Insert(vertexChannelIndex + 2, weightsName, outputWeights);

            // remove the original weights channel
            geometry.Vertices.Channels.RemoveAt(vertexChannelIndex);
        }
        public void BasicMeshBuilderTest()
        {
            var output = CreateBasicMesh(material1);

            Assert.NotNull(output);
            Assert.NotNull(output.Geometry);
            Assert.NotNull(output.Positions);

            Assert.AreEqual(new Vector3(0, 0, 0), output.Positions[0]);
            Assert.AreEqual(new Vector3(1, 0, 0), output.Positions[1]);
            Assert.AreEqual(new Vector3(1, 1, 1), output.Positions[2]);

            Assert.AreEqual(1, output.Geometry.Count);

            Assert.AreEqual(0, output.Geometry[0].Indices[0]);
            Assert.AreEqual(1, output.Geometry[0].Indices[1]);
            Assert.AreEqual(2, output.Geometry[0].Indices[2]);

            Assert.AreEqual(0, output.Geometry[0].Vertices.PositionIndices[0]);
            Assert.AreEqual(1, output.Geometry[0].Vertices.PositionIndices[1]);
            Assert.AreEqual(2, output.Geometry[0].Vertices.PositionIndices[2]);

            Assert.AreEqual(new Vector3(0, 0, 0), output.Geometry[0].Vertices.Positions[0]);
            Assert.AreEqual(new Vector3(1, 0, 0), output.Geometry[0].Vertices.Positions[1]);
            Assert.AreEqual(new Vector3(1, 1, 1), output.Geometry[0].Vertices.Positions[2]);

            //Check if normals are generated
            Assert.NotNull(output.Geometry[0].Vertices.Channels[VertexChannelNames.Normal(0)]);

            Assert.AreEqual(material1, output.Geometry[0].Material);
            Assert.AreEqual(Matrix.Identity, output.Transform);

            Assert.AreEqual(3, output.Positions.Count);
            Assert.AreEqual("Mesh1", output.Name);
        }
Example #8
0
        private int[] ComputeBoneSet(GeometryContent geometry, ContentProcessorContext context, string asset, Dictionary <string, int> boneIndices)
        {
            SortedDictionary <int, bool> indicesInUse = new SortedDictionary <int, bool>();

            foreach (VertexChannel vc in geometry.Vertices.Channels)
            {
                string str = VertexChannelNames.DecodeBaseName(vc.Name);
                if (str == "Weights")
                {
                    VertexChannel <BoneWeightCollection> channel = vc as VertexChannel <BoneWeightCollection>;
                    if (vc == null)
                    {
                        continue;
                    }
                    for (int n = 0; n < channel.Count; n++)
                    {
                        VertexWeightsInUse(context, asset, channel[n], boneIndices, indicesInUse);
                    }
                }
            }
            int[] values = new int[indicesInUse.Count];
            int   i      = 0;

            foreach (int index in indicesInUse.Keys)
            {
                values[i++] = index;
            }
            return(values);
        }
            /// <summary>
            /// Creates the vertex channel using the MeshBuilder (no data is added yet).
            /// </summary>
            protected virtual void Create()
            {
                var usage      = _colladaVertexChannel.Description.VertexElementUsage;
                int usageIndex = _colladaVertexChannel.Description.UsageIndex;

                // Construct correct usage string
                String usageString = VertexChannelNames.EncodeName(usage, usageIndex);

                // Generic standard channel (TexCoord, Normal, Binormal, etc.)
                switch (_colladaVertexChannel.Description.VertexElementFormat)
                {
                case VertexElementFormat.Vector4:
                    _channelIndex = _meshBuilder.CreateVertexChannel <Vector4>(usageString);
                    break;

                case VertexElementFormat.Vector3:
                    _channelIndex = _meshBuilder.CreateVertexChannel <Vector3>(usageString);
                    break;

                case VertexElementFormat.Vector2:
                    _channelIndex = _meshBuilder.CreateVertexChannel <Vector2>(usageString);
                    break;

                case VertexElementFormat.Single:
                    _channelIndex = _meshBuilder.CreateVertexChannel <Single>(usageString);
                    break;

                default:
                    throw new Exception("Unexpected vertex element format");
                }
            }
Example #10
0
        static void ProcessWeightsChannel(GeometryContent geometry, int vertexChannelIndex)
        {
            // create a map of Name->Index of the bones
            BoneContent skeleton = MeshHelper.FindSkeleton(geometry.Parent);
            Dictionary <string, int> boneIndices    = new Dictionary <string, int>();
            IList <BoneContent>      flattenedBones = MeshHelper.FlattenSkeleton(skeleton);

            for (int i = 0; i < flattenedBones.Count; i++)
            {
                boneIndices.Add(flattenedBones[i].Name, i);
            }

            // convert all of our bone weights into the correct indices and weight values
            VertexChannel <BoneWeightCollection> inputWeights = geometry.Vertices.Channels[vertexChannelIndex] as VertexChannel <BoneWeightCollection>;

            Vector4[] outputIndices = new Vector4[inputWeights.Count];
            Vector4[] outputWeights = new Vector4[inputWeights.Count];
            for (int i = 0; i < inputWeights.Count; i++)
            {
                ConvertWeights(inputWeights[i], boneIndices, outputIndices, outputWeights, i, geometry);
            }

            // create our new channel names
            int    usageIndex  = VertexChannelNames.DecodeUsageIndex(inputWeights.Name);
            string indicesName = VertexChannelNames.EncodeName(VertexElementUsage.BlendIndices, usageIndex);
            string weightsName = VertexChannelNames.EncodeName(VertexElementUsage.BlendWeight, usageIndex);

            // add in the index and weight channels
            geometry.Vertices.Channels.Insert(vertexChannelIndex + 1, indicesName, outputIndices);
            geometry.Vertices.Channels.Insert(vertexChannelIndex + 2, weightsName, outputWeights);

            // remove the original weights channel
            geometry.Vertices.Channels.RemoveAt(vertexChannelIndex);
        }
        /// <summary>
        /// As an optimization, ProcessVertexChannel is overriden to remove data which
        /// is not used by the vertex shader.
        /// </summary>
        /// <param name="geometry">the geometry object which contains the
        /// vertex channel</param>
        /// <param name="vertexChannelIndex">the index of the vertex channel
        /// to operate on</param>
        /// <param name="context">the context that the processor is operating
        /// under.  in most cases, this parameter isn't necessary; but could
        /// be used to log a warning that a channel had been removed.</param>
        protected override void ProcessVertexChannel(GeometryContent geometry,
                                                     int vertexChannelIndex, ContentProcessorContext context)
        {
            String vertexChannelName =
                geometry.Vertices.Channels[vertexChannelIndex].Name;

            // if this vertex channel has an acceptable names, process it as normal.
            if (acceptableVertexChannelNames.Contains(vertexChannelName))
            {
                base.ProcessVertexChannel(geometry, vertexChannelIndex, context);
            }
            // otherwise, remove it from the vertex channels; it's just extra data
            // we don't need.
            else
            {
                geometry.Vertices.Channels.Remove(vertexChannelName);
            }

            // Remove texture channel for untextured meshes
            if (!geometry.Vertices.Channels.Contains(VertexChannelNames.TextureCoordinate(0)))
            {
                geometry.Vertices.Channels.Remove(VertexChannelNames.TextureCoordinate(0));
            }

            // Remove vertex weights for unskinned meshes
            if (!geometry.Vertices.Channels.Contains(VertexChannelNames.Weights()))
            {
                geometry.Vertices.Channels.Remove(VertexChannelNames.Weights());
            }
        }
        private static void ProcessWeightsChannel(
            GeometryContent geometry, int vertexChannelIndex, ContentIdentity identity)
        {
            // NOTE: Portions of this code is from the XNA CPU Skinning
            // sample under Ms-PL, (c) Microsoft Corporation.

            // create a map of Name->Index of the bones
            var skeleton = MeshHelper.FindSkeleton(geometry.Parent);

            if (skeleton == null)
            {
                throw new InvalidContentException(
                          "Skeleton not found. Meshes that contain a Weights vertex channel cannot " +
                          "be processed without access to the skeleton data.",
                          identity);
            }

            var boneIndices    = new Dictionary <string, byte>();
            var flattenedBones = MeshHelper.FlattenSkeleton(skeleton);

            if (flattenedBones.Count > byte.MaxValue)
            {
                throw new NotSupportedException("The flattened skeleton contains more than 255 bones.");
            }

            for (int i = 0; i < flattenedBones.Count; i++)
            {
                boneIndices.Add(flattenedBones[i].Name, (byte)i);
            }

            var vertexChannel = geometry.Vertices.Channels[vertexChannelIndex];

            if (!(vertexChannel is VertexChannel <BoneWeightCollection> inputWeights))
            {
                throw new InvalidContentException(
                          string.Format(
                              "Vertex channel \"{0}\" is the wrong type. It has element type {1}. Type {2} is expected.",
                              vertexChannel.Name, vertexChannel.ElementType.FullName, typeof(BoneWeightCollection).FullName),
                          identity);
            }
            var outputIndices = new Byte4[inputWeights.Count];
            var outputWeights = new Vector4[inputWeights.Count];

            for (var i = 0; i < inputWeights.Count; i++)
            {
                ConvertWeights(inputWeights[i], boneIndices, outputIndices, outputWeights, i);
            }

            // create our new channel names
            var usageIndex  = VertexChannelNames.DecodeUsageIndex(inputWeights.Name);
            var indicesName = VertexChannelNames.EncodeName(VertexElementUsage.BlendIndices, usageIndex);
            var weightsName = VertexChannelNames.EncodeName(VertexElementUsage.BlendWeight, usageIndex);

            // add in the index and weight channels
            geometry.Vertices.Channels.Insert(vertexChannelIndex + 1, indicesName, outputIndices);
            geometry.Vertices.Channels.Insert(vertexChannelIndex + 2, weightsName, outputWeights);

            // remove the original weights channel
            geometry.Vertices.Channels.RemoveAt(vertexChannelIndex);
        }
        public void SetChannelData()
        {
            var mb = MeshBuilder.StartMesh("Test");

            mb.SetMaterial(material1);

            var channelIndex = mb.CreateVertexChannel <Vector2>(VertexChannelNames.TextureCoordinate(0));
            var p1           = mb.CreatePosition(0f, 0f, 0f);
            var p2           = mb.CreatePosition(1f, 0f, 0f);
            var p3           = mb.CreatePosition(0f, 1f, 0f);
            var t1           = Vector2.Zero;
            var t2           = Vector2.UnitX;
            var t3           = Vector2.UnitY;

            // this should be overwritten by the next call
            mb.SetVertexChannelData(channelIndex, t3);
            mb.SetVertexChannelData(channelIndex, t1);

            // setting the material here should not reset the channel data
            mb.SetMaterial(material2);

            mb.AddTriangleVertex(p1);
            mb.SetVertexChannelData(channelIndex, t2);
            mb.AddTriangleVertex(p2);
            mb.SetVertexChannelData(channelIndex, t3);
            mb.AddTriangleVertex(p3);

            var mesh       = mb.FinishMesh();
            var geom       = mesh.Geometry[0];
            var texChannel = geom.Vertices.Channels[channelIndex];

            Assert.AreEqual(t1, texChannel[0]);
            Assert.AreEqual(t2, texChannel[1]);
            Assert.AreEqual(t3, texChannel[2]);
        }
Example #14
0
        public static string GetXNAName(VertexAttribute attr)
        {
            switch (attr.usage)
            {
            case COLOR:
                return(VertexChannelNames.Color(0));

            case NORMAL:
                return(VertexChannelNames.Normal());

            case TEX_COORD:
                return(VertexChannelNames.TextureCoordinate(attr.attrIndex));

            case BONE_WEIGHT:
                return(VertexChannelNames.Weights(attr.attrIndex));

            case TANGENT:
                return(VertexChannelNames.Tangent(0));

            case BINORMAL:
                return(VertexChannelNames.Binormal(0));
            }

            return(null);
        }
        private bool ValidateGeometry(GeometryContent geometry, ContentProcessorContext context)
        {
            // Check if the geometry has material
            if (geometry.Material == null)
            {
                throw new InvalidContentException(string.Format(
                                                      "Mesh {0} has a geometry that does not have a material.", geometry.Parent.Name));
            }

            // Check if the geometry has skinning information
            if (!geometry.Vertices.Channels.Contains(VertexChannelNames.Weights()))
            {
                /*
                 * context.Logger.LogWarning(null, geometry.Parent.Identity,
                 *  string.Format("Mesh {0} has a geometry that does not have a skinning " +
                 *  "blend weights channel and will be skipped.", geometry.Parent.Name));
                 *
                 * geometry.Parent.Geometry.Remove(geometry);
                 */

                throw new InvalidContentException(string.Format("Mesh {0} has a geometry " +
                                                                "that does not have a skinning blend weights channel.", geometry.Parent.Name));
            }

            return(true);
        }
Example #16
0
        private static void ProcessWeightsChannel(ContentProcessorContext context, string asset, GeometryContent geometry, int vertexChannelIndex, Dictionary <string, int> boneIndices, Dictionary <int, int> boneRemap)
        {
            if (boneIndices == null)
            {
                throw new InvalidContentException("Mesh has bone weights with no skeleton");
            }

            VertexChannelCollection channels             = geometry.Vertices.Channels;
            VertexChannel           channel2             = channels[vertexChannelIndex];
            VertexChannel <BoneWeightCollection> channel = channel2 as VertexChannel <BoneWeightCollection>;

            Byte4[]   outputIndices = new Byte4[channel.Count];
            Vector4[] outputWeights = new Vector4[channel.Count];
            for (int i = 0; i < channel.Count; i++)
            {
                BoneWeightCollection inputWeights = channel[i];
                ConvertVertexWeights(context, asset, inputWeights, boneIndices, outputIndices, outputWeights, i, geometry, boneRemap);
            }
            int    usageIndex = VertexChannelNames.DecodeUsageIndex(channel.Name);
            string name       = VertexChannelNames.EncodeName(VertexElementUsage.BlendIndices, usageIndex);
            string str        = VertexChannelNames.EncodeName(VertexElementUsage.BlendWeight, usageIndex);

            channels.Insert <Byte4>(vertexChannelIndex + 1, name, outputIndices);
            channels.Insert <Vector4>(vertexChannelIndex + 2, str, outputWeights);
            channels.RemoveAt(vertexChannelIndex);
        }
Example #17
0
        /// <summary>
        /// This function removes geometry that contains no bone weights, because the ModelProcessor
        /// will throw an exception if we give it geometry content like that.
        /// </summary>
        /// <param name="node"></param>
        /// <param name="context"></param>
        static void RemoveInvalidGeometry(NodeContent node, ContentProcessorContext context)
        {
            MeshContent meshContent = node as MeshContent;

            if (meshContent != null)
            {
                // Maintain a list of all the geometry that was invalid that we will be removing
                List <GeometryContent> removeGeometry = new List <GeometryContent>();
                foreach (GeometryContent geometry in meshContent.Geometry)
                {
                    VertexChannelCollection channels = geometry.Vertices.Channels;

                    // Does this geometry contain bone weight information?
                    if (geometry.Vertices.Channels.Contains(VertexChannelNames.Weights(0)))
                    {
                        bool removed = false;

                        VertexChannel <BoneWeightCollection> weights = geometry.Vertices.Channels.Get <BoneWeightCollection>(VertexChannelNames.Weights(0));
                        foreach (BoneWeightCollection collection in weights)
                        {
                            // If we don't have any weights, then this isn't going to be good. The geometry has no bone weights,
                            // so lets just remove it.
                            if (collection.Count <= 0)
                            {
                                removeGeometry.Add(geometry);
                                removed = true;
                                break;
                            }
                            else
                            {
                                // Otherwise, normalize the weights. This call is probably unnecessary.
                                collection.NormalizeWeights(4);
                            }
                        }

                        //If we removed something from this geometry, just remove the whole geometry - there's no point in going farther
                        if (removed)
                        {
                            break;
                        }
                    }
                }

                // Remove all the invalid geometry we found, and log a warning.
                foreach (GeometryContent geometry in removeGeometry)
                {
                    meshContent.Geometry.Remove(geometry);
                    context.Logger.LogWarning(null, null,
                                              "Mesh part {0} has been removed because it has no bone weights associated with it.",
                                              geometry.Name);
                }
            }

            // Recursively call this function for each child
            foreach (NodeContent child in node.Children)
            {
                RemoveInvalidGeometry(child, context);
            }
        }
        /// <summary>
        /// Converts a single piece of input geometry into our instanced format.
        /// </summary>
        void ProcessGeometry(GeometryContent geometry)
        {
            int indexCount  = geometry.Indices.Count;
            int vertexCount = geometry.Vertices.VertexCount;

            // Validate that the number of vertices is suitable for instancing.
            if (vertexCount > ushort.MaxValue)
            {
                throw new InvalidContentException(
                          string.Format("Geometry contains {0} vertices: " +
                                        "this is too many to be instanced.", vertexCount));
            }

            if (vertexCount > ushort.MaxValue / 8)
            {
                context.Logger.LogWarning(null, rootNode.Identity,
                                          "Geometry contains {0} vertices: " +
                                          "this will only allow it to be instanced " +
                                          "{1} times per batch. A model with fewer " +
                                          "vertices would be more efficient.",
                                          vertexCount, ushort.MaxValue / vertexCount);
            }

            // Validate that the vertex channels we are going to use to pass
            // through our instancing data aren't already in use.
            VertexChannelCollection vertexChannels = geometry.Vertices.Channels;

            for (int i = 1; i <= 4; i++)
            {
                if (vertexChannels.Contains(VertexChannelNames.TextureCoordinate(i)))
                {
                    throw new InvalidContentException(
                              string.Format("Model already contains data for texture " +
                                            "coordinate channel {0}, but instancing " +
                                            "requires this channel for its own use.", i));
                }
            }

            // Flatten the flexible input vertex channel data into
            // a simple GPU style vertex buffer byte array.
            VertexBufferContent vertexBufferContent;

            VertexElement[] vertexElements;

            geometry.Vertices.CreateVertexBuffer(out vertexBufferContent,
                                                 out vertexElements,
                                                 context.TargetPlatform);

            int vertexStride = VertexDeclaration.GetVertexStrideSize(vertexElements, 0);

            // Convert the input material.
            MaterialContent material = ProcessMaterial(geometry.Material);

            // Add the new piece of geometry to our output model.
            outputModel.AddModelPart(indexCount, vertexCount, vertexStride,
                                     vertexElements, vertexBufferContent,
                                     geometry.Indices, material);
        }
        public void SetMaterialDoesNotClearChannels()
        {
            var mb  = MeshBuilder.StartMesh("Test");
            var mat = new BasicMaterialContent();

            mb.CreateVertexChannel <Vector2>(VertexChannelNames.TextureCoordinate(0));
            mb.SetMaterial(mat);
            Assert.DoesNotThrow(() => mb.SetVertexChannelData(0, Vector2.Zero));
        }
Example #20
0
        private void ProcessGeometry(GeometryContent xnaGeometry)
        {
            // find and process the geometry's bone weights
            for (int i = 0; i < xnaGeometry.Vertices.Channels.Count; i++)
            {
                string channelName = xnaGeometry.Vertices.Channels[i].Name;
                string baseName    = VertexChannelNames.DecodeBaseName(channelName);

                if (baseName == "Weights")
                {
                    ProcessWeightsChannel(xnaGeometry, i, outputModel.skeleton);
                }
            }


            // retrieve the four vertex channels we require for CPU skinning. we ignore any
            // other channels the model might have.
            string normalName      = VertexChannelNames.EncodeName(Microsoft.Xna.Framework.Graphics.VertexElementUsage.Normal, 0);
            string texCoordName    = VertexChannelNames.EncodeName(Microsoft.Xna.Framework.Graphics.VertexElementUsage.TextureCoordinate, 0);
            string blendWeightName = VertexChannelNames.EncodeName(Microsoft.Xna.Framework.Graphics.VertexElementUsage.BlendWeight, 0);
            string blendIndexName  = VertexChannelNames.EncodeName(Microsoft.Xna.Framework.Graphics.VertexElementUsage.BlendIndices, 0);

            VertexChannel <Vector3> normals      = xnaGeometry.Vertices.Channels[normalName] as VertexChannel <Vector3>;
            VertexChannel <Vector2> texCoords    = xnaGeometry.Vertices.Channels[texCoordName] as VertexChannel <Vector2>;
            VertexChannel <Vector4> blendWeights = xnaGeometry.Vertices.Channels[blendWeightName] as VertexChannel <Vector4>;
            VertexChannel <Vector4> blendIndices = xnaGeometry.Vertices.Channels[blendIndexName] as VertexChannel <Vector4>;

            // create our array of vertices
            int triangleCount = xnaGeometry.Indices.Count / 3;

            SerializableVertex[] vertices = new SerializableVertex[xnaGeometry.Vertices.VertexCount];
            for (int i = 0; i < vertices.Length; i++)
            {
                vertices[i] = new SerializableVertex
                {
                    position     = xnaGeometry.Vertices.Positions[i],
                    normal       = normals[i],
                    texture      = texCoords[i],
                    blendweights = blendWeights[i],
                    blendindices = blendIndices[i]
                };
            }

            int[] indices = new int[xnaGeometry.Indices.Count];
            for (int i = 0; i < xnaGeometry.Indices.Count; i++)
            {
                indices[i] = xnaGeometry.Indices[i];
            }

            SerializableMesh mesh = new SerializableMesh();

            mesh.name        = string.Format("mesh_{0}_{1}", outputModel.meshList.Count, xnaGeometry.Name);
            mesh.textureName = GetTextureName(xnaGeometry);
            mesh.vertices    = vertices;
            mesh.indices     = indices;
            outputModel.meshList.Add(mesh);
        }
Example #21
0
        private DRModelNodeContent CreateModel(Texture2DContent input, ContentProcessorContext context, HeightField heightField)
        {
            // We use the XNA MeshBuilder to create the model.
            MeshBuilder meshBuilder = MeshBuilder.StartMesh(input.Name);

            int numberOfSamplesX = heightField.NumberOfSamplesX;
            int numberOfSamplesZ = heightField.NumberOfSamplesZ;
            int numberOfCellsInX = numberOfSamplesX - 1;
            int numberOfCellsInZ = numberOfSamplesZ - 1;

            // Add vertex positions.
            for (int z = 0; z < numberOfSamplesZ; z++)
            {
                for (int x = 0; x < numberOfSamplesX; x++)
                {
                    meshBuilder.CreatePosition((float)x / numberOfCellsInX * heightField.WidthX,
                                               heightField.Samples[z * numberOfSamplesX + x],
                                               (float)z / numberOfCellsInZ * heightField.WidthZ);
                }
            }

            // Set a BasicMaterial for the model.
            var material = new BasicMaterialContent
            {
                SpecularColor = Vector3.Zero,
                Texture       = new ExternalReference <TextureContent>(TextureFilename, input.Identity)
            };

            meshBuilder.SetMaterial(material);

            // Add texture coordinates. Each height field cell consists of two triangles.
            int textureChannelId = meshBuilder.CreateVertexChannel <Vector2>(VertexChannelNames.TextureCoordinate(0));

            for (int x = 0; x < numberOfCellsInX; x++)
            {
                for (int z = 0; z < numberOfCellsInZ; z++)
                {
                    // First triangle.
                    AddVertex(meshBuilder, textureChannelId, x, z, numberOfSamplesX, numberOfSamplesZ);
                    AddVertex(meshBuilder, textureChannelId, x + 1, z, numberOfSamplesX, numberOfSamplesZ);
                    AddVertex(meshBuilder, textureChannelId, x, z + 1, numberOfSamplesX, numberOfSamplesZ);

                    // Second triangle.
                    AddVertex(meshBuilder, textureChannelId, x, z + 1, numberOfSamplesX, numberOfSamplesZ);
                    AddVertex(meshBuilder, textureChannelId, x + 1, z, numberOfSamplesX, numberOfSamplesZ);
                    AddVertex(meshBuilder, textureChannelId, x + 1, z + 1, numberOfSamplesX, numberOfSamplesZ);
                }
            }

            // Create MeshContent. FinishMesh() automatically computes normal vectors.
            MeshContent meshContent = meshBuilder.FinishMesh();

            // Call the DRModelProcessor to convert the MeshContent to DRModelNodeContent.
            DRModelNodeContent model = context.Convert <MeshContent, DRModelNodeContent>(meshContent, "DRModelProcessor");

            return(model);
        }
        public void CannotCallCreateMethodsAfterAddingVertex()
        {
            var builder = MeshBuilder.StartMesh("Mesh1");

            builder.CreatePosition(new Vector3(0, 0, 0));
            builder.AddTriangleVertex(0);
            Assert.Throws <InvalidOperationException>(
                () => builder.CreatePosition(new Vector3(1, 2, 3)));
            Assert.Throws <InvalidOperationException>(
                () => builder.CreateVertexChannel <Vector2>(VertexChannelNames.TextureCoordinate(0)));
        }
        // Generates the tangent frames for all meshes. Note: for the normal generation, the
        // texture channel is needed. Unfortunatly the arena model doesn't seem to be consistent
        // in the used texture channels. We therefore have to find the correct channel by analysing
        // all the used channel indices for all geometry batches in each mesh.
        private void GenerateTangents(NodeContent input, ContentProcessorContext context)
        {
            MeshContent mesh    = input as MeshContent;
            int         channel = -1;

            // find the index of the texture channel (sometimes 0, sometimes 1)
            if (mesh != null)
            {
                // loop through all geometry batches
                foreach (GeometryContent geometryBatch in mesh.Geometry)
                {
                    // check the index of the texture channel
                    foreach (VertexChannel vertexChannel in geometryBatch.Vertices.Channels)
                    {
                        // is this a texture channel
                        if (vertexChannel.Name.Contains("Texture"))
                        {
                            // extract index (last letter, convert it to int)
                            char c          = vertexChannel.Name[vertexChannel.Name.Length - 1];
                            int  curChannel = (int)(c - '0');


                            if (channel == -1)
                            {
                                // first time we see a texture channel for this mesh: store index
                                channel = curChannel;
                            }
                            else if (channel != curChannel)
                            {
                                // we have already seen a texture channel for this mesh, but with a
                                // different index => signal error
                                channel = -2;
                            }
                        }
                    }
                }

                // have we found a valid texture channel?
                if (channel >= 0)
                {
                    // compute tangent frames
                    MeshHelper.CalculateTangentFrames(mesh,
                                                      VertexChannelNames.TextureCoordinate(channel),
                                                      VertexChannelNames.Tangent(0),
                                                      VertexChannelNames.Binormal(0));
                }
            }

            // recurse to all children
            foreach (NodeContent child in input.Children)
            {
                GenerateTangents(child, context);
            }
        }
Example #24
0
 private VertexChannel <BoneWeightCollection> GetWeightChannel(GeometryContent geom)
 {
     foreach (VertexChannel channel in geom.Vertices.Channels)
     {
         if (channel.Name == VertexChannelNames.Weights())
         {
             return((VertexChannel <BoneWeightCollection>)channel);
         }
     }
     return(null);
 }
Example #25
0
 private void GetWeightChannel()
 {
     foreach (VertexChannel channel in geom.Vertices.Channels)
     {
         if (channel.Name == VertexChannelNames.Weights())
         {
             weightChannel = (VertexChannel <BoneWeightCollection>)channel;
             break;
         }
     }
 }
 /// <summary>
 /// Checks whether mesh contains skinning information.
 /// </summary>
 /// <param name="mesh"></param>
 /// <returns></returns>
 static bool MeshHasSkinning(MeshContent mesh)
 {
     foreach (GeometryContent geometry in mesh.Geometry)
     {
         if (!geometry.Vertices.Channels.Contains(VertexChannelNames.Weights()))
         {
             return(false);
         }
     }
     return(true);
 }
 private void AddVertexColorChannel(VertexContent content)
 {
     if (content.Channels.Contains(VertexChannelNames.Color(0)) == false)
     {
         List <Microsoft.Xna.Framework.Color> VertexColors = new List <Microsoft.Xna.Framework.Color>();
         for (int i = 0; i < content.VertexCount; i++)
         {
             VertexColors.Add(Color.Purple);
         }
         content.Channels.Add(VertexChannelNames.Color(0), VertexColors);
     }
 }
Example #28
0
            /// <summary>
            /// Adds all the buffered channels to the mesh and merges duplicate positions/verts
            /// </summary>
            private void AddAllChannels()
            {
                bool recalcNormal = false;

                if (model.AnimationOptions.Contains("RecalcNormals") || (normals == null && !hasNormals))
                {
                    recalcNormal = true;
                }
                else
                {
                    AddChannel <Vector3>(VertexElementUsage.Normal.ToString() + "0", normals);
                }


                if (texCoords != null)
                {
                    AddChannel <Vector2>("TextureCoordinate0", texCoords);
                }

                //for (int i = 0; i < weightIndices.Count; i++)
                //{
                //    AddChannel<Byte4>(VertexElementUsage.BlendIndices.ToString() + i.ToString(),
                //        weightIndices[i]);
                //}
                //for (int i = 0; i < weights.Count; i++)
                //{
                //    AddChannel<Vector4>(VertexElementUsage.BlendWeight.ToString() + i.ToString(),
                //        weights[i]);
                //}
                bool isSkinned = false;

                foreach (BoneWeightCollection bwc in skinInfo)
                {
                    if (bwc.Count > 0)
                    {
                        isSkinned = true;
                        break;
                    }
                }
                if (isSkinned)
                {
                    AddChannel <BoneWeightCollection>(VertexChannelNames.Weights(), skinInfo.ToArray());
                }

                MeshHelper.MergeDuplicatePositions(mesh, 0);
                MeshHelper.MergeDuplicateVertices(mesh);
                if (recalcNormal)
                {
                    MeshHelper.CalculateNormals(mesh, true);
                }
                MeshHelper.OptimizeForCache(mesh);
            }
        protected virtual void ProcessVertexChannel(
            GeometryContent geometry, int vertexChannelIndex, ContentProcessorContext context)
        {
            var channel = geometry.Vertices.Channels[vertexChannelIndex];

            // TODO: According to docs, channels with VertexElementUsage.Color -> Color

            // Channels[VertexChannelNames.Weights] -> { Byte4 boneIndices, Color boneWeights }
            if (channel.Name.StartsWith(VertexChannelNames.Weights(), StringComparison.Ordinal))
            {
                ProcessWeightsChannel(geometry, vertexChannelIndex, _identity);
            }
        }
Example #30
0
        public override ModelContent Process(Texture2DContent input, ContentProcessorContext context)
        {
            var builder = MeshBuilder.StartMesh("terrain");

            input.ConvertBitmapType(typeof(PixelBitmapContent <float>));

            var heightField = (PixelBitmapContent <float>)input.Mipmaps[0];

            for (var y = 0; y < heightField.Height; y++)
            {
                for (var x = 0; x < heightField.Width; x++)
                {
                    Vector3 position;
                    position.X = TerrainScale * (x - (heightField.Width - 1) / 2.0f);
                    position.Z = TerrainScale * (y - (heightField.Height - 1) / 2.0f);
                    position.Y = (heightField.GetPixel(x, y) - 1) * TerrainBumpiness;
                    builder.CreatePosition(position);
                }
            }

            var material = new BasicMaterialContent {
                SpecularColor = new Vector3(.4f, .4f, .4f)
            };
            var directory = Path.GetDirectoryName(input.Identity.SourceFilename);
            var texture   = Path.Combine(directory, TerrainTexture);

            material.Texture = new ExternalReference <TextureContent>(texture);
            builder.SetMaterial(material);

            var texCoordId = builder.CreateVertexChannel <Vector2>(VertexChannelNames.TextureCoordinate(0));

            for (var y = 0; y < heightField.Height - 1; y++)
            {
                for (var x = 0; x < heightField.Width - 1; x++)
                {
                    AddVertex(builder, texCoordId, heightField.Width, x, y);
                    AddVertex(builder, texCoordId, heightField.Width, x + 1, y);
                    AddVertex(builder, texCoordId, heightField.Width, x + 1, y + 1);

                    AddVertex(builder, texCoordId, heightField.Width, x, y);
                    AddVertex(builder, texCoordId, heightField.Width, x + 1, y + 1);
                    AddVertex(builder, texCoordId, heightField.Width, x, y + 1);
                }
            }

            var terrainMesh = builder.FinishMesh();
            var model       = context.Convert <MeshContent, ModelContent>(terrainMesh, "ModelProcessor");

            model.Tag = new HeightMapInfoContent(heightField, TerrainScale, TerrainBumpiness);
            return(model);
        }