I'm trying to render a terrain using directx 11 and applying a heightmap to it.
I load the heightmap then I copy it to a integer vector, then for each vertex position I assign the Y position of that vertex to the heightmap value, but the terrain is completely destroyed and distorted. When I remove the calculation on the Y axis, I get a flat grid and no problem.
bool cGrid::readRawFile(std::string fileName, int m, int n)
{
// A height for each vertex
std::vector<BYTE> in(m*n);
std::ifstream inFile(fileName.c_str(), std::ios_base::binary);
if (!inFile)
return false;
inFile.read(
(char*)&in[0], // buffer
in.size());// number of bytes to read into buffer
inFile.close();
// copy BYTE vector to int vector
m_heightmap.resize(n*m);
for (int i = 0; i < in.size(); i++)
m_heightmap[i] = in[i];
return true;
}
for (size_t i = 0; i<m_Mesh.m_Vertices.size(); ++i)
{
XMFLOAT3 p = m_Mesh.m_Vertices[i].Position;
p.y = (float)m_heightmap[i]*0.5f;
m_Mesh.m_Vertices[i].Position = p;
}
here is a video of the problem
https://www.youtube.com/watch?v=lnlIz3DjebM&feature=youtu.be
HRESULT cGrid::CreateGrid(float width, float depth, UINT n, UINT m)
{
HRESULT hr;
int vertexCount = m*n;
UINT faceCount = (m - 1)*(n - 1) * 2; // each quad consists of two triangles
float halfWidth = 0.5f*width;
float halfDepth = 0.5f*depth;
// project the grid into xz plane
float dx = width / (n - 1);
float dz = depth / (m - 1);
float du = 1.0f / (n - 1); // texture co-ordinates
float dv = 1.0f / (m - 1);
m_Mesh.m_Vertices.resize(vertexCount);
// build the vertices of the grid, including the normals and the tangent,
//you can build then the bitanget by cross product for normal maps -_-
for (UINT i = 0; i < m; ++i)
{
float z = halfDepth - i*dz; // reset for the next cell
for (UINT j = 0; j < n; ++j)
{
float x = -halfWidth + j*dx;
float y = (float)m_heightmap[j + i*m];
m_Mesh.m_Vertices[i*n + j].Position = XMFLOAT3(x, y, z);
// m_Mesh.m_Vertices[i*n + j].Normal = XMFLOAT3(0.0f, 1.0f, 0.0f);
// m_Mesh.m_Vertices[i*n + j].TangentU = XMFLOAT3(1.0f, 0.0f, 0.0f);
// Stretch texture over grid.
m_Mesh.m_Vertices[i*n + j].TextureCords.x = j*du;
m_Mesh.m_Vertices[i*n + j].TextureCords.y = i*dv;
}
}
m_Mesh.m_Indices.resize(faceCount * 3); // 3 indices per face
// Iterate over each quad and compute indices.
UINT k = 0;
for (UINT i = 0; i < m - 1; ++i)
{
for (UINT j = 0; j < n - 1; ++j)
{
m_Mesh.m_Indices[k] = i*n + j;
m_Mesh.m_Indices[k + 1] = i*n + j + 1;
m_Mesh.m_Indices[k + 2] = (i + 1)*n + j;
m_Mesh.m_Indices[k + 3] = (i + 1)*n + j;
m_Mesh.m_Indices[k + 4] = i*n + j + 1;
m_Mesh.m_Indices[k + 5] = (i + 1)*n + j + 1;
k += 6; // next quad
}
}
m_IndicesSize = m_Mesh.m_Indices.size();
// Pack all the vertices into vertex buffer
D3D11_BUFFER_DESC vbd;
vbd.Usage = D3D11_USAGE_IMMUTABLE;
vbd.ByteWidth = sizeof(MeshVertex)* vertexCount;
vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vbd.CPUAccessFlags = 0;
vbd.MiscFlags = 0;
D3D11_SUBRESOURCE_DATA vinitData;
vinitData.pSysMem = &(m_Mesh.m_Vertices[0]);
m_pGraphics->getDevice()->CreateBuffer(&vbd, &vinitData, &mVB);
// Pack the indices of all the meshes into one index buffer.
D3D11_BUFFER_DESC ibd;
ibd.Usage = D3D11_USAGE_DEFAULT;
ibd.ByteWidth = sizeof(UINT)* m_IndicesSize;
ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
ibd.CPUAccessFlags = 0;
ibd.MiscFlags = 0;
D3D11_SUBRESOURCE_DATA iinitData;
iinitData.pSysMem = &m_Mesh.m_Indices[0];
m_pGraphics->getDevice()->CreateBuffer(&ibd, &iinitData, &mIB);
// Create the constant buffer
ibd.Usage = D3D11_USAGE_DEFAULT;
ibd.ByteWidth = sizeof(ConstantBuffer);
ibd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
ibd.CPUAccessFlags = 0;
hr = m_pGraphics->getDevice()->CreateBuffer(&ibd, nullptr, &m_pConstantBuffer);
if (FAILED(hr))
return hr;
return hr;
}
I would use unsigned char instead of BYTE when defining std::vector<BYTE> in(m*n) since it isn't a part of the C standard library so it is system dependent.
Also use a cast on this line
in.size());// number of bytes to read into buffer
to the actual parameter type of ifstream::read which is std::streamsize.
Like this:
(std::streamsize)in.size());// number of bytes to read into buffer
Since you're working with an 8-bit height map you should perhaps not just copy the value from the RAW file into your height map like this:
for (int i = 0; i < in.size(); i++)
m_heightmap[i] = in[i];
Since each height map value is represented by an 8-bit integer you could try dividing the height map value as well as multiply it with some scale modifier. This would make it more convenient if you want to test your way to some good values. Purely for visual purposes...
for (int i = 0; i < in.size(); i++)
m_heightmap[i] = (float)( in[i] / 255.0f ) * scaleModifier;
Related
I have had a terrain generation algorithm for a while and have had a lot of success with it. However when I decided to start work on Level of Detail (Has not been implemented), I started to notice that my terrain would begin to draw underneath itself as it got larger (when it gets to around 257 by 257). I'm not too sure why it starts to do this however I have a feeling its either due to me converting the 2d vector into a 1d or when i generate my indices but i am not 100 percent. If someone could have a look that would be amazing
Terrain at 100 by 100
Terrain at 1000 by 1000
Code used to Generate Vertices
void TerrainObject::LoadFlatTerrain()
{
float F_terrainDimentions = terrainDimentions; //used to stop integer division
m_vertexCount = terrainDimentions * terrainDimentions; //terrainDimentions = the width and depth of the terrain
float halfWidth = 0.5f * F_terrainDimentions;
float halfDepth = 0.5f * F_terrainDimentions;
// project the grid into xz plane
float dx = F_terrainDimentions / (F_terrainDimentions - 1);
float dz = F_terrainDimentions / (F_terrainDimentions - 1);
float du = 1.0f / (F_terrainDimentions - 1); // texture co-ordinates
float dv = 1.0f / (F_terrainDimentions - 1);
//Resizes Vectors for Vertices
vertices.resize(m_vertexCount);
verts2d.resize(terrainDimentions);
for (int i = 0; i < verts2d.size(); i++)
{
verts2d[i].resize(terrainDimentions);
}
//Generates Vertices for 2d array
for (int i = 0; i < terrainDimentions; i++)
{
float z = halfDepth - i * dz;
for (int j = 0; j < terrainDimentions; j++)
{
float x = -halfWidth + j * dx;
float y = 0;
verts2d[i][j].Position.x = x;
verts2d[i][j].Position.y = y;
verts2d[i][j].Position.z = z;
verts2d[i][j].Normal = XMFLOAT3(0.0f, 1.0f, 0.0f);
verts2d[i][j].Tangent = XMFLOAT3(1.0f, 0.0f, 0.0f);
verts2d[i][j].TexCoord.x = j * du;
verts2d[i][j].TexCoord.y = i * dv;
}
}
//Converts to 1d array
for (int i = 0; i < terrainDimentions; i++)
{
for (int j = 0; j < terrainDimentions; j++)
{
vertices[i * terrainDimentions + j].Position = verts2d[i][j].Position;
vertices[i * terrainDimentions + j].TexCoord = verts2d[i][j].TexCoord;
vertices[i * terrainDimentions + j].Normal = verts2d[i][j].Normal;
vertices[i * terrainDimentions + j].Tangent = verts2d[i][j].Tangent;
}
}
// Create vertex buffer
D3D11_BUFFER_DESC vbd;
vbd.Usage = D3D11_USAGE_IMMUTABLE;
vbd.ByteWidth = sizeof(ComplexVertex) * m_vertexCount;
vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vbd.CPUAccessFlags = 0;
vbd.MiscFlags = 0;
D3D11_SUBRESOURCE_DATA vinitData;
vinitData.pSysMem = &(vertices[0]);
m_pd3dDevice->CreateBuffer(&vbd, &vinitData, &m_pVertexBuffer);
CreateIndices();
//Sets terrains Current position in the world to be the top corner
m_position = verts2d[terrainDimentions - 1][terrainDimentions - 1].Position;
}
Code to Generate Indices
HRESULT TerrainObject::CreateIndices()
{
UINT faceCount = (terrainDimentions - 1) * (terrainDimentions - 1) * 2; // each quad consists of two triangles
int index = 0;
indices.resize(faceCount * 3);
for (UINT i = 0; i < terrainDimentions - 1; ++i)
{
for (UINT j = 0; j < terrainDimentions - 1; ++j)
{
indices[index] = i * terrainDimentions + j;
indices[index + 1] = i * terrainDimentions + j + 1;
indices[index + 2] = (i + 1) * terrainDimentions + j;
indices[index + 3] = (i + 1) * terrainDimentions + j;
indices[index + 4] = i * terrainDimentions + j + 1;
indices[index + 5] = (i + 1) * terrainDimentions + j + 1;
index += 6; // next quad
}
}
m_indexCount = indices.size();
// Creates index buffer
D3D11_BUFFER_DESC ibd;
ibd.Usage = D3D11_USAGE_DEFAULT;
ibd.ByteWidth = sizeof(WORD) * m_indexCount;
ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
ibd.CPUAccessFlags = 0;
ibd.MiscFlags = 0;
D3D11_SUBRESOURCE_DATA iinitData;
iinitData.pSysMem = &indices[0];
return m_pd3dDevice->CreateBuffer(&ibd, &iinitData, &m_pIndexBuffer);
}
I am trying to draw a 3D cylinder by LWJGL,
and i am trying to generate the vertices, indices and textCoordinate
and storing them in arrays
, but i am stuck how to calculate the size of the vertices, indices and textCoordinate arrays...etc.
anyone knows how i can do it please:
Here the snippet of the code:
// generate vertices for a cylinder
void buildVerticesSmooth() {
//=====> vertices = new float[]; <========
//=====> normals = new float[]; <========
//=====> texcoords = new float[]; <========
int texCoordsIndex = -1;
int verticesIndex = -1;
int normalsIndex = -1;
int indicesIndex = -1; // get unit circle vectors on XY-plane
float[] unitVertices = getUnitCircleVertices();
// put side vertices to arrays
for (int i = 0; i < 2; ++i) {
float h = -height / 2.0f + i * height; // z value; -h/2 to h/2
float t = 1.0f - i; // vertical tex coord; 1 to 0
for (int j = 0, k = 0; j <= sectors; ++j, k += 3) {
float ux = unitVertices[k];
float uy = unitVertices[k + 1];
float uz = unitVertices[k + 2];
// position vector
vertices[++verticesIndex] = (ux * radius); // vx
vertices[++verticesIndex] = (uy * radius); // vy
vertices[++verticesIndex] = (h); // vz
// normal vector
normals[++normalsIndex] = (ux); // nx
normals[++normalsIndex] = (uy); // ny
normals[++normalsIndex] = (uz); // nz
// texture coordinate
texcoords[++texCoordsIndex] = ((float) j / sectors); // s
texcoords[++texCoordsIndex] = (t); // t
}
}
// the starting index for the base/top surface
//NOTE: it is used for generating indices later
int baseCenterIndex = vertices.length / 3;
int topCenterIndex = baseCenterIndex + sectors + 1; // include center vertex
// put base and top vertices to arrays
for (int i = 0; i < 2; ++i) {
float h = -height / 2.0f + i * height; // z value; -h/2 to h/2
float nz = -1 + i * 2; // z value of normal; -1 to 1
// center point
vertices[++verticesIndex] = 0;
vertices[++verticesIndex] = 0;
vertices[++verticesIndex] = h;
normals[++normalsIndex] = 0;
normals[++normalsIndex] = 0;
normals[++normalsIndex] = nz;
texcoords[++texCoordsIndex] = 0.5f;
texcoords[++texCoordsIndex] = 0.5f;
for (int j = 0, k = 0; j < sectors; ++j, k += 3) {
float ux = unitVertices[k];
float uy = unitVertices[k + 1];
// position vector
vertices[++verticesIndex] = (ux * radius); // vx
vertices[++verticesIndex] = (uy * radius); // vy
vertices[++verticesIndex] = (h); // vz
// normal vector
normals[++normalsIndex] = (0); // nx
normals[++normalsIndex] = (0); // ny
normals[++normalsIndex] = (nz); // nz
// texture coordinate
texcoords[++texCoordsIndex] = (-ux * 0.5f + 0.5f); // s
texcoords[++texCoordsIndex] = (-uy * 0.5f + 0.5f); // t
}
}
int[] indices;
int k1 = 0; // 1st vertex index at base
int k2 = sectors + 1; // 1st vertex index at top
// indices for the side surface
for(int i = 0; i < sectors; ++i, ++k1, ++k2)
{
// 2 triangles per sector
// k1 => k1+1 => k2
indices[++indicesIndex] = (k1);
indices[++indicesIndex] = (k1 + 1);
indices[++indicesIndex] = (k2);
// k2 => k1+1 => k2+1
indices[++indicesIndex] = (k2);
indices[++indicesIndex] = (k1 + 1);
indices[++indicesIndex] = (k2 + 1);
}
// indices for the base surface
// NOTE: baseCenterIndex and topCenterIndices are pre-computed during vertex generation
// please see the previous code snippet
for(int i = 0, k = baseCenterIndex + 1; i < sectors; ++i, ++k)
{
if(i < sectors - 1)
{
indices[++indicesIndex] = (baseCenterIndex);
indices[++indicesIndex] = (k + 1);
indices[++indicesIndex] = (k);
}
else // last triangle
{
indices[++indicesIndex] = (baseCenterIndex);
indices[++indicesIndex] = (baseCenterIndex + 1);
indices[++indicesIndex] = (k);
}
}
// indices for the top surface
for(int i = 0, k = topCenterIndex + 1; i < sectors; ++i, ++k)
{
if(i < sectors - 1)
{
indices[++indicesIndex] = (topCenterIndex);
indices[++indicesIndex] = (k);
indices[++indicesIndex] = (k + 1);
}
else // last triangle
{
indices[++indicesIndex] = (topCenterIndex);
indices[++indicesIndex] = (k);
indices[++indicesIndex] = (topCenterIndex + 1);
}
}
}
As httpdigest said:
you know how many iterations every loop performs and you know how
many increments/additions you do per each array. Should be very simple
math now.
I'm trying to make a grid of triangles for a terrain generation project in DirectX 11, but when it gets drawn to the screen it draws in all three axis, instead of just the x and z.
I do get the correct amount of vertices and indices, but in the vector of indices it has a size of 972, the first 486 of them are set to 0 instead of the actual values.
I was wondering if I could get some clarification on whether I was setting the vertex/index buffers correctly.
Below is an example for a 10 by 10 grid.
GenerateTerrain method
void Application::GenerateTerrain(int vertRows, int vertCols)
{
HRESULT hr;
// ------------------------------------- Create Vertex Buffer --------------------------------------
totalCellRows = vertRows - 1;
totalCellCols = vertCols - 1;
// Width and Total Width
float dx = 1.0f;
float totalWidth = totalCellCols * dx;
// Depth and Total Depth
float dz = 1.0f;
float totalDepth = totalCellRows * dz;
// X and Z Offsets
float xOffset = -totalWidth * 0.5f;
float zOffset = totalDepth * 0.5f;
totalVertices = vertRows * vertCols;
totalTriangles = (totalCellRows * totalCellCols) * 2;
totalIndices = totalTriangles * 3;
terrainVertices = new SimpleVertex[totalVertices];
// Array Version
int k = 0;
for (int i = 0; i < vertRows; i++)
{
for (int j = 0; j < vertCols; j++)
{
SimpleVertex newVertex;
terrainVertices[k].PosL = XMFLOAT3(j * dx + xOffset, 0.0f, -(i * dz) + zOffset);
terrainVertices[k].NormL = XMFLOAT3(0.0f, 1.0f, 0.0f);
terrainVertices[k].Tex = XMFLOAT2(0.0f, 0.0f);
k++;
}
}
D3D11_BUFFER_DESC bd;
ZeroMemory(&bd, sizeof(bd));
bd.Usage = D3D11_USAGE_DEFAULT;
bd.ByteWidth = sizeof(SimpleVertex) * totalVertices;
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bd.CPUAccessFlags = 0;
D3D11_SUBRESOURCE_DATA InitData;
ZeroMemory(&InitData, sizeof(InitData));
InitData.pSysMem = &terrainVertices;
hr = _pd3dDevice->CreateBuffer(&bd, &InitData, &_pGridVertexBuffer);
// ------------------------------------- Create Index Buffer --------------------------------------
// Vector Version
indices.resize(totalIndices);
for (WORD i = 0; i < (WORD)vertRows - 1; i++)
{
for (WORD j = 0; j < (WORD)vertCols - 1; j++)
{
indices.push_back(i * vertCols + j);
indices.push_back(i * vertCols + (j + 1));
indices.push_back((i + 1) * vertCols + j);
indices.push_back((i + 1) * vertCols + j);
indices.push_back((i * vertCols + (j + 1)));
indices.push_back((i + 1) * vertCols + (j + 1));
}
}
ZeroMemory(&bd, sizeof(bd));
bd.Usage = D3D11_USAGE_DEFAULT;
bd.ByteWidth = sizeof(WORD) * totalIndices;
bd.BindFlags = D3D11_BIND_INDEX_BUFFER;
bd.CPUAccessFlags = 0;
ZeroMemory(&InitData, sizeof(InitData));
InitData.pSysMem = &indices;
hr = _pd3dDevice->CreateBuffer(&bd, &InitData, &_pGridIndexBuffer);
}
indices.resize(totalIndices); <----- !!!!!!ERROR!!!! u mean reserve
for (WORD i = 0; i < (WORD)vertRows - 1; i++)
{
for (WORD j = 0; j < (WORD)vertCols - 1; j++)
{
indices.push_back(i * vertCols + j);
indices.push_back(i * vertCols + (j + 1));
indices.push_back((i + 1) * vertCols + j);
indices.push_back((i + 1) * vertCols + j);
indices.push_back((i * vertCols + (j + 1)));
indices.push_back((i + 1) * vertCols + (j + 1));
}
}
You write resize, so the vector is resized, and then you add more indices with pushback. I think you want to reserve memory "reserve" and add them with pushback.
Also i would recommend to use a pointer to the first value, instead of a pointer to the vector
you:
InitData.pSysMem = &indices;
better:
InitData.pSysMem = &indices[0];
Buffer initialization seems to be ok.
Good luck
I am getting a bit confused as to why my manually created mesh is not appearing correctly. I have created the vertex and index buffers and they seem (although I am not 100% sure) to contain the correct values.
Essentially I am creating a grid of mapSize * mapSize vetrices, at a height of 0, then creating the triangles out of them.
void TerrainGeneration::createTerrainMesh() {
/// Create the mesh via the MeshManager
Ogre::MeshPtr msh = Ogre::MeshManager::getSingleton().createManual("TerrainTest", "General");
Ogre::SubMesh* sub = msh->createSubMesh();
const size_t nVertices = mapSize*mapSize;
const size_t vbufCount = 3*2*nVertices;
float vertices[vbufCount];
size_t vBufCounter = 0;
for(int z = 0; z < mapSize; z++) {
for(int x = 0; x < mapSize; x++) {
//Position
vertices[vBufCounter] = x;
vertices[vBufCounter+1] = 0;
vertices[vBufCounter+2] = z;
//Normal
vertices[vBufCounter+3] = 0;
vertices[vBufCounter+4] = 1;
vertices[vBufCounter+5] = 0;
vBufCounter += 6;
}
}
Ogre::RenderSystem* rs = Ogre::Root::getSingleton().getRenderSystem();
Ogre::RGBA colours[nVertices];
Ogre::RGBA *pColour = colours;
//Create triangles
const size_t ibufCount = 6*(mapSize - 1)*(mapSize - 1);
unsigned int faces[ibufCount];
size_t iBufCounter = 0;
for(int x=0; x <= mapSize -2; x++) {
for(int y=0; y <= mapSize -2; y++) {
faces[iBufCounter] = vertices[(y*mapSize) + x];
faces[iBufCounter+1] = vertices[((y+1)*mapSize) + x];
faces[iBufCounter+2] = vertices[((y+1)*mapSize) + (x+1)];
faces[iBufCounter+3] = vertices[(y*mapSize) + x];
faces[iBufCounter+4] = vertices[((y+1)*mapSize) + (x+1)];
faces[iBufCounter+5] = vertices[(y*mapSize) + (x+1)];
iBufCounter += 6;
}
}
/// Create vertex data structure for n*n vertices shared between submeshes
msh->sharedVertexData = new Ogre::VertexData();
msh->sharedVertexData->vertexCount = nVertices;
/// Create declaration (memory format) of vertex data
Ogre::VertexDeclaration* decl = msh->sharedVertexData->vertexDeclaration;
size_t offset = 0;
// 1st buffer
decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL);
offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
/// Allocate vertex buffer of the requested number of vertices (vertexCount)
/// and bytes per vertex (offset)
Ogre::HardwareVertexBufferSharedPtr vbuf =
Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(
offset, msh->sharedVertexData->vertexCount, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
/// Upload the vertex data to the card
vbuf->writeData(0, vbuf->getSizeInBytes(), vertices, true);
/// Set vertex buffer binding so buffer 0 is bound to our vertex buffer
Ogre::VertexBufferBinding* bind = msh->sharedVertexData->vertexBufferBinding;
bind->setBinding(0, vbuf);
/// Allocate index buffer of the requested number of vertices (ibufCount)
Ogre::HardwareIndexBufferSharedPtr ibuf = Ogre::HardwareBufferManager::getSingleton().
createIndexBuffer(
Ogre::HardwareIndexBuffer::IT_16BIT,
ibufCount,
Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
/// Upload the index data to the card
ibuf->writeData(0, ibuf->getSizeInBytes(), faces, true);
/// Set parameters of the submesh
sub->useSharedVertices = true;
sub->indexData->indexBuffer = ibuf;
sub->indexData->indexCount = ibufCount;
sub->indexData->indexStart = 0;
/// Set bounding information (for culling)
msh->_setBounds(Ogre::AxisAlignedBox(-5000,-5000,-5000,5000,5000,5000));
//msh->_setBoundingSphereRadius(Ogre::Math::Sqrt(3*100*100));
/// Notify -Mesh object that it has been loaded
msh->load();
}
I initialise the mesh and load it as follows
Ogre::Entity* thisEntity = mSceneMgr->createEntity("cc", "TerrainTest", "General");
thisEntity->setMaterialName("Examples/Rockwall");
Ogre::SceneNode* thisSceneNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
thisSceneNode->setPosition(0, 0, 0);
thisSceneNode->attachObject(thisEntity);
Any insight would be greatly appreciated.
Ok so I got an answer off the Ogre3d forums from a very helpful person called bstone.
It turns out that when creating my index list to create the faces I was mistakenly passing coordinates from the vertex list rather than indexes of the vertices.
faces[iBufCounter] = vertices[(y*mapSize) + x];
faces[iBufCounter+1] = vertices[((y+1)*mapSize) + x];
faces[iBufCounter+2] = vertices[((y+1)*mapSize) + (x+1)];
faces[iBufCounter+3] = vertices[(y*mapSize) + x];
faces[iBufCounter+4] = vertices[((y+1)*mapSize) + (x+1)];
faces[iBufCounter+5] = vertices[(y*mapSize) + (x+1)];
Should have been
faces[iBufCounter] = (y*mapSize) + x;
faces[iBufCounter+1] = ((y+1)*mapSize) + x;
faces[iBufCounter+2] = ((y+1)*mapSize) + (x+1);
faces[iBufCounter+3] = (y*mapSize) + x;
faces[iBufCounter+4] = ((y+1)*mapSize) + (x+1);
faces[iBufCounter+5] = (y*mapSize) + (x+1);
However I still have a problem in my code somewhere, although from what others have said it probably isn't in this code that i've posted.
Another user also proposed that I create the terrain ina much simpler way and posted the following code
int mapSize = 16;
Ogre::ManualObject *man = m_sceneManager->createManualObject("TerrainTest");
man->begin("Examples/Rockwall",Ogre::RenderOperation::OT_TRIANGLE_LIST);
for(int z = 0; z < mapSize; ++z)
{
for(int x = 0; x < mapSize; ++x)
{
man->position(x,0,z);
man->normal(0,1,0);
man->textureCoord(x,z);
}
}
for(int z = 0; z < mapSize-1; ++z)
{
for(int x = 0; x < mapSize-1; ++x)
{
man->quad((x) + (z) * mapSize, (x) + (z + 1) * mapSize, (x + 1) + (z + 1) * mapSize, (x + 1) + (z) * mapSize);
}
}
man->end();
m_sceneManager->getRootSceneNode()->attachObject(man);
I am creating a 3d plane that lies on the x and z axis, and has hills that extend on the y axis. The bulk of the code looks like this:
float PeaksAndValleys::getHeight(float x, float z)const
{
return 0.3f*( z*sinf(0.1f*x) + x*cosf(0.1f*z) );
}
void PeaksAndValleys::init(ID3D10Device* device, DWORD m, DWORD n, float dx)
{
md3dDevice = device;
mNumRows = m;
mNumCols = n;
mNumVertices = m*n;
mNumFaces = (m-1)*(n-1)*2;
// Create the geometry and fill the vertex buffer.
std::vector<Vertex> vertices(mNumVertices);
float halfWidth = (n-1)*dx*0.5f;
float halfDepth = (m-1)*dx*0.5f;
for(DWORD i = 0; i < m; ++i)
{
float z = halfDepth - i*dx;
for(DWORD j = 0; j < n; ++j)
{
float x = -halfWidth + j*dx;
// Graph of this function looks like a mountain range.
float y = getHeight(x,z);
vertices[i*n+j].pos = D3DXVECTOR3(x, y, z);
// Color the vertex based on its height.
if( y < -10.0f )
vertices[i*n+j].color = BEACH_SAND;
else if( y < 5.0f )
vertices[i*n+j].color = LIGHT_YELLOW_GREEN;
else if( y < 12.0f )
vertices[i*n+j].color = DARK_YELLOW_GREEN;
else if( y < 20.0f )
vertices[i*n+j].color = DARKBROWN;
else
vertices[i*n+j].color = WHITE;
}
}
D3D10_BUFFER_DESC vbd;
vbd.Usage = D3D10_USAGE_IMMUTABLE;
vbd.ByteWidth = sizeof(Vertex) * mNumVertices;
vbd.BindFlags = D3D10_BIND_VERTEX_BUFFER;
vbd.CPUAccessFlags = 0;
vbd.MiscFlags = 0;
D3D10_SUBRESOURCE_DATA vinitData;
vinitData.pSysMem = &vertices[0];
HR(md3dDevice->CreateBuffer(&vbd, &vinitData, &mVB));
// Create the index buffer. The index buffer is fixed, so we only
// need to create and set once.
std::vector<DWORD> indices(mNumFaces*3); // 3 indices per face
// Iterate over each quad and compute indices.
int k = 0;
for(DWORD i = 0; i < m-1; ++i)
{
for(DWORD j = 0; j < n-1; ++j)
{
indices[k] = i*n+j;
indices[k+1] = i*n+j+1;
indices[k+2] = (i+1)*n+j;
indices[k+3] = (i+1)*n+j;
indices[k+4] = i*n+j+1;
indices[k+5] = (i+1)*n+j+1;
k += 6; // next quad
}
}
D3D10_BUFFER_DESC ibd;
ibd.Usage = D3D10_USAGE_IMMUTABLE;
ibd.ByteWidth = sizeof(DWORD) * mNumFaces*3;
ibd.BindFlags = D3D10_BIND_INDEX_BUFFER;
ibd.CPUAccessFlags = 0;
ibd.MiscFlags = 0;
D3D10_SUBRESOURCE_DATA iinitData;
iinitData.pSysMem = &indices[0];
HR(md3dDevice->CreateBuffer(&ibd, &iinitData, &mIB));
}
My question pertains to the cosf and sinf. I am familiar with trigonometry and I understand sin, cosine, and tangent, but I am not familiar with cosf and sinf and what they do. From looking at this example, they have a lot to do with finding a y value.
cosf and sinf are simply the float versions of cos and sin. The normal cos and sin functions return double values instead of floats. Note that all these functions work in radians, not degrees.
Combined in the way above, they give a landscape that looks somewhat like a mountain range, as in this plot.