Reputation: 135
I created a simple scene with a cube moving parallel to the x-axis. Everything works as expected until I rotate the camera around the y-axis. Then the cube follows this rotation and moves parallel to the screen (x-axis in camera coordinates).
Again the initial setup:
Why does my camera movement affect the orientation of the cube?
Here is some of the relevant code. I you would like to see more, don't hesitate to ask. I am using glMatrix for vector and matrix operations.
Main drawing routine:
// 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();
}
Camera rotation:
// 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);
};
My setPOI() method (POI = point of interest):
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);
};
Object draw method for the cube:
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();
};
And finally the setShader() used above:
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);
};
Sorry for posting all this code here. If you have any idea, please let me know!
Upvotes: 1
Views: 2816
Reputation: 956
I suspect you answered your question in your own question:
a simple scene with a cube moving parallel to the x-axis ... Then the cube follows this rotation and moves parallel to the screen (x-axis in camera coordinates).
Something like this happening leads me to believe that you applied the translation operation to your model-view matrix, not your model matrix, and from your code, I think I am right:
mat4.translate(mvMatrix, mvMatrix, position);
To fix this, you'll want to separate out your model and your view matrix, apply the translation to your model matrix, and then multiply the result by your view. Let me know how it goes!
If you're still confused by matrices, give this a read:
http://solarianprogrammer.com/2013/05/22/opengl-101-matrices-projection-view-model/
Upvotes: 3