【问题标题】:WebGL: Object moves according to current camera orientationWebGL:对象根据当前相机方向移动
【发布时间】:2014-03-18 13:15:21
【问题描述】:

我创建了一个简单的场景,其中一个立方体平行于 x 轴移动。一切都按预期工作,直到我围绕 y 轴旋转相机。然后立方体跟随这个旋转并平行于屏幕移动(相机坐标中的 x 轴)。

再次进行初始设置:

  • 相机位于 [0, 2, 10] 处,正在查看 [0, 0, 0]
  • 立方体最初放置在 [0, 0, 0] 处,沿 x 轴在 [-10, 10] 之间移动

为什么我的相机移动会影响立方体的方向?

这里是一些相关的代码。我想看更多,请不要犹豫。我正在使用 glMatrix 进行向量和矩阵运算。

主要绘图例程:

// Clear the canvas before we start drawing on it.    
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

// Use the full window (minus border)
canvas.width = window.innerWidth - 16;
canvas.height = window.innerHeight - 16;

// Set viewport
gl.viewport(0, 0, canvas.width, canvas.height);

// Reset the perspective matrix
cam.aspectRatio = canvas.width / canvas.height;
mat4.perspective(perspectiveMatrix, cam.fovy, cam.aspectRatio, cam.nearPlane, cam.farPlane);

// Create the mvMatrix
mat4.lookAt(mvMatrix, cam.position, cam.poi, cam.up);

// Draw all objects
for (i = 0; i < ObjectStack.length; i++) {
    ObjectStack[i].draw();
}

相机旋转:

// Rotation via yaw and pitch (FPS-style)
this.rotateYP = function (yaw, pitch) {

    // Rotation speed
    var rotSpeed = 0.5;
    yaw *= rotSpeed;
    pitch *= rotSpeed;

    // Update rotation
    var quatYaw = quat.create();
    quat.setAxisAngle(quatYaw, this.up, degToRad(yaw));
    var quatPitch = quat.create();
    quat.setAxisAngle(quatPitch, this.right, degToRad(pitch)); 
    var quatCombined = quat.create();
    quat.multiply(quatCombined, quatYaw, quatPitch);

    // Update camera vectors
    var tmp = vec3.create();
    vec3.subtract(tmp, this.poi, this.position);
    vec3.transformQuat(tmp, tmp, quatCombined);
    vec3.add(tmp, this.position, tmp);
    this.setPOI(tmp);
};

我的 setPOI() 方法(POI = 兴趣点):

this.setPOI = function (poi) {

    // Set new poi
    vec3.copy(this.poi, poi);

    // Set new view vector
    vec3.subtract(this.view, poi, this.position);
    vec3.normalize(this.view, this.view);

    // Set new right vector
    vec3.cross(this.right, this.view, [0.0, 1.0, 0.0]);
    vec3.normalize(this.right, this.right);

    // Set new up vector
    vec3.cross(this.up, this.right, this.view); 
    vec3.normalize(this.up, this.up);     
};

立方体的对象绘制方法:

this.draw = function () {

    // Save current mvMatrix
    mvPushMatrix();

    // Object movement
    mat4.translate(mvMatrix, mvMatrix, position);

    // Object rotation
    //mat4.mul(mvMatrix, mvMatrix, orientation);

    // Object scaling
    // ...

    // Set shader
    setShader();

    // Bind the necessary buffers
    gl.bindBuffer(gl.ARRAY_BUFFER, verticesBuffer);
    gl.vertexAttribPointer(positionAttribute, 3, gl.FLOAT, false, 0, 0);
    gl.bindBuffer(gl.ARRAY_BUFFER, normalsBuffer);
    gl.vertexAttribPointer(normalAttribute, 3, gl.FLOAT, false, 0, 0);
    gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
    gl.vertexAttribPointer(texCoordAttribute, 2, gl.FLOAT, false, 0, 0);
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, vertexIndexBuffer);

    // Set active texture
    gl.activeTexture(gl.TEXTURE0);
    gl.bindTexture(gl.TEXTURE_2D, cubeTexture);
    gl.uniform1i(gl.getUniformLocation(ShaderStack[shader], "uSampler"), 0);

    // Send the triangles to the graphics card for drawing
    gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_SHORT, 0);

    gl.bindTexture(gl.TEXTURE_2D, null);

    // Clean up the changed mvMatrix
    mvPopMatrix();
};

最后是上面使用的 setShader():

    function setShader() {

    var shaderProgram = ShaderStack[shader];
    gl.useProgram(shaderProgram);

    var pUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
    gl.uniformMatrix4fv(pUniform, false, perspectiveMatrix);

    var mvUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix");
    gl.uniformMatrix4fv(mvUniform, false, mvMatrix);

    var normalMatrix = mat4.create();
    mat4.invert(normalMatrix, mvMatrix);
    mat4.transpose(normalMatrix, normalMatrix);
    var nUniform = gl.getUniformLocation(shaderProgram, "uNormalMatrix");
    gl.uniformMatrix4fv(nUniform, false, normalMatrix);

    normalAttribute = gl.getAttribLocation(shaderProgram, "aVertexNormal");
    gl.enableVertexAttribArray(normalAttribute);

    positionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
    gl.enableVertexAttribArray(positionAttribute);

    texCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord");
    gl.enableVertexAttribArray(texCoordAttribute);
};

很抱歉在这里发布所有这些代码。如果您有任何想法,请告诉我!

【问题讨论】:

    标签: javascript opengl-es camera webgl


    【解决方案1】:

    我怀疑你在自己的问题中回答了你的问题:

    一个简单的场景,一个立方体平行于 x 轴移动......然后立方体跟随这个旋转并平行于屏幕移动(x 轴在相机坐标中)。

    发生这样的事情让我相信您将翻译操作应用于您的模型视图矩阵,而不是您的模型矩阵,并且从您的代码来看,我认为我是对的:

    mat4.translate(mvMatrix, mvMatrix, 位置);

    要解决此问题,您需要将模型和视图矩阵分开,将转换应用于模型矩阵,然后将结果乘以您的视图。告诉我进展如何!

    如果您仍然对矩阵感到困惑,请阅读以下内容:

    http://solarianprogrammer.com/2013/05/22/opengl-101-matrices-projection-view-model/

    【讨论】:

    • 好的,这听起来很合理。但我正在使用返回 mvMatrix 的lookAt()。仅获取视图矩阵的常用方法是什么?到目前为止,谢谢!
    • 我有点困惑。你能指出我在哪里读到 lookAt() 返回一个模型视图矩阵吗?我的理解是,lookAt() 的大多数实现将只返回一个视图矩阵,然后在后面的步骤中乘以模型矩阵。
    • 天啊,我想从现在开始我需要在地下的某个地方挖一个深洞来藏起来。当然,lookAt() 只创建一个视图矩阵。知道了这一点,我现在在 10 秒内纠正了所有问题。非常感谢!你拯救了我的一天!
    • 没问题!很高兴为您提供帮助
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多