Я пытаюсь переместить пирамиду в opengl в C ++, и я пытаюсь заставить ее двигаться вперед в том направлении, в котором она стоит. Тем не менее, я не могу понять, как это сделать. Это мой код для рисования моей пирамиды:
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();
}
Вот как пирамида рисуется на экране:
glPushMatrix();
glTranslatef(Xtri,0,Ztri);
glRotatef(heading,0,1,0);
drawTriangle();
glPopMatrix();
glFlush();
А вот как переменные обновляются, чтобы пирамида могла двигаться:
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));
}
Я пытаюсь заставить пирамиду двигаться вперед, чтобы красная или задняя поверхность была лицом, которым я хочу быть в направлении, в котором движется пирамида, но когда я использую этот код, он вообще не работает таким образом, и он движется очень забавным образом.
Вот один из способов, которым вы можете сделать это. Он основан на Direct3D, но я предполагаю, что он должен быть очень похож на OpenGL.
У вашей пирамиды есть два вектора: один содержит ее положение, а другой — ее вращение. Первоначально оба инициализированы до 0,0,0. Также имейте вектор направления, первоначально обращенный в направлении, в котором движется ваш объект (например, 1,0,0), и скорость, снова равную 0.
При нажатии a или d отрегулируйте элемент y вектора поворота на нужный угол. Аналогично, нажимая w или s, отрегулируйте скорость вашего объекта. Вы, вероятно, хотите принять во внимание время рендеринга кадров, чтобы сделать движение fps независимым.
Затем создайте матрицу вращения вокруг оси Y, как вы делаете. Используйте эту матрицу, чтобы создать новый нормализованный вектор, умножив его на начальный вектор положения. Затем добавьте этот вектор, умноженный на скорость, к вашим координатам положения и используйте эти координаты для матрицы перевода.
Надеюсь, это имеет смысл. Вот некоторый псевдокод:
// 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
Я столкнулся с этим, когда искал идеи для подобной проблемы, и решил поделиться своим решением:
Для треугольника с основанием 1 единица и высотой 2 единицы на 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;
}
Надеюсь, что я помог, для кого-то сталкивающихся с подобными проблемами, сталкивающимися с этим.
Вы должны сделать повороты перед переводом, предполагая, что ваш объект находится в начале координат (если я правильно помню свою математику). Я полагаю, что примененная матрица вращения вращается вокруг оси (0, 1, 0), если вы уже перевели на новое место, это вращение повлияет на ваше положение, а также направление, в котором вы находитесь.