Должен ли я сначала перевести или повернуть первым? - PullRequest
2 голосов
/ 03 апреля 2012

Я пытаюсь создать простую сцену, где я могу ходить, с критериями, чтобы можно было перемещаться и ходить с ключами.Однако в моей функции рисования сцены, когда я перевожу свою сцену, а не поворачиваю, панорамирование не работает должным образом, так как вся сцена просто вращается вокруг меня, заставляя объекты проходить сквозь меня.Когда я вращаюсь, а не перевожу свою сцену, я могу правильно перемещаться, однако я могу двигаться только в определенном направлении, поэтому, если я поверну вправо на 90 градусов, я буду двигаться влево, а не идти вперед.Есть ли способ объединить эти два эффекта?

Это код, который я использую для рисования моего вида:


glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glPushMatrix();

glTranslated(xposition, 0, zposition); //This is where I translate my views
glRotated(yrot, 0, 1, 0); //

glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER_ARB, quadVBO);

glNormalPointer(GL_FLOAT, 0, (void*)sizeof(sideArray));
glColorPointer(3, GL_FLOAT, 0, (void*)sizeof(sideArray)+sizeof(normals));
glVertexPointer(3, GL_FLOAT, 0, 0);

glDrawArrays(GL_QUADS, 0, sizeof(sideArray)/sizeof(GLfloat)/3);

glPopMatrix();
glFlush();
glDisableClientState(GL_VERTEX_ARRAY);  
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);

Вот несколько картинок, которые иллюстрируют мою проблему прямо сейчас:

Поверните, а затем переведите:

Pic1

http://dl.dropbox.com/u/2747708/Screen%20Shot%202012-04-03%20at%2010.17.39%20PM.PNG

Pic2

Я могу имитировать поворот камеры

http://dl.dropbox.com/u/2747708/Screen%20Shot%202012-04-03%20at%2010.17.48%20PM.PNG

Pic3

Однако, когда я иду вперед, он идет только в одном направлении, а не в том направлении, на которое я смотрю.

http://dl.dropbox.com/u/2747708/Screen%20Shot%202012-04-03%20at%2010.18.30%20PM.PNG

http://dl.dropbox.com/u/2747708/Screen%20Shot%202012-04-03%20at%2010.18.39%20PM.PNG

Перевести, затем повернуть:

Pic1

http://dl.dropbox.com/u/2747708/Screen%20Shot%202012-04-03%20at%2010.19.44%20PM.PNG

Pic2

Я могу свободно перемещаться, идя прямо в любом направлении.Я смотрю.

http://dl.dropbox.com/u/2747708/Screen%20Shot%202012-04-03%20at%2010.19.52%20PM.PNG

Pic3

Однако, когда я поворачиваю сцену, вращается вся вещь, которая заставляет объекты проходить сквозь меня и не 't "панорамирование" больше, как когда я поворачиваюсь, затем переводит мой взгляд.

http://dl.dropbox.com/u/2747708/Screen%20Shot%202012-04-03%20at%2010.20.01%20PM.PNG

Ответы [ 2 ]

3 голосов
/ 03 апреля 2012

Ваша проблема не в порядке преобразований. Вы должны вращаться, а затем переводить.

Проблема в том, что вы не учитываете вращение при движении. Формула для движения:

movementX = sin(direction);
movementY = cos(direction);

где направление - это число радианов, повернутых по часовой стрелке с севера, положительный X - восток, а положительный Y - север.

1 голос
/ 04 апреля 2012

Я не уверен, как прокомментировать или добавить ответ Кендалла, поэтому я просто добавлю его как новый ответ.

Я думаю, что вы можете использовать Y для вверх, так что вы бы использовали этоесли направление в радианах:

movementX = sin(direction);
movementZ = cos(direction);

если направление в градусах, вам придется преобразовать его в радианы:

radians = degrees*(PI/180);

Просто умножьте движение на 1 или -1 в зависимости от того,вы двигаетесь вперед или назад:

movementX = sin(direction)*forwardsBackwards;
movementZ = cos(direction)*forwardsBackwards;

Если вам также нужен страйфинг, вы можете сделать:

movementX = sin(direction)*forwardsBackwards+sin(direction+1.5707)*sideToSide;
movementZ = cos(direction)*forwardsBackwards+cos(direction+1.5707)*sideToSide;

Где sideToSide равен 1 или -1 в зависимости от того, стреляете ли вы влево илиправо.1.5707 - это 90 градусов в радианах (PI / 2), что означает, что независимо от того, в каком направлении вы находитесь, он принимает угол 90 градусов справа от него.Вы также можете добавить 90 градусов к повороту градуса перед преобразованием, если хотите.

Умножьте всю вещь на желаемую скорость движения:

movementX = (sin...eToSide)*speed;
movementZ = (cos...eToSide)*speed;

Это, однако, создаст эффект перебоя, когдаВы будете двигаться быстрее, если будете двигаться в двух направлениях одновременно.Если вы хотите, чтобы этого не происходило, добавьте это перед вычислением движения:

if (!forwardsBackwards && !sideToSide )
{
    forwardsBackwards *= 0.7071; 
    sideToSide *= 0.7071;
}

Вы также можете заменить .7071 на cos (45), если вам это нужно, чтобы быть чрезвычайно точным.

В качестве альтернативы вы можете:

float diagonalMod = 1;
if (!forwardsBackwards && !sideToSide)
     diagonalMod = 0.7071; // or cos(45)

movementX = (sin...eToSide)*speed*diagonalMod;
movementZ = (cos...eToSide)*speed*diagonalMod;

Сначала вы захотите повернуть, а затем перевести. Другой способ, если я правильно об этом думаю, в основном похожперемещение точки, в которой ваша камера будет вращаться, точка поворота.Вот почему вы должны обрезать объекты при вращении.

Кроме того, вы должны выполнять вращение «камеры» и перевод сразу после glLoadIdentity ();так как вы хотите, чтобы все остальное в вашей сцене двигалось и вращалось, именно так функционирует «камера» OpenGL.Вот как это будет сделано:

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glLoadIdentity();

glRotated(yrot, 0, 1, 0);
glTranslated(xposition, 0, zposition);

glPushMatrix();

И для дальнейшего использования в случае, если вы расширите его:

glRotatef(Pitch, 1, 0, 0); // Up and down look
glRotatef(Yaw, 0, 1, 0); // Left and right look
glRotatef(Roll, 0, 0, 1); // Like a barrel roll in a jet
glTranslatef(X,Y,Z);
...