This code draws a pin on which disks are ordered ( Tower of Hanoi Pins ) in opengl . I am not understanding how this sequence of functions are gradually drawing a pin . I know primarily about the functions , their parameter lists and usage . But what I exactly want to know is the step by step output of each of them called. here is the function :
void drawPin(GLUquadricObj **quadric, const GLfloat radius, const GLfloat height)
{
glPushMatrix();
glRotatef(-90.0, 1.0, 0.0, 0.0);
gluCylinder(*quadric, radius, radius, BREITE/2, SLICES, LOOPS);
gluQuadricOrientation(*quadric, GLU_INSIDE);
gluDisk(*quadric, 0.0, radius, SLICES, LOOPS);
gluQuadricOrientation(*quadric, GLU_OUTSIDE);
glTranslatef(0.0, 0.0, BREITE/2);
gluDisk(*quadric, 0.0, radius, SLICES, LOOPS);
gluCylinder(*quadric, STANGENBREITE, STANGENBREITE, height, INNERSLICES, LOOPS);
glTranslatef(0.0, 0.0, height);
gluDisk(*quadric, 0.0, STANGENBREITE, INNERSLICES, LOOPS);
glPopMatrix();
}
This function only draws primitives with given parameters. All parameters change outside function.
Related
First of all, let me tell i am quite new using OpenGL and C++. However, i want to get involved with this two topics.
So let me explain my case, ive been searching how to get the new coordinates of an object after glTrasnlatef and glRotatef were applied. However, i did not find the find info, actually i found some info about java but i am not getting it, as i told you i am working with C++.
I read there is something to deal with the glPushMatrix(); function but idont know how to handle it.
I know that after applying some trnaslation and rotation i am doing changes into the actual matrix.
Finally, the main purpose of this is because ill use those vertices from the rombohedrom and do a lot of translations and rotations, those are going to be needed as well.
So far this is my code (BTW i am working with lines and the vertices of course because i only need those).
i will really appreciate if someone can address me through the right path.
Thanks in advance
Alberto
#include <GL/glut.h>
#include <iostream>
#include <cmath>
#include <vector>
using namespace std;
// Global variables
double rotate_y=0;
double rotate_x=0;
int width = 640;
int height = 640;
#define PI 3.14159265
float theta = 60;
float edgeLength = 1;
float sinThetaOverHypotenuse = (sin((theta*PI)/180))/edgeLength;
vector<vector<float>> coordinates{{0.0, 0.0, 0.0},
{1.0, 0.0, 0.0},
{1.0, 0.0, 0.0},
{1.5, sinThetaOverHypotenuse, 0.0},
{1.5, sinThetaOverHypotenuse, 0.0},
{0.5, sinThetaOverHypotenuse, 0},
{0.5, sinThetaOverHypotenuse, 0},
{0.0, 0.0, 0.0}};
void rhombohedrom()
{
vector<vector<float>> rotated {};
// glClearColor(1,1,0,0)
// Clear screen and Z-buffer
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
double w = glutGet( GLUT_WINDOW_WIDTH ) / 300.0;
double h = glutGet( GLUT_WINDOW_HEIGHT ) / 300.0;
glOrtho( -1 * w, 1 * w, -1 * h, 1 * h, 10, -10);
glMatrixMode( GL_MODELVIEW );
// Reset transformations
glLoadIdentity();
// Rotate when user changes rotate_x and rotate_y
glRotatef( rotate_x, 1.0, 0.0, 0.0 );
glRotatef( rotate_y, 0.0, 1.0, 0.0 );
/*
FACE 0
FACE 0
FACE 0
FACE 0
*/
// random color side - front
glBegin(GL_LINE_LOOP);
glColor3f( 0.7, 0.3, 0.8 );
for (int i = 0; i < 8; ++i)
{
glVertex3f(coordinates[i][0], coordinates[i][1], coordinates[i][2]);
}
glEnd();
/*
FACE 1
FACE 1
FACE 1
FACE 1
*/
glPushMatrix();
glTranslatef(0.0,0.0,0.0);
glRotatef(90.0, 1.0, 0.0, 0.0);
glBegin(GL_LINE_LOOP);
glColor3f( 1.0, 1.0, 1.0 );
for (int i = 0; i < 8; ++i)
{
glVertex3f(coordinates[i][0], coordinates[i][1], coordinates[i][2]);
}
glEnd();
glPopMatrix();
/*
FACE 2
FACE 2
FACE 2
FACE 2
*/
glPushMatrix();
glTranslatef(0.5,0.0,sinThetaOverHypotenuse);
glBegin(GL_LINE_LOOP);
glColor3f( 0.5, 0.5, 0.0 );
for (int i = 0; i < 8; ++i)
{
glVertex3f(coordinates[i][0], coordinates[i][1], coordinates[i][2]);
}
glEnd();
glPopMatrix();
/*
FACE 3
FACE 3
FACE 3
FACE 3
*/
glPushMatrix();
glTranslatef(0.5,sinThetaOverHypotenuse,0.0);
glRotatef(90.0, 1.0, 0.0, 0.0);
glBegin(GL_LINE_LOOP);
glColor3f( 0.5, 0.0, 0.0 );
for (int i = 0; i < 8; ++i)
{
glVertex3f(coordinates[i][0], coordinates[i][1], coordinates[i][2]);
}
glEnd();
glPopMatrix();
glFlush();
glutSwapBuffers();
}
void specialKeys(int key, int x, int y)
{
// Right arrow - increase rotation by 5 degree
if (key == GLUT_KEY_RIGHT)
rotate_y += 5;
// Left arrow - decrease rotation by 5 degree
else if (key == GLUT_KEY_LEFT)
rotate_y -= 5;
else if (key == GLUT_KEY_UP)
rotate_x += 5;
else if (key == GLUT_KEY_DOWN)
rotate_x -= 5;
// Request display update
glutPostRedisplay();
}
int main(int argc, char *argv[])
{
// Initialize GLUT and process user parameters
glutInit(&argc,argv);
glutInitWindowSize(width,height);
// Position of the window
glutInitWindowPosition(10,10);
// Request double buffered true color window with Z-buffer
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
// Create window
glutCreateWindow("rhombohedrom");
// Enable Z-buffer depth test
glEnable(GL_DEPTH_TEST);
// Callback functions
glutDisplayFunc(rhombohedrom);
glutSpecialFunc(specialKeys);
//
glutMainLoop();
return 0;
}
First, I want to address some remarks such as:
glPushMatrix() is an old way, try to use the MVP technique which will help you solving your problem. So, you have to write your Vertex Shader and pass the Matrices through what called uniform in OpenGL. Obviously, you have to use new Routines.
glPopMatrix() is also an old routine.
I'm happy to answer your further questions if you want to know more about those remarks.
Use Vertex Shader instead of simple calculus using the CPU!
you can change glTranslatef() and glRotatef() by lookAt so you can change the scale, rotation and translation.
Use Vertex Shader instead of using or stressing the CPU by graphic calculus. Even if you have an Intel integrated GPU
I am trying to create a project in OpenGL C++ that has 3 sides of a cube showing at run time. No rotation needed to see the 3 sides. I'm very new to OpenGL, my plan of attack right now has been changing the x, y, and z values. I am fine working in 2d but adding z to mix is what I think is tripping me up. I know using a negative value will bring the image closer to the camera and positive further away, but in my code below when I change the Z value it does nothing to the object.
I only have the front and right side showing(running) just to attempt to get those 2 in the right position in the window first before the whole cube is drawn. Originally I drew them out in terms of 0.5 or -0.5 but that only produces a rectangle on the screen.
So my main question is, is there an easier way to predict the behavior of each of the vertices? Yes I know i'm working in a graphical space, but why are some of my points not even moving when the value is changed?
#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
#include <stdlib.h> //For exit function
void exit(int); //To Exit Program
void init(void)
{
glClearColor (0.0, 0.0, 0.0, 1.0);
glColor3f(1.0, 1.0, 1.0);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
}
void cube()
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glBegin(GL_QUADS);
glColor3f( 1.0, 0.0, 0.0 ); glVertex3f( 0.2, -0.3, -0.5 ); // P1 is red lb
glColor3f( 0.0, 1.0, 0.0 ); glVertex3f( 0.3, 0.2, -0.5 ); // P2 is green lt
glColor3f( 0.0, 0.0, 1.0 ); glVertex3f( -0.2, 0.3, -0.5 ); // P3 is blue tt
glColor3f( 1.0, 0.0, 1.0 ); glVertex3f( -0.3, -0.2, -0.5 ); // P4 is purple tb
glEnd();
// Green side - LEFT
glBegin(GL_QUADS);
glColor3f( 0.0, 1.0, 0.0 );
glVertex3f( -0.2, -0.3, 0.5 );
glVertex3f( -0.3, 0.2, 0.5 );
glVertex3f( -0.2, 0.3, -0.5 );
glVertex3f( -0.3, -0.2, -0.5 );
glEnd();
glFlush();
}
void myKeyboard(unsigned char theKey, int mouseX, int mouseY)
{
switch(theKey)
{
case 'Q':
case 'q':
exit(-1); //terminate the program
default:
break; // do nothing
}
}
int main(int argc, char** argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(640,480);
glutInitWindowPosition(100,150);
glutCreateWindow("Shapes: Q or q to quit");
glutDisplayFunc(cube);
glutKeyboardFunc(myKeyboard);
init();
glEnable(GL_DEPTH_TEST);
glutMainLoop();
}
The problem isn't with the behavior of the vertices, but rather that you're using an orthographic projection instead of a perspective one. If you'd like to continue using ancient OpenGL, gluPerspective is what you want instead of glOrtho. If you want to move up to more modern OpenGL, all the matrix math functions are removed, so you'd have to use a library like glm to do all your math instead.
A rectangle is getting produced because in an orthographic projection, parallel lines remain parallel, so there's no horizon point or anything. If it's behind or parallel to an edge of the front face of the rectangle, you're not seeing it. A perspective projection more closely matches how a camera sees the world, with parallel points eventually converging in the distance.
A good way to think about this is to think about a really long segment of straight railroad tracks. In an orthographic projection, you would just see two rails continuing on straight forever. In a perspective projection, you would eventually see the two rails meet at a single point in the distance and would also be able to partially see the inner edge of the rail.
How can I create a bounding box around a 3d object that I've created in 3DS MAX, and then used it in an openGL application? I need the bounding box for collision detection, but I don't understand how to link a bounding box to an object. The function that creates the object is:
void drawR2D2(){
if (xrot <= 5.0) xrot = 5.0;
if (xrot >= 70.0) xrot = 70.0;
if (ztransKit2 >= 0.7) ztransKit2 = 0.7;
if (xtransS1 >= 0.2) xtransS1 = 0.2;
if (ztransKit2 <= 0.0) ztransKit2 = 0.0;
if (xtransS1 <= 0.0) xtransS1 = 0.0;
glPushMatrix();
drawBodyR2();
glPopMatrix();
glPushMatrix();
glTranslatef(0.0, 1.2, 0.0);
glScalef(2.85, 2.85, 2.85);
glRotatef(yrotHead, 0.0, 1.0, 0.0);
drawHeadR2();
glPopMatrix();
glPushMatrix();
glScalef(3.5, 3.5, 3.5);
drawLegsR2();
glPopMatrix();
glPushMatrix();
glTranslatef(-0.41, 0.45, 0.26);
glScalef(1.4, 1.4, 1.4);
glRotatef(xrotKit1, 1.0, 0.0, 0.0);
drawKit1R2();
glPopMatrix();
glPushMatrix();
glTranslatef(-0.2, 0.5, 0.0 + ztransKit2);
glScalef(2.0, 2.0, 2.0);
glRotatef(zrotKit2, 0.0, 0.0, 1.0);
drawKit2R2();
glPopMatrix();
glPushMatrix();
glTranslatef(-0.25 + xtransS1, 0.48, 0.45);
glScalef(1.55, 1.55, 1.55);
drawShield1R2();
glPopMatrix();
glPushMatrix();
glTranslatef(-0.44 + xtransS2, 0.48, 0.37);
glScalef(1.12, 1.12, 1.12);
drawShield2R2();
glPopMatrix();
}
The other functions: drawBodyR2(),drawHeadR2, etc are the components of the entire object.
The code for the drawBodyR2, for example, is:
void drawBodyR2(){
InitModel("r2d2/body.obj", &body);//function to initialize the object
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, bodyId);
glmDraw(body, GLM_SMOOTH | GLM_TEXTURE);
glDisable(GL_TEXTURE_2D);
}
Can anyone show me how to create a bounding box around the object resulted from the drawR2D2 function?
The "best" box you can build for collision detection is an oriented bounding box (OBB), that is the smallest possible box that fits the object. In order to do that you need to learn some maths (what eigenvectors are mainly) and use them for the OBB (check this answer for a detailed explanation about OBB computation).
Note that:
OBB has nothing to do with OpenGL. You can compute the OBB/ABB having a model and never drawing it. Separate the tasks!
An OBB should never be computed twice for the same model, it is computational nonsensical. The ideal thing would be to precompute the coordinates of the 8 points forming the OBB of each of the objects you are going to draw and store them. Remember that this implies that whatever geometric transformation you apply to your object, you need to also apply it to the OBB.
I'm trying to simulate the solar system and need to get the moon to orbit a planet orbiting the sun
i am currently using the following code to rotate the planets
glPushMatrix();
glRotated((GLdouble)(spin*earth.speed), 0.0, 0.0, 1.0);
glTranslated(earth.xPos, earth.yPos, earth.zPos);
earth.draw();
glPopMatrix();
i'm trying to use the code below to make my moon orbit the earth however at the moment all i can do is rotate around a specific point.
glPushMatrix();
//define one time only start location
bool start = true;
if (start)
{
glTranslated(earthMoon.xPos, earthMoon.yPos, earthMoon.zPos);
start = false;
}
//orbit earths start point
//perfectly fits around earth
glTranslatef(-0.1, -0.1, 0);
glRotatef(spin*10, 0, 0, 1);
glTranslatef(0.1, 0.1, 0);
// need translation vector to follow earth
//glTranslated(earthMoon.xPos, earthMoon.yPos, earthMoon.zPos);
earthMoon.draw();
glPopMatrix();
i think what i need to do is find some way of knowing earths position from the rotatef function.
I have a class for the planets with the following attributes and methods:
float radius;
float xPos;
float yPos;
float zPos;
float speed;
planet(float r, float x, float y, float z, float speed);
~planet();
void draw(void)
{
glPushMatrix();
glColor3f(0.0, 1.0, 1.0);
glutSolidSphere(radius, 20, 10);
glPopMatrix();
}
the class' coordinates do not get updated when the planet rotates
Does anyone know how to get this to work?
Don't pop your matrix once you drew earth,
then your new referential will be the earth position,
you just have to call the moon drawing code and it will rotate around your earth.
Found a fix that works as intended in case anyone else is struggling with this concept
//earth
glPushMatrix();
//earth orbit
glRotated((GLdouble)(spin*earth.speed), 0.0, 0.0, 1.0);
glTranslated(earth.xPos, earth.yPos, earth.zPos);
//earth mooon
glPushMatrix();
//orbit around earth
glRotatef(spin * 5, 0, 0, 1);
glTranslatef(0.1, 0.1, 0.0);
//rotate around self
glRotated((GLdouble)spin, 0.0, 1.0, 0.0);
//draw moon
earthMoon.draw();
glPopMatrix();
//rotate around self
glRotated((GLdouble)spin, 0.0, 1.0, 0.0);
//draw earth
earth.draw();
glPopMatrix();
//
Hope this helps anyone else
I am working on the solar system and I am trying to get the sun to be the central light source of this program but it's not working the way I thought it would.
Here is a picture of what I have without lighting.
Here is the same program with lighting.
A different angle here so you can see that the Earth has no shadow as it is supposed to (ignore the red on the moon, that's for my reference)
I don't know if you can tell, but it looks like the light is centered in each sphere, and not in the Sun.
The shadow on the Earth is as if the light was coming from the top. Same with the Sun. The Sun here is not a light source, it's just a sphere that is also being lit by some some source. There is no shadow from the Earth on the moon or from the moon on the Earth.
This here is the code that draws the system
GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat pos[] = { 0.0, 0.0, 1.0, 0.0 };
glEnable(GL_LIGHTING);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightf(GL_LIGHT0, GL_POSITION, pos);
//SUN
//Picture location, major radius, minor radius, major orbit, minor orbit, angle
Planet Sun ("/home/rodrtu/Desktop/SolarSystem/images/Sun.png",
100, 99, 200.0, 0.0, 0.0);
double sunOrbS = 0;
double sunRotS = rotatSpeed/10;
//orbit speed, rotation speed, moon reference coordinates (Parent planet's major and minor Axis)
Sun.displayPlanet(sunOrbS, sunRotS, 0.0, 0.0);
//EARTH
Planet Earth ("/home/rodrtu/Desktop/SolarSystem/images/EarthTopography.png",
50, 49, 500.0, 450.0, 23.5);
double eaOrbS = orbitSpeed*2;
double eaRotS = rotatSpeed*5;
Earth.displayPlanet(eaOrbS, eaRotS, 0.0, 0.0);
//Orbit path
drawCircle(800, 720, 1, 50);
//EARTH'S MOON
Planet Moon ("/home/rodrtu/Desktop/SolarSystem/images/moonTest.png",
25, 23, 100.0, 100.0, 15);
double moOrbS = rotatSpeed*4;
double moRotS = eaOrbS;
Moon.displayPlanet(moOrbS, moRotS, Earth.getMajorAxis(), Earth.getMinorAxis());
orbitSpeed+=.9;
if (orbitSpeed > 359.0)
orbitSpeed = 0.0;
rotatSpeed+=2.0;
if (rotatSpeed > 719.0)
rotatSpeed = 0.0;
These next two functions are responsible for coordinates and drawing the spheres
void Planet::setOrbit(double orbitSpeed, double rotationSpeed,
double moonOrbitX, double moonOrbitY)
{
majorAxis = orbitSemiMajor * cos(orbitSpeed / 180.0 * Math::Constants<double>::pi);
minorAxis = orbitSemiMinor * sin(orbitSpeed / 180.0 * Math::Constants<double>::pi);
glTranslate(majorAxis+moonOrbitX, minorAxis+moonOrbitY, 0.0);
glRotatef(orbitAngle, 0.0, 1.0, 1.0);
glRotatef(rotationSpeed, 0.0, 0.0, 1.0);
}
void Planet::displayPlanet(double orbitSpeed,double rotationSpeed,
double moonOrbitX, double moonOrbitY)
{
GLuint surf;
Images::RGBImage surfaceImage;
surfaceImage=Images::readImageFile(texture);
glEnable(GL_TEXTURE_2D);
glGenTextures(0, &surf);
glBindTexture(GL_TEXTURE_2D, surf);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
surfaceImage.glTexImage2D(GL_TEXTURE_2D,0,GL_RGB);
glPushMatrix();
setOrbit(orbitSpeed,rotationSpeed, moonOrbitX, moonOrbitY);
drawSolidPlanet(equatRadius, polarRadius, 1, 40, 40);
glPopMatrix();
}
If I'm way off on what I am doing could you point me to a good tutorial? I have read a few but I guess I didn't understand them as I thought I did.
If I'm on track, could you show me where I'm wrong and what I need to do right?
You need to call glLightfv(GL_LIGHT0, GL_POSITION, pos); and set the position of the light source to the center of the sun.