Detecting collisions in Solar System (openGL) - c++

i'm working on a project in wich i need to develop a solar system in openGL, then i need to add a rocket and launch it into another planet detecting the collision.
This is the code where i generate the planet, the rocket and the destination:
GLfloat dirCoheteX1 = 0.0f;
GLfloat dirCoheteY1 = 0.0f;
GLfloat dirCoheteZ1 = 0.0f;
GLfloat posx = 80.0f;
GLfloat posy = 0.0f;
GLfloat posz = 0.0f;
//Planet
glPushMatrix();
//Cambiamos el angulo para que tenga una órbita diferente.
glRotatef(angulo+160,0.0f,1.0f,0.0f);
glTranslatef(70.0f,0.0f,0.0f);
glRotatef(angulo+15,0.0f,1.0f,0.0f);
glRotatef(270,1,0,0);
//Carga de texturas
glBindTexture(GL_TEXTURE_2D,texturaTerra);
GLUquadricObj* q=gluNewQuadric();
gluQuadricDrawStyle(q, GLU_FILL);
gluQuadricNormals(q, GLU_SMOOTH);
gluQuadricOrientation(q, GLU_OUTSIDE);
gluQuadricTexture(q, GL_TRUE);
gluSphere(q,10,20,20);
gluDeleteQuadric(q);
glRotatef(-270,1,0,0);
//rocket
glPushMatrix();
glTranslatef(dirCoheteX1+0.0f,dirCoheteY1+0.0f,dirCoheteZ1+0.0f);
glRotatef(anguloY,0.0f,1.0f,0.0f);
glLineWidth(2.5);
glBegin(GL_LINES);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(15, 0, 0);
glEnd();
glPopMatrix();
//Target
glPushMatrix();
//Cambiamos el angulo para que tenga una órbita diferente.
glRotatef(angulo+240,0.0f,1.0f,0.0f);
glTranslatef(posx,posy,posz);
glRotatef(angulo+15,0.0f,1.0f,0.0f);
glBindTexture(GL_TEXTURE_2D,texturaSaturno);
GLUquadricObj* q5=gluNewQuadric();
gluQuadricDrawStyle(q5, GLU_FILL);
gluQuadricNormals(q5, GLU_SMOOTH);
gluQuadricOrientation(q5, GLU_OUTSIDE);
gluQuadricTexture(q5, GL_TRUE);
gluSphere(q5,5,20,20);
gluDeleteQuadric(q5);
glPushMatrix();
The planets are generated on X axis and they rotate around the Sun on Y axis.
Right now i'm adding the rocket's X position to move it from the planet and rotating it in it's Y axis to head it to the planet, but i don't know how to detect the collision correctly.
I'm using this algorithm:
dirCoheteX1+=0.05f; //move the rocket
anguloY+=0.05f; //rotate the rocket
dx = posx- dirCoheteX1;
dy = posy- dirCoheteY1;
dz = posz- dirCoheteZ1 ;
distance = sqrt(dx*dx + dy*dy + dz*dz);
if (distance < (1.0)) {
contact = true;
}
But the collision is being detected before it actually the rocket reaches the target.

Related

Rotation along a path in opengl

i want to move an object along a path (sine wave), lets suppose object is a roller coaster.
it moves through translate but my problem is that i also want to rotate that object according to the path.
i tried this code before translate but its not working.
if (x = -4.8)
{
glRotatef(89, 1, 1, 0);
}
my code with only translation looks like this.
i want to add rotation here along sine waves
void object()
{ glPushMatrix();
glTranslatef(x, y, 0);
glColor3f(0.0f, 0.0f, 0.0f);//Set drawing color
glBegin(GL_QUADS);
glVertex2f(-0.3, 0.1);
glVertex2f(0.3, 0.1);
glVertex2f(0.3, -0.1);
glVertex2f(-0.3, -0.1);
glEnd();
glFlush();
glPopMatrix();
glFlush();
}
void drawsine()
{
glBegin(GL_LINE_STRIP);//Primitive
glColor3f(255, 0, 0);//Set drawing color
int i = 0;
float x = 0, y = 0;
for (x = -5; x < 6; x = x + 0.1)
{
y = (sin(3.142*x)) / 3.142*x;
glVertex2f(x, y);
//int j= 0;
sinex[i] = x;
siney[i] = y;
i++;
}
glEnd();
glFlush();
}
The angle of rotation depends on the direction vector along the sine wave.
The direction vector can be calculated by the subtraction of 2 positions. Subtract the position before the current position from the positions after the current position, to calcaulte the direction vector. In the following i is the current position of the object:
dx = sinex[i+1] - sinex[i-1];
dy = siney[i+1] - siney[i-1];
The angle of rotation can be calculated by the arcus tangent using atan2, which returns an angle in radians:
float ang_rad = atan2( dy, dx );
Since the angle has to be passed to glRotatef in degrees, the angle has to be converted from radians to degrees, before a rotation around the z axis can be performed.
A full circle in has 360 degrees or 2*Pi radians. So the scale from radians to degrees 180/Pi:
float ang_deg = ang_rad * 180.0f / M_PI;
glRotatef( ang_deg, 0, 0, 1 );
The following cde snippet show how to apply the code. Be aware that there is no bounds check. This means i has to be grater or equal 1 and less than the number of points - 1 (1 <= i < 110):
#define _USE_MATH_DEFINES
#include <math.h>
{
// [...]
drawsine();
x = sinex[i];
y = siney[i];
dx = sinex[i+1] - sinex[i-1];
dy = siney[i+1] - siney[i-1];
object();
// [...]
}
void object()
{
glPushMatrix();
glTranslatef(x, y, 0);
float ang_rad = atan2( dy, dx );
float ang_deg = ang_rad * 180.0f / M_PI;
glRotatef( ang_deg, 0, 0, 1 );
glColor3f(0.0f, 0.0f, 0.0f);
glBegin(GL_QUADS);
glVertex2f(-0.3, 0.1);
glVertex2f(0.3, 0.1);
glVertex2f(0.3, -0.1);
glVertex2f(-0.3, -0.1);
glEnd();
glPopMatrix();
}

How to fix zoom in & out with mouse scroll wheel?

I'm trying to make a program where I'm able to zoom in & out on the figures I've drawn, but is not doing it; it's switching the orientation of the figures and if I keep scrolling, it just disappears. The function that are suppose to be executed for this to work are the MouseFunc() along with the renderScene(). Any explanation for the problem or help is welcomed.
#include"glut.h"
#include<cmath>
#include<iostream>
using namespace std;
float xr = 0, yr = 0; //to control the object's movement from left to right
// XZ position of the camera
float x = 0.0f, z = 5.0f; //Module 4
float angleX = 0.0f; //Module 4
//Shift + ArrowKey rotation
float transX = 0.0f;
float transY = 0.0f;
float rotY = 0.0f;
//end
//Mouse Commands
//float ZoomFactor = 0.5;
GLfloat theta3 = 0;
GLfloat phi = 0;
GLfloat rho = 5;
GLfloat camX = 0;
GLfloat camY = 0;
GLfloat camZ = 0;
GLfloat upX = 0;
GLfloat upY = 0;
GLfloat upZ = 0;
//end
GLfloat angle = 0.0f;
int refreshmill = 1;
void timer(int value) { //to control the rotation of the object
glutTimerFunc(refreshmill, timer, 0);
}
void myDisplay(void) {
//Circle One
float theta;
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1, 0, 0);
glPushMatrix();
glBegin(GL_POLYGON);
for (int x = 0; x < 360; x++) {
theta = x * 3.142 / 180;
glVertex2f(150 * cos(theta) + xr, 150 * sin(theta) + yr);
}
glEnd();
glPopMatrix();
//Circle Two
float theta2;
glPushMatrix();
glTranslatef(0.5f, 0.0f, 0.0f); // rotation
glRotatef(angle, 0.0f, 0.0f, -0.5f); // rotation
glBegin(GL_POLYGON);
glColor3f(0, 0, 1);
for (int x = 0; x < 360; x++) {
theta2 = x * 3.142 / 180;
glVertex2f(150 + 15 * cos(theta2) + xr, 15 * sin(theta2) + yr);
}
angle += 0.2; // rotation
glEnd();
glPopMatrix();
//Draw Star
glColor3ub(119, 193, 15);
glPushMatrix();
glBegin(GL_POLYGON);
glVertex2d(15 + xr, 60 + yr);
glVertex2d(75 + xr, 75 + yr); //right peak
glVertex2d(15 + xr, 90 + yr);
glVertex2d(0 + xr, 150 + yr); //Up-peak Changed
glVertex2d(-15 + xr, 90 + yr);
glVertex2d(-75 + xr, 75 + yr);
glVertex2d(-15 + xr, 60 + yr);
glVertex2d(0 + xr, 0 + yr);
glEnd();
glPopMatrix();
}
//Close code
void handleKeypress(unsigned char key, int x, int y){
switch (key){
case 27: //when the escape key is pressed the program will exit.
exit(0);
}
}
//Movement of drawing
void keyboard(int key, int x, int y) {
float fraction = 0.1f;
bool shift = false;
int mod = glutGetModifiers();
if (mod == GLUT_ACTIVE_SHIFT) {
shift = true;
}
if (!shift) {
switch (key) {
case GLUT_KEY_RIGHT: xr++; break;
case GLUT_KEY_LEFT: xr--; break;
case GLUT_KEY_UP: angleX -= 1.0f; break; //Module 4
case GLUT_KEY_DOWN: angleX += 1.0f; break; //Module 4
}
}
else {
switch (key) {
case GLUT_KEY_LEFT:// Rotación del dibujo hacia la izquierda en el eje de Y
rotY -= 1.0f;
break;
case GLUT_KEY_RIGHT:// Rotación del dibujo hacia la derecha en el eje de Y
rotY += 1.0f;
break;
}
}
}
//Mouse Function
void MouseFunc(int button, int state, int x, int y){
if (button > 4){
rho = rho + 3.0;
}
else (button < 3);{
rho = rho - 3.0;
}
}
void renderScene(void) {
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0, 1.0, 0.0);
glRotatef(rotY, 0.0, 1.0, 0.0); //Rotation with Shift + ArrowKey
GLfloat camX = rho * cos(theta3*3.1415926f / 180)*sin(phi*3.1415926f / 180);
GLfloat camY = rho * sin(theta3*3.1415926f / 180);
GLfloat camZ = rho * cos(theta3*3.1415926f / 180)*cos(phi*3.1415926f / 180);
// Reduce theta slightly to obtain another point on the same longitude line on the sphere.
GLfloat dt = 1;
GLfloat eyeXtemp = -rho * cos((theta3 - dt)*3.1415926f / 180)*sin(phi*3.1415926f / 180);
GLfloat eyeYtemp = -rho * sin((theta3 - dt)*3.1415926f / 180);
GLfloat eyeZtemp = -rho * cos((theta3 - dt)*3.1415926f / 180)*cos(phi*3.1415926f / 180);
// Connect these two points to obtain the camera's up vector.
GLfloat upX = eyeXtemp - camX;
GLfloat upY = eyeYtemp - camY;
GLfloat upZ = eyeZtemp - camZ;
// Clear Color and Depth Buffers
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Reset transformations
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// Set the camera
gluLookAt(camX, camY, camZ, 0, 0, 0, upX, upY, upZ);
gluLookAt(x, 0.0f, z, x, 0.0f, z - 1.0f, 0.0f, 1.0f, 0.0f); //Module 4
glRotatef(angleX, 1, 0, 0); //Module 4
myDisplay();
glFlush();
glutPostRedisplay();
glutSwapBuffers();
}
void init() {
glClearColor(0, 0, 0, 1);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(0.0f, 0.1f, 0.1f, 0.0f);
glOrtho(-250, 250, -250, 250, -250, 250); //IMPORTANT- Define from negative to positive
glMatrixMode(GL_MODELVIEW);
}
int main(int argc, char** argv) {
// init GLUT and create window
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(0, 0);
glutCreateWindow("Homework: Circle");
// register callbacks
glutDisplayFunc(renderScene);
glutTimerFunc(0,timer,0);
glutKeyboardFunc(handleKeypress);
glutSpecialFunc(keyboard);
glutMouseFunc(MouseFunc);
// OpenGL init
init();
// enter GLUT event processing cycle
glutMainLoop();
}
Is wired to set a perspective and an orthographic projection. Delete the perspective projection gluPerspective:
void init() {
glClearColor(0, 0, 0, 1);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//gluPerspective(0.0f, 0.1f, 0.1f, 0.0f); <---- delete
glOrtho(-250, 250, -250, 250, -250, 250);
glMatrixMode(GL_MODELVIEW);
}
If you want to zoom, the the orthographic projection has to be changed (glOrtho). The projection matrix describes the mapping from 3D points of a scene, to 2D points of the viewport.
Implement a mouse wheel event, which changes the zoom, in a restricted range:
e.g.
GLdouble zoom = 0.0f;
void MouseFunc(int button, int state, int x, int y){
GLdouble min_z = -100.0;
GLdouble max_z = 100.0;
if (button == 4 && zoom < max_z) {
zoom += 3.0;
}
else if (button == 3 && zoom > min_z) {
zoom -= 3.0;
}
}
Modify the orthographic projection, dependent on the zoom in the display loop renderScene:
void renderScene(void) {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
GLdouble ortho = 250 + zoom;
glOrtho(-ortho, ortho, -ortho, ortho, -250, 250);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// [...]
}

glutWarpPointer for FP camera issue

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);
}

OpenGL the direction of translation is not right after rotation

I'm writing a simple demo with the fixed pipeline mode in OpenGL
First I write some codes that will draw a rectangle, with top-left point (x1,y1), and buttom-right point (x2,y2)
// Drawing here
glPushMatrix();
// Perform rotation first
glTranslatef(x_cent, y_cent, 0.0f);
glRotatef(angle, 0.0f, 0.0f, 1.0f);
glScalef(scale, scale, 1.0f);
// Set origin back to the screen center with the rotation set above
glTranslatef(-x_cent, -y_cent, 0.0f);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glBegin(GL_QUADS);
{
glVertex2f(x1, y2);
glVertex2f(x2, y2);
glVertex2f(x2, y1);
glVertex2f(x1, y1);
}
glEnd();
// End of drawing
glPopMatrix();
After I tweak the value of the angle with arrow keys, say 45 degrees counter-clockwise, and now the rectangle will rotate 45 degrees counter-clockwise. Then I translate it with arrow keys, it moves in the direction of up, down, left, and right. Everything works fine.
So I write anoter part of code that will draw a general polygon. It's similar to the code above. I simply draw lines between each pair of points
for (int i = 0; i < p_size; i++)
{
float x1 = point[i].x, x2 = point[(i + 1) % p_size].x;
float y1 = point[i].y, y2 = point[(i + 1) % p_size].y;
x1 = ((x1 + 0.5f) / winWidth) * 2.0f - 1.0f;
x2 = ((x2 + 0.5f) / winWidth) * 2.0f - 1.0f;
y1 = ((-y1 + 0.5f) / winHeight) * 2.0f + 1.0f;
y2 = ((-y2 + 0.5f) / winHeight) * 2.0f + 1.0f;
// Set the curent coord origin to this poly's center
float x_cent = (left + right) / 2.0, y_cent = (top + down) / 2.0;
float ratio = winWidth / winHeight;
if (ratio > 1)
{
x1 *= ratio;
x2 *= ratio;
}
else //if (ratio < 1)
{
y1 /= ratio;
y2 /= ratio;
}
// Drawing here
glPushMatrix();
// Perform rotation first
glTranslatef(x_cent, y_cent, 0.0f);
glRotatef(angle, 0.0f, 0.0f, 1.0f);
glScalef(scale, scale, 1.0f);
// Set origin back to the screen center with the rotation set above
glTranslatef(-x_cent, -y_cent, 0.0f);
glBegin(GL_LINES);
{
glVertex2f(x1, y1);
glVertex2f(x2, y2);
}
glEnd();
// End of drawing
glPopMatrix();
}
I rotate the polygon with arrow keys, that works fine, say also 45 degrees counter-clockwise. But after the rotation, when I translate it with up key, it moves not up but in the direction of 45 degrees.
Bbut why can the rectangle translate normally in the 4 directions after rotation? These two part of codes are almost the same, why is this happening...

opengl: rotating an ellipse

I am having trouble rotating an ellipse in OpenGL. So, I have some code to draw an ellipse as follows:
glPushAttrib(GL_CURRENT_BIT);
glColor3f(1.0f, 0.0f, 0.0f);
glLineWidth(2.0);
glPushMatrix();
glTranslatef(0, 0, 0); // ellipse centre
glBegin(GL_LINE_LOOP);
float inc = (float) M_PI / 500.0;
for (GLfloat i = 0; i < M_PI * 2; i+=inc)
{
float x = cos(i) * 0.4;
float y = sin(i) * 0.4;
glVertex2f(x, y);
}
glEnd();
glPopMatrix();
glPopAttrib();
This produces a picture as so:
Now what I want to do is rotate this ellipse clockwise. So I added a glrotate in between but the result was not what I had expected.
So, I did something like:
glPushAttrib(GL_CURRENT_BIT);
glColor3f(1.0f, 0.0f, 0.0f);
glLineWidth(2.0);
glPushMatrix();
glTranslatef(0, 0, 0);
glRotatef(-90, 1, 1, 0);
glBegin(GL_LINE_LOOP);
float inc = (float) M_PI / 500.0;
for (GLfloat i = 0; i < M_PI * 2; i+=inc)
{
float x = cos(i) * 0.4;
float y = sin(i) * 0.4;
glVertex2f(x, y);
}
glEnd();
glPopMatrix();
glPopAttrib();
This produced an image which was simply collapsed. What I wanted to do was rotate the ellipse along its center by the specified degrees. Also, I tried playing around with the various parameters of glRotatef but could not get it do as I expected. The resulting image looks like:
You're working in the XY plane, so you can't really rotate around a vector in XY. Instead, you want to rotate along the unit Z axis (glRotate (angle, 0, 0, 1);). Imagine your screen being the XY coordinate system and the Z axis pointing inwards. What you want is to rotate around the Z axis, so your XY plane remains in the XY plane.