Why doesn't my OpenGL Radar implementation render on screen? - c++

I want to implement radar for my 3D game using openGL. I have been trying to accomplish it in many ways, but none of them approved to be correct. Here is the snippet of my code below:
int xi, yi;
GLfloat x,z;
glPushMatrix();
{
glTranslatef(-0.8f, 0.2f, -3.0f);
glColor3f(0.0f, 0.0f, 1.0f);
x = playerTank->givePosX();
z = playerTank->givePosZ();
xi = (int)((x + 1000) / 20) + 5;
yi = (int)(((z + 1000) / 20) + screenHeight - 105);
glPushMatrix();
{
glScalef(xi,yi,1.0f);
glBegin(GL_QUADS);
glVertex2i(xi-5, yi-5);
glVertex2i(xi+5, yi-5);
glVertex2i(xi+5, yi+5);
glVertex2i(xi-5, yi+5);
glEnd();
}
glPopMatrix();
glColor3f(1.0f, 0.0f, 0.0f);
glPushMatrix();
{
glScalef(xi,yi,1.0f);
for (int i = 0; i < tanks.size(); i++)
{
x = tanks[i]->givePosX();
z = tanks[i]->givePosZ();
xi = (int)((x + 1000) / 20) + 5;
yi = (int)(((z + 1000) / 20) + screenHeight - 105);
if (xi > 0 && xi < 110 && yi > (screenHeight - 110) && yi < screenHeight)
{
if (tanks[i] != playerTank)
{
glBegin(GL_TRIANGLES);
glVertex2i(xi, yi-5);
glVertex2i(xi+5, yi+5);
glVertex2i(xi-5, yi+5);
glEnd();
}
}
}
}
glPopMatrix();
glColor3f(0.0f, 1.0f, 0.0f);
glPushMatrix();
{
glScalef(xi,yi,1.0f);
for (int i = 0; i < obstacles.size(); i++)
{
x = obstacles[i]->givePosX();
z = obstacles[i]->givePosZ();
xi = (int)((x + 1000) / 20) + 5;
yi = (int)(((z + 1000) / 20) + screenHeight - 105);
glBegin(GL_LINE_LOOP);
glVertex2i(xi-3, yi-3);
glVertex2i(xi+3, yi-3);
glVertex2i(xi+3, yi+3);
glVertex2i(xi-3, yi+3);
glEnd();
}
}
glPopMatrix();
}
glPopMatrix();
Why doesn't anything appear on the screen?

Some things to try:
Make sure you've set up the renderer correctly - what calls are you making to set up the scene? Take a look at some of the lessons on nehe for some hints.
Make a simple square the size of the screen. You're doing something along those lines in the top section (blue quad right?) but make sure it's centred - looks like you might be pushing it up and right by 1000 units.
Check you're winding the correct way. Looks like you are from my somewhat rusty OGL memories.
Try translating in different directions. Looks to me like you might be translating the wrong way with your first translatef.

Related

OpenGL reverse movement

I'm trying to decrease the values of 'left_eye_b' and 'left_eye_b'and then increase the values again to simulate wink on a human I made on OpenGL.
Here I created the eye:
left_eye_b=10.0;
left_eye_s=10.0;
glColor3f(1.0f, 1.0f, 0.0f);
glBegin(GL_POLYGON);
for (float i = 0; i <= (2 * p); i += 0.001) { // Left Eye Inside
x = 10.0 * cos(i) - 24.56;
y = left_eye_s * sin(i) + 56.45;
glVertex2f(x, y);
}
glEnd();
glColor3f(0.0f, 0.0f, 0.0f);
glPointSize(2);
glBegin(GL_POINTS);
for (float i = 0; i <= (2 * p); i += 0.001) { // Left Eye Border
x = 10.0 * cos(i) - 24.56;
y = left_eye_b * sin(i) + 56.45;
glVertex2f(x, y);
}
glEnd();
Here is where I tried to make the eye wink:
void timer(int a) {
/// Simulating Wink
if (left_eye_b >= 1.12)
left_eye_b -= 0.1; // Eye Close
if (left_eye_s >= 1.12)
left_eye_s -= 0.1;
glutTimerFunc(10, timer, 1);
if (left_eye_b <= 10.0)
left_eye_b += 0.1; // Eye Open
if (left_eye_s <= 10.0)
left_eye_s += 0.1;
glutPostRedisplay();
glutTimerFunc(10, timer, 1);
}
Problem statement:
If I remove the 'eye open' part, I works perfectly and the eye closes.
However, I want to use the 'Eye Open' part to make increase the values back and
open the eye again after a few seconds.
Any suggestion about how that can be achieved?
Add a variable that indicates whether the eye will be opened or closed. The value of the variable is 1.0 to open and -1.0 to close:
double eye_change = -1.0;
Change the sign of the variable when the exe has opened or closed:
void timer(int a) {
left_eye_b += 0.1 * eye_change;
left_eye_s += 0.1 * eye_change;
if (left_eye_b <= 1.12)
eye_change = 1.0;
if (left_eye_b >= 10.0)
eye_change = -1.0;
glutPostRedisplay();
glutTimerFunc(10, timer, 1);
}

OpenGL independent rotation

I'm trying to draw these shaped bellow this this:
What I want
Tried this code:
glLoadIdentity();
glColor3f(0.98f, 0.83f, 0.73f);
glBegin(GL_POLYGON);
for (float i = 0; i <= (2 * p); i += 0.001) {
x = 100 * cos(i)-10;
y = 115 * sin(i)+270;
glVertex2f(x, y);
}
glEnd();
glRotatef(-135.0f, 0.0f, 0.0f, 1.0f);
glColor3f(1.0f, 0.83f, 0.0f);
glBegin(GL_POLYGON);
for (float i = p; i <= (2 * p); i += 0.001) {
x = 100 * cos(i) - 10;
y = 115 * sin(i) + 270;
glVertex2f(x, y);
}
But this is what I get:
What I get
If I want to only use the glLoadIdentity and glRotatef for rotation, do you have any idea about how to fix it?
Note:
I don't want to use push/pop or translation
You have to rotate the object around its center and move the rotated object to its position in the world. glRotatef rotates the vertices around (0, 0). Draw the object around (0, 0) and glTranslate to move the object to its position in the world:
glTranslate(-10.0f, 270.0f, 0.0f);
glRotatef(-135.0f, 0.0f, 0.0f, 1.0f);
glColor3f(1.0f, 0.83f, 0.0f);
glBegin(GL_POLYGON);
for (float i = p; i <= (2 * p); i += 0.001) {
x = 100 * cos(i);
y = 115 * sin(i);
glVertex2f(x, y);
}
Note, the matrix operations like glRotate and glTranslate specify a new matrix and multiply the current matrix by the new matrix.
If you are not allowed to use glTranslate, you have to rotate the translation vector (-10, 270) in the opposite direction. Use the trigonometric functions sin an cos to rotate the vector (see Rotation matrix). You need to invert the angle and convert it to Radians since the unit of sin and cos is Radian.
float tx = -10.0f;
float ty = 270.0f;
float angle = -135.0f;
float inv_angle_rad = -angle * M_PI / 180.0f;
float tx_rot = tx * cos(inv_angle_rad) - ty * sin(inv_angle_rad);
float ty_rot = tx * sin(inv_angle_rad) + ty * cos(inv_angle_rad);
glRotatef(angle, 0.0f, 0.0f, 1.0f);
glColor3f(1.0f, 0.83f, 0.0f);
glBegin(GL_POLYGON);
for (float i = p; i <= (2 * p); i += 0.001) {
x = 100 * cos(i) + tx_rot;
y = 115 * sin(i) + ty_rot;
glVertex2f(x, y);
}

Picking in OpenGL using glRenderMode(GL_SELECT) and glReadPixels

I'm trying to do selection in opengl but it is not working.
I draw objects I receive from a .obj file (v, vn, f, o and such indices). Each object consists from "groups" and each group is a group of GL_POLYGON.
Here is the draw function:
void draw(GLenum mode) {
glBegin(GL_LINES);
glColor3f(1, 0, 0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(100.0, 0.0, 0.0);
glColor3f(0, 0, 1);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(0.0, 100.0, 0.0);
glColor3f(0, 1, 0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(0.0, 0.0, 100.0);
glEnd();
glColor4f(1.0, 1.0, 1.0, 1.0);
if (changeFOV) {
fovAngle += fovScale;
changeFOV = false;
setTransformations();
}
for (unsigned int i = 0; i < objects.size(); i++) {
objectItem currObject = objects[i];
for (unsigned int j = 0; j < currObject.getGroups().size(); j++) {
group currGroup = currObject.getGroups().at(j);
for (unsigned int k = 0; k < currGroup.getFs().size(); k++) {
if (mode == GL_SELECT)
glPushName(currGroup.getName());
glPushMatrix();
vector<pair<int, int> > currF = currGroup.getFs()[k];
glBegin(GL_POLYGON);
for (unsigned int kk = 0; kk < currF.size(); kk++) {
Vector3f currVertex = vertexes.at(
(currF.at(kk).first - 1 >= 0) ?
currF.at(kk).first - 1 : 0);
Vector3f currNormal = vertexesNormal.at(
(currF.at(kk).second - 1 >= 0) ?
currF.at(kk).second - 1 : 0);
glNormal3f(currNormal.x, currNormal.y, currNormal.z);
glVertex3f(currVertex.x / 1, currVertex.y / 1,
currVertex.z / 1);
}
glEnd();
glPopMatrix();
}
}
}
}
The drawing works ok and I see the object on the screen.
This is all the picking procedure
/* PICKING */
void processHits(GLint hits, GLuint *buffer) {
float z1, z2;
for (int i = 0; buffer[i] > 0; i += 5) {
z1 = buffer[i + 1] / 4294967295.0;
z2 = buffer[i + 2] / 4294967295.0;
printf("z1 = %f ,z2 = %f zValue = %f\n", z1, z2, zValue[0]);
if ((zValue[0] <= z1 + 0.0001 && zValue[0] >= z2 - 0.0001)
|| (zValue[0] >= z1 - 0.0001 && zValue[0] <= z2 + 0.0001)) { //try to locate which name is correlated with the pressed pixel according to z value
ii = buffer[i + 3];
jj = buffer[i + 4];
}
}
}
void startPicking(GLuint *selectionBuf) {
glSelectBuffer(bufSize, selectionBuf); //declare buffer for input in selection mode
glRenderMode(GL_SELECT); //change to selecting mode
glInitNames(); //initialize names stack
glPushName(-1); //push name
}
void pick(int button, int x, int y) {
//use selection mode to pick
glReadPixels(x, viewport[3] - y, 1, 1, GL_RGBA, GL_FLOAT, pix);
//printf("depth = %f, x = %d, y = %d\n",pixels[(viewport[3]-y)*512+x],x,viewport[3]-y);
glMatrixMode(GL_PROJECTION);
glReadPixels((GLdouble) x, (GLdouble) viewport[3] - y, 2, 2,
GL_DEPTH_COMPONENT, GL_FLOAT, zValue);
glPushMatrix(); //saves current projection matrix
startPicking(selectionBuf); //preper selection mode
glLoadIdentity();
gluPickMatrix((GLdouble) x, (GLdouble) viewport[3] - y, 1, 1, viewport); //change matrices so only the area of the picking pixel can be seen.
gluPerspective(fovAngle, 1, near, far); //return to perspective state
glMatrixMode(GL_MODELVIEW);
draw(GL_SELECT); //draws board on background
hits = glRenderMode(GL_RENDER); //gets hits number
glMatrixMode(GL_PROJECTION);
glPopMatrix(); //restores projection matrix
glMatrixMode(GL_MODELVIEW);
processHits(hits, selectionBuf); //check hits
if(hits > 0)
printf("touched: %d\n",selectionBuf[3]);
//printf("depth %f hits: %d\n\n",pixels[(viewport[3]-y)*512+x], hits);
if (zValue[0] < 1.0) {
isPick = true;
xx = x;
yy = y;
if (button == GLUT_RIGHT_BUTTON)
zMove = true;
else
zMove = false;
}
}
the pick function is called when the mouse is clicked (using opengl mouse function).
The error I'm receiving is that no objects appears to be hit when clicking on an object.
I'm using Ubuntu 14.04 LTS with Opengl 3.0
I don't know how to ask or what specifically ask, I would appreciate some inputs on the code if you see something wrong..
You seemed to have missed using glPopName()
GLNames used in the selection buffer are pushed on a stack. So unless you call glPopName() the stack would never unwind. The working of this is similar to the calls glPushMatrix() and glPopMatrix().
Typically this is what the code flow looks like.
//Push the name of the primitives on top of selection stack
glPushName(...)
//Set Transformations / Draw the primitives
..
..
//Pop the name (Clear the stack for pushing another name)
glPopName();

glRotatef results on a wirecube

I am using a rand() function for and x variable and y variable to be used in glRotatef. Rand is working just fine. What is happening is when I get a 0 value in both X and Y, the cube fluctuates by shrinking and inflating. I have tried a couple of ways to make sure this does not happen but alas, I am here. Here is the function I am working with:
void initRandoms()
{
maxCubes = rand() % (CUBE_HIGH - CUBE_LOW + 1) + CUBE_LOW;
for (int i = 0; i < maxCubes; i++)
{
cubeOrigins[i].x = X_LOW + (float)rand() / (float)RAND_MAX * (X_HIGH - X_LOW);
cubeOrigins[i].y = Y_LOW + (float)rand() / (float)RAND_MAX * (Y_HIGH - Y_LOW);
//cubeOrigins[i].z =
cubeOrigins[i].size = SIZE_LOW + (double)rand() / (double)RAND_MAX * (SIZE_HIGH - SIZE_LOW);
cubeOrigins[i].rotateX = rand() % 2;
cubeOrigins[i].rotateY = rand() % 2;
}
As I said before, each cube will rotate either on the X-axis, Y-axis, XY-axis or shrink and inflate. It is the shrink and inflate I need to remove which corresponds to 0 = X AND 0 = Y. I can have X = 0 OR Y = 0. What I have tried is some if else conditionals but what happens is I take the shrink & inflate out but then all the cubes rotate in the same direction. I am hoping someone can figure out what I am doing wrong and show me what I need to do. I appreciate everyone's help. I will put more code up if needed.
Here is myDisplay function where the above function is used. The above function is also called in main:
void myDisplay()
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
for(int i = 0; i < maxCubes; i++)
{
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -120.0);
glTranslatef(cubeOrigins[i].x, cubeOrigins[i].y, cubeZ);
glRotatef(rotateAxis, cubeOrigins[i].rotateX, cubeOrigins[i].rotateY, 0.0f);
//glRotatef(rotateAxis, 1, 1, 0);
glutWireCube(cubeOrigins[i].size);
}
cubeZ += 0.050f;
glutSwapBuffers();
glFlush();
if (cubeZ > 120.0f)
{
cubeZ -= 100.f;
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
for(int i = 0; i < maxCubes; i++)
{
initRandoms();
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -120.0);
glTranslatef(cubeOrigins[i].x, cubeOrigins[i].y, cubeZ);
glRotatef(rotateAxis, cubeOrigins[i].rotateX, cubeOrigins[i].rotateY, 0.0f);
//glRotatef(rotateAxis, 1, 1, 0);
glutWireCube(cubeOrigins[i].size);
}
cubeZ += 0.050f;
glutSwapBuffers();
glFlush();
}
}
Looking at your code, I could see that you are rotating your cubes by using this function:
glRotatef(rotateAxis, cubeOrigins[i].rotateX, cubeOrigins[i].rotateY, 0.0f);
The question is: What happens when both, cubeOrigins[i].rotateX and cubeOrigins[i].rotateY are zero? OpenGL rotates matrix by using a mathematic function called quaternion (http://www.opengl.org/sdk/docs/man2/xhtml/glRotate.xml) and, when x, y and z are zero, I guess (because your are violating one of its premises that is ||x, y, z|| must be 1) it is reduced to this matrix:
|cos(angle) 0 0 0|
| 0 cos(angle) 0 0|
| 0 0 cos(angle) 0|
| 0 0 0 1|
which is essentially a scale matrix. This explain your beforementioned effect of shrinking and inflating.
So, as you observed before, you need to avoid this situation.
Second, you are using, for all cubes, the same rotateAxis. So, every cube that is with same cubeOrigins[i].rotateX and cubeOrigins[i].rotateY will got the same rotations. You need to get some variations here (changing rotateAxis for each cube)
Finally, you dont need to call both:
glutSwapBuffers();
glFlush();
glutSwapBuffers() already call, internally glFlush
first things first pls
(im not sure if you already did but)
before using the C rand() method you need to give it a seed so that you get "real" random numbers using the srand() function

Obtaining normal of vertices of torus mesh

I'm trying to create my own torus with smooth shading. However, the normal seems to be wrong. Here is my code.
GLfloat NoMat[] = { 0.0f, 0.0f, 0.0f, 1.0f };
GLfloat MatAmbient[] = { 0.7f, 0.7f, 0.7f, 1.0f };
GLfloat MatAmbientColor[] = { 0.21f, 0.13f, 0.05f, 1.0f };
GLfloat MatDiffuse[] = { 0.71f, 0.43f, 0.18f, 1.0f };
GLfloat Shine = 100.0f;
GLfloat NoShine = 0.0f;
glMaterialfv(GL_FRONT, GL_AMBIENT, MatAmbientColor);
glMaterialfv(GL_FRONT, GL_DIFFUSE, MatDiffuse);
glEnable(GL_NORMALIZE);
glMaterialfv(GL_FRONT, GL_SPECULAR, MatAmbient);
glMaterialf(GL_FRONT, GL_SHININESS, Shine);
int i, j, k;
double s, t, x, y, z;
for (i = 0; i < nsides; i++) {
glBegin(GL_QUAD_STRIP);
for (j = 0; j <= rings + 1; j++) {
for (k = 1; k >= 0; k--) { //for both negative and positive
s = (i + k) % nsides + 0.5;
t = j % rings;
x = (totalRadius + centerRadius * cos(s*2*M_PI/nsides)) * cos(t*2*M_PI/rings);
z = (totalRadius + centerRadius * cos(s*2*M_PI/nsides)) * sin(t*2*M_PI/rings);
y = centerRadius * sin(s*2*M_PI/nsides);
glVertex3f(x, y, z);
glNormal3f(x, y, z);
}
}
glEnd();
}
However, the lighting does not work properly, as it behaves like flat shading instead of smooth shading. I've did some googling, but apparantly it seems that I need to use differention. However, I'm not too sure how to do this. Anyone has any idea?
You're using the vertex positions for normals? This will work only (and only) for a unit radius sphere!
You need to calculate the normal. That is
The nice thing about a torus is, that you can evaluate this easily on paper, giving you an exact formula, instead of working with a numerical approximation.