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.
Related
I had drawn a circle in opengl using lines.But it shows a pattern of holes at outer edges.
I want to fill this holes without reducing the radius and increasing the number of samples.
This is my code:
void drawcirc(float xi,float yj,float r1,int num1)
{
glClear(GL_COLOR_BUFFER_BIT);
//glBegin(GL_LINES);
glVertex2f(0,0);
for (int i=0;i<=num1;i++)
{
float theta=2.0f*3.141592f*float(i)/float(num1);
float x1=r1*cosf(theta);
float y1=r1*sinf(theta);
glBegin(GL_LINES);
glVertex2f(0,0);
glVertex2f(xi+x1,yj+y1);
glEnd();
sleep(5000);
glFlush();
}
}
then function call drawcirc(0, 0, 0.6, 1250);
what to do? this is my o/p with holes at outer edges.
Okay, well you're not really drawing a circle. GL_LINES will go from point to point until the primitive ends
You draw a line from 0,0 to a point on the rim of the circle + the offset you give the function.
So you're drawing the spokes of a wheel essentially, the holes at the edge are the gaps between the spokes.
AlecTeal already answered what is going on. I give you the fix:
#include <math.h>
void drawFilledCircle(float xi,float yj,float r1,int num1)
{
glBegin(GL_TRIANGLE_FAN);
glVertex2f(0,0);
for(int i = 0; i <= num1; i++)
{
float theta = 2.0f*M_PI * float(i)/float(num1);
float x1 = r1*cosf(theta);
float y1 = r1*sinf(theta);
glVertex2f(xi+x1,yj+y1);
}
glEnd();
}
void drawCircle(float xi,float yj,float r1,int num1)
{
glBegin(GL_LINE_LOOP);
for(int i = 0; i < num1; i++)
{
float theta = 2.0f*M_PI * float(i)/float(num1);
float x1 = r1*cosf(theta);
float y1 = r1*sinf(theta);
glVertex2f(xi+x1,yj+y1);
}
glEnd();
}
A few hints:
Never put glFlush, glClear, sleep or similar into function intended to draw a geometrical shape. You want to be able to call such functions from higher level drawing code and such calls are highly disruptive.
glBegin and glEnd are deprecated, their use has been discouraged for well over 15 years now. Better use vertex arrays.
If you must use glBegin/glEnd put them outside of the loop, not inside it.
For the entire night, I've been looking around the internet, both stackoverflow and elsewhere, to find something to say how to print text on GLUT. While I've found places that say how, none have explained it well, saying which parts of the function is neccessary, which parts aren't. I've also tried to copy in some of the code with the closest to a success is something that made my entire screen white except for some blue pixels. So I've given up, and I'm hoping this will clear up confusion for me and the many people who are confused, like me.
So, I have found this code:
glColor3f(1.0f, 0.0f, 0.0f);
glRasterPos2f(1280, 720);
int len = menu.length();
for (int i = 0; i < len; i++) {
glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_10, menu[i]);
}
and I have placed it in my code:
void drawScene() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(-_cameraAngle, 0.0f, 1.0f, 0.0f);
glTranslatef(0.0f, 0.0f, -9.0f + zoom);
glTranslatef(0.0f, -1.0f, 0.0f);
string menu = "Hello!";
glColor3f(1.0f, 0.0f, 0.0f);
glRasterPos2f(1280, 720);
int len = menu.length();
for (int i = 0; i < len; i++) {
glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_10, menu[i]);
} /*if I need to post the rest of drawScene(), which is the function delegated
as the Display Func, tell me. I don't want to because it's long
What I want to know is what am I doing wrong, and what do future readers in my position need to do in order to get good results.
You don't say what's specifically wrong, but I'm suspecting that your text is not showing up. The reason is likely that the raster position is being clipped, and this is causing your text to not be rendered.
The raster position is the "anchor point" of where a bitmap will be drawn. Usually, this is the lower-left corner of the bitmap (the glBitmap can change that with by setting the x and y parameters to something other than zero, but assume you're not doing that). The raster position is transformed by the model-view matrix, just like a vertex in a geometric primitive. And just like a vertex, if the transformed raster position lies outside of the viewport, it's clipped, and nothing is rendered. What's important to know here is that any rendering of a bitmap - regardless of its size - is predicated on the raster position being inside of the viewport.
In your example, you don't show the viewport you're using, nor the projection transformation (the matrix on the GL_PROJECTION stack), but you set the raster position to (1280, 720), which may well be outside of the viewport.
Let's say you want to render your text in the lower-left corner of your window (and for the sake of argument, let's say your window is 1280 x 1024). When it's time to render your text, drop the following into your rendering routine:
glMatrixMode( GL_PROJECTION );
glPushMatrix();
glLoadIdentity();
gluOrtho2D( 0, 1280, 0, 1024 );
glMatrixMode( GL_MODELVIEW );
glPushMatrix();
glLoadIdentity();
glRasterPos2i( 10, 1014 ); // move in 10 pixels from the left and bottom edges
for ( int i = 0; i < len; ++i ) {
glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_10, menu[i]);
}
glPopMatrix();
glMatrixMode( GL_PROJECTION );
glPopMatrix();
glMatrixMode( GL_MODELVIEW );
Depending on which version of OpenGL you're using, you may be able to use a simpler routine glWindowPos2i() (the 2i can be replaced with other dimension-type pairs like other OpenGL functions), which bypasses transforming the raster position by the model-view and projection matrices, and works directly in window coordinates. In that case, you'd write the above code as:
glWindowPos2i( 10, 1014 ); // move in 10 pixels from the left and bottom edges
for ( int i = 0; i < len; ++i ) {
glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_10, menu[i]);
}
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
I'm teaching myself how to use OpenGL to create graphics, and I've got a basic spiral script+rotation. The Y-Axis rotation is automatic based on a timer function, but I noticed that when I move my mouse inside the window, it seems to rotate faster than intended. Could someone please look over my script and tell me what is causing the acceleration of the timer function?
#include <Windows.h>
#include <glut.h>
#include <stdio.h>
#include <math.h>
// Change viewing volume and viewport. Called when window is resized
void ChangeSize(GLsizei w, GLsizei h)
{
GLfloat nRange = 100.0f;
//Prevent a divide by zero
if(h == 0)
h = 1;
// Set Viewport to window dimensions
glViewport(0, 0, w, h);
// Reset projection matrix stack
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Establish clipping volume (left, right, buttom, top, near, far)
if (w<= h)
glOrtho (-nRange, nRange, -nRange*h/w, nRange*h/w, -nRange, nRange);
else
glOrtho (-nRange*w/h, nRange*w/h, -nRange, nRange, -nRange, nRange);
//Reset Model view matrix stack
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
//Define a constant for pi
#define GL_PI 3.1415f
// This function does all the initialization
void SetupRC()
{
// Black background
glClearColor(0.0f, 0.0f, 0.0f, 1.0f );
// Set drawing color to green
glColor3f(0.0f, 1.0f, 0.0f);
}
// Test declaration of rotation angle
GLfloat xRot = 0;
GLfloat yRot = 0;
// Modifiable variables for the eccentricity
GLfloat xMod = 50.0f;
GLfloat yMod = 50.0f;
// Called to draw scene
void RenderScene(void)
{
GLfloat x,y,z,angle; // Storage for coordinates and angles
GLfloat sizes[2]; // Store supported point size range
GLfloat step; // Store point size increments
GLfloat curSize; //Store current point size
// Get supported point size range and step size
glGetFloatv(GL_POINT_SIZE_RANGE, sizes);
glGetFloatv(GL_POINT_SIZE_GRANULARITY, &step);
//Set the initial point size
curSize = sizes[0];
// Clear the window with current clearing color
glClear(GL_COLOR_BUFFER_BIT);
// Save matrix state and do the rotation
glPushMatrix();
glRotatef(xRot, 1.0f, 0.0f, 0.0f);
glRotatef(yRot, 0.0f, 1.0f, 0.0f);
// specify point size before primitive is specified
glPointSize(curSize);
//Call only once for remaining points
glBegin(GL_LINE_STRIP);
//Set beginning z coordinate
z = -50.0f;
//Loop around in a circle three times
for (angle = 0.0f; angle <= (2.0f*GL_PI)*3.0f; angle += 0.1f)
{
// Calculate x and y values on the circle (the major and minor axis)
x = xMod*sin(angle);
y = yMod*cos(angle);
// Specify the point and move the z value up a little
glVertex3f(x, y, z);
z += 0.5f;
}
// Done drawing points
glEnd();
// Restore transformations
glPopMatrix();
//Flush drawing commands
glFlush();
}
// Modifier Code
void CircleController (int key, int x, int y)
{
switch (key)
{
case 27 : break;
case 100 :
(yRot -= 5.0f); ; break;
case 102 :
(yRot += 5.0f); ; break;
case 101 :
(xRot -= 5.0f); ; break;
case 103 :
(xRot += 5.0f); ; break;
glutDisplayFunc(RenderScene);
}
}
void MouseHandler (int button, int state, int x, int y)
{
// Holder variable assigned to overcome printf limitation and prevent double- printing due to MouseUp function call
GLfloat Holder = xMod;
// Increases size, and decreases timer speed by increasing the amount of time needed.
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
{
xMod+= 5.0f;
}
// Decreases size, and increases timer speed by decreasing the amount of time needed.
if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
{
xMod-= 5.0f ;
}
if (Holder != xMod)
printf("%d \n", Holder);
}
void TimerFunction(int value)
{
//Call the arrow key function
glutSpecialFunc(CircleController);
//Call the Mouseclick Modifier function
glutMouseFunc(MouseHandler);
if (xRot < 360)
(xRot += 1.0f);
else
(xRot = 0.0f);
// Redraw the scene with new coordinates
glutPostRedisplay();
glutTimerFunc(1.6666f, TimerFunction, 1);
}
void main(void)
{
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutCreateWindow("Drawing Lines");
glutDisplayFunc(RenderScene);
glutReshapeFunc(ChangeSize);
glutTimerFunc(1.6666f, TimerFunction, 1);
SetupRC();
glutMainLoop();
}
Eric Palace gave me the start
My personal theory was always that it had something to do with the window focus and which program is given more CPU time, but that's just pure speculation.
That makes sense to me. But wait, don't you only paint on a timer? Wouldn't that prevent additional CPU time from modifying movement speed? Yes you do. Sortof.
glutTimerFunc(1.6666f, TimerFunction, 1);
The doc's for glutTimerFunc say that the first parameter is an unsigned int, representing the timer in milliseconds. So you're telling glut "call this function every 1 millsecond." (Approx 1000FPS) And since it takes longer than one millisecond to execute, you're effectively telling it "run this function over and over as fast as you possibly can". Which it does. And so additional CPU time is making a difference.
To avoid situtations like this (aside from correcting the 1.6666f parameter), it's usually suggested to
update the "world" in separate functions from painting the screen. In fact, I would imagine it to be common to have two or more world update functions. One for stuff that needs updating with the paint: arrows and running characters, one for stuff that only changes once a second or so: mana regen and npc decisions, and one for really slow stuff: respawns.
During an "update", check how much time has passed since the last update, (maxing out at half a second or so), and make the world update that much. Then if updates run twice as often or half as often for any reason, the game doesn't appear to speed up or slow down, you just just more/fewer frames instead.
Here's what such an update might look like
radians xrot = 0; //use a units class
radians rot_per_second = .01;
void updateFrame(double time_passed) {
assert(time_passed>=0 && time_passed <= 1.0);
radians rotate_thistime = rot_per_second * time_passed;
xrot += rotate_thistime;
}
void do_updates() {
static clock_t lastupdatetime = clock()-1; //use openGL functions instead of C
clock_t thisupdatetime = clock();
double seconds = double(thisupdatetime-lastupdatetime)/CLOCKS_PER_SEC;
if (seconds > 0.5) //if something happened and haven't update in a long time
seconds = 0.5; //pretend only half a second passed.
//this can happen if
// computer is overloaded
// computer hibernates
// the process is debugged
// the clock changes
if (seconds <= 0.0) //computer is REALLY fast or clock changed
return; //skip this update, we'll do it when we have sane numbers
updateFrame(seconds);
lastupdatetime = thisupdatetime;
}
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.