Ejemplo n.º 1
0
        /// <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);
                    }
                }
            }
        }
Ejemplo n.º 2
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);
        }
Ejemplo n.º 3
0
        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);
                }
            }
        }
Ejemplo n.º 4
0
 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);
     }
 }
        // Checks if the geometries have a Color vertex channel and updates the VertexColorEnabled
        // flag in the opaque material data. If necessary, the material is cloned to create one
        // material with and one without vertex colors.
        private static void SetVertexColorEnabled(List <GeometryContent> geometries)
        {
            var material = geometries[0].Material;

            bool geometryWithVertexColorsFound    = false;
            bool geometryWithoutVertexColorsFound = false;

            foreach (GeometryContent geometry in geometries)
            {
                if (geometry.Vertices.Channels.Contains(VertexChannelNames.Color(0)))
                {
                    geometryWithVertexColorsFound = true;
                }
                else
                {
                    geometryWithoutVertexColorsFound = true;
                }
            }

            if (geometryWithVertexColorsFound && geometryWithoutVertexColorsFound)
            {
                // There are some geometries that have a vertex color and some that don't.
                // --> Create a copy of the current material. One material is used for geometry
                // with vertex colors enabled. The other for the geometry where vertex colors
                // are disabled.
                MaterialContent clonedMaterial = (MaterialContent)Activator.CreateInstance(material.GetType());
                ContentHelper.CopyMaterialContent(material, clonedMaterial);
                material.OpaqueData["VertexColorEnabled"]       = true;
                clonedMaterial.OpaqueData["VertexColorEnabled"] = false;
                foreach (GeometryContent geometry in geometries)
                {
                    if (!geometry.Vertices.Channels.Contains(VertexChannelNames.Color(0)))
                    {
                        geometry.Material = clonedMaterial;
                    }
                }
            }
            else
            {
                if (geometryWithVertexColorsFound)
                {
                    material.OpaqueData["VertexColorEnabled"] = true;
                }
                else
                {
                    material.OpaqueData.Remove("VertexColorEnabled");
                }
            }
        }
Ejemplo n.º 6
0
        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()))
            {
                ProcessWeightsChannel(geometry, vertexChannelIndex, _identity);
            }

            // Looks like XNA models usually put a default color channel in..
            if (!geometry.Vertices.Channels.Contains(VertexChannelNames.Color(0)))
            {
                geometry.Vertices.Channels.Add(VertexChannelNames.Color(0), Enumerable.Repeat(Color.White, geometry.Vertices.VertexCount));
            }
        }
Ejemplo n.º 7
0
        private void GenerateVertexColorChannel(NodeContent node)
        {
            MeshContent mesh = node as MeshContent;

            if (mesh != null)
            {
                foreach (var geometry in mesh.Geometry)
                {
                    if (!geometry.Vertices.Channels.Contains(VertexChannelNames.Color(0)))
                    {
                        geometry.Vertices.Channels.Add <Color>(VertexChannelNames.Color(0),
                                                               Enumerable.Range(0, geometry.Vertices.VertexCount).Select(i => Color.White));
                    }
                }
            }

            foreach (NodeContent child in node.Children)
            {
                GenerateVertexColorChannel(child);
            }
        }
Ejemplo n.º 8
0
        private void ProcessBasicMaterial(BasicMaterialContent basicMaterial, GeometryContent geometry)
        {
            if (basicMaterial == null)
            {
                return;
            }

            // If the basic material specifies a texture, geometry must have coordinates.
            if (!geometry.Vertices.Channels.Contains(VertexChannelNames.TextureCoordinate(0)))
            {
                throw new InvalidContentException(
                          "Geometry references material with texture, but no texture coordinates were found.",
                          _identity);
            }

            // Enable vertex color if the geometry has the channel to support it.
            if (geometry.Vertices.Channels.Contains(VertexChannelNames.Color(0)))
            {
                basicMaterial.VertexColorEnabled = true;
            }
        }
Ejemplo n.º 9
0
        protected virtual void ProcessGeometryUsingMaterial(MaterialContent material,
                                                            IEnumerable <GeometryContent> geometryCollection,
                                                            ContentProcessorContext context)
        {
            var basicMaterial = material as BasicMaterialContent;

            if (material == null)
            {
                material = basicMaterial = new BasicMaterialContent();
            }

            foreach (var geometry in geometryCollection)
            {
                for (var i = 0; i < geometry.Vertices.Channels.Count; i++)
                {
                    ProcessVertexChannel(geometry, i, context);
                }

                if (basicMaterial != null)
                {
                    // If the basic material specifies a texture, geometry must have coordinates.
                    if (!geometry.Vertices.Channels.Contains(VertexChannelNames.TextureCoordinate(0)))
                    {
                        throw new InvalidContentException(
                                  "Geometry references material with texture, but no texture coordinates were found.",
                                  _identity);
                    }

                    // Enable vertex color if the geometry has the channel to support it.
                    if (geometry.Vertices.Channels.Contains(VertexChannelNames.Color(0)))
                    {
                        basicMaterial.VertexColorEnabled = true;
                    }
                }
            }
        }
Ejemplo n.º 10
0
        protected virtual void ProcessGeometryUsingMaterial(MaterialContent material,
                                                            IEnumerable <GeometryContent> geometryCollection,
                                                            ContentProcessorContext context)
        {
            // If we don't get a material then assign a default one.
            if (material == null)
            {
                material = MaterialProcessor.CreateDefaultMaterial(DefaultEffect);
            }

            // Test requirements from the assigned material.
            int  textureChannels;
            bool vertexWeights = false;

            if (material is DualTextureMaterialContent)
            {
                textureChannels = 2;
            }
            else if (material is SkinnedMaterialContent)
            {
                textureChannels = 1;
                vertexWeights   = true;
            }
            else if (material is EnvironmentMapMaterialContent)
            {
                textureChannels = 1;
            }
            else if (material is AlphaTestMaterialContent)
            {
                textureChannels = 1;
            }
            else
            {
                // Just check for a "Texture" which should cover custom Effects
                // and BasicEffect which can have an optional texture.
                textureChannels = material.Textures.ContainsKey("Texture") ? 1 : 0;
            }

            // By default we must set the vertex color property
            // to match XNA behavior.
            material.OpaqueData["VertexColorEnabled"] = false;

            // If we run into a geometry that requires vertex
            // color we need a seperate material for it.
            var colorMaterial = material.Clone();

            colorMaterial.OpaqueData["VertexColorEnabled"] = true;

            foreach (var geometry in geometryCollection)
            {
                // Process the geometry.
                for (var i = 0; i < geometry.Vertices.Channels.Count; i++)
                {
                    ProcessVertexChannel(geometry, i, context);
                }

                // Verify we have the right number of texture coords.
                for (var i = 0; i < textureChannels; i++)
                {
                    if (!geometry.Vertices.Channels.Contains(VertexChannelNames.TextureCoordinate(i)))
                    {
                        throw new InvalidContentException(
                                  string.Format("The mesh \"{0}\", using {1}, contains geometry that is missing texture coordinates for channel {2}.",
                                                geometry.Parent.Name,
                                                MaterialProcessor.GetDefaultEffect(material),
                                                i),
                                  _identity);
                    }
                }

                // Do we need to enable vertex color?
                if (geometry.Vertices.Channels.Contains(VertexChannelNames.Color(0)))
                {
                    geometry.Material = colorMaterial;
                }
                else
                {
                    geometry.Material = material;
                }

                // Do we need vertex weights?
                if (vertexWeights)
                {
                    var weightsName = VertexChannelNames.EncodeName(VertexElementUsage.BlendWeight, 0);
                    if (!geometry.Vertices.Channels.Contains(weightsName))
                    {
                        throw new InvalidContentException(
                                  string.Format("The skinned mesh \"{0}\" contains geometry without any vertex weights.", geometry.Parent.Name),
                                  _identity);
                    }
                }
            }
        }
Ejemplo n.º 11
0
        } // Process

        #endregion

        #region Process Vertex Channel

        /// <summary>
        /// Processes geometry content vertex channels at the specified index.
        /// </summary>
        protected override void ProcessVertexChannel(GeometryContent geometry, int vertexChannelIndex, ContentProcessorContext context)
        {
            // Compressed Vertex Data
            VertexChannelCollection channels = geometry.Vertices.Channels;
            string name = channels[vertexChannelIndex].Name;

            if (name == VertexChannelNames.Normal())
            {
                channels.ConvertChannelContent <NormalizedShort4>(vertexChannelIndex);
            }
            else if (name == VertexChannelNames.TextureCoordinate(0))
            {
                // If the resource has texture coordinates outside the range [-1, 1] the values will be clamped.
                channels.ConvertChannelContent <HalfVector2>(vertexChannelIndex);
            }
            else if (name == VertexChannelNames.TextureCoordinate(1))
            {
                channels.Remove(VertexChannelNames.TextureCoordinate(1));
            }
            else if (name == VertexChannelNames.TextureCoordinate(2))
            {
                channels.Remove(VertexChannelNames.TextureCoordinate(2));
            }
            else if (name == VertexChannelNames.TextureCoordinate(3))
            {
                channels.Remove(VertexChannelNames.TextureCoordinate(3));
            }
            else if (name == VertexChannelNames.TextureCoordinate(4))
            {
                channels.Remove(VertexChannelNames.TextureCoordinate(4));
            }
            else if (name == VertexChannelNames.TextureCoordinate(5))
            {
                channels.Remove(VertexChannelNames.TextureCoordinate(5));
            }
            else if (name == VertexChannelNames.TextureCoordinate(6))
            {
                channels.Remove(VertexChannelNames.TextureCoordinate(6));
            }
            else if (name == VertexChannelNames.TextureCoordinate(7))
            {
                channels.Remove(VertexChannelNames.TextureCoordinate(7));
            }
            else if (name == VertexChannelNames.Color(0))
            {
                channels.Remove(VertexChannelNames.Color(0));
            }
            else if (name == VertexChannelNames.Tangent(0))
            {
                channels.ConvertChannelContent <NormalizedShort4>(vertexChannelIndex);
            }
            else if (name == VertexChannelNames.Binormal(0))
            {
                // Not need to get rid of the binormal data because the model will use more than 32 bytes per vertex.
                // We can actually try to align the data to 64 bytes per vertex.
                channels.ConvertChannelContent <NormalizedShort4>(vertexChannelIndex);
            }
            else
            {
                // Blend indices, blend weights and everything else.
                // Don't use "BlendWeight0" as a name, nor weights0. Both names don't work.
                base.ProcessVertexChannel(geometry, vertexChannelIndex, context);
                channels.ConvertChannelContent <Byte4>("BlendIndices0");
                channels.ConvertChannelContent <NormalizedShort4>(VertexChannelNames.EncodeName(VertexElementUsage.BlendWeight, 0));
            }
        } // ProcessVertexChannel
        } // Process

        #endregion

        #region Process Vertex Channel

        /// <summary>
        /// Processes geometry content vertex channels at the specified index.
        /// </summary>
        protected override void ProcessVertexChannel(GeometryContent geometry, int vertexChannelIndex, ContentProcessorContext context)
        {
            VertexChannelCollection channels = geometry.Vertices.Channels;

            // If the model has only position and normals a UV channel is added.
            // http://xnafinalengine.codeplex.com/wikipage?title=Compressed%20Vertex%20Data
            if (channels.Count == 1 && channels.Contains(VertexChannelNames.Normal()))
            {
                channels.Add<Vector2>(VertexChannelNames.TextureCoordinate(0), null);
            }

            // If the model has position, normal and UV then the data is packed on 32 bytes aliagned vertex data.
            if (channels.Count == 2 && channels.Contains(VertexChannelNames.Normal()) && channels.Contains(VertexChannelNames.TextureCoordinate(0)))
            {
                // No compressed Vertex Data
                base.ProcessVertexChannel(geometry, vertexChannelIndex, context);
            }
            else // If not then the data is compressed.
            {
                string name = channels[vertexChannelIndex].Name;

                if (name == VertexChannelNames.Normal())
                {
                    channels.ConvertChannelContent<NormalizedShort4>(vertexChannelIndex);
                }
                else if (name == VertexChannelNames.TextureCoordinate(0))
                {
                    // Clamp values.
                    /*for (int i = 0; i < channels[vertexChannelIndex].Count; i++)
                    {
                        Vector2 uv = (Vector2)channels[vertexChannelIndex][i];
                        if (uv.X < 0) 
                            uv.X *= -1;
                        if (uv.Y < 0) 
                            uv.Y *= -1;
                        Vector2 uvCampled = new Vector2(uv.X - (float)Math.Truncate(uv.X), uv.Y - (float)Math.Truncate(uv.Y));
                        channels[vertexChannelIndex][i] = uvCampled;
                    }
                    // If the resource has texture coordinates outside the range [-1, 1] the values will be clamped.
                    channels.ConvertChannelContent<NormalizedShort2>(vertexChannelIndex);*/
                    // Sometimes you can't just clamp values, because the distance between vertices surpass 1 uv unit.
                    // And given that I am not removing the binormals I won't normalize the UVs.
                    channels.ConvertChannelContent<HalfVector2>(vertexChannelIndex);
                }
                else if (name == VertexChannelNames.TextureCoordinate(1))
                    channels.Remove(VertexChannelNames.TextureCoordinate(1));
                else if (name == VertexChannelNames.TextureCoordinate(2))
                    channels.Remove(VertexChannelNames.TextureCoordinate(2));
                else if (name == VertexChannelNames.TextureCoordinate(3))
                    channels.Remove(VertexChannelNames.TextureCoordinate(3));
                else if (name == VertexChannelNames.TextureCoordinate(4))
                    channels.Remove(VertexChannelNames.TextureCoordinate(4));
                else if (name == VertexChannelNames.TextureCoordinate(5))
                    channels.Remove(VertexChannelNames.TextureCoordinate(5));
                else if (name == VertexChannelNames.TextureCoordinate(6))
                    channels.Remove(VertexChannelNames.TextureCoordinate(6));
                else if (name == VertexChannelNames.TextureCoordinate(7))
                    channels.Remove(VertexChannelNames.TextureCoordinate(7));
                else if (name == VertexChannelNames.Color(0))
                    channels.Remove(VertexChannelNames.Color(0));
                else if (name == VertexChannelNames.Tangent(0))
                {
                    channels.ConvertChannelContent<NormalizedShort4>(vertexChannelIndex);
                }
                else if (name == VertexChannelNames.Binormal(0))
                {
                    channels.ConvertChannelContent<NormalizedShort4>(vertexChannelIndex);
                    // If the binormal is removed then the position, the normal,
                    // the tangent and one texture coordinate can be fetched in one single block of 32 bytes.
                    // Still, it is more fast to just pass the value. At least on the test I made.
                    //channels.Remove(VertexChannelNames.Binormal(0));
                }
                else
                {
                    base.ProcessVertexChannel(geometry, vertexChannelIndex, context);
                }
            }
        } // ProcessVertexChannel
Ejemplo n.º 13
0
        MeshData ProcessMesh(MeshContent mesh, ContentProcessorContext context, string rootPath, Dictionary <string, object> processedContent, SkeletonData skeletonData, AnimationData[] animations, ref int geometryCount)
        {
            MeshHelper.TransformScene(mesh, mesh.AbsoluteTransform);

            string[] normalMapNames = new string[] { "Bump0", "Bump", "NormalMap", "Normalmap", "Normals", "BumpMap" };
            MeshHelper.OptimizeForCache(mesh);

            foreach (GeometryContent geom in mesh.Geometry)
            {
                if (geom.Material != null)
                {
                    string map = MaterialTexture(geom.Material, rootPath, null, null, normalMapNames);
                    if (map != null && map.Length > 0)
                    {
                        generateTangents = true;
                    }
                }
            }

            if (generateTangents)
            {
                MeshHelper.CalculateNormals(mesh, false);

                bool hasNoTangent = !GeometryContainsChannel(mesh, VertexChannelNames.Tangent(0));
                bool hasNoBinorm  = !GeometryContainsChannel(mesh, VertexChannelNames.Binormal(0));
                if (hasNoTangent || hasNoBinorm)
                {
                    string tangentChannelName  = hasNoTangent ? VertexChannelNames.Tangent(0) : null;
                    string binormalChannelName = hasNoBinorm ? VertexChannelNames.Binormal(0) : null;
                    MeshHelper.CalculateTangentFrames(mesh, VertexChannelNames.TextureCoordinate(0), tangentChannelName, binormalChannelName);
                }
            }
            if (swapWinding)
            {
                MeshHelper.SwapWindingOrder(mesh);
            }

            List <GeometryData> geometry = new List <GeometryData>();

            BoneContent skeleton = MeshHelper.FindSkeleton(mesh);
            Dictionary <string, int> boneIndices = null;

            if (skeleton != null)
            {
                boneIndices = FlattenSkeleton(skeleton);
            }

            foreach (GeometryContent geom in mesh.Geometry)
            {
                this.ProcessVertexChannels(geom, context, rootPath, boneIndices, null);
                MeshHelper.MergeDuplicateVertices(geom);

                MaterialData material = new MaterialData(
                    MaterialValue <float>("Alpha", geom.Material, 1),
                    MaterialValue <float>("SpecularPower", geom.Material, 24),
                    MaterialValue <Vector3>("DiffuseColor", geom.Material, Vector3.One),
                    MaterialValue <Vector3>("EmissiveColor", geom.Material, Vector3.Zero),
                    MaterialValue <Vector3>("SpecularColor", geom.Material, Vector3.Zero),
                    MaterialTexture(geom.Material, rootPath, context, processedContent, "Texture"),
                    MaterialTexture(geom.Material, rootPath, context, processedContent, normalMapNames),
                    MaterialValue <bool>("VertexColorEnabled", geom.Material, true) && geom.Vertices.Channels.Contains(VertexChannelNames.Color(0)));

                VertexBufferContent vb;
                VertexElement[]     ve;
                geom.Vertices.CreateVertexBuffer(out vb, out ve, context.TargetPlatform);

                int[] indices = new int[geom.Indices.Count];
                geom.Indices.CopyTo(indices, 0);

                geometry.Add(new GeometryData(geometryCount++, geom.Name, ve, vb.VertexData, indices, material, skeletonData, animations, context.TargetPlatform == TargetPlatform.Xbox360));
            }

            return(new MeshData(mesh.Name, geometry.ToArray(), animations));
        }
Ejemplo n.º 14
0
        private MeshContent ExtractMesh(aiMesh aiMesh)
        {
            if (!String.IsNullOrEmpty(aiMesh.mName.Data))
            {
                log("modelname " + aiMesh.mName.Data);
                meshBuilder = MeshBuilder.StartMesh(aiMesh.mName.Data);
            }
            else
            {
                meshBuilder = MeshBuilder.StartMesh(Path.GetFileNameWithoutExtension(filename));
            }

            if (!aiMesh.HasPositions())
            {
                throw new Exception("MOdel does not have Position");
            }

            // Add additional vertex channels for texture coordinates and normals
            if (aiMesh.HasTextureCoords(0))
            {
                textureCoordinateDataIndex = meshBuilder.CreateVertexChannel <Vector2>(VertexChannelNames.TextureCoordinate(0));
            }
            else if (aiMesh.HasVertexColors(0))
            {
                colorCoordinateDataIndex = meshBuilder.CreateVertexChannel <Vector4>(VertexChannelNames.Color(0));
            }
            if (aiMesh.HasNormals())
            {
                normalDataIndex = meshBuilder.CreateVertexChannel <Vector3>(VertexChannelNames.Normal());
            }
            if (aiMesh.HasTangentsAndBitangents())
            {
                tangentDataIndex  = meshBuilder.CreateVertexChannel <Vector3>(VertexChannelNames.Tangent(0));
                binormalDataIndex = meshBuilder.CreateVertexChannel <Vector3>(VertexChannelNames.Binormal(0));
            }
            if (aiMesh.HasBones())
            {
                boneDataIndex = meshBuilder.CreateVertexChannel <BoneWeightCollection>(VertexChannelNames.Weights(0));
            }

            var numFaces           = (int)aiMesh.mNumFaces;
            var numVertices        = (int)aiMesh.mNumVertices;
            var aiPositions        = aiMesh.mVertices;
            var aiNormals          = aiMesh.mNormals;
            var aiTextureCoordsAll = aiMesh.mTextureCoords;
            var aiTextureCoords    = (aiTextureCoordsAll != null) ? aiTextureCoordsAll[0] : null;

            for (int j = 0; j < aiMesh.mNumVertices; j++)
            {
                meshBuilder.CreatePosition(aiMesh.mVertices[j].x, aiMesh.mVertices[j].y, aiMesh.mVertices[j].z);
            }

            meshBuilder.SetMaterial(GetMaterial(aiMesh));

            var aiFaces   = aiMesh.mFaces;
            var dxIndices = new uint[numFaces * 3];

            for (int k = 0; k < numFaces; ++k)
            {
                var aiFace    = aiFaces[k];
                var aiIndices = aiFace.mIndices;
                for (int j = 0; j < 3; ++j)
                {
                    int index = (int)aiIndices[j];
                    if (aiMesh.HasTextureCoords(0))
                    {
                        meshBuilder.SetVertexChannelData(textureCoordinateDataIndex, new Vector2(aiMesh.mTextureCoords[0][index].x, aiMesh.mTextureCoords[0][index].y));
                    }
                    else if (aiMesh.HasVertexColors(0))
                    {
                        meshBuilder.SetVertexChannelData(colorCoordinateDataIndex, new Vector4(aiMesh.mColors[0][index].r, aiMesh.mColors[0][index].g, aiMesh.mColors[0][index].b, aiMesh.mColors[0][index].a));
                    }
                    if (aiMesh.HasNormals())
                    {
                        meshBuilder.SetVertexChannelData(normalDataIndex, new Vector3(aiMesh.mNormals[index].x, aiMesh.mNormals[index].y, aiMesh.mNormals[index].z));
                    }

                    if (aiMesh.HasTangentsAndBitangents())
                    {
                        meshBuilder.SetVertexChannelData(tangentDataIndex, new Vector3(aiMesh.mTangents[index].x, aiMesh.mTangents[index].y, aiMesh.mTangents[index].z));
                        meshBuilder.SetVertexChannelData(binormalDataIndex, new Vector3(aiMesh.mBitangents[index].x, aiMesh.mBitangents[index].y, aiMesh.mBitangents[index].z));
                    }
                    if (aiMesh.HasBones())
                    {
                        BoneWeightCollection BoneWeightCollection = new BoneWeightCollection();
                        if (wbone.ContainsKey(index))
                        {
                            foreach (var item in wbone[index])
                            {
                                BoneWeightCollection.Add(new BoneWeight(item.Key, item.Value));
                            }
                        }
                        meshBuilder.SetVertexChannelData(boneDataIndex, BoneWeightCollection);
                    }

                    meshBuilder.AddTriangleVertex(index);
                }
            }

            MeshContent meshContent = meshBuilder.FinishMesh();

            return(meshContent);
        }
Ejemplo n.º 15
0
        public override NodeContent Import(string filename, ContentImporterContext context)
        {
            context.Logger.LogMessage("Importing H3D file: {0}", filename);

            _identity = new ContentIdentity(filename, GetType().Name);
            _rootNode = new NodeContent()
            {
                Identity = _identity, Name = "RootNode"
            };

            var scene = FormatIdentifier.IdentifyAndOpen(filename);
            var model = scene.Models[0];

            if (!scene.Textures.Any())
            {
                var path = Path.Combine(Path.GetDirectoryName(filename), $"{Path.GetFileNameWithoutExtension(filename)}@Textures{Path.GetExtension(filename)}");
                if (File.Exists(path))
                {
                    context.Logger.LogMessage($"Found texture file {path}. Loading data...");
                    scene.Merge(FormatIdentifier.IdentifyAndOpen(path, model.Skeleton));
                }
                else
                {
                    context.Logger.LogMessage($"Couldn't find texture file {path}!");
                }
            }

            // Textures
            var textures = new Dictionary <string, Texture2DContent>();

            foreach (var texture in scene.Textures)
            {
                var bitmapContent = new PixelBitmapContent <Color>(texture.Width, texture.Height)
                {
                    Identity = _identity,
                    Name     = texture.Name
                };
                bitmapContent.SetPixelData(texture.ToRGBA());

                var textureContent = new Texture2DContent()
                {
                    Identity = _identity,
                    Name     = texture.Name
                };
                textureContent.Faces[0].Add(bitmapContent);
                textures.Add(textureContent.Name, textureContent);
            }

            // Materials
            var materials = new Dictionary <string, H3DMaterialContent>();

            foreach (var material in model.Materials)
            {
#if DEBUG
                var hlslCode = new HLSLShaderGenerator(material.MaterialParams)
                {
                    BoneCount = model.Skeleton.Count
                }.GetShader();
                var glslCode = new GLSLFragmentShaderGenerator(material.MaterialParams).GetFragShader();
#endif
                var materialContent = new H3DMaterialContent()
                {
                    Identity = _identity,
                    Name     = material.Name,

                    Effect = new EffectContent
                    {
                        Identity   = _identity,
                        Name       = "H3DEffect",
                        EffectCode = new HLSLShaderGenerator(material.MaterialParams)
                        {
                            BoneCount = model.Skeleton.Count
                        }.GetShader()
                    },
                    Material = material.Name,

                    FaceCulling = (H3DFaceCulling?)material.MaterialParams.FaceCulling,

                    EmissionColor      = material.MaterialParams.EmissionColor.ToXNA(),
                    AmbientColor       = material.MaterialParams.AmbientColor.ToXNA(),
                    DiffuseColor       = material.MaterialParams.DiffuseColor.ToXNA(),
                    Specular0Color     = material.MaterialParams.Specular0Color.ToXNA(),
                    Specular1Color     = material.MaterialParams.Specular1Color.ToXNA(),
                    Constant0Color     = material.MaterialParams.Constant0Color.ToXNA(),
                    Constant1Color     = material.MaterialParams.Constant1Color.ToXNA(),
                    Constant2Color     = material.MaterialParams.Constant2Color.ToXNA(),
                    Constant3Color     = material.MaterialParams.Constant3Color.ToXNA(),
                    Constant4Color     = material.MaterialParams.Constant4Color.ToXNA(),
                    Constant5Color     = material.MaterialParams.Constant5Color.ToXNA(),
                    BlendColor         = material.MaterialParams.BlendColor.ToXNA(),
                    DepthBufferRead    = material.MaterialParams.DepthBufferRead,
                    DepthBufferWrite   = material.MaterialParams.DepthBufferWrite,
                    StencilBufferRead  = material.MaterialParams.StencilBufferRead,
                    StencilBufferWrite = material.MaterialParams.StencilBufferWrite,
                };

                var texCount = 0;
                if (material.EnabledTextures[0])
                {
                    texCount++;
                }
                if (material.EnabledTextures[1])
                {
                    texCount++;
                }
                if (material.EnabledTextures[2])
                {
                    texCount++;
                }
                materialContent.TextureList = new Texture2DContent[texCount];
                if (material.EnabledTextures[0])
                {
                    materialContent.TextureList[0] = textures[material.Texture0Name];
                }
                if (material.EnabledTextures[1])
                {
                    materialContent.TextureList[1] = textures[material.Texture1Name];
                }
                if (material.EnabledTextures[2])
                {
                    materialContent.TextureList[2] = textures[material.Texture2Name];
                }

                materialContent.TextureSamplerSettings = material.TextureMappers.Select(tm => new TextureSamplerSettings()
                {
                    WrapU     = tm.WrapU.ToXNAWrap(),
                    WrapV     = tm.WrapV.ToXNAWrap(),
                    MagFilter = (TextureSamplerSettings.TextureMagFilter)tm.MagFilter,
                    MinFilter = (TextureSamplerSettings.TextureMinFilter)tm.MinFilter
                }).ToArray();

                materials.Add(material.Name, materialContent);
            }

            // Geometry
            var meshes = new List <MeshContent>();
            for (var i = 0; i < model.Meshes.Count; i++)
            {
                var modelMesh = model.Meshes[i];

                if (modelMesh.Type == H3DMeshType.Silhouette)
                {
                    continue;
                }

                var mesh = new MeshContent()
                {
                    Identity = _identity,
                    Name     = $"{model.Materials[modelMesh.MaterialIndex].Name}_node{i}",
                };
                var geometry = new GeometryContent
                {
                    Identity = _identity,
                    Material = materials[model.Materials[modelMesh.MaterialIndex].Name]
                };
                var vertices   = GetWorldSpaceVertices(model.Skeleton, modelMesh);
                var baseVertex = mesh.Positions.Count;
                foreach (var vertex in vertices)
                {
                    mesh.Positions.Add(vertex.Position.ToVector3());
                }
                geometry.Vertices.AddRange(Enumerable.Range(baseVertex, vertices.Length));

                foreach (var attribute in modelMesh.Attributes)
                {
                    if (attribute.Name >= PICAAttributeName.BoneIndex)
                    {
                        continue;
                    }

                    switch (attribute.Name)
                    {
                    case PICAAttributeName.Position: break;     // Already added

                    case PICAAttributeName.Normal:
                        geometry.Vertices.Channels.Add(VertexChannelNames.Normal(0), vertices.Select(vertex => vertex.Normal.ToVector3()));
                        break;

                    case PICAAttributeName.Tangent:
                        geometry.Vertices.Channels.Add(VertexChannelNames.Tangent(0), vertices.Select(vertex => vertex.Tangent.ToVector3()));
                        break;

                    case PICAAttributeName.Color:
                        geometry.Vertices.Channels.Add(VertexChannelNames.Color(0), vertices.Select(vertex => vertex.Color.ToColor()));
                        break;

                    case PICAAttributeName.TexCoord0:
                        geometry.Vertices.Channels.Add(VertexChannelNames.TextureCoordinate(0), vertices.Select(vertex => vertex.TexCoord0.ToVector2().ToUV()));
                        break;

                    case PICAAttributeName.TexCoord1:
                        geometry.Vertices.Channels.Add(VertexChannelNames.TextureCoordinate(1), vertices.Select(vertex => vertex.TexCoord1.ToVector2().ToUV()));
                        break;

                    case PICAAttributeName.TexCoord2:
                        geometry.Vertices.Channels.Add(VertexChannelNames.TextureCoordinate(2), vertices.Select(vertex => vertex.TexCoord2.ToVector2().ToUV()));
                        break;
                    }
                }

                var vertexOffset = 0;
                var xnaWeights   = new List <BoneWeightCollection>();
                foreach (var modelSubMesh in modelMesh.SubMeshes)
                {
                    geometry.Indices.AddRange(modelSubMesh.Indices.Select(index => (int)index));

                    var vertexCount     = modelSubMesh.MaxIndex + 1 - vertexOffset;
                    var subMeshVertices = vertices.Skip(vertexOffset).Take(vertexCount).ToList();

                    if (modelSubMesh.Skinning == H3DSubMeshSkinning.Smooth)
                    {
                        foreach (var vertex in subMeshVertices)
                        {
                            var list = new BoneWeightCollection();
                            for (var index = 0; index < 4; index++)
                            {
                                var bIndex = vertex.Indices[index];
                                var weight = vertex.Weights[index];

                                if (weight == 0)
                                {
                                    break;
                                }

                                if (bIndex < modelSubMesh.BoneIndicesCount && bIndex > -1)
                                {
                                    bIndex = modelSubMesh.BoneIndices[bIndex];
                                }
                                else
                                {
                                    bIndex = 0;
                                }

                                list.Add(new BoneWeight(model.Skeleton[bIndex].Name, weight));
                            }
                            xnaWeights.Add(list);
                        }
                    }
                    else
                    {
                        foreach (var vertex in vertices)
                        {
                            var bIndex = vertex.Indices[0];

                            if (bIndex < modelSubMesh.BoneIndices.Length && bIndex > -1)
                            {
                                bIndex = modelSubMesh.BoneIndices[bIndex];
                            }
                            else
                            {
                                bIndex = 0;
                            }

                            xnaWeights.Add(new BoneWeightCollection()
                            {
                                new BoneWeight(model.Skeleton[bIndex].Name, 0)
                            });
                        }
                    }
                    vertexOffset += vertexCount;
                }
                geometry.Vertices.Channels.Add(VertexChannelNames.Weights(0), xnaWeights);
                mesh.Geometry.Add(geometry);
                meshes.Add(mesh);
            }

            foreach (var mesh in meshes)
            {
                _rootNode.Children.Add(mesh);
            }

            var rootBone = ImportBones(model);
            _rootNode.Children.Add(rootBone);

            if (!scene.SkeletalAnimations.Any())
            {
                var path = Path.Combine(Path.GetDirectoryName(filename), $"{Path.GetFileNameWithoutExtension(filename)}@Animations{Path.GetExtension(filename)}");
                if (File.Exists(path))
                {
                    context.Logger.LogMessage($"Found animation file {path}. Loading data...");
                    scene.Merge(FormatIdentifier.IdentifyAndOpen(path, model.Skeleton));
                }
                else
                {
                    context.Logger.LogMessage($"Couldn't find animation file {path}!");
                }
            }

            foreach (var animation in ImportSkeletalAnimations(scene))
            {
                rootBone.Animations.Add(animation.Name, animation);
            }

            foreach (var animation in ImportMaterialAnimations(scene))
            {
                _rootNode.Children.Add(animation);
            }

            return(_rootNode);
        }
Ejemplo n.º 16
0
        private GeometryContent CreateGeometry(MeshContent mesh, Mesh aiMesh)
        {
            var geom = new GeometryContent {
                Material = _materials[aiMesh.MaterialIndex]
            };

            // Vertices
            var baseVertex = mesh.Positions.Count;

            foreach (var vert in aiMesh.Vertices)
            {
                mesh.Positions.Add(ToXna(vert));
            }
            geom.Vertices.AddRange(Enumerable.Range(baseVertex, aiMesh.VertexCount));
            geom.Indices.AddRange(aiMesh.GetIndices());

            if (aiMesh.HasBones)
            {
                var xnaWeights = new List <BoneWeightCollection>();
                for (var i = 0; i < geom.Indices.Count; i++)
                {
                    var list = new BoneWeightCollection();
                    for (var boneIndex = 0; boneIndex < aiMesh.BoneCount; boneIndex++)
                    {
                        var bone = aiMesh.Bones[boneIndex];
                        foreach (var weight in bone.VertexWeights)
                        {
                            if (weight.VertexID != i)
                            {
                                continue;
                            }

                            list.Add(new BoneWeight(bone.Name, weight.Weight));
                        }
                    }
                    if (list.Count > 0)
                    {
                        xnaWeights.Add(list);
                    }
                }

                geom.Vertices.Channels.Add(VertexChannelNames.Weights(0), xnaWeights);
            }

            // Individual channels go here
            if (aiMesh.HasNormals)
            {
                geom.Vertices.Channels.Add(VertexChannelNames.Normal(), ToXna(aiMesh.Normals));
            }

            for (var i = 0; i < aiMesh.TextureCoordinateChannelCount; i++)
            {
                geom.Vertices.Channels.Add(VertexChannelNames.TextureCoordinate(i),
                                           ToXnaTexCoord(aiMesh.TextureCoordinateChannels[i]));
            }

            for (var i = 0; i < aiMesh.VertexColorChannelCount; i++)
            {
                geom.Vertices.Channels.Add(VertexChannelNames.Color(i),
                                           ToXnaColors(aiMesh.VertexColorChannels[i]));
            }

            return(geom);
        }
Ejemplo n.º 17
0
        /// <summary>
        /// Import a VOX file as Model
        /// </summary>
        private NodeContent VoxelProcess(VoxelContent voxel, ContentImporterContext context)
        {
            XYZI[] voxels  = voxel.Voxels;
            uint[] palette = voxel.Palette;

            var     scale        = voxel.RealSize / voxel.GridSize;
            Vector3 centerOffset = new Vector3(1f, 0f, 1f) * (voxel.RealSize / -2f);

            var corner000 = new Point3(0, 0, 0);
            var corner100 = new Point3(1, 0, 0);
            var corner010 = new Point3(0, 1, 0);
            var corner110 = new Point3(1, 1, 0);
            var corner001 = new Point3(0, 0, 1);
            var corner101 = new Point3(1, 0, 1);
            var corner011 = new Point3(0, 1, 1);
            var corner111 = new Point3(1, 1, 1);


            var Forward  = Vector3.Forward;
            var Backward = Vector3.Backward;
            var Left     = Vector3.Left;
            var Right    = Vector3.Right;
            var Up       = Vector3.Up;
            var Down     = Vector3.Down;

            for (int i = 0; i < voxels.Length; i++)
            {
                var pt000 = voxels[i].Point.Add(ref corner000);
                var pt100 = voxels[i].Point.Add(ref corner100);
                var pt010 = voxels[i].Point.Add(ref corner010);
                var pt110 = voxels[i].Point.Add(ref corner110);
                var pt001 = voxels[i].Point.Add(ref corner001);
                var pt101 = voxels[i].Point.Add(ref corner101);
                var pt011 = voxels[i].Point.Add(ref corner011);
                var pt111 = voxels[i].Point.Add(ref corner111);

                // back
                var p0 = pt000.ToVector3();
                var p1 = pt100.ToVector3();
                var p2 = pt010.ToVector3();
                var p3 = pt110.ToVector3();

                // front
                var p4 = pt001.ToVector3();
                var p5 = pt101.ToVector3();
                var p6 = pt011.ToVector3();
                var p7 = pt111.ToVector3();

                Vector3.Multiply(ref p0, ref scale, out p0); Vector3.Add(ref p0, ref centerOffset, out p0);
                Vector3.Multiply(ref p1, ref scale, out p1); Vector3.Add(ref p1, ref centerOffset, out p1);
                Vector3.Multiply(ref p2, ref scale, out p2); Vector3.Add(ref p2, ref centerOffset, out p2);
                Vector3.Multiply(ref p3, ref scale, out p3); Vector3.Add(ref p3, ref centerOffset, out p3);
                Vector3.Multiply(ref p4, ref scale, out p4); Vector3.Add(ref p4, ref centerOffset, out p4);
                Vector3.Multiply(ref p5, ref scale, out p5); Vector3.Add(ref p5, ref centerOffset, out p5);
                Vector3.Multiply(ref p6, ref scale, out p6); Vector3.Add(ref p6, ref centerOffset, out p6);
                Vector3.Multiply(ref p7, ref scale, out p7); Vector3.Add(ref p7, ref centerOffset, out p7);

                vertex.Color.PackedValue = palette[voxels[i].ColorIndex];

                if ((voxels[i].SharedSides & Sides.Forward) == 0)
                {
                    vertex.Normal = Forward;
                    AddVertex(ref p1);
                    AddVertex(ref p3);
                    AddVertex(ref p0);

                    AddVertex(ref p0);
                    AddVertex(ref p3);
                    AddVertex(ref p2);
                }
                if ((voxels[i].SharedSides & Sides.Backward) == 0)
                {
                    vertex.Normal = Backward;
                    AddVertex(ref p4);
                    AddVertex(ref p6);
                    AddVertex(ref p5);

                    AddVertex(ref p5);
                    AddVertex(ref p6);
                    AddVertex(ref p7);
                }

                if ((voxels[i].SharedSides & Sides.Left) == 0)
                {
                    vertex.Normal = Left;
                    AddVertex(ref p2);
                    AddVertex(ref p6);
                    AddVertex(ref p0);

                    AddVertex(ref p0);
                    AddVertex(ref p6);
                    AddVertex(ref p4);
                }
                if ((voxels[i].SharedSides & Sides.Right) == 0)
                {
                    vertex.Normal = Right;
                    AddVertex(ref p1);
                    AddVertex(ref p5);
                    AddVertex(ref p3);

                    AddVertex(ref p3);
                    AddVertex(ref p5);
                    AddVertex(ref p7);
                }

                if ((voxels[i].SharedSides & Sides.Up) == 0)
                {
                    vertex.Normal = Up;
                    AddVertex(ref p7);
                    AddVertex(ref p6);
                    AddVertex(ref p3);

                    AddVertex(ref p3);
                    AddVertex(ref p6);
                    AddVertex(ref p2);
                }
                if ((voxels[i].SharedSides & Sides.Down) == 0)
                {
                    vertex.Normal = Down;
                    AddVertex(ref p5);
                    AddVertex(ref p1);
                    AddVertex(ref p4);

                    AddVertex(ref p4);
                    AddVertex(ref p1);
                    AddVertex(ref p0);
                }
            }

            MeshContent mesh = new MeshContent();

            mesh.Name = "voxel";

            for (int pi = 0; pi < this.vertices.Count; pi++)
            {
                mesh.Positions.Add(this.vertices[pi].Position);
            }

            var geom = new GeometryContent();

            mesh.Geometry.Add(geom);
            BasicMaterialContent material = new BasicMaterialContent();

            geom.Material = material;

            for (int pi = 0; pi < this.vertices.Count; pi++)
            {
                geom.Vertices.Add(pi);
            }

            for (int ii = 0; ii < this.indices.Count; ii++)
            {
                geom.Indices.Add(this.indices[ii]);
            }

            List <Vector3> normals = new List <Vector3>();
            List <Color>   colors  = new List <Color>();

            for (int vi = 0; vi < this.vertices.Count; vi++)
            {
                var vertex = vertices[vi];
                normals.Add(vertex.Normal);
                colors.Add(vertex.Color);
            }

            geom.Vertices.Channels.Add <Vector3>(VertexChannelNames.Normal(0), normals);
            geom.Vertices.Channels.Add <Color>(VertexChannelNames.Color(0), colors);

            return(mesh);
        }
Ejemplo n.º 18
0
        // Build a SubmeshInfo for each GeometryContent.
        private SubmeshInfo[] BuildSubmeshInfos(MeshContent mesh, List <MeshContent> inputMorphs)
        {
            bool hasMorphTargets = (inputMorphs != null && inputMorphs.Count > 0);

            // A lookup table that maps each material to its index.
            // The key is the name of the XML file (string) or the local material (MaterialContent).
            var materialLookupTable = new Dictionary <object, int>();

            int numberOfSubmeshes = mesh.Geometry.Count;
            var submeshInfos      = new SubmeshInfo[numberOfSubmeshes];

            for (int i = 0; i < numberOfSubmeshes; i++)
            {
                var geometry = mesh.Geometry[i];

                // Build morph targets for current submesh.
                List <DRMorphTargetContent> morphTargets = null;
                if (hasMorphTargets)
                {
                    morphTargets = BuildMorphTargets(geometry, inputMorphs, i);
                    if (morphTargets != null && morphTargets.Count > 0)
                    {
                        // When morph targets are used remove the "BINORMAL" channel. (Otherwise,
                        // the number of vertex attributes would exceed the limit. Binormals need
                        // to be reconstructed from normal and tangent in the vertex shader.)
                        string binormalName          = VertexChannelNames.Binormal(0);
                        bool   containsTangentFrames = geometry.Vertices.Channels.Remove(binormalName);

                        if (containsTangentFrames)
                        {
                            // A submesh cannot use vertex colors and tangents at the same time.
                            // This would also exceed the vertex attribute limit.
                            string colorName = VertexChannelNames.Color(0);
                            if (geometry.Vertices.Channels.Contains(colorName))
                            {
                                geometry.Vertices.Channels.Remove(colorName);
                            }
                        }
                    }
                }

                var submeshInfo = new SubmeshInfo
                {
                    Geometry      = geometry,
                    OriginalIndex = i,
                    VertexBuffer  = geometry.Vertices.CreateVertexBuffer(),
                    MorphTargets  = morphTargets
                };
                submeshInfo.VertexBufferIndex = GetVertexBufferIndex(submeshInfo.VertexBuffer.VertexDeclaration);

                // Get material file or local material.
                object material = (object)GetExternalMaterial(mesh, geometry) ?? geometry.Material;
                if (material == null)
                {
                    var message = string.Format(CultureInfo.InvariantCulture, "Mesh \"{0}\" does not have a material.", mesh);
                    throw new InvalidContentException(message, mesh.Identity);
                }

                int materialIndex;
                if (!materialLookupTable.TryGetValue(material, out materialIndex))
                {
                    materialIndex = materialLookupTable.Count;
                    materialLookupTable.Add(material, materialIndex);
                }

                submeshInfo.MaterialIndex = materialIndex;
                submeshInfo.Material      = material;

                submeshInfos[i] = submeshInfo;
            }

            return(submeshInfos);
        }