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
Related
Ship Asteroid primitive:
just draw a Ship for Asteroid game but cant move and rotate ship correctly
Problem: Cant find how use the Angle variable to rotate ship by center correctly;
Problem: Cant find how use angle with position to got correct direction to move ship
Look my code and if possible help me:
typedef struct {float x; float y; float z; float angle;} point2D;
class player //player class is ship
{
protected:
public:
point2D position, angle;
player()
{
position.x = 0.0;
position.y = 0.0;
angle.z = 0.0;
}
void set_position(float x, float y) //Set position of player
{
position.x=x;
position.y=y;
}
void draw_ship()
{
glPushMatrix();
glTranslatef(position.x,position.y,0);
glRotatef(angle.z, 0.,0.,0.1);
glScalef(0.10,0.075,0.10);
glBegin(GL_LINE_LOOP);
glColor3ub(redc, greenc, bluec);
glVertex2f( 1.0f, 2.0f);
glVertex2f( 1.4f, 0.4f);
glVertex2f( 1.2f, 0.6f);
glVertex2f( 0.8f, 0.6f);
glVertex2f( 0.6f, 0.4f);
glEnd();
glPopMatrix();
}
};
player ship;
void display() {
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set background color to black and opaque
glClear(GL_COLOR_BUFFER_BIT);// Clear the color buffer (background
glEnable( GL_TEXTURE_2D );
background();
gluLookAt (0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
glDisable( GL_TEXTURE_2D );
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
ship.draw_ship();
glutSwapBuffers(); // Double buffered - swap the front and back buffers
}
* Callback handler for special-key event */
void specialKeys(int key, int x, int y) {
switch (key) {
case GLUT_KEY_RIGHT:
ship.angle.z -= 10.0f;
break;
case GLUT_KEY_LEFT:
ship.angle.z += 10.0f;
break;
case GLUT_KEY_UP:
ship.position.x = ship.position.x + sin(ship.angle.z) * 0.02;
ship.position.y = ship.position.y + cos(ship.angle.z) * 0.02;
printf("posx is: %f", ship.position.x);
printf("posy is: %f", ship.position.y);
break;
}
}
You problem is that glRotate is always rotating around (0,0,0) ... so to make your transform right first rotate identity and then translate. But there is a slight problem because glTranslate will use local coordinates and you need global ... luckily you can set the matrix origin directly. As the comments where not enough for you here how it would look like:
glMatrixMode(GL_MODELVIEW);
glLoadIdentity(); // unit matrix
glRotatef(angle.z,0.0,0.0,1.0); // rotate around (0,0,0) and z axis
double m[16];
glGetDoublev(GL_MODELVIEW_MATRIX,m);// get actual matrix into CPU side memory/code
m[12]=position.x; // change the global position
m[13]=position.y;
m[14]=0.0;
glLoadMatrix(m); // update GL matrix with the changed one
glScalef(0.10,0.075,0.10); // scale ship
In case your position is in already scaled coordiantes then the scale will go directly after the rotate.
Beware I wrote this directly in answer editor so there might be minor syntax errors ...
btw you can use the m also for movement in ship direction m[0,1,2] is x axis direction and m[4,5,6] is y axis. not sure in which your ship model points. You just add this forward vector multiplied by speed/deltatime to your position in some timer.
For more info about matrices see: Understanding 4x4 homogenous transform matrices
I am working on a project for mouse control to look around. I have been successful with rotating the camera using the mouse however I am trying to get the mouse to do 360 turns without the mouse leaving the screen before it can fully rotate. I read around and came across glutWarpPointer(), where most posts said to use it after getting the difference between the centre and the new mouse position in the window.
The issue this causes with my program is that when I move the mouse it will rotate very slightly for that frame the restart the location to the original point. Basically it i have a blue ball in front of me and green behind when i try to rotate towards the green ball the camera will move slightly but stay locked on the blue ball.
Is there a way to around or a fix?
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//rotate and translating the camera
glRotatef(-camVert, 1.0, 0.0, 0.0);
glRotatef(-camHor, 0.0, 1.0, 0.0);
glTranslatef(-posx,-posy,-posz);
//blue and green ball
glPushMatrix();
glColor3f(0.0, 1.0, 0.0);
glTranslatef(1, 0, 25);
glutSolidSphere(5, 20, 20);
glPopMatrix();
glPushMatrix();
glColor3f(0.0,0.0,1.0);
glTranslatef(0, 0, -25);
glutSolidSphere(5, 20, 20);
glPopMatrix();
};
void setAngle(float angy, float angx)
{
camVert = angy*1.5;
if (camVert > 90)
camVert = 90;
else if (camVert < -90)
camVert = -90;
camHor = angx*0.5;
}
void MoveCam(float distance, float direction)
{
float rads = (camHor+direction)*PI / 180;
posx -= sin(rads)*distance;
posz -= cos(rads)*distance;
};
void mouseMove(int x, int y)
{
float diffx = midx - x;
float diffy = midy - y;
setAngle(diffy,diffx);
//glutWarpPointer(glutGet(GLUT_WINDOW_WIDTH) / 2, glutGet(GLUT_WINDOW_HEIGHT) / 2);
}
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 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.
I draw a solid sphere like the followings:
glPushMatrix();
glScalef(0.015, 0.015, 0.015);
glRotatef(90, 1.0, 0.0, 0.0);
glTranslatef(0.0, 200, 0.0);
glRotatef(-20, 0.0, 0.0, 1.0);
glRotatef(-20, 1.0, 0.0, 0.0);
glTranslatef(78.75, -110.74, -13.53);
glutSolidSphere(4.0f,15,15);
glPopMatrix();
How can I get the transformed coordinates of this solid sphere?
You can get the state variables GL_MODELVIEW_MATRIX by the function glget.
It returns the current matrix from ModelView stack. I think that is what you need.
Put the translated coordinates in variables, then you won't have to retrieve the transformed coordinates of the shape.
float solidSphereX = whatever;
float solidSphereY = whatever;
float solidSphereZ = whatever;
float solidSphereRotationX = whatever in radians;
float solidSphereRotationY = whatever in radians;
float solidSphereRotationZ = whatever in radians;
...
glPushMatrix();
glRotatef(solidSphereRotationX, solidSphereRotationY, solidSphereRotationZ);
glTranslatef(solidSphereX, solidSphereY, solidSphereZ);
glPopMatrix();