PDA

View Full Version : Drawing 2 different objects at the same time...



adpward
09-16-2015, 11:52 AM
Hi,

I'm sorry for asking such a basic question - but this has really stumped me for weeks and it's about time I ask some experts rather than continue to bang my head against a brick wall.

I cut my teeth on OpenGL 1 many years ago, then had a gap and currently find myself writing something on OpenGL 4.1 for OS X.

I want to draw a sphere. Once I have a sphere, I want to draw "shapes" on the sphere. This is a game idea which I also hope to port to iOS.

The shapes can move over the sphere and the sphere can be rotated under the shapes.

The shapes are coloured, the sphere is textured. Here lies the problem.

I've managed to draw a sphere. I've managed to texture the sphere. What I cannot seem to then do is plot the coordinates on top of the sphere and draw coloured shapes (triangles and circles).

What I am looking for and don't seem able to find is a simple example where two different objects are drawn at the same time, one with textures, one without. Any help would be greatly appreciated.

mogumbo
09-16-2015, 01:20 PM
If you have already drawn a textured object you would have needed to call

glEnable(GL_TEXTURE_2D);

So before you try to draw an object without textures, call

glDisable(GL_TEXTURE_2D);

adpward
09-16-2015, 10:47 PM
Thank you for such a prompt reply. Unfortunately that made no difference. I'll post some code later today to demonstrate my drawing routines.

Carmine
09-17-2015, 09:42 AM
Post some pictures too.

adpward
09-17-2015, 12:09 PM
I have changed the GL_POINTS into GL_TRIANGLE_FAN otherwise it becomes almost impossible to view. The points are supposed to be fish, they're also supposed to be off the coast of England, but that is an entirely different problem.

For some reason, I am getting a point within the sphere - I cannot see this point within the data, so believe it may be a result of something I am doing wrong causing a knock on effect.

2100210121022103


My render method is as follows: -


glViewport(0,0,g_gl_width, g_gl_height);
glEnable(GL_TEXTURE_2D);
glClearColor(0.0f, 0.5f, 0.75f,1.0f);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);


glUseProgram (sphereShader.programObject);
glBindVertexArray (g_sphere_vao);

// Draw sphere
Ms = identity_mat4 ();

mat4 T = translate(identity_mat4(), vec3( -cam_pos[0], -cam_pos[1], -cam_pos[2]));
mat4 R = rotate_y_deg(identity_mat4(), -cam_yaw);
mat4 view_mat = R * T;

glUniformMatrix4fv (sphere_M_loc, 1, GL_FALSE, view_mat.m);
glDrawArrays (GL_TRIANGLES, 0, g_sphere_point_count );
glBindVertexArray(0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisable(GL_TEXTURE_2D);

if ( showFish == YES)
{
glUseProgram(fishShader.programObject);
glBindVertexArray(g_fish_vao);
glUniformMatrix4fv (fish_M_loc, 1, GL_FALSE, view_mat.m);
glDrawArrays(GL_TRIANGLE_FAN, 1, fishPointCount);
glBindVertexArray(0);
glDisableVertexAttribArray(0);
}


//Wire frame
if (useWireframe == YES)
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
else
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);


The fish are initialised here: -


glGenVertexArrays(1, &g_fish_vao);
glBindVertexArray(g_fish_vao);

GLuint fish_vbo;
glGenBuffers(1, &fish_vbo);
glBindBuffer (GL_ARRAY_BUFFER, fish_vbo);
glBufferData ( GL_ARRAY_BUFFER, sphereData.fishPointCount, sphereData.fishCloudVerticies , GL_STATIC_DRAW );
glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray (0);
glBindVertexArray(0);

The vertices are currently a collection of X, Y and Z co-ordinates calculated based upon lat and long just off the coast of england, converted to radians and then to X,Y,Z. The Z value is one which is always greater than the surface of the sphere.



The Sphere is produced here: -


void generateSphereData( float r, float thetaValue, float phiValue)
{
int vertexIndex = 0;
int normalsIndex = 0;
int textureIndex = 0;

float v1x, v1y, v1z;
float v2x, v2y, v2z;
float d;

int theta, phi, x;

float theta0, theta1;
float phi0, phi1;



myVertex vertexQuad[4];
myNormals normalQuad[4];
myTexCoords texQuad[4];


// * 3 for xyz and * 4 for the 4 quads.
int sizeOfVertex = thetaValue * phiValue * 6 * 3 * sizeof(GLfloat);
int sizeOfTextures = thetaValue * phiValue * 6 * 2 * sizeof(GLfloat);


myVertex *vertexData = (myVertex*)malloc( sizeOfVertex);
myTexCoords *texData = (myTexCoords*)malloc( sizeOfTextures);


GLfloat PI = 3.1415926535897;

GLfloat delta = (GLfloat)(PI / thetaValue);

int theCount = 0;

// theta vertical segments
for(theta = 0; theta < thetaValue; theta++)
{
theta0 = theta*delta;
theta1 = (theta+1)*delta;

// phi horizontal segments
for(phi = 0; phi < phiValue; phi++)
{
phi0 = phi*delta;
phi1 = (phi+1)*delta;

// Generate 4 points per quad
vertexQuad[0].x = 1.0 - r * sin(theta0)*cos(phi0);
vertexQuad[0].y = r * cos(theta0);
vertexQuad[0].z = r * sin(theta0)*sin(phi0);
texQuad[0].u = (GLfloat)phi / (GLfloat)phiValue;
texQuad[0].v = (GLfloat)theta / (GLfloat)thetaValue;

vertexQuad[1].x = 1.0 -r * sin(theta0)*cos(phi1);
vertexQuad[1].y = r * cos(theta0);
vertexQuad[1].z = r * sin(theta0)*sin(phi1);
texQuad[1].u = (GLfloat)(phi + 1) / (GLfloat)phiValue;
texQuad[1].v = (GLfloat)theta / (GLfloat)thetaValue;

vertexQuad[2].x =1.0 - r * sin(theta1)*cos(phi1);
vertexQuad[2].y = r * cos(theta1);
vertexQuad[2].z = r * sin(theta1)*sin(phi1);
texQuad[2].u = (GLfloat)(phi + 1) / (GLfloat)phiValue;
texQuad[2].v = (GLfloat)(theta + 1)/ (GLfloat)thetaValue;

vertexQuad[3].x = 1.0 -r * sin(theta1)*cos(phi0);
vertexQuad[3].y = r * cos(theta1);
vertexQuad[3].z = r * sin(theta1)*sin(phi0);
texQuad[3].u = (GLfloat)phi / (GLfloat)phiValue;
texQuad[3].v = (GLfloat)(theta + 1) / (GLfloat)thetaValue;

// Generate normal
if(theta >= thetaValue /2)
{
v1x = vertexQuad[1].x - vertexQuad[0].x;
v1y = vertexQuad[1].y - vertexQuad[0].y;
v1z = vertexQuad[1].z - vertexQuad[0].z;

v2x = vertexQuad[3].x - vertexQuad[0].x;
v2y = vertexQuad[3].y - vertexQuad[0].y;
v2z = vertexQuad[3].z - vertexQuad[0].z;
}
else
{
v1x = vertexQuad[0].x - vertexQuad[3].x;
v1y = vertexQuad[0].y - vertexQuad[3].y;
v1z = vertexQuad[0].z - vertexQuad[3].z;

v2x = vertexQuad[2].x - vertexQuad[3].x;
v2y = vertexQuad[2].y - vertexQuad[3].y;
v2z = vertexQuad[2].z - vertexQuad[3].z;
}

normalQuad[0].nx = (v1y * v2z) - (v2y * v1z);
normalQuad[0].ny = (v1z * v2x) - (v2z * v1x);
normalQuad[0].nz = (v1x * v2y) - (v2x * v1y);

d = 1.0f/sqrt(normalQuad[0].nx * normalQuad[0].nx +
normalQuad[0].ny * normalQuad[0].ny +
normalQuad[0].nz * normalQuad[0].nz);

normalQuad[0].nx *= d;
normalQuad[0].ny *= d;
normalQuad[0].nz *= d;


// Replicate vertex info
for(x = 1; x < 4; x++)
{
normalQuad[x].nx = normalQuad[0].nx;
normalQuad[x].ny = normalQuad[0].ny;
normalQuad[x].nz = normalQuad[0].nz;
}

// OpenGL draws triangles under the hood. Core Profile officially drops support
// of the GL_QUADS mode in the glDrawArrays/Elements calls.
// Store vertices as in two consisting triangles

vertexData[vertexIndex++] = vertexQuad[2];
vertexData[vertexIndex++] = vertexQuad[1];
vertexData[vertexIndex++] = vertexQuad[0];
vertexData[vertexIndex++] = vertexQuad[0];
vertexData[vertexIndex++] = vertexQuad[3];
vertexData[vertexIndex++] = vertexQuad[2];


// normalsData[normalsIndex++] = normalQuad[0];
// normalsData[normalsIndex++] = normalQuad[1];
// normalsData[normalsIndex++] = normalQuad[2];
// normalsData[normalsIndex++] = normalQuad[2];
// normalsData[normalsIndex++] = normalQuad[3];
// normalsData[normalsIndex++] = normalQuad[0];


texData[textureIndex++] = texQuad[2];
texData[textureIndex++] = texQuad[1];
texData[textureIndex++] = texQuad[0];
texData[textureIndex++] = texQuad[0];
texData[textureIndex++] = texQuad[3];
texData[textureIndex++] = texQuad[2];

theCount += 6;
}
}


// Reorganise texture data

g_sphere_point_count = theCount;

glGenVertexArrays (1, &g_sphere_vao);
glBindVertexArray (g_sphere_vao);

GLuint points_vbo;
glGenBuffers (1, &points_vbo);
glBindBuffer (GL_ARRAY_BUFFER, points_vbo);
glBufferData ( GL_ARRAY_BUFFER, sizeOfVertex, vertexData, GL_STATIC_DRAW );
glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray (0);


// GLuint normals_vbo;
// glGenBuffers(1, &normals_vbo);
// glBindBuffer(GL_ARRAY_BUFFER, normals_vbo);
// glBufferData(GL_ARRAY_BUFFER, normals_count, normalsData, GL_STATIC_DRAW);
// glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, NULL);
// glEnableVertexAttribArray(2);

GLuint texcoords_vbo;
glGenBuffers(1, &texcoords_vbo);
glBindBuffer(GL_ARRAY_BUFFER, texcoords_vbo);
glBufferData(GL_ARRAY_BUFFER, sizeOfTextures , texData, GL_STATIC_DRAW);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(1);


// At this point the VAO is set up with three vertex attributes referencing the same buffer object.

free(vertexData);
// free(normalsData);
free(texData);
}

Carmine
09-17-2015, 04:03 PM
Sounds like a problem with coordinate system transformations.
Try this. Do one fish only. Put it at 0 degs lat and 0 degs lon.
Do your transformations handle it correctly?
This depends on how your earth is placed with the global coordinate system.

Let's make some basic assumptions (which are fairly common).
The earth has a radius of 1.0. It is positioned so that +Z goes
through the north pole and +X goes through 0 degs lat and 0 degs lon.
If you set it up this way, your transformations should convert a fish
at 0 degs lat and 0 degs lon to (1.0, 0.0, 0.0). If that isn't happening,
there's something wrong with the transformations.

If your earth isn't set up that way, I still suggest trying your code
with one fish at 0 degs lat and 0 degs lon. Does it get converted
to the correct x,y,z coordinates? Do you know what those coor-
dinates should be?

adpward
09-18-2015, 02:44 PM
Thank you Carmine - I will take a look and report back.

adpward
09-29-2015, 12:07 PM
The issue was definitely the coordinates - they are now working as expected.

Thank you for the recommendation - it was a great help.