旋转相机后的WebGL翻译(作为FPS)

时间:2013-08-27 11:15:55

标签: javascript html5-canvas webgl shader

我已经用c ++和OpenGL完成了一些项目,现在我用html5和WebGL创建了一个简单的项目。

问题是,在旋转相机后,移动始终沿着默认轴而不是沿着旋转轴移动。例如:我向前迈进 - >没问题,我将相机旋转90度 - >没问题,现在我认为,如果我继续前进,相机会在世界轴上向右移动(所以在相机前面,作为FPS游戏)但是相机始终朝向起始z轴(起始前进轴) 。奇怪的是,我的代码在OpenGL中运行良好,现在不再适用于webGL。

代码的主要部分是用JavaScript编写的。我使用“glMatrix-0.9.5.min”库来简化矩阵计算。

这些是保存相机状态的变量:

var px = 0.0, py = 2.0, pz = 10.0, ang = 0.0, elev = 0.0, roll = 0.0;
var DELTA_ANG = 0.5, DELTA_MOVE = 0.5;

这是我计算模型视图矩阵并将其传递给着色器的部分:

mat4.identity(mvMatrix);    
mat4.translate(mvMatrix, [-px, -py, -pz], mvMatrix);
mat4.rotateX(mvMatrix, degToRad(elev), mvMatrix);   
mat4.rotateY(mvMatrix, degToRad(-ang), mvMatrix);   
mat4.rotateZ(mvMatrix, degToRad(roll), mvMatrix);  
gl.uniformMatrix4fv(shaderProgram.mv_matrix, false, new Float32Array(mvMatrix));

这就是我处理键事件的方法(currentPressedKeys是我保存最后一个输入的数组):

// rotations    
if(currentlyPressedKeys[J])
{
    ang -= DELTA_ANG;
}
if(currentlyPressedKeys[L])
{
    ang += DELTA_ANG;   
}
if(currentlyPressedKeys[I])
{
    elev += DELTA_ANG;
}
if(currentlyPressedKeys[K])
{
    elev -= DELTA_ANG;  
}
if(currentlyPressedKeys[E]) 
{
    roll += DELTA_ANG;
}
if(currentlyPressedKeys[Q]) 
{
    roll -= DELTA_ANG;
}   

// movements
if(currentlyPressedKeys[A])
{
    px -= DELTA_MOVE * Math.cos(ang * Math.PI / 180.0);
    py += DELTA_MOVE * Math.sin(roll * Math.PI / 180.0);
    pz -= DELTA_MOVE * Math.sin(ang * Math.PI / 180.0);
}
if(currentlyPressedKeys[D])
{
    px += DELTA_MOVE * Math.cos(ang * Math.PI / 180.0);
    py -= DELTA_MOVE * Math.sin(roll * Math.PI / 180.0);
    pz += DELTA_MOVE * Math.sin(ang * Math.PI / 180.0);
}
if(currentlyPressedKeys[W])
{
    px += DELTA_MOVE * Math.sin(ang * Math.PI / 180.0);
    py += DELTA_MOVE * Math.sin(elev * Math.PI / 180.0);
    pz -= DELTA_MOVE * Math.cos(ang * Math.PI / 180.0); 
}
if(currentlyPressedKeys[S])
{
    px -= DELTA_MOVE * Math.sin(ang * Math.PI / 180.0);
    py -= DELTA_MOVE * Math.sin(elev * Math.PI / 180.0);
    pz += DELTA_MOVE * Math.cos(ang * Math.PI / 180.0);
}       

// height
if(currentlyPressedKeys[R])
{
    py += DELTA_MOVE;
}
if(currentlyPressedKeys[F])
{
    py -= DELTA_MOVE;
}   

最后,这是一个简单的顶点着色器(透视矩阵只是用mat4.perspective计算):

attribute vec3 position;
attribute vec3 normal;
attribute vec2 uv;

uniform mat4 p_matrix, mv_matrix;    

varying vec3 f_position;
varying vec3 f_normal;
varying vec2 f_uv;

void main() {
    gl_Position = p_matrix * mv_matrix * vec4(position, 1.0);   
    f_position = position;  
    f_normal = normal;  
    f_uv = uv;
}

我无法理解与OpenGL有什么区别,任何想法?

1 个答案:

答案 0 :(得分:0)

我解决了,问题是我在相机位置的计算中忘记了一些组件。 这是正确的代码:

// movements
if(currentlyPressedKeys[A])
{       
    px -= DELTA_MOVE * Math.cos(ang * Math.PI / 180.0);
    px -= DELTA_MOVE * Math.cos(roll * Math.PI / 180.0);
    py -= DELTA_MOVE * Math.sin(elev * Math.PI / 180.0);
    py += DELTA_MOVE * Math.sin(roll * Math.PI / 180.0);
    pz -= DELTA_MOVE * Math.sin(ang * Math.PI / 180.0);
    pz -= DELTA_MOVE * Math.sin(elev * Math.PI / 180.0);        
}
if(currentlyPressedKeys[D])
{
    px += DELTA_MOVE * Math.cos(ang * Math.PI / 180.0);
    px += DELTA_MOVE * Math.cos(roll * Math.PI / 180.0);
    py += DELTA_MOVE * Math.sin(elev * Math.PI / 180.0);
    py -= DELTA_MOVE * Math.sin(roll * Math.PI / 180.0);
    pz += DELTA_MOVE * Math.sin(ang * Math.PI / 180.0);
    pz += DELTA_MOVE * Math.sin(elev * Math.PI / 180.0);
}
if(currentlyPressedKeys[W])
{
    px += DELTA_MOVE * Math.sin(ang * Math.PI / 180.0);
    px += DELTA_MOVE * Math.sin(roll * Math.PI / 180.0);
    py -= DELTA_MOVE * Math.sin(elev * Math.PI / 180.0);
    py += DELTA_MOVE * Math.sin(roll * Math.PI / 180.0);
    pz -= DELTA_MOVE * Math.cos(ang * Math.PI / 180.0);
    pz -= DELTA_MOVE * Math.cos(elev * Math.PI / 180.0);        
}
if(currentlyPressedKeys[S])
{
    px -= DELTA_MOVE * Math.sin(ang * Math.PI / 180.0);
    px -= DELTA_MOVE * Math.sin(roll * Math.PI / 180.0);
    py += DELTA_MOVE * Math.sin(elev * Math.PI / 180.0);
    py -= DELTA_MOVE * Math.sin(roll * Math.PI / 180.0);
    pz += DELTA_MOVE * Math.cos(ang * Math.PI / 180.0);
    pz += DELTA_MOVE * Math.cos(elev * Math.PI / 180.0);
}       

它是如何在OpenGL中发挥作用的,但现在它是正确的。