private VertexData buildVertexData() { VertexData vertexData = new VertexData(); vertexData.vertexCount = numSamples * numSamples; vertexData.vertexStart = 0; // set up the vertex declaration int vDecOffset = 0; vertexData.vertexDeclaration.AddElement(0, vDecOffset, VertexElementType.Float3, VertexElementSemantic.Position); vDecOffset += VertexElement.GetTypeSize(VertexElementType.Float3); vertexData.vertexDeclaration.AddElement(0, vDecOffset, VertexElementType.Float3, VertexElementSemantic.Normal); vDecOffset += VertexElement.GetTypeSize(VertexElementType.Float3); vertexData.vertexDeclaration.AddElement(0, vDecOffset, VertexElementType.Float2, VertexElementSemantic.TexCoords); vDecOffset += VertexElement.GetTypeSize(VertexElementType.Float2); // create the hardware vertex buffer and set up the buffer binding HardwareVertexBuffer hvBuffer = HardwareBufferManager.Instance.CreateVertexBuffer( vertexData.vertexDeclaration.GetVertexSize(0), vertexData.vertexCount, BufferUsage.StaticWriteOnly, false); vertexData.vertexBufferBinding.SetBinding(0, hvBuffer); // lock the vertex buffer IntPtr ipBuf = hvBuffer.Lock(BufferLocking.Discard); int bufferOff = 0; unsafe { float *buffer = (float *)ipBuf.ToPointer(); int heightMapOffset = 0; for (int zIndex = 0; zIndex < numSamples; zIndex++) { float z = (zIndex * metersPerSample * WorldManager.oneMeter); for (int xIndex = 0; xIndex < numSamples; xIndex++) { float height = heightMap[heightMapOffset++]; // Position float x = (xIndex * metersPerSample * WorldManager.oneMeter); buffer[bufferOff++] = x; buffer[bufferOff++] = height; buffer[bufferOff++] = z; // normals // XXX - this can be optimized quite a bit Vector3 norm = tile.GetNormalAt(new Vector3(x + tile.Location.x, height, z + tile.Location.z)); buffer[bufferOff++] = norm.x; buffer[bufferOff++] = norm.y; buffer[bufferOff++] = norm.z; // Texture // XXX - assumes one unit of texture space is one page. // how does the vertex shader deal with texture coords? buffer[bufferOff++] = (x + location.x - tile.Page.Location.x) / (WorldManager.Instance.PageSize * WorldManager.oneMeter); buffer[bufferOff++] = (z + location.z - tile.Page.Location.z) / (WorldManager.Instance.PageSize * WorldManager.oneMeter); } } } hvBuffer.Unlock(); return(vertexData); }