Rotating an isosceles triangle given a certain direction in OpenGL - c++

I'm trying to rotate an isosceles triangle given a certain direction in OpenGL (All this in 2D). For example, if the triangle is moving up, then the triangle must be pointing up, and this has to be applicated in all the directions(down-right side-left side-up right...etc) in the plane.
The question is, how this can be done? I have the dots (x,y) for the translation and the direction that is an angle(not radian). The code is the following.
void Graphics::draw(){
double P[2];
double Direction;
for (int i = 0; i < numBirds; i++)
{
P[0] = flock[i]->Px;
P[1] = flock[i]->Py;
Direction = flock[i]->Dir - 90;
glPushMatrix();
glColor3d(1, 1, 1);
//Operacion para el triangulo
glTranslated(P[0], P[1], 0.0);
glRotated(Direction, 0.0, 0.0, 1.0);
/*
Se mantienen estas proporciones:
Base: 1
Altura: 1.9364916731
Lado (isosceles): 2
*/
glBegin(GL_TRIANGLES); // Inicio del dibujo
glVertex3d(-1.5, 0, 0); // Primer vertice
glVertex3d( 1.5, 0, 0); // Segundo vertice
glVertex3d( 0, 7.9364916731, 0); // Tercer vertice
glEnd(); // Fin del dibujo
// Deshago las operaciones de rotacion y translacion
glRotated(-Direction, 0, 0, 1);
glTranslated(-P[0], -P[1], 0.0);
glPopMatrix();
//cout << "Velocidad pajaro "<< i <<" Graph x: "<<flock[i]->Vx << " Velocidad pajaro Graph Y:"<< flock[i]->Vy<<endl;
//flock[i]->Py
physics.updatePosition(flock, flock[i]);
//cout << "Velocidad update pajaro "<< i <<" Graph x: "<<flock[i]->Vx << " Velocidad pajaro Graph Y:"<< flock[i]->Vy<<endl;
}
}
In this version of the code, the triangles are moving in a certain direction(x,y), but the triangle is not pointing(isosceles triangles can point with one vertex) to/toward(?) that dir
ection.

Related

Cannot draw my model twice in OpenGL?

I want to draw a model of a chair that I exported from 3ds max as a txt file. I read the file and display it in OpenGL (using Visual Studio -> C++). My problem is that I have to multiplicate the chair many times (10). I did try to multiplicate it twice but it does not work. The program crashes with these "Program is not responding" Windows errors. I have a main class that calls all of the nessessery methods from CDrawModel like that:
CDrawModel mModel;
int main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB);
glutInitWindowSize( 1000, 600 );
glutInitWindowPosition(100, 100);
glutCreateWindow("Georgi Koemdzhiev - 1306794");
glutKeyboardFunc(KeyResponse);
glutDisplayFunc(DrawGLScene);
glutReshapeFunc(ReSizeGLScene);
mModel.initGL();
glutMainLoop();
}
void DrawGLScene(void) {
mModel.myDrawGLScene();
}
GLvoid ReSizeGLScene(GLsizei fwidth, GLsizei fheight) {
mModel.MyReSizeGLScene(fwidth, fheight);
}
CDrawModal initialises an object of type CPolygonMesh which handles the reading from the file and drawing on the screen functionality. I know my code works since I am getting my modal drawn on the screen:
this is my CDrawModal class:
oid CDrawModel::initGL(void) {
glClearColor(1.0, 1.0, 1.0, 1.0);
near = 1.0;
far = 1000.0;
height = 1.5;
glCullFace(GL_BACK); // don’t draw back facing faces
glEnable(GL_CULL_FACE); // enable face culling
glPolygonMode(GL_FRONT, GL_LINE); // select front polygons and draw edges only
}
void CDrawModel::MyReSizeGLScene(int fwidth, int fheight) // Resize And Initialize The GL Window{
// Store window size so it can be accessed in myDrawGLScene()
wWidth = fwidth;
wHeight = fheight;
// Set fovy so that the viewing frustum has the specified height at the
// near clipping plane
fovy = (360 / PI) * atan(height / (2.0 * near));
// Calculate the aspect ratio of the VIEWPORT
// so that we can set the camera’s aspect ratio to the same value
aspect_ratio = (double)fwidth / (double)fheight;
glMatrixMode(GL_PROJECTION); // Select The Projection Stack
glLoadIdentity();
/* void glOrtho( GLdouble left,
GLdouble right,
GLdouble bottom,
GLdouble top,
GLdouble nearVal,
GLdouble farVal);*/
gluPerspective(90, aspect_ratio, near, far); // perspective view
//glOrtho(-130.0,130.0,-130.0,130.0,near,far);
glViewport(0, 0, wWidth, wHeight); // Viewport fills the window
// Print values of parameters
cout << fixed; // Use fixed-point notation
cout.precision(3); // Number of digits after the decimal point
cout << "fovy = " << fovy << endl;
cout << "aspect_ratio = " << aspect_ratio << endl;
cout << "near = " << near << endl;
cout << "far = " << far << endl;
}
void CDrawModel::myDrawGLScene(GLvoid) // Here's Where We Do All The Drawing
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the drawing area
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, -200);
mesh.draw_model();
glutSwapBuffers(); // Needed if we're running an animation
glFlush();
}
What I need to do in order to draw it twice.This is my drawModal method in CPolugonMesh:
void CPolygonMesh::draw_model(void){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.0, 0.0, 0.0); // draw red things
glBegin(GL_TRIANGLES);
for (int i = 0; i < Mesh_NumFaces; i++) {
// Look up the coordinates of each vertex
// in vertex_list[]
glVertex3fv(vertex_list[ face_list[i][0] ]);
glVertex3fv(vertex_list[ face_list[i][1] ]);
glVertex3fv(vertex_list[ face_list[i][2] ]);
//cout << "Drawing face: " << i << endl;
}
glEnd();
}
Your CPolygonMesh::draw_model(void) method actually clears the screen each time you draw a model, so only the last call will leave anything on the screen.
The line
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
is totally wrong there. You already do clear the screen at the beginning of your frame.

Translating triangles with OpenGL and uC++

I'm struggling with a triangle translation in OpenGL and using uC++. Every bird (triangle) is a thread. The thing is that when the birds are translating, the camera or general image is moving up or down.
The draw code is this one:
void Graphics::draw(){
double AxisX;
double AxisY;
double Direction;
for (int i = 0; i < numBirds; i++)
{
AxisX = birds[i]->Px;
AxisY = birds[i]->Py;
Direction = birds[i]->Dir - 90;
glColor3d(1, 1, 1);
//Operacion para el triangulo
glTranslated(AxisX, AxisY, 0.0f);
glRotated(Direction, 0, 0, 1);
/*
Se mantienen estas proporciones:
Base: 1
Altura: 1.9364916731
Lado (isosceles): 2
*/
glBegin(GL_TRIANGLES); // Inicio del dibujo
glVertex3d(-5, 0, 0); // Primer vertice
glVertex3d( 5, 0, 0); // Segundo vertice
glVertex3d( 0, 15, 0); // Tercer vertice
glEnd(); // Fin del dibujo
// Deshago las operaciones de rotacion y translacion
glRotated(-Direction, 0, 0, 1);
glTranslated(-AxisX, -AxisY, 0.0f);
}
}
The question is, how can I fix this? I've been struggling for hours getting nothing.

Detecting collisions in Solar System (openGL)

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.

How to move an object around a 3D environment in the direction it is facing in C++

I am trying to move a pyramid around in opengl in C++ and I am trying to get it to move forward in the direction it is facing. However, I cannot seem to figure out how to do this. This is my code for drawing my pyramid:
void drawTriangle()
{
//back
glBegin(GL_POLYGON);
glColor3f(1,0,0);
glVertex3f(-1,-1,-1);
glVertex3f(1,-1,-1);
glVertex3f(0,1,0);
glEnd();
//front
glBegin(GL_POLYGON);
glColor3f(0,1,0);
glVertex3f(-1,-1,1);
glVertex3f(1,-1,1);
glVertex3f(0,1,0);
glEnd();
//right
glBegin(GL_POLYGON);
glColor3f(0,0,1);
glVertex3f(1,-1,-1);
glVertex3f(1,-1,1);
glVertex3f(0,1,0);
glEnd();
//left
glBegin(GL_POLYGON);
glColor3f(1,1,0);
glVertex3f(-1,-1,-1);
glVertex3f(-1,-1,1);
glVertex3f(0,1,0);
glEnd();
//bottom
glBegin(GL_POLYGON);
glColor3f(1,0,1);
glVertex3f(-1,-1,-1);
glVertex3f(1,-1,-1);
glVertex3f(1,-1,1);
glVertex3f(-1,-1,1);
glEnd();
}
This is how the pyramid is drawn to the screen:
glPushMatrix();
glTranslatef(Xtri,0,Ztri);
glRotatef(heading,0,1,0);
drawTriangle();
glPopMatrix();
glFlush();
And here is how the variables are updated so that the pyramid could move around :
void processKeys()
{
if(keys[VK_LEFT])
{
heading-=1.0f;
}
if(keys[VK_RIGHT])
{
heading+=1.0f;
}
if(keys[VK_UP])
{
Vtri-=0.001f;
}
if(keys[VK_DOWN])
{
Vtri+=0.001f;
}
}
void update()
{
Xtri += Vtri*cos((90+heading)*(PI/180.0f));
Ztri += Vtri*sin((90+heading)*(PI/180.0f));
}
I am trying to get the pyramid to move forward so that the red or back face is the face that I want to be the direction that the pyramid moves in but when I use this code it doesn't work that way at all and it moves in a very funny way.
Here's one way you can do it. It's based on Direct3D, but I assume it should be very similar for OpenGL.
Have two vectors for your pyramid: one containing its position and another one containing its rotation. Initially both initialized to 0,0,0. Also have a direction vector initially facing in the direction your object does (e.g. 1,0,0) and speed, again set to 0.
Upon pressing a or d adjust the y element of the rotation vector to a desired angle. Similarly upon pressing w or s adjust the speed of your object. You probably want to take frame rendering time into account to make the movement fps independent.
Then create a rotation matrix around Y axis, like you do. Use that matrix to create new normalized vector by multiplying it with the initial position vector. Then add this vector multiplied by speed to your position coordinates and use these coordinates for translation matrix.
Hope it makes sense. Here's some pseudo-code:
// in constructor:
x = y = z = 0.0f; // position
ry = 0.0f; // rotation
speed = 0.0f;
initVec(1,0,0); // initial direction vector
// in event handler:
// upon key press adjust speed and/or ry
// in move():
// create rotation matrix around Y axis by ry = rotationMatrix
// use it to find new direction vector
newDirectionVector = initVec * rotationMatrix;
// adjust your position
x += newDirectionVector * speed;
y += newDirectionVector * speed;
z += newDirectionVector * speed;
glTranslatef(x, y, z);
// render
I came across this when searching for ideas for a similar problem, and decided to share my solution:
For a triangle with 1 unit base, and 2 units height, on y = 0.3 = pos[2]
void triangle::draw() {
glPushMatrix();
//pos[0] is the x value initialized to 0
//pos[2] is the z value initialized to 0
glTranslatef(pos[0], 0, pos[2]);
glRotatef(direction, 0, 1, 0);
glBegin(GL_TRIANGLES);
glVertex3f(.5, pos[1], 0);
glVertex3f(-.5, pos[1], 0);
glVertex3f(0, pos[1], 2);
glEnd();
glPopMatrix();
}
//called when key w is pressed
void triangle::forward() {
// convert degrees to rads and multiply (I used 0.5)
pos[0] += sin(M_PI * direction / 180) * .5;
pos[2] += cos(M_PI * direction / 180) * .5;
std::cout << pos[0] << "," << pos[2] << std::endl;
}
//called when key s is pressed
void triangle::back() {
pos[0] -= sin(M_PI * direction / 180) * .5;
pos[2] -= cos(M_PI * direction / 180) * .5;
std::cout << pos[0] << "," << pos[2] << std::endl;
}
//called when key d is pressed
void triangle::right() {
direction -= 5;
//direction is the angle (int)
//this is probably not needed but, if you keep turning in the same direction
//an overflow is not going to happen
if (direction <= 360)direction %= 360;
std::cout << direction << std::endl;
}
//called when key a is pressed
void triangle::left() {
direction += 5;
if (direction >= -360)direction %= 360;
std::cout << direction << std::endl;
}
Hope I was of help, for someone facing similar problems bumping into this.
You need to do rotations before translations, assuming your object is at the origin to begin with (if I recall my math correctly). I believe the rotation matrix applied rotates around the axis (0, 1, 0), if you've already translated to a new location, that rotation will affect your position as well as direction you are facing.

How does gluLookAt work?

From my understanding,
gluLookAt(
eye_x, eye_y, eye_z,
center_x, center_y, center_z,
up_x, up_y, up_z
);
is equivalent to:
glRotatef(B, 0.0, 0.0, 1.0);
glRotatef(A, wx, wy, wz);
glTranslatef(-eye_x, -eye_y, -eye_z);
But when I print out the ModelView matrix, the call to glTranslatef() doesn't seem to work properly. Here is the code snippet:
#include <stdlib.h>
#include <stdio.h>
#include <GL/glut.h>
#include <iomanip>
#include <iostream>
#include <string>
using namespace std;
static const int Rx = 0;
static const int Ry = 1;
static const int Rz = 2;
static const int Ux = 4;
static const int Uy = 5;
static const int Uz = 6;
static const int Ax = 8;
static const int Ay = 9;
static const int Az = 10;
static const int Tx = 12;
static const int Ty = 13;
static const int Tz = 14;
void init() {
glClearColor(0.0, 0.0, 0.0, 0.0);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
GLfloat lmodel_ambient[] = { 0.8, 0.0, 0.0, 0.0 };
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
}
void displayModelviewMatrix(float MV[16]) {
int SPACING = 12;
cout << left;
cout << "\tMODELVIEW MATRIX\n";
cout << "--------------------------------------------------" << endl;
cout << setw(SPACING) << "R" << setw(SPACING) << "U" << setw(SPACING) << "A" << setw(SPACING) << "T" << endl;
cout << "--------------------------------------------------" << endl;
cout << setw(SPACING) << MV[Rx] << setw(SPACING) << MV[Ux] << setw(SPACING) << MV[Ax] << setw(SPACING) << MV[Tx] << endl;
cout << setw(SPACING) << MV[Ry] << setw(SPACING) << MV[Uy] << setw(SPACING) << MV[Ay] << setw(SPACING) << MV[Ty] << endl;
cout << setw(SPACING) << MV[Rz] << setw(SPACING) << MV[Uz] << setw(SPACING) << MV[Az] << setw(SPACING) << MV[Tz] << endl;
cout << setw(SPACING) << MV[3] << setw(SPACING) << MV[7] << setw(SPACING) << MV[11] << setw(SPACING) << MV[15] << endl;
cout << "--------------------------------------------------" << endl;
cout << endl;
}
void reshape(int w, int h) {
float ratio = static_cast<float>(w)/h;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, ratio, 1.0, 425.0);
}
void draw() {
float m[16];
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glGetFloatv(GL_MODELVIEW_MATRIX, m);
gluLookAt(
300.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f
);
glColor3f(1.0, 0.0, 0.0);
glutSolidCube(100.0);
glGetFloatv(GL_MODELVIEW_MATRIX, m);
displayModelviewMatrix(m);
glutSwapBuffers();
}
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(400, 400);
glutInitWindowPosition(100, 100);
glutCreateWindow("Demo");
glutReshapeFunc(reshape);
glutDisplayFunc(draw);
init();
glutMainLoop();
return 0;
}
No matter what value I use for the eye vector:
300, 0, 0 or
0, 300, 0 or
0, 0, 300
the translation vector is the same, which doesn't make any sense because the order of code is in backward order so glTranslatef should run first, then the 2 rotations. Plus, the rotation matrix, is completely independent of the translation column (in the ModelView matrix), then what would cause this weird behavior?
Here is the output with the eye vector is (0.0f, 300.0f, 0.0f)
MODELVIEW MATRIX
--------------------------------------------------
R U A T
--------------------------------------------------
0 0 0 0
0 0 0 0
0 1 0 -300
0 0 0 1
--------------------------------------------------
I would expect the T column to be (0, -300, 0)! So could anyone help me explain this?
The implementation of gluLookAt from http://www.mesa3d.org
void GLAPIENTRY
gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez, GLdouble centerx,
GLdouble centery, GLdouble centerz, GLdouble upx, GLdouble upy,
GLdouble upz)
{
float forward[3], side[3], up[3];
GLfloat m[4][4];
forward[0] = centerx - eyex;
forward[1] = centery - eyey;
forward[2] = centerz - eyez;
up[0] = upx;
up[1] = upy;
up[2] = upz;
normalize(forward);
/* Side = forward x up */
cross(forward, up, side);
normalize(side);
/* Recompute up as: up = side x forward */
cross(side, forward, up);
__gluMakeIdentityf(&m[0][0]);
m[0][0] = side[0];
m[1][0] = side[1];
m[2][0] = side[2];
m[0][1] = up[0];
m[1][1] = up[1];
m[2][1] = up[2];
m[0][2] = -forward[0];
m[1][2] = -forward[1];
m[2][2] = -forward[2];
glMultMatrixf(&m[0][0]);
glTranslated(-eyex, -eyey, -eyez);
}
If we let a rotation and translation matrix like your modelview matrix
Rxx Rxy Rxz Tx
Ryx Ryy Ryz Ty
Rzx Rzy Rzz Tz
0 0 0 1
act on an arbitrary vector
x
y
z
1
we get
Rxx x + Rxy y + Rxz z + Tx
Ryx x + Ryy y + Ryz z + Ty
Rzx x + Rzy y + Rzz z + Tz
1
(I'm writing things so vectors get multiplied by matrices on the left).
This shows that the translation components of the matrix give the translation to apply after doing the rotation. That's why they aren't the same as your (-eye_x, -eye_y, -eye_z) vector, because as you point out that translation is being done before the rotation.
The reason that the translation is always along the -z direction is because in the view frame the -z direction points towards the centre. Since you always have the centre 300 units from the eye, all of your eye positions put the centre at (0, 0, -300) in the view frame. Therefore, because the centre starts at the origin before we do any translating, the translation to give it the correct co-orindates must be (0, 0, -300).
Also, you might have noticed this, but the modelview matrix you show is pathological because you have the up vector pointing along the view direction (from eye to centre). That explains why it has two full rows of zeros.
" I'm very confused about how the rotations are performed using the forward, up and side vectors in this code..."
I think you should know something about "UVN camera".There is some theory about coordinates translates between two coordinate systems.In the above examle, the two coordinates are world coordinates and camera coordinates.
And the result is:
x
N - The vector from the target to camera. Also known as the 'look at' vector in some 3D literature. This vector corresponds to the -Z axe.
V - When standing upright this is the vector from your head to the sky. If you are writing a flight simulator and the plane is reversed that vector may very well point to the ground. This vector corresponds to the Y axe.
U - This vector points from the camera to its "right" side". It corresponds to the X axe.
#Andon M. Coleman - how is the above diagram row major?
Having a Row or Column major matrix is about the memory representation of 2D structures in 1D memory and has nothing to do with the above diagram of a 4x4 transformation matrix.
If vectors U,V,N were written as columns as you seem to suggest, then you would have a camera-space to world-space transformation.
However, the input to the matrix is world-space position and the output is camera-space position and so the matrix is a transformation world-space to camera-space.
The reason U,V,N are transposed is because this is the inverse of the matrix you suggest and by using the property of orthogonal matrices, where their inverse is also its transpose. That is, we write U,V,N vectors to the rows to get a world-space to camera-space transformation and U,V,N to the columns to get camera-space to world-space transform.
Also, the choice of multiplying with the world position on the right is because the diagram is using column vectors. We would left multiply if we were using row vectors. It has NOTHING to do with how we store the matrix in memory and has everything to do with how we multiply two matrices together, that is, do we convert our vector to a 1X4 or a 4X1 matrix before we multiply it with the 4x4 matrix.
In short, the above diagram is fine, it's just a transformation from one space to another, please don't confuse the matter with talk about memory layout which is a programming detail.