Обработка OpenGL +: вращаться и двигаться в зависимости от направления - PullRequest
2 голосов
/ 21 ноября 2010

Я пытаюсь повернуть и переместить треугольник в определенном направлении, основываясь на направлении наведения треугольника. Теоретически я вычисляю синус и косинус направления (0-360 градусов) и добавляю эти значения в x- и y-позицию, верно? Это просто не работает.

Кроме того, треугольник должен указывать вверх, а не вниз.

public void speedUp() {
  float dirX, dirY;
  speed *= acceleration;
  if(speed > 50) speed = 50;
  println("dir: " + direction + " x: " + cos(direction) + " y: " + sin(direction));
  dirX = cos(direction);
  dirY = sin(direction);
  xPos+=dirX;
  yPos+=dirY;
}

public void redraw() {
  GL gl = pgl.beginGL();  // always use the GL object returned by beginGL
  gl.glTranslatef(xPos, yPos, 0);
  gl.glRotatef(direction, 0, 0, 1000);

  gl.glBegin(GL.GL_TRIANGLES);
  gl.glColor4f(0.1, 0.9, 0.7, 0.8);
  gl.glVertex3f(-10, -10, 0);    // lower left vertex
  gl.glVertex3f( 10, -10, 0);    // lower right vertex
  gl.glVertex3f( 0,  15, 0);    // upper vertex
  gl.glEnd();
}

Ответы [ 4 ]

5 голосов
/ 21 ноября 2010

Похоже, вам нужно преобразовать полярные координаты (перемещаясь с использованием угла и радиуса) в декартовы (перемещаясь с использованием x и y).

Формула выглядит примерно так:

x = cos(angle) * radius;
y = sin(angle) * radius;

Итак, как упоминает @Lie Ryan, вам также нужно умножаться со скоростью (которая является вашим радиусом в полярных координатах).

Либо укажите свой угол в градусах, но используйте радианы () при использовании cos, sin при работе с радианами, либо используйте радианы и используйте градусов () с glRotatef , до вас

Кроме того, вы можете взглянуть на glPushMatrix () и glPopMatrix (). По сути, они позволяют вам вкладывать преобразования. Какие бы преобразования вы ни делали с блоками, они влияют только на этот блок локально.

Вот что я имею в виду, используйте клавиши w, a, s, d:

import processing.opengl.*;
import javax.media.opengl.*;

float direction = 0;//angle in degrees
float speed = 0;//radius
float xPos,yPos;

void setup() {
  size(600, 500, OPENGL);
}

void keyPressed(){
  if(key == 'w') speed += 1;
  if(key == 'a') direction -= 10;
  if(key == 'd') direction += 10;
  if(key == 's') speed -= 1;
  if(speed > 10) speed = 10;
  if(speed < 0) speed = 0;
  println("direction: " + direction + " speed: " + speed);
}

void draw() {
  //update
  xPos += cos(radians(direction)) * speed;
  yPos += sin(radians(direction)) * speed;
  //draw
  background(255);
  PGraphicsOpenGL pgl = (PGraphicsOpenGL) g; 
  GL gl = pgl.beginGL();
  gl.glTranslatef(width * .5,height * .5,0);//start from center, not top left

  gl.glPushMatrix();
  {//enter local/relative
    gl.glTranslatef(xPos,yPos,0);
    gl.glRotatef(direction-90,0,0,1);
    gl.glColor3f(.75, 0, 0);
    gl.glBegin(GL.GL_TRIANGLES);
    gl.glVertex2i(0, 10);
    gl.glVertex2i(-10, -10);
    gl.glVertex2i(10, -10);
    gl.glEnd();
  }//exit local, back to global/absolute coords
  gl.glPopMatrix();

  pgl.endGL();
}

На самом деле вам не нужны {} для вызовов матрицы push и pop, я добавил их как наглядное пособие. Кроме того, вы можете сделать это без push / pop, объединяя ваши преобразования, но удобно знать, что они есть, когда они вам нужны. Может пригодиться, если вы хотите выстрелить несколько GL_LINES из этого треугольника ... пиу пиу пиу!

НТН

5 голосов
/ 21 ноября 2010

У вас все испорчено. glRotatef исключает градусы , а тригонометрические функции ожидают радиан . Это самая очевидная ошибка.


Кроме того, speed никогда не используется в вашем фрагменте. Я предполагаю, что каждый кадр, который вы используете, каким-то образом, но в вставленном вами коде есть:

xPos+=dirX

Что по сути означает «добавить направление к позиции» - не имеет особого смысла, если только вы не хотите «переместить его ровно на 1 единицу в заданном направлении мгновенно в момент, когда speedUp() называется . Обычный подход для непрерывного движения заключается в следующем:

// each frame:
xPos += dirX * speed * deltaTime;
yPos += dirY * speed * deltaTime;
3 голосов
/ 21 ноября 2010

Попробуйте это:

dirX = speed * cos(direction);
dirY = speed * sin(direction);
3 голосов
/ 21 ноября 2010

Вы, очевидно, новичок в OpenGl, поэтому я бы порекомендовал вам, чтобы вы посмотрели в кватернионы, чтобы сделать ваши вращения. Вот две довольно хороших статьи на эту тему: Gamedev и Nehe . Я бы порекомендовал вам использовать класс Quaternion из JMonkeyEngine. Просто удалите сохраняемый и некоторые другие интерфейсы, и вы можете использовать их с легкостью. Здесь они расположены: JMonkey Source

Я также использую математические классы JME для своих собственных проектов. Я уже вычеркнул большинство зависимостей, и вы можете скачать некоторые классы отсюда: Volume Shadow . Однако класс Quaternion отсутствует, но вам понадобится Vector3f: D.

...