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
Related
I'm trying to write code for a weaving pattern in OpenGL.
Weaving Pattern
Pic
Now, I am trying to write code for a similar pattern using a circle.
I draw a circle using points, each point is drawn using cos and sin functions.
I understand this is not as efiicient as SeigeLord's method as it makes higher use of resources.
I am able to get the circle, I want to get points on it's circumference.
My code :
#include<GL/glut.h>
#include<stdio.h>
#include<math.h>
int n, r;
void display()
{
int i, j;
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-50, 50, -50, 50);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
for (i = 0;i <= 360;i += 1)
{
glBegin(GL_POINTS);
glVertex2f(r*cos(i), r*sin(i));
glEnd();
}
/*for (i = 0;i < 360;i += 10)
{
glBegin(GL_LINES);
glVertex2f(r*cos(i), r*sin(i));
glVertex2f(r*cos(i + 300), r*sin(i + 300));
glEnd();
}*/
glFlush();
}
int main(int argc, char **argv)
{
r = 30;
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
glutInitWindowPosition(300, 50);
glutInitWindowSize(800, 800);
glutCreateWindow("Cylinder");
glutDisplayFunc(display);
glutMainLoop();
}
I tried using the commented code for getting lines between points 300 degrees apart, do this every at point 10 degrees apart.(It looks good at 3 degrees apart).
Now, this obviously doesn't work as we use trigonometric functions, which won't space out the points equally.
I hope you understand my question, how can I get points on the circle equally apart?
One solution, I think might work is, while plotting the points itself, if I use an array to save every nth point, I may get equidistant points. Am I right? Is there any other way of getting the points?
Please do correct me if I am wrong anywhere above, I am just newbie here.
Note that sin and cos take their input in radians(i.e. 0 to 2* pi), not degrees(0 to 360). So your code should probably be
for (i = 0;i <= 360;i += 1)
{
glBegin(GL_POINTS);
glVertex2f(r*cos(i * (M_PI / 180.)), r*sin(i* (M_PI / 180.)));
glEnd();
}
edit:
To get N equidistant point we have to put them (1/N) part of the circle away from each other:
for (i = 0;i < N;i += 1)
{
double angle = i * (2.0 * M_PI / N);
glBegin(GL_POINTS);
glVertex2f(r*cos(angle), r*sin(angle));
glEnd();
}
So I'm working with a 2d array, and I'm trying to display it on a widget using opengl. It seems to work fine, but it does not fill the widget properly. Rather than filling it evenly it's moved to the top right as seen in the image below. How can I get this to be centered?
int x = -0.1;
int y = -0.1;
float lengthX = 0.9 / ROW;
float lengthY = 0.9 / COLM;
for (int i = 0; i < ROW; i++) {
for (int j = 0; j < COLM; j++) {
if (arr[i][j] == 1) {
glColor3f(1.0f, 1.0f, 1.0f);
} else {
glColor3f(0.0f, 0.0f, 0.0f);
}
glBegin(GL_QUADS);
// Q3 Q4 Q1 Q2
glVertex2f((-x) + 2 * i * lengthX, (-y) + 2 * j * lengthY);
glVertex2f(x + (2 * i + 1) * lengthX, (-y) + (2 * j + 1) * lengthX);
glVertex2f(x + (2 * i + 1) * lengthX, y + (2 * j + 1) * lengthY);
glVertex2f((-x) + 2 * i * lengthX, y + 2 * j * lengthY);
glEnd();
}
}
First off, your code is wrong with it's variables; Such as int x = -0.1.
Now, to fix the problem just add this to the beginning of your code:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 1, 1, 0, -1, 1);
glMatrixMode(GL_MODELVIEW);
The problem was that you're using the default matrix setup. Basically, it ranges from -1, -1 to 1, 1, instead of 0, 0, to 1, 1. I can't quite read your code, but if you can edit the glOrtho function's first 4 parameters (the last two shouldn't effect anything) to change the visible range of what you're drawing.
Just to explain a bit more, the first parameter sets the left side, the second right, the third bottom, and the fourth top. So glOrtho(0, 600, 800, 0) means setting a vertex to 0, 0 means it's showing on the top left, while a vertex set to 800, 600 will be showing on the bottom right.
Your setup was only showing a part of what it was supposed to show because the center of it, was the corner of your screen.
I have created a function to move several cubes along the z-axis. I can get all the cubes to move at once and repeat but I am trying to get each individual cube to move independently of the other. My z-axis function is:
void moveCubes()
{
cubeZ += 0.050f;
if(cubeZ > 120)
cubeZ -= 110.0f;
glutPostRedisplay();
}
and the display function is:
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, -110);
glTranslatef(cubeOrigins[i].x, cubeOrigins[i].y, cubeZ);
glRotatef(rotateAxis, cubeOrigins[i].rotateX, cubeOrigins[i].rotateY, 0.0f);
drawCubes();
}
moveCubes();
glutSwapBuffers();
}
cubeZ is defined at the top of my code and is:
GLfloat cubeZ = 0.0;
cubeOrigins[i].x and .y are generated rands(). I can add more code if needed but I believe this is the important part. I am hoping someone can show me what I need to do. Frankly it is getting pretty frustrating. I appreciate any help.
You've hard-coded a constant Z-position for all cubes. You probably want to use cubeOrigins[i].z instead. If you don't have such a value in your struct, perhaps you should (and randomize that the same as your x- and y-values).
When you update:
void moveCubes() {
for( int i = 0; i < maxCubes; i++ ) {
cubeOrigins[i].z += 0.05f;
if( cubeOrigins[i].z > 120 )
cubeOrigins[i].z -= 110.0f;
}
glutPostRedisplay();
}
And of course:
glTranslatef(cubeOrigins[i].x, cubeOrigins[i].y, cubeOrigins[i].z);
If you want to get techy, you may also want to randomize the speed of the cubes. So you can create an array of floats to represent each cube's speed and use that instead of the constant 0.05f speed.
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.
I'm trying to make a light source rotate around my character model in my OpenGL project, but as I try it, all I got so far is my model rotating like crazy (or the floor).
My rendering code looks like this:
void mainRender() {
updateState();
renderScene();
glFlush();
glutPostRedisplay();
//spin = (spin + 30) % 360;
Sleep(30);
}
void renderScene() {
glClearColor(backgrundColor[0],backgrundColor[1],backgrundColor[2],backgrundColor[3]);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // limpar o depth buffer
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
updateCam();
renderFloor();
modelAL.Translate(0.0f,1.0f,0.0f);
modelAL.Draw();
}
void renderFloor() {
// set things up to render the floor with the texture
glShadeModel(GL_SMOOTH);
glEnable(type);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glPushMatrix();
glTranslatef(-(float)planeSize/2.0f, 0.0f, -(float)planeSize/2.0f);
float textureScaleX = 10.0;
float textureScaleY = 10.0;
glColor4f(1.0f,1.0f,1.0f,1.0f);
int xQuads = 40;
int zQuads = 40;
for (int i = 0; i < xQuads; i++) {
for (int j = 0; j < zQuads; j++) {
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 0.0f); // coords for the texture
glNormal3f(0.0f,1.0f,0.0f);
glVertex3f(i * (float)planeSize/xQuads, 0.0f, (j+1) * (float)planeSize/zQuads);
glTexCoord2f(0.0f, 0.0f); // coords for the texture
glNormal3f(0.0f,1.0f,0.0f);
glVertex3f((i+1) * (float)planeSize/xQuads, 0.0f, (j+1) * (float)planeSize/zQuads);
glTexCoord2f(0.0f, 1.0f); // coords for the texture
glNormal3f(0.0f,1.0f,0.0f);
glVertex3f((i+1) * (float)planeSize/xQuads, 0.0f, j * (float)planeSize/zQuads);
glTexCoord2f(1.0f, 1.0f); // coords for the texture
glNormal3f(0.0f,1.0f,0.0f);
glVertex3f(i * (float)planeSize/xQuads, 0.0f, j * (float)planeSize/zQuads);
glEnd();
}
}
glDisable(type);
glPopMatrix();
}
How could I make this new lightsource rotate around my "modelAL" object?
For the fixed pipeline, light source position assigned with glLight() are transformed with the model-view matrix, just as normal objects are. So you can use the transformation functions to position and rotate your light source as you would normal objects.
To rotate a light source (or other object) around a point, you need to follow these steps. Let L be where the light source will be when the rotation is 0 degrees, and O be the subject - the object around which you want to rotate the light source.
Position the light source at L-O (the position of the light source relative to the subject)
Rotate it about the required axis (probably the Y axis)
Translate it by O to move it into position.
Because of the way OpenGL works, you essentially do these in backwards order. Basically it would go like this:
glPushMatrix();
glTranslatef(O.x,O.y,O.z);
glRotate(angle,0,1,0);
GLfloat lightpos[4] = {L.x-O.x,L.y-O.y,L.z-O.z,1};
glLightfv(GL_LIGHT0,GL_POSITION,lightpos);
glPopMatrix();
Note, this only applies to positioned light sources, not directional ones i.e. with w=0.