Reputation: 35
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.
Upvotes: 1
Views: 8634
Reputation:
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.
Upvotes: 2
Reputation: 5002
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
Upvotes: 2
Reputation: 4752
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.
Upvotes: 0