/// <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); }
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); }
/// <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; }
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, }); }
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 }); }