示例#1
0
        /// <summary>
        /// Converts design-time vertex position and channel data into a vertex buffer format that a graphics device can recognize.
        /// </summary>
        /// <returns>A packed vertex buffer.</returns>
        /// <exception cref="InvalidContentException">
        /// One or more of the vertex channel types are invalid or an unrecognized name was passed to <see cref="VertexElementUsage"/>.
        /// </exception>
        public VertexBufferContent CreateVertexBuffer()
        {
            var vertexBuffer = new VertexBufferContent(positions.Count);
            var stride       = SetupVertexDeclaration(vertexBuffer);

            // TODO: Verify enough elements in channels to match positions?

            // Write out data in an interleaved fashion each channel at a time, for example:
            //    |------------------------------------------------------------|
            //    |POSITION[0] | NORMAL[0]  |TEX0[0] | POSITION[1]| NORMAL[1]  |
            //    |-----------------------------------------------|------------|
            // #0 |111111111111|____________|________|111111111111|____________|
            // #1 |111111111111|111111111111|________|111111111111|111111111111|
            // #2 |111111111111|111111111111|11111111|111111111111|111111111111|

            // #0: Write position vertices using stride to skip over the other channels:
            vertexBuffer.Write(0, stride, positions);

            var channelOffset = VertexBufferContent.SizeOf(typeof(Vector3));

            foreach (var channel in Channels)
            {
                // #N: Fill in the channel within each vertex
                var channelType = channel.ElementType;
                vertexBuffer.Write(channelOffset, stride, channelType, channel);
                channelOffset += VertexBufferContent.SizeOf(channelType);
            }

            return(vertexBuffer);
        }
示例#2
0
 public GeometryDataContent(string name, VertexBufferContent vertices, IndexCollection indices, BoundingSphere bounds)
 {
     this.Name     = name;
     this.Vertices = vertices;
     this.Indices  = indices;
     this.Bounds   = bounds;
 }
示例#3
0
        private List <DRSubmeshContent> BuildSubmeshes(MeshContent mesh, SubmeshInfo[] submeshInfos)
        {
            var submeshes = new List <DRSubmeshContent>(mesh.Geometry.Count);

            for (int i = 0; i < submeshInfos.Length; i++)
            {
                var submeshInfo = submeshInfos[i];
                var geometry    = submeshInfo.Geometry;

                // Append vertices to one of the _vertexBuffers.
                VertexBufferContent vertexBuffer = null;
                int vertexCount  = 0;
                int vertexOffset = 0;
                if (submeshInfo.VertexBuffer.VertexData.Length > 0)
                {
                    vertexBuffer = _vertexBuffers[submeshInfo.VertexBufferIndex];
                    if (!vertexBuffer.VertexDeclaration.VertexStride.HasValue)
                    {
                        string message = string.Format(CultureInfo.InvariantCulture, "Vertex declaration of \"{0}\" does not have a vertex stride.", mesh);
                        throw new InvalidContentException(message, mesh.Identity);
                    }

                    vertexCount  = submeshInfo.Geometry.Vertices.VertexCount;
                    vertexOffset = vertexBuffer.VertexData.Length / vertexBuffer.VertexDeclaration.VertexStride.Value;
                    vertexBuffer.Write(vertexBuffer.VertexData.Length, 1, submeshInfo.VertexBuffer.VertexData);
                }

                // Append indices to _indices.
                int startIndex     = 0;
                int primitiveCount = 0;
                if (geometry.Indices.Count > 0)
                {
                    startIndex     = _indices.Count;
                    primitiveCount = geometry.Indices.Count / 3;
                    _indices.AddRange(geometry.Indices);
                }

                // Build material.
                object material = BuildMaterial(submeshInfo.Material);

                // Create Submesh.
                DRSubmeshContent submesh = new DRSubmeshContent
                {
                    IndexBuffer      = _indices,
                    VertexCount      = vertexCount,
                    StartIndex       = startIndex,
                    PrimitiveCount   = primitiveCount,
                    VertexBuffer     = vertexBuffer,
                    StartVertex      = vertexOffset,
                    MorphTargets     = submeshInfo.MorphTargets,
                    ExternalMaterial = material as ExternalReference <DRMaterialContent>,
                    LocalMaterial    = material as DRMaterialContent,
                };
                submeshes.Add(submesh);
            }
            return(submeshes);
        }
        private void CopyStream(VertexBufferContent source)
        {
            var vertexBufferType          = typeof(VertexBufferContent);
            var vertexBufferStreamField   = vertexBufferType.GetField("stream", BindingFlags.Instance | BindingFlags.NonPublic);
            var vertexBufferStream        = (MemoryStream)vertexBufferStreamField.GetValue(source);
            var dynamicVertexBufferStream = new MemoryStream(vertexBufferStream.ToArray());

            vertexBufferStreamField.SetValue(this, dynamicVertexBufferStream);
        }
 internal SkinnedModelMeshContent(int numVertices, int numTriangles, VertexBufferContent vertices,
     IndexCollection indices, MaterialContent material)
 {
     this.numVertices = numVertices;
     this.numTriangles = numTriangles;
     this.vertices = vertices;
     this.indices = indices;
     this.material = material;
 }
示例#6
0
 internal ModelMeshPartContent(VertexBufferContent vertexBuffer, IndexCollection indices, int vertexOffset,
                               int numVertices, int startIndex, int primitiveCount)
 {
     _vertexBuffer = vertexBuffer;
     _indexBuffer = indices;
     _vertexOffset = vertexOffset;
     _numVertices = numVertices;
     _startIndex = startIndex;
     _primitiveCount = primitiveCount;
 }
 public DynamicVertexBufferContent(VertexBufferContent source, int size = 0) : base(size)
 {
     Identity = source.Identity;
     Name     = source.Name;
     foreach (var keyPair in source.OpaqueData)
     {
         OpaqueData.Add(keyPair.Key, keyPair.Value);
     }
     VertexDeclaration = source.VertexDeclaration;
     CopyStream(source);
 }
示例#8
0
        /// <summary>
        /// Initializes a new instance of a static model.
        /// </summary>
        public StaticModelContent()
        {
            vertexContent = new VertexBufferContent();
            VertexDeclarationContent vertContent = new VertexDeclarationContent();

            foreach (VertexElement element in VertexStaticModel.VertexDeclaration.GetVertexElements())
            {
                vertContent.VertexElements.Add(element);
            }
            vertexContent.VertexDeclaration = vertContent;
            indexContent = new IndexCollection();
        }
        /// <summary>
        /// Helper function used by the CustomModelProcessor
        /// to add new ModelPart information.
        /// </summary>
        public void AddModelPart(int triangleCount, int vertexCount,
                                 VertexBufferContent vertexBufferContent,
                                 IndexCollection indexCollection,
                                 MaterialContent materialContent)
        {
            ModelPart modelPart = new ModelPart();

            modelPart.TriangleCount       = triangleCount;
            modelPart.VertexCount         = vertexCount;
            modelPart.VertexBufferContent = vertexBufferContent;
            modelPart.IndexCollection     = indexCollection;
            modelPart.MaterialContent     = materialContent;

            modelParts.Add(modelPart);
        }
示例#10
0
        /// <summary>
        /// Converts a single piece of input geometry into our custom format.
        /// </summary>
        void ProcessGeometry(GeometryContent geometry)
        {
            int triangleCount = geometry.Indices.Count / 3;
            int vertexCount   = geometry.Vertices.VertexCount;

            // Flatten the flexible input vertex channel data into
            // a simple GPU style vertex buffer byte array.
            VertexBufferContent vertexBufferContent = geometry.Vertices.CreateVertexBuffer();

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

            // Add the new piece of geometry to our output model.
            outputModel.AddModelPart(triangleCount, vertexCount,
                                     vertexBufferContent, geometry.Indices, material);
        }
示例#11
0
        private int SetupVertexDeclaration(VertexBufferContent result)
        {
            var offset = 0;

            // We always have a position channel
            result.VertexDeclaration.VertexElements.Add(new VertexElement(offset, VertexElementFormat.Vector3,
                                                                          VertexElementUsage.Position, 0));
            offset += VertexElementFormat.Vector3.GetTypeSize();

            // Optional channels
            foreach (var channel in Channels)
            {
                VertexElementFormat format;
                VertexElementUsage  usage;

                // Try to determine the vertex format
                // TODO: Add support for additional formats as they become testable
                if (channel.ElementType == typeof(Vector3))
                {
                    format = VertexElementFormat.Vector3;
                }
                else if (channel.ElementType == typeof(Vector2))
                {
                    format = VertexElementFormat.Vector2;
                }
                else
                {
                    throw new InvalidContentException("Unrecognized vertex content type.");
                }

                // Try to determine the vertex usage
                if (!VertexChannelNames.TryDecodeUsage(channel.Name, out usage))
                {
                    throw new InvalidContentException("Unknown vertex element usage.");
                }

                // Try getting the usage index
                var usageIndex = VertexChannelNames.DecodeUsageIndex(channel.Name);

                result.VertexDeclaration.VertexElements.Add(new VertexElement(offset, format, usage, usageIndex));
                offset += format.GetTypeSize();
                result.VertexDeclaration.VertexStride = offset;
            }
            return(offset);
        }
        /// <summary>
        /// Helper function used by the CustomModelProcessor
        /// to add new ModelPart information.
        /// </summary>
        public void AddModelPart( int triangleCount, int vertexCount, int vertexStride,
            VertexElement[] vertexElements,
            VertexBufferContent vertexBufferContent,
            IndexCollection indexCollection,
            MaterialContent materialContent)
        {
            ModelPart modelPart = new ModelPart();

              modelPart.TriangleCount = triangleCount;
              modelPart.VertexCount = vertexCount;
              modelPart.VertexStride = vertexStride;
              modelPart.VertexElements = vertexElements;
              modelPart.VertexBufferContent = vertexBufferContent;
              modelPart.IndexCollection = indexCollection;
              modelPart.MaterialContent = materialContent;

              modelParts.Add( modelPart );
        }
        /// <summary>
        /// Helper function used by the InstancedModelProcessor
        /// to add new ModelPart information.
        /// </summary>
        public void AddModelPart(int indexCount, int vertexCount, int vertexStride,
                                 VertexElement[] vertexElements,
                                 VertexBufferContent vertexBufferContent,
                                 IndexCollection indexCollection,
                                 MaterialContent materialContent)
        {
            ModelPart modelPart = new ModelPart();

            modelPart.IndexCount          = indexCount;
            modelPart.VertexCount         = vertexCount;
            modelPart.VertexStride        = vertexStride;
            modelPart.VertexElements      = vertexElements;
            modelPart.VertexBufferContent = vertexBufferContent;
            modelPart.IndexCollection     = indexCollection;
            modelPart.MaterialContent     = materialContent;

            modelParts.Add(modelPart);
        }
 public H3DAnimatedDynamicVertexBufferContent(VertexBufferContent source, int size = 0) : base(source, size)
 {
 }
示例#15
0
        private int SetupVertexDeclaration(VertexBufferContent result)
        {
            var offset = 0;

            // We always have a position channel
            result.VertexDeclaration.VertexElements.Add(new VertexElement(offset, VertexElementFormat.Vector3,
                                                                          VertexElementUsage.Position, 0));
            offset += VertexElementFormat.Vector3.GetTypeSize();

            // Optional channels
            foreach (var channel in Channels)
            {
                VertexElementFormat format;
                VertexElementUsage usage;

                // Try to determine the vertex format
                // TODO: Add support for additional formats as they become testable
                if (channel.ElementType == typeof(Vector3))
                    format = VertexElementFormat.Vector3;
                else if (channel.ElementType == typeof(Vector2))
                    format = VertexElementFormat.Vector2;
                else
                    throw new InvalidContentException("Unrecognized vertex content type.");

                // Try to determine the vertex usage
                if (!VertexChannelNames.TryDecodeUsage(channel.Name, out usage))
                    throw new InvalidContentException("Unknown vertex element usage.");

                // Try getting the usage index
                var usageIndex = VertexChannelNames.DecodeUsageIndex(channel.Name);

                result.VertexDeclaration.VertexElements.Add(new VertexElement(offset, format, usage, usageIndex));
                offset += format.GetTypeSize();
                result.VertexDeclaration.VertexStride = offset;
            }
            return offset;
        }
		public PatchContent Build()
		{
			#region Local vertex buffer

			// create local vertex buffer for patch
			int numVertices = _patchSize * _patchSize;
			VertexBufferContent localVertexBuffer = new VertexBufferContent(numVertices);

			// fill vertex buffer
			VertexPositionNormalTexture2[] vertices = new VertexPositionNormalTexture2[numVertices];

			int nStartX = _patchOffsetX * (_patchSize - 1);
			int nStartY = _patchOffsetY * (_patchSize - 1);
			int nEndX = nStartX + _patchSize;
			int nEndY = nStartY + _patchSize;

			float fMinZ = float.MaxValue, fMaxZ = float.MinValue;
			int index = 0;
			for (int y = nStartY; y < nEndY; y++)
			{
				for (int x = nStartX; x < nEndX; x++)
				{
					// write local data
					float fZ = _heightMap[x, y];

					if (fZ < fMinZ) fMinZ = fZ;
					if (fZ > fMaxZ) fMaxZ = fZ;

					Vector2 texCoords1 = new Vector2(x / (float) (_heightMap.Width - 1), y / (float) (_heightMap.Height - 1));
					Vector2 texCoords2 = texCoords1 * _detailTextureTiling;

					vertices[index++] = new VertexPositionNormalTexture2(
						new Vector3(x * _horizontalScale, fZ, y * _horizontalScale),
						new Vector3(0, 1, 0),
						texCoords1,
						texCoords2);
				}
			}

			localVertexBuffer.Write(0, VertexBufferContent.SizeOf(typeof(VertexPositionNormalTexture2)), vertices);
			localVertexBuffer.VertexDeclaration = new VertexDeclarationContent();
			foreach (VertexElement vertexElement in VertexPositionNormalTexture2.VertexDeclaration.GetVertexElements())
				localVertexBuffer.VertexDeclaration.VertexElements.Add(vertexElement);

			#endregion

			LevelContent[] levels = new LevelContent[_numLevels];
			for (int i = 0; i < _numLevels; i++)
			{
				LevelContentBuilder levelContentBuilder = new LevelContentBuilder(_heightMap, _patchSize, _numLevels, i, nStartX,
					nEndX, nStartY, nEndY);
				levels[i] = levelContentBuilder.Build();
			}

			#region Bounding box, centre, and offset

			BoundingBox boundingBox = new BoundingBox(
				new Vector3(nStartX * _horizontalScale, fMinZ, nStartY * _horizontalScale),
				new Vector3(nEndX * _horizontalScale, fMaxZ, nEndY * _horizontalScale));

			float fAverageZ = (fMinZ + fMaxZ) / 2.0f;

			Vector3 center = new Vector3(
				(nStartX + ((_patchSize - 1) / 2.0f)) * _horizontalScale,
				fAverageZ,
				(nStartY + ((_patchSize - 1) / 2.0f)) * _horizontalScale);

			Vector2 offset = new Vector2(
				(_patchOffsetX * (_patchSize - 1)) * _horizontalScale,
				(_patchOffsetY * (_patchSize - 1)) * _horizontalScale);

			#endregion

			return new PatchContent
			{
				VertexBuffer = localVertexBuffer,
				Levels = levels,
				BoundingBox  =boundingBox,
				Center = center,
				Offset = offset
			};
		}
示例#17
0
        private int SetupVertexDeclaration(VertexBufferContent result)
        {
            var offset = 0;

            // We always have a position channel
            result.VertexDeclaration.VertexElements.Add(
                new VertexElement(offset, VertexElementFormat.Vector3, VertexElementUsage.Position, 0));
            offset += VertexElementFormat.Vector3.GetSize();

            // Optional channels
            foreach (var channel in Channels)
            {
                VertexElementFormat format;

                // Try to determine the vertex format
                if (channel.ElementType == typeof(float))
                {
                    format = VertexElementFormat.Single;
                }
                else if (channel.ElementType == typeof(Vector2))
                {
                    format = VertexElementFormat.Vector2;
                }
                else if (channel.ElementType == typeof(Vector3))
                {
                    format = VertexElementFormat.Vector3;
                }
                else if (channel.ElementType == typeof(Vector4))
                {
                    format = VertexElementFormat.Vector4;
                }
                else if (channel.ElementType == typeof(Color))
                {
                    format = VertexElementFormat.Color;
                }
                else if (channel.ElementType == typeof(Byte4))
                {
                    format = VertexElementFormat.Byte4;
                }
                else if (channel.ElementType == typeof(Short2))
                {
                    format = VertexElementFormat.Short2;
                }
                else if (channel.ElementType == typeof(Short4))
                {
                    format = VertexElementFormat.Short4;
                }
                else if (channel.ElementType == typeof(NormalizedShort2))
                {
                    format = VertexElementFormat.NormalizedShort2;
                }
                else if (channel.ElementType == typeof(NormalizedShort4))
                {
                    format = VertexElementFormat.NormalizedShort4;
                }
                else if (channel.ElementType == typeof(HalfVector2))
                {
                    format = VertexElementFormat.HalfVector2;
                }
                else if (channel.ElementType == typeof(HalfVector4))
                {
                    format = VertexElementFormat.HalfVector4;
                }
                else
                {
                    throw new InvalidContentException(string.Format("Unrecognized vertex content type: '{0}'", channel.ElementType));
                }

                // Try to determine the vertex usage
                if (!VertexChannelNames.TryDecodeUsage(channel.Name, out VertexElementUsage usage))
                {
                    throw new InvalidContentException(string.Format("Unknown vertex element usage for channel '{0}'", channel.Name));
                }

                // Try getting the usage index
                var usageIndex = VertexChannelNames.DecodeUsageIndex(channel.Name);

                result.VertexDeclaration.VertexElements.Add(new VertexElement(offset, format, usage, usageIndex));
                offset += format.GetSize();
            }

            result.VertexDeclaration.VertexStride = offset;
            return(offset);
        }
示例#18
0
 public void CreateVertexBuffer(out VertexBufferContent vertexBuffer, out VertexElement[] vertexElements, TargetPlatform targetPlatform)
 {
     throw new NotImplementedException();
 }
示例#19
0
 // From VertexBufferWriter in MonoGame.Framework.Content.Pipeline
 private static void Write(ContentWriter output, VertexBufferContent value)
 {
     output.WriteRawObject(value.VertexDeclaration);
     output.Write((uint)(value.VertexData.Length / value.VertexDeclaration.VertexStride));
     output.Write(value.VertexData);
 }
示例#20
0
        public ModelContent ImportModel(string filename, IContentImporter importer)
        {
            if (File.Exists(filename))
            {
            }
            else if (File.Exists(filename + ".fbx"))
            {
                filename += ".fbx";
            }
            else if (next != null)
            {
                return(next(filename, importer));
            }
            else
            {
                throw new FileNotFoundException("The file could not be found", filename);
            }

            var fimporter = new Importer();

            var scene = fimporter.Import(filename);



            var model = new ModelContent();

            model.Filename = filename;


            var bonesByNode = new Dictionary <Node, BoneContent>();
            var nodesByBone = new Dictionary <BoneContent, Node>();

            foreach (var node in scene.Nodes)
            {
                var bone = BoneFromNode(node);
                bonesByNode[node] = bone;
                nodesByBone[bone] = node;
                model.Bones.Add(bone);
                if (node == scene.GetRootNode())
                {
                    model.RootBoneIndex = model.Bones.Count - 1;
                    bone.Transform      = bone.Transform.Transposed();
                }
            }
            foreach (var node in scene.Nodes)
            {
                var bone = bonesByNode[node];

                if (node.GetNodeAttributeCount() > 0 &&
                    node.GetNodeAttributeByIndex(0) is Mesh)
                {
                    var mesh  = (Mesh)node.GetNodeAttributeByIndex(0);
                    var mesh2 = new MeshContent();
                    model.Meshes.Add(mesh2);
                    mesh2.ParentBone = bone;
                    mesh2.Name       = mesh.GetName();

                    bool          isSkinned = true;
                    ShaderContent vert;
                    if (mesh.GetDeformerCount() < 1)
                    {
                        isSkinned = false;
                        vert      = importer.ImportShaderStage("$basic", ShaderType.Vertex, importer);
                    }
                    else if (mesh.GetDeformerCount() > 1)
                    {
                        throw new NotImplementedException();
                    }
                    else
                    {
                        vert = importer.ImportShaderStage("$skinned", ShaderType.Vertex, importer);
                    }
                    var frag = importer.ImportShaderStage("$basic", ShaderType.Fragment, importer);

                    // calculate the global transform for the mesh

                    var meshTransform = node.EvaluateGlobalTransform();

                    // extract the vertex postions

                    var vertices =
                        Enumerable.Range(0, mesh.GetControlPointsCount())
                        .Select(ix => {
                        var cp    = mesh.GetControlPointAt((int)ix);
                        var baked = meshTransform.MultNormalize(cp);
                        var pos   = baked.ToChamber().ToVectorXYZ();
                        return(new Vertex_PBiBwNT {
                            Position = pos
                        });
                    })
                        .ToList();

                    // extract the blend indices and weights

                    if (mesh.GetDeformerCount() == 1)
                    {
                        if (!(mesh.GetDeformer(0) is Skin))
                        {
                            throw new NotImplementedException("Only Skin deformers are implemented");
                        }

                        var boneIndicesL =
                            Enumerable.Range(
                                0,
                                mesh.GetControlPointsCount())
                            .Select(x => new List <float>())
                            .ToList();
                        var boneWeightsL =
                            Enumerable.Range(
                                0,
                                mesh.GetControlPointsCount())
                            .Select(x => new List <float>())
                            .ToList();

                        int i;

                        var skin = (Skin)mesh.GetDeformer(0);
                        foreach (var cluster in skin.Clusters)
                        {
                            var cnode     = cluster.GetLink();
                            var cbone     = bonesByNode[cnode];
                            var boneIndex = model.Bones.IndexOf(cbone);

                            for (i = 0; i < cluster.ControlPointIndices.Count; i++)
                            {
                                var index  = cluster.ControlPointIndices[i];
                                var weight = cluster.ControlPointWeights[i];

                                if (boneIndicesL[index].Count > 4 ||
                                    boneWeightsL[index].Count > 4)
                                {
                                    throw new NotImplementedException("Too many indices or weights");
                                }

                                boneIndicesL[index].Add((float)boneIndex);
                                boneWeightsL[index].Add((float)weight);

                                if (boneIndicesL[index].Count > 4 ||
                                    boneWeightsL[index].Count > 4)
                                {
                                    throw new NotImplementedException("Too many indices or weights");
                                }
                            }
                        }

                        Func <List <float>, Vector4> convert = fs => {
                            if (fs.Count == 4)
                            {
                                return(new Vector4(fs[0], fs[1], fs[2], fs[3]));
                            }
                            if (fs.Count == 3)
                            {
                                return(new Vector4(fs[0], fs[1], fs[2], 0));
                            }
                            if (fs.Count == 2)
                            {
                                return(new Vector4(fs[0], fs[1], 0, 0));
                            }
                            if (fs.Count == 1)
                            {
                                return(new Vector4(fs[0], 0, 0, 0));
                            }
                            return(Vector4.Zero);
                        };

                        var boneIndicesV = boneIndicesL.Select(convert).ToList();
                        var boneWeightsV = boneWeightsL.Select(convert).ToList();

                        for (i = 0; i < vertices.Count; i++)
                        {
                            var vertex = vertices[i];
                            vertex.SetBlendIndices(boneIndicesV[i]);
                            vertex.SetBlendWeights(boneWeightsV[i]);
                            vertices[i] = vertex;
                        }
                    }


                    // construct a list of polygons
                    //  beyond this point, we don't need `vertices` until it
                    //  gets re-used to build the vertex buffer

                    var polygons = mesh.PolygonIndexes.Select(p =>
                                                              new PolygonBuilder {
                        PolygonVertexIndexes = p,
                        Vertexes             = p.Select(ix => vertices[(int)ix]).ToList(),
                    }).ToList();

                    var polygonsByMaterial = new Dictionary <SurfaceMaterial, List <PolygonBuilder> >();

                    // organize the mesh's polygons by material

                    var layer      = mesh.GetLayer(0);
                    var matelem    = layer.GetMaterials();
                    var matindexes = matelem.MaterialIndexes.List;// GetIndexArray().List;
                    if (matelem.ReferenceMode != LayerElement.EReferenceMode.IndexToDirect)
                    {
                        throw new NotImplementedException("A materials must have a reference mode of IndexToDirect");
                    }
                    if (matelem.MappingMode == LayerElement.EMappingMode.AllSame)
                    {
                        // only one material
                        var material = node.GetMaterial(matindexes[0]);

                        polygonsByMaterial[material] = new List <PolygonBuilder>(polygons);
                    }
                    else if (matelem.MappingMode == LayerElement.EMappingMode.ByPolygon)
                    {
                        // multiple materials
                        foreach (var mat in node.Materials)
                        {
                            polygonsByMaterial[mat] = new List <PolygonBuilder>();
                        }
                        int i;
                        for (i = 0; i < matindexes.Count; i++)
                        {
                            var mat = node.Materials[matindexes[i]];
                            polygonsByMaterial[mat].Add(polygons[i]);
                        }
                    }
                    else
                    {
                        throw new NotImplementedException("Materials must have mapping modes of AllSame or ByPolygon");
                    }

                    // extract the vertex normals

                    if (layer.GetNormals() != null)
                    {
                        var normalElement = layer.GetNormals();
                        if (normalElement.MappingMode != LayerElement.EMappingMode.ByPolygonVertex)
                        {
                            throw new NotImplementedException("Normals layer elements must have a mapping mode of ByPolygonVertex");
                        }
                        if (normalElement.ReferenceMode != LayerElement.EReferenceMode.Direct &&
                            normalElement.ReferenceMode != LayerElement.EReferenceMode.IndexToDirect)
                        {
                            throw new NotImplementedException("Normals layer elements must have a reference mode of Direct or IndexToDirect");
                        }
                        int k = 0;
                        foreach (var poly in polygons)
                        {
                            int i;
                            for (i = 0; i < poly.Vertexes.Count; i++)
                            {
                                int nindex;
                                if (normalElement.ReferenceMode == LayerElement.EReferenceMode.Direct)
                                {
                                    nindex = k;
                                }
                                else
                                {
                                    nindex = normalElement.GetIndexArray().GetAt(k);
                                }

                                var v      = normalElement.GetDirectArray().GetAt(nindex);
                                var vertex = poly.Vertexes[i];
                                vertex.Normal    = meshTransform.MultNormalize(v).ToChamber().ToVectorXYZ();
                                poly.Vertexes[i] = vertex;
                                k++;
                            }
                        }
                    }

                    // extract the texture coordinates

                    if (layer.GetUVs() != null)
                    {
                        var uvElement = layer.GetUVs();
                        if (uvElement.MappingMode != LayerElement.EMappingMode.ByPolygonVertex)
                        {
                            throw new NotImplementedException("UV layer elements must have a mapping mode of ByPolygonVertex");
                        }
                        if (uvElement.ReferenceMode != LayerElement.EReferenceMode.Direct &&
                            uvElement.ReferenceMode != LayerElement.EReferenceMode.IndexToDirect)
                        {
                            throw new NotImplementedException("UV layer elements must have a reference mode of Direct or IndexToDirect");
                        }
                        int k = 0;
                        foreach (var poly in polygons)
                        {
                            int i;
                            for (i = 0; i < poly.Vertexes.Count; i++)
                            {
                                int nindex;
                                if (uvElement.ReferenceMode == LayerElement.EReferenceMode.Direct)
                                {
                                    nindex = k;
                                }
                                else
                                {
                                    nindex = uvElement.GetIndexArray().GetAt(k);
                                }

                                var v      = uvElement.GetDirectArray().GetAt(nindex);
                                var vv     = v.ToChamber();
                                var vertex = poly.Vertexes[i];
                                vertex.SetTextureCoords(new ChamberLib.Vector2(vv.X, 1 - vv.Y));
                                poly.Vertexes[i] = vertex;
                                k++;
                            }
                        }
                    }

                    // trianglize polygons with more than three points

                    foreach (var mat in polygonsByMaterial.Keys.ToArray())
                    {
                        var polys = polygonsByMaterial[mat];
                        polygonsByMaterial[mat] = polys.SelectMany(p => {
                            if (p.Vertexes.Count < 3)
                            {
                                throw new InvalidOperationException();
                            }
                            if (p.Vertexes.Count == 3)
                            {
                                return(p.Yield());
                            }
                            int i;
                            var newPolys = new List <PolygonBuilder>();
                            for (i = 2; i < p.Vertexes.Count; i++)
                            {
                                var pb = new PolygonBuilder();

                                pb.PolygonVertexIndexes = new List <long>();
                                pb.PolygonVertexIndexes.Add(p.PolygonVertexIndexes[0]);
                                pb.PolygonVertexIndexes.Add(p.PolygonVertexIndexes[i - 1]);
                                pb.PolygonVertexIndexes.Add(p.PolygonVertexIndexes[i]);

                                pb.Vertexes = new List <Vertex_PBiBwNT>();
                                pb.Vertexes.Add(p.Vertexes[0]);
                                pb.Vertexes.Add(p.Vertexes[i - 1]);
                                pb.Vertexes.Add(p.Vertexes[i]);

                                newPolys.Add(pb);
                            }
                            return(newPolys);
                        }).ToList();
                    }

                    // construct the vertex and index buffers

                    var vertset = new HashSet <Vertex_PBiBwNT>();
                    vertices.Clear();
                    var indices = new List <int>();

                    var vertexBuffer = new VertexBufferContent();
                    var indexBuffer  = new IndexBufferContent();

                    model.VertexBuffers.Add(vertexBuffer);
                    model.IndexBuffers.Add(indexBuffer);

                    var indexByVertex = new Dictionary <Vertex_PBiBwNT, int>();

                    foreach (var mat in polygonsByMaterial.Keys)
                    {
                        var polys     = polygonsByMaterial[mat];
                        var polyverts = polys.SelectMany(p => p.Vertexes).ToArray();

                        var startIndex = indices.Count;

                        int n0 = vertices.Count;
                        vertices.AddRange(polyverts.Except(vertset));
                        int n1 = vertices.Count;
                        int i;
                        for (i = n0; i < n1; i++)
                        {
                            indexByVertex[vertices[i]] = i;
                        }

                        var polyindices = polyverts.Select(p => indexByVertex[p]);
                        indices.AddRange(polyindices);

                        vertset.AddRange(polyverts);

                        mesh2.Parts.Add(new PartContent()
                        {
                            Material       = GetMaterialFromMaterial(mat, vert, frag, importer, filename),
                            StartIndex     = startIndex,
                            PrimitiveCount = polys.Count,
                            Vertexes       = vertexBuffer,
                            Indexes        = indexBuffer,
                        });
                    }

                    indexBuffer.Indexes = indices.Select(ix => (short)ix).ToArray();

                    if (isSkinned)
                    {
                        vertexBuffer.Vertices = vertices.Cast <IVertex>().ToArray();
                    }
                    else
                    {
                        vertexBuffer.Vertices =
                            vertices.Select <Vertex_PBiBwNT, IVertex>(v =>
                                                                      new Vertex_PNT {
                            Position      = v.Position,
                            Normal        = v.Normal,
                            TextureCoords = v.TextureCoords,
                        }).ToArray();
                    }
                }
            }
            foreach (var node in scene.Nodes)
            {
                var bone = bonesByNode[node];
                int i;
                int n = node.GetChildCount();
                for (i = 0; i < n; i++)
                {
                    bone.ChildBoneIndexes.Add(scene.Nodes.IndexOf(node.GetChild(i)));
                }
            }

            if (scene.Poses.Count > 0)
            {
                var pose = scene.Poses[0];
                foreach (var pi in pose.PoseInfos)
                {
                    var bone = bonesByNode[pi.Node];
                    var m    = pi.Matrix.ToChamber();
                    bone.Transform = m;
                }
            }

            // animations

            Dictionary <string, AnimationSequence> sequences = null;
            var numstacks = scene.GetSrcObjectCount <AnimStack>();
            int j;

            for (j = 0; j < numstacks; j++)
            {
                var stack = scene.GetSrcObject <AnimStack>(j);

                if (sequences == null)
                {
                    sequences = new Dictionary <string, AnimationSequence>();
                }

                var timespan = stack.GetLocalTimeSpan();
                var layer    = (AnimLayer)stack.SrcObjects.FirstOrDefault(x => x is AnimLayer);

                scene.SetCurrentAnimationStack(stack);
                var        eval   = scene.GetAnimationEvaluator();
                var        frames = new List <AnimationFrame>();
                FbxTime    t;
                int        i;
                var        startOffset     = timespan.Start.GetSecondDouble();
                const int  framesPerSecond = 60;
                const long timeStep        = FbxTime.UnitsPerSecond / framesPerSecond;
                for (t = timespan.Start; t.Value <= timespan.Stop.Value; t = new FbxTime(t.Value + timeStep))
                {
                    var transforms = new ChamberLib.Matrix[model.Bones.Count];
                    for (i = 0; i < model.Bones.Count; i++)
                    {
                        var node = nodesByBone[model.Bones[i]];
                        var m    = eval.GetNodeLocalTransform(node, t).ToChamber();

                        transforms[i] = m;
                    }
                    frames.Add(new AnimationFrame((float)(t.GetSecondDouble() - startOffset), transforms));
                }

                var name = stack.Name.Replace("AnimStack::", "");
                sequences.Add(
                    name,
                    new AnimationSequence(
                        (float)(timespan.Stop.GetSecondDouble() - timespan.Start.GetSecondDouble()),
                        frames.ToArray(),
                        name));
            }

            Matrix[]   localTransforms    = null;
            Matrix[]   absoluteTransforms = null;
            List <int> skeletonHierarchy  = null;

            if (model.Bones != null && model.Bones.Count > 0)
            {
                skeletonHierarchy = Enumerable.Repeat(-1, model.Bones.Count).ToList();
                int i;
                for (i = 0; i < model.Bones.Count; i++)
                {
                    foreach (var childIndex in model.Bones[i].ChildBoneIndexes)
                    {
                        skeletonHierarchy[childIndex] = i;
                    }
                }
                localTransforms = new Matrix[model.Bones.Count];
                var globalTransforms = model.Bones.Select(b => b.Transform).ToArray();
                for (i = 0; i < model.Bones.Count; i++)
                {
                    var p = skeletonHierarchy[i];
                    if (p < 0)
                    {
                        localTransforms[i] = globalTransforms[i];
                    }
                    else
                    {
                        localTransforms[i] = globalTransforms[i] * globalTransforms[p].Inverted();
                    }
                }

                absoluteTransforms = new Matrix[model.Bones.Count];
                for (i = 0; i < model.Bones.Count; i++)
                {
                    absoluteTransforms[i] = globalTransforms[i].Inverted();
                }
            }

            if (sequences != null ||
                localTransforms != null ||
                absoluteTransforms != null ||
                skeletonHierarchy != null)
            {
                if (sequences == null)
                {
                    sequences = new Dictionary <string, AnimationSequence>();
                }
                if (localTransforms == null)
                {
                    localTransforms = new Matrix[0];
                }
                if (absoluteTransforms == null)
                {
                    absoluteTransforms = new Matrix[0];
                }
                if (skeletonHierarchy == null)
                {
                    skeletonHierarchy = new List <int>();
                }

                model.AnimationData =
                    new AnimationData(
                        sequences,
                        localTransforms.ToList(),
                        absoluteTransforms.ToList(),
                        skeletonHierarchy);
            }

            return(model);
        }
 public CpuAnimatedVertexBufferContent(VertexBufferContent source) : base(source)
 {
 }
示例#22
0
 public DynamicVertexBufferContent(VertexBufferContent source, int size) : base(size)
 {
     Source = source;
 }
示例#23
0
 public DynamicVertexBufferContent(VertexBufferContent source) : base()
 {
     Source = source;
 }
示例#24
0
        private int SetupVertexDeclaration(VertexBufferContent result)
        {
            var offset = 0;

            // We always have a position channel
            result.VertexDeclaration.VertexElements.Add(new VertexElement(offset, VertexElementFormat.Vector3,
                                                                           VertexElementUsage.Position, 0));
            offset += VertexElementFormat.Vector3.GetSize();

            // Optional channels
            foreach (var channel in Channels)
            {
                VertexElementFormat format;
                VertexElementUsage usage;

                // Try to determine the vertex format
                if (channel.ElementType == typeof(Single))
                    format = VertexElementFormat.Single;
                else if (channel.ElementType == typeof(Vector2))
                    format = VertexElementFormat.Vector2;
                else if (channel.ElementType == typeof(Vector3))
                    format = VertexElementFormat.Vector3;
                else if (channel.ElementType == typeof(Vector4))
                    format = VertexElementFormat.Vector4;
                else if (channel.ElementType == typeof(Color))
                    format = VertexElementFormat.Color;
                else if (channel.ElementType == typeof(Byte4))
                    format = VertexElementFormat.Byte4;
                else if (channel.ElementType == typeof(Short2))
                    format = VertexElementFormat.Short2;
                else if (channel.ElementType == typeof(Short4))
                    format = VertexElementFormat.Short4;
                else if (channel.ElementType == typeof(NormalizedShort2))
                    format = VertexElementFormat.NormalizedShort2;
                else if (channel.ElementType == typeof(NormalizedShort4))
                    format = VertexElementFormat.NormalizedShort4;
                else if (channel.ElementType == typeof(HalfVector2))
                    format = VertexElementFormat.HalfVector2;
                else if (channel.ElementType == typeof(HalfVector4))
                    format = VertexElementFormat.HalfVector4;
                else
                    throw new InvalidContentException(string.Format("Unrecognized vertex content type: '{0}'", channel.ElementType));

                // Try to determine the vertex usage
                if (!VertexChannelNames.TryDecodeUsage(channel.Name, out usage))
                    throw new InvalidContentException(string.Format("Unknown vertex element usage for channel '{0}'", channel.Name));

                // Try getting the usage index
                var usageIndex = VertexChannelNames.DecodeUsageIndex(channel.Name);

                result.VertexDeclaration.VertexElements.Add(new VertexElement(offset, format, usage, usageIndex));
                offset += format.GetSize();
                result.VertexDeclaration.VertexStride = offset;
            }
            return offset;
        }
示例#25
0
		public void CreateVertexBuffer(out VertexBufferContent vertexBuffer, out VertexElement[] vertexElements, TargetPlatform targetPlatform)
		{
			throw new NotImplementedException();
		}
示例#26
0
        /// <summary>
        /// Converts design-time vertex position and channel data into a vertex buffer format that a graphics device can recognize.
        /// </summary>
        /// <returns>A packed vertex buffer.</returns>
        /// <exception cref="InvalidContentException">One or more of the vertex channel types are invalid or an unrecognized name was passed to VertexElementUsage.</exception>
        public VertexBufferContent CreateVertexBuffer()
        {
            var vertexBuffer = new VertexBufferContent(positions.Count);
            var stride = SetupVertexDeclaration(vertexBuffer);

            // TODO: Verify enough elements in channels to match positions?

            // Write out data in an interleaved fashion each channel at a time, for example:
            //    |------------------------------------------------------------|
            //    |POSITION[0] | NORMAL[0]  |TEX0[0] | POSITION[1]| NORMAL[1]  |
            //    |-----------------------------------------------|------------|
            // #0 |111111111111|____________|________|111111111111|____________|
            // #1 |111111111111|111111111111|________|111111111111|111111111111|
            // #2 |111111111111|111111111111|11111111|111111111111|111111111111|

            // #0: Write position vertices using stride to skip over the other channels:
            vertexBuffer.Write(0, stride, positions);

            var channelOffset = VertexBufferContent.SizeOf(typeof(Vector3));
            foreach (var channel in Channels)
            {
                // #N: Fill in the channel within each vertex
                var channelType = channel.ElementType;
                vertexBuffer.Write(channelOffset, stride, channelType, channel);
                channelOffset += VertexBufferContent.SizeOf(channelType);
            }

            return vertexBuffer;
        }
示例#27
0
        public override ModelContent Process(SceneContent input, ContentProcessorContext context)
        {
            List <ModelMeshContent> meshes       = new List <ModelMeshContent>();
            VertexBufferContent     vertexBuffer = new VertexBufferContent(new VertexAttribute[] {
                new PositionAttribute(),
                new NormalAttribute(),
                new TextureCoordinateAttribute(),
            });

            if (Skin)
            {
                vertexBuffer.AddAttribute(new BlendWeightsAttribute());
                vertexBuffer.AddAttribute(new BlendIndicesAttribute());
            }

            BoneContent rootBone = BuildSkeleton(input.Scene.RootNode, null);

            MaterialContent[] materials = new MaterialContent[input.Scene.MaterialCount];
            for (int i = 0; i < input.Scene.MaterialCount; i++)
            {
                Dictionary <string, object> parameters = new Dictionary <string, object>();
                GetMaterialParameters(input.Scene.Materials[i], parameters, context);
                string materialFactory;
                if (!MaterialTypeFactoryReplacements.TryGetValue(i, out materialFactory))
                {
                    materialFactory = DefaultMaterialTypeFactory;
                }
                MaterialContent material = context.ContentManager.MaterialFactoryManager.GetMaterialFactory(materialFactory)(context, parameters);
                material.Name = input.Scene.Materials[i].HasName ? input.Scene.Materials[i].Name : string.Format("{0}_Material_{1}", input.Name, i);
                materials[i]  = material;
            }

            uint numVertices = 0;
            uint numIndices  = 0;

            for (int i = 0; i < input.Scene.MeshCount; i++)
            {
                Mesh mesh            = input.Scene.Meshes[i];
                uint primitiveCount  = (uint)mesh.FaceCount;
                uint baseVertex      = numVertices;
                uint baseIndex       = numIndices;
                uint partNumIndices  = (uint)mesh.FaceCount * 3;
                uint partNumVertices = (uint)mesh.VertexCount;

                numVertices += (uint)mesh.VertexCount;
                numIndices  += (uint)mesh.FaceCount * 3;

                Dictionary <uint, List <VertexWeight> > boneVertWeights = new Dictionary <uint, List <VertexWeight> >();
                if (Skin)
                {
                    ExtractBoneWeights(mesh, boneVertWeights);
                }

                for (int j = 0; j < mesh.VertexCount; j++)
                {
                    vertexBuffer[Minotaur.Graphics.VertexUsage.Position].AddValues(mesh, j);
                    vertexBuffer[Minotaur.Graphics.VertexUsage.Normal].AddValues(mesh, j);
                    vertexBuffer[Minotaur.Graphics.VertexUsage.TextureCoordinate].AddValues(mesh, j);
                    if (Skin)
                    {
                        float[] weights = new float[4];
                        byte[]  indices = new byte[4];
                        GetNormalizedBoneWeights(boneVertWeights[(uint)j], weights, indices);
                        ((BlendWeightsAttribute)vertexBuffer[Minotaur.Graphics.VertexUsage.BlendWeight]).AddValues(weights);
                        ((BlendIndicesAttribute)vertexBuffer[Minotaur.Graphics.VertexUsage.BlendIndices]).AddValues(indices);
                    }
                }

                IndexCollection indecies = new IndexCollection();
                indecies.AddRange(mesh.GetIndices().Select(k => k + (uint)baseVertex));

                ModelMeshPartContent         part           = new ModelMeshPartContent(vertexBuffer, indecies, baseVertex, partNumVertices, baseIndex, partNumIndices, primitiveCount);
                Minotaur.Core.BoundingSphere boundingSphere = Minotaur.Core.BoundingSphere.CreateFromPoints(
                    ((PositionAttribute)vertexBuffer[Minotaur.Graphics.VertexUsage.Position]).Values.Select(
                        p => new OpenTK.Vector3(p.X, p.Y, p.Z)));
                ModelMeshContent modelmesh = new ModelMeshContent(mesh.Name, GetMeshParentBone(input.Scene.RootNode, i), new[] { part }, boundingSphere);
                meshes.Add(modelmesh);

                part.Material = materials[mesh.MaterialIndex];
            }

            List <ExternalReferenceContent <BoneAnimationsContent> > animations = new List <ExternalReferenceContent <BoneAnimationsContent> >();

            foreach (Animation anim in input.Scene.Animations)
            {
                if (ExportAnimations.Count == 0 || ExportAnimations.Contains(anim.Name))
                {
                    animations.Add(context.ContentManager.BuildContent <BoneAnimationsContent>(input.Name, "ModelImporter",
                                                                                               processorName: "BoneAnimProcessor",
                                                                                               processorData: new Dictionary <string, object>()
                    {
                        { "AnimationName", anim.Name },
                        { "NamePre", string.Format("{0}_", Path.GetFileNameWithoutExtension(input.Name)) },
                    },
                                                                                               ignoreBuildItem: true
                                                                                               ));
                }
            }

            return(new ModelContent(rootBone, _bones, meshes, animations));
        }
示例#28
0
        public PatchContent Build()
        {
            #region Local vertex buffer

            // create local vertex buffer for patch
            int numVertices = _patchSize * _patchSize;
            VertexBufferContent localVertexBuffer = new VertexBufferContent(numVertices);

            // fill vertex buffer
            VertexPositionNormalTexture2[] vertices = new VertexPositionNormalTexture2[numVertices];

            int nStartX = _patchOffsetX * (_patchSize - 1);
            int nStartY = _patchOffsetY * (_patchSize - 1);
            int nEndX   = nStartX + _patchSize;
            int nEndY   = nStartY + _patchSize;

            float fMinZ = float.MaxValue, fMaxZ = float.MinValue;
            int   index = 0;
            for (int y = nStartY; y < nEndY; y++)
            {
                for (int x = nStartX; x < nEndX; x++)
                {
                    // write local data
                    float fZ = _heightMap[x, y];

                    if (fZ < fMinZ)
                    {
                        fMinZ = fZ;
                    }
                    if (fZ > fMaxZ)
                    {
                        fMaxZ = fZ;
                    }

                    Vector2 texCoords1 = new Vector2(x / (float)(_heightMap.Width - 1), y / (float)(_heightMap.Height - 1));
                    Vector2 texCoords2 = texCoords1 * _detailTextureTiling;

                    vertices[index++] = new VertexPositionNormalTexture2(
                        new Vector3(x * _horizontalScale, fZ, y * _horizontalScale),
                        new Vector3(0, 1, 0),
                        texCoords1,
                        texCoords2);
                }
            }

            localVertexBuffer.Write(0, VertexBufferContent.SizeOf(typeof(VertexPositionNormalTexture2)), vertices);
            localVertexBuffer.VertexDeclaration = new VertexDeclarationContent();
            foreach (VertexElement vertexElement in VertexPositionNormalTexture2.VertexDeclaration.GetVertexElements())
            {
                localVertexBuffer.VertexDeclaration.VertexElements.Add(vertexElement);
            }

            #endregion

            LevelContent[] levels = new LevelContent[_numLevels];
            for (int i = 0; i < _numLevels; i++)
            {
                LevelContentBuilder levelContentBuilder = new LevelContentBuilder(_heightMap, _patchSize, _numLevels, i, nStartX,
                                                                                  nEndX, nStartY, nEndY);
                levels[i] = levelContentBuilder.Build();
            }

            #region Bounding box, centre, and offset

            BoundingBox boundingBox = new BoundingBox(
                new Vector3(nStartX * _horizontalScale, fMinZ, nStartY * _horizontalScale),
                new Vector3(nEndX * _horizontalScale, fMaxZ, nEndY * _horizontalScale));

            float fAverageZ = (fMinZ + fMaxZ) / 2.0f;

            Vector3 center = new Vector3(
                (nStartX + ((_patchSize - 1) / 2.0f)) * _horizontalScale,
                fAverageZ,
                (nStartY + ((_patchSize - 1) / 2.0f)) * _horizontalScale);

            Vector2 offset = new Vector2(
                (_patchOffsetX * (_patchSize - 1)) * _horizontalScale,
                (_patchOffsetY * (_patchSize - 1)) * _horizontalScale);

            #endregion

            return(new PatchContent
            {
                VertexBuffer = localVertexBuffer,
                Levels = levels,
                BoundingBox = boundingBox,
                Center = center,
                Offset = offset
            });
        }
        /// <summary>
        /// Procesar el mapa de alturas
        /// </summary>
        /// <param name="input">Información del escenario de entrada</param>
        /// <param name="context">Contexto de procesado</param>
        /// <returns>Devuelve la información de escenario leída</returns>
        public override SceneryInfo Process(SceneryFile input, ContentProcessorContext context)
        {
            // Cargar la textura del mapa de alturas
            Texture2DContent terrain = context.BuildAndLoadAsset <Texture2DContent, Texture2DContent>(new ExternalReference <Texture2DContent>(input.HeightMapFile), null);

            // Obtener el mapa de alturas
            HeightMap heightMap = this.BuildHeightMap(terrain, input.HeightMapCellScale, context);

            // Generar los vértices e inicializar el buffer de vértices
            VertexMultitextured[] vertList = heightMap.BuildVertices(
                input.HeightMapCellSize,
                input.ProportionTexture1,
                input.ProportionTexture2,
                input.ProportionTexture3);
            VertexBufferContent vertexBuffer = new VertexBufferContent(VertexMultitextured.SizeInBytes * vertList.Length);

            vertexBuffer.Write <VertexMultitextured>(0, VertexMultitextured.SizeInBytes, vertList, context.TargetPlatform);

            // Generar los índices e inicializar los buffers de índices
            double          lowOrderLevels   = (Math.Sqrt(heightMap.DataLength) - 1) * 0.5f;
            int             levelCount       = Convert.ToInt32(Math.Log(lowOrderLevels, 4.0d));
            SceneryNodeInfo sceneryIndexInfo = SceneryNodeInfo.Build(
                vertList,
                heightMap.Width,
                heightMap.Deep,
                levelCount);

            // Efecto de renderización
            CompiledEffect effect = Effect.CompileEffectFromFile(
                input.EffectFile,
                null,
                null,
                CompilerOptions.None,
                context.TargetPlatform);

            // Texturas del terreno
            Texture2DContent texture1       = context.BuildAndLoadAsset <Texture2DContent, Texture2DContent>(new ExternalReference <Texture2DContent>(input.Texture1File), null);
            Texture2DContent texture2       = context.BuildAndLoadAsset <Texture2DContent, Texture2DContent>(new ExternalReference <Texture2DContent>(input.Texture2File), null);
            Texture2DContent texture3       = context.BuildAndLoadAsset <Texture2DContent, Texture2DContent>(new ExternalReference <Texture2DContent>(input.Texture3File), null);
            Texture2DContent texture4       = context.BuildAndLoadAsset <Texture2DContent, Texture2DContent>(new ExternalReference <Texture2DContent>(input.Texture4File), null);
            Texture2DContent detailTexture1 = context.BuildAndLoadAsset <Texture2DContent, Texture2DContent>(new ExternalReference <Texture2DContent>(input.DetailTexture1File), null);
            Texture2DContent detailTexture2 = context.BuildAndLoadAsset <Texture2DContent, Texture2DContent>(new ExternalReference <Texture2DContent>(input.DetailTexture2File), null);
            Texture2DContent detailTexture3 = context.BuildAndLoadAsset <Texture2DContent, Texture2DContent>(new ExternalReference <Texture2DContent>(input.DetailTexture3File), null);
            Texture2DContent detailTexture4 = context.BuildAndLoadAsset <Texture2DContent, Texture2DContent>(new ExternalReference <Texture2DContent>(input.DetailTexture4File), null);

            CompiledEffect billboardEffect = Effect.CompileEffectFromFile(
                input.BillboardEffectFile,
                null,
                null,
                CompilerOptions.None,
                context.TargetPlatform);

            Texture2DContent billboardGrassTexture = context.BuildAndLoadAsset <Texture2DContent, Texture2DContent>(new ExternalReference <Texture2DContent>(input.BillboardGrassTextureFile), null);
            Texture2DContent billboardTreeTexture  = context.BuildAndLoadAsset <Texture2DContent, Texture2DContent>(new ExternalReference <Texture2DContent>(input.BillboardTreeTextureFile), null);
            int   billboardsPerTriangle            = input.BillboardsPerTriangle;
            float billboardTreesPercent            = input.BillboardTreesPercent;

            return(new SceneryInfo()
            {
                Terrain = terrain,
                TerrainBuffer = vertexBuffer,
                TerrainBufferVertexCount = vertList.Length,
                TerrainInfo = sceneryIndexInfo,
                Effect = effect,
                Texture1 = texture1,
                Texture2 = texture2,
                Texture3 = texture3,
                Texture4 = texture4,
                DetailTexture1 = detailTexture1,
                DetailTexture2 = detailTexture2,
                DetailTexture3 = detailTexture3,
                DetailTexture4 = detailTexture4,
                BillboardEffect = billboardEffect,
                BillboardGrass = billboardGrassTexture,
                BillboardTree = billboardTreeTexture,
                BillboardsPerTriangle = billboardsPerTriangle,
                BillboardTreesPercent = billboardTreesPercent,
            });
        }