glDrawElements does not show anything when I move it to another method - c++

When I draw terrain like this - it works normal
void Terrain::RenderLandscape()
{
int x, y;
int Index = 0;
for (int i = 0; i < MapSize-1; i++)
{
Index = 0;
for (int j = 0;j < MapSize-1; j++)
{
x = j * Zoom;
y = i * Zoom;
TextureMap[Index+0][0]= j * TextureBit;
TextureMap[Index+0][1]= i * TextureBit;
TextureMap[Index+1][0]= j * TextureBit;
TextureMap[Index+1][1]= (i+1) * TextureBit;
VertexMap[Index+0][2] = HeightMap[j][i];
VertexMap[Index+1][2] = HeightMap[j][i+1];
VertexMap[Index+0][0] = x;
VertexMap[Index+0][1] = y;
VertexMap[Index+1][0] = x;
VertexMap[Index+1][1] = y+Zoom;
Index += 2;
}
glDrawElements(GL_TRIANGLE_STRIP, Index, GL_UNSIGNED_INT, Indices);
}
}
But when I move loops to another method and leave in RenderLandscape
void Terrain::RenderLandscape()
{
glDrawElements(GL_TRIANGLE_STRIP, 512, GL_UNSIGNED_INT, Indices);
}
Where 512 - size of Indices array - It shows only black screen without terrain.
What is the problem?
I move loops to method which is called before renderLandscape. There I initialize vertex, normals, texture arrays. Method init.
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer (3, GL_FLOAT, 0, VertexMap);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 0, TextureMap);
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT,0, NormalMap);
for (int Row = 0; Row < MapSize*2; Row++)
{
Indices[Row] = Row;
}
int x, y;
int Index = 0;
for (int i = 0; i < MapSize-1; i++)
{
Index = 0;
for (int j = 0;j < MapSize-1; j++)
{
x = j * Zoom;
y = i * Zoom;
TextureMap[Index+0][0]= j * TextureBit;
TextureMap[Index+0][1]= i * TextureBit;
TextureMap[Index+1][0]= j * TextureBit;
TextureMap[Index+1][1]= (i+1) * TextureBit;
VertexMap[Index+0][2] = HeightMap[j][i];
VertexMap[Index+1][2] = HeightMap[j][i+1];
VertexMap[Index+0][0] = x;
VertexMap[Index+0][1] = y;
VertexMap[Index+1][0] = x;
VertexMap[Index+1][1] = y+Zoom;
Index += 2;
}
}
Index = 0;
for(int i = 0; i < MapSize - 1; i++)
{
Index = 0;
for (int j = 0;j < MapSize-1; j++)
{
CVector3 vTriangle[] = { CVector3(VertexMap[Index + 0]),
CVector3(VertexMap[Index + 1]),
CVector3(VertexMap[Index + 2]) };
CVector3 normal = Normal(vTriangle);
NormalMap[Index + 0][0] = normal.x;
NormalMap[Index + 0][1] = normal.y;
NormalMap[Index + 0][2] = normal.z;
NormalMap[Index + 1][0] = normal.x;
NormalMap[Index + 1][1] = normal.y;
NormalMap[Index + 1][2] = normal.z;
NormalMap[Index + 2][0] = normal.x;
NormalMap[Index + 2][1] = normal.y;
NormalMap[Index + 2][2] = normal.z;
Index += 3;
}
}
So it works like this
1) I initialize opengl and create terrain object.
........
landscape.Init();
glutPassiveMotionFunc(MousePassive);
glutIdleFunc(draw)
........
2) in method draw I call renderLandscape method
glPushMatrix();
glTranslatef(-20, 0, 0);
glScalef(0.01, 0.01, 0.01);
glRotatef(90, 1, 0, 0);
landscape.RenderLandscape();
glPopMatrix();

Related

Terrain drawing over itself at larger sizes

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

3D Cylinder how to calculate vertexSize, indicesSize and textCoordinateSize In openGl

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.

Drawing the top and bottom of a cylinder

I'm trying to create a class that can procedurally create prisms (or cylinders if the precision is high enough) but only the sides of the 3d model are showing (not the top and bottom). This is using openGL and c++. Not going for efficiency, just modifying a previous class that made a sphere.
#define numSlices 2
Prism::Prism() {
init(3);
}
Prism::Prism(int prec) {
init(prec);
}
float Prism::toRadians(float degrees) { return (degrees * 2.0f * 3.14159f) / 360.0f; }
void Prism::init(int prec) {
prec = (prec < 3) ? 3 : prec;
numVertices = (prec + 1) * (numSlices+1);
numIndices = prec * numSlices * 6;
for (int i = 0; i < numVertices; i++) { vertices.push_back(glm::vec3()); }
for (int i = 0; i < numVertices; i++) { texCoords.push_back(glm::vec2()); }
for (int i = 0; i < numVertices; i++) { normals.push_back(glm::vec3()); }
for (int i = 0; i < numVertices; i++) { tangents.push_back(glm::vec3()); }
for (int i = 0; i < numIndices; i++) { indices.push_back(0); }
// calculate triangle vertices
for (int i = 0; i <= numSlices; i++) {
for (int j = 0; j <= prec; j++) {
float y = i;
float x = -(float)cos(toRadians(j * 360.0f / (float)prec));
float z = (float)sin(toRadians(j * 360.0f / (float)prec));
vertices[i * (prec + 1) + j] = glm::vec3(x, y, z);
texCoords[i * (prec + 1) + j] = glm::vec2(((float)j / prec), ((float)i / numSlices));
}
}
// calculate triangle indices
for (int i = 0; i < numSlices; i++) {
for (int j = 0; j < prec; j++) {
indices[6 * (i * prec + j) + 0] = i * (prec + 1) + j;
indices[6 * (i * prec + j) + 1] = i * (prec + 1) + j + 1;
indices[6 * (i * prec + j) + 2] = (i + 1) * (prec + 1) + j;
indices[6 * (i * prec + j) + 3] = i * (prec + 1) + j + 1;
indices[6 * (i * prec + j) + 4] = (i + 1) * (prec + 1) + j + 1;
indices[6 * (i * prec + j) + 5] = (i + 1) * (prec + 1) + j;
}
}
}
Any tips or solutions that stick closely to the code already written would much appreciated.
To render the top and bottom of the cylinder, you can create a "triangle fan" that starts from a vertex at the center of the top/bottom of the cylinder and creates one triangle for every side.
Adapting your code: (untested, I may have made mistakes against winding order)
int bottom_center = vertices.length(); vertices.push_back(glm::vec3(0,0,0));
int top_center = vertices.length(); vertices.push_back(glm::vec3(0,numSlices,0));
// Bottom
for (int j = 0; j < prec; j++) {
int base = 0;
indices.push_back(bottom_center);
indices.push_back(base+j);
indices.push_back(base+j+1);
}
// Top
for (int j = 0; j < prec; j++) {
int base = numSlices * (prec+1);
indices.push_back(top_center);
indices.push_back(base+j);
indices.push_back(base+j+1);
}
See http://www.songho.ca/opengl/gl_cylinder.html for a more worked-out example.

Triangle Grid Not Rendering correctly [DirectX 11]

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

how to draw a circle using opengl4

I want to draw a circle. but anything isn't drawn.
for (int i = 0; i < 1080; i += 3) {
angle = (float)M_PI / 180.0f * i;
vertices[i] = sinf((float)angle) * 0.5f;
vertices[i + 1] = cosf((float)angle) * 0.5f;
vertices[i + 2] = 0.0f;
}
bool isFirst = true;
int temp;
for (int i = 0, j = 1; i < 360; i++) {
if (i % 3 == 0) {
indices[i] = 0;
}
else {
if (!isFirst) {
temp = ++j;
isFirst = true;
}
else {
temp = j;
isFirst = false;
}
indices[i] = (GLushort)temp;
}
}
.
.
.
glDrawElements(GL_TRIANGLE_STRIP, 360, GL_UNSIGNED_SHORT, 0);
Please help me......
first code works fine on android java gl es2.0.
for (int i = 0; i < 1080; i += 3) {
angle = (float)M_PI / 180.0f * i;
vertices[i] = sinf((float)angle) * 0.5f;
vertices[i + 1] = cosf((float)angle) * 0.5f;
vertices[i + 2] = 0.25f;
}
bool isFirst = true;
int temp;
for (int i = 0, j = 1; i < 360; i++) {
if (i % 3 == 0) {
indices[i] = 0;
}
else {
if (!isFirst) {
temp = ++j;
isFirst = true;
}
else {
temp = j;
isFirst = false;
}
indices[i] = (GLushort)temp;
}
}