PKivolowitz
PKivolowitz

Reputation: 91

glmatrix.js anomaly - changing order of transforms does not change outcome

In creating a webgl "hello world" for demonstration to a high school class, I am experiencing an anomalous result.

Using gl-matrix.js version 2.2.0, reversing the order of two transforms does not produce a difference in output.

This code produces the desired result:

function DrawScene(gl) {
    var time_now = new Date();
    var elapsed_time = new Date();
    elapsed_time.setDate(time_program_started - time_now);
    var projection_matrix = mat4.create();
    var modelview_matrix = mat4.create();
    var mvp = mat4.create();
    gl.viewport(0, 0, gl.size[0], gl.size[1]);
    gl.clearColor(0.2, 0.2, 0.2, 1.0);
    gl.clear(gl.COLOR_BUFFER_BIT);
    mat4.perspective(projection_matrix, D2R(50.0), gl.size[0] / gl.size[1], 1.0, 10.0);
    mat4.translate(modelview_matrix, modelview_matrix, [0.0, 0.0, -3.5]);
    mat4.rotate(modelview_matrix, modelview_matrix, D2R(elapsed_time / 1000.0 * 60.0), [0.0, 1.0, 0.0]);
    mat4.multiply(mvp, projection_matrix, modelview_matrix);
    triangle.Render(gl, shader_index, [1.0, 1.0, 1.0, 1.0], mvp);
}

namely a triangle that spins in place about its Y axis.

Reversing the order of the translate and rotate should spin the triangle around the camera (part of my intended lesson), but instead continues to spin the triangle in place. I sanity checked this in an equivalent legacy OpenGL "hello world" producing exactly the expected results.

The vertex shader simply multiples the vertex position attribute with the mvp uniform. Is there a problem in gl-matrix.js or in this code?

For completeness, here is the render function.

Triangle.prototype.Render = function (gl, shader_index, color, mvp) {
    gl.bindBuffer(gl.ARRAY_BUFFER, this.vertex_buffer_object);
    gl.vertexAttribPointer(shaders[shader_index].VP, 3, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(shaders[shader_index].VP);
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.element_buffer_object);
    shaders[shader_index].Use(gl);
    gl.uniformMatrix4fv(shaders[shader_index].MVP, false, mvp);
    if (shader_index == 0)
        gl.uniform4fv(shaders[shader_index].COLOR, color);
    else {
        gl.bindBuffer(gl.ARRAY_BUFFER, this.color_buffer_object);
        gl.vertexAttribPointer(shaders[shader_index].COLOR, 3, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray(shaders[shader_index].COLOR);
    }
    gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 0);
    shaders[shader_index].StopUsing(gl);
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
    gl.bindBuffer(gl.ARRAY_BUFFER, null);
}

Thank you.

Upvotes: 1

Views: 338

Answers (1)

PKivolowitz
PKivolowitz

Reputation: 91

I believe there is an error in my use of gl-matrix or gl-matrix itself. Replacing gl-matrix with mjs.js works as expacted.

function DrawScene(gl) {
    var time_now = new Date();
    var elapsed_time = new Date();
    elapsed_time.setDate(time_program_started - time_now);

    var projection_matrix = M4x4.I;
    var modelview_matrix = M4x4.I;
    var mvp = M4x4.I;

    gl.viewport(0, 0, gl.size[0], gl.size[1]);
    gl.clearColor(0.2, 0.2, 0.2, 1.0);
    gl.clear(gl.COLOR_BUFFER_BIT);

    projection_matrix = M4x4.makePerspective(50.0, gl.size[0] / gl.size[1], 1.0, 10.0);
    modelview_matrix = M4x4.rotate(D2R(elapsed_time / 1000.0 * 60.0), [0.0, 1.0, 0.0], modelview_matrix);
    modelview_matrix = M4x4.translate([0.0, 0.0, -5.5], modelview_matrix);
    mvp = M4x4.mul(projection_matrix, modelview_matrix);
    triangle.Render(gl, shader_index, [1.0, 1.0, 1.0, 1.0], mvp);
}

Does indeed rotate about the camera. Reversing to translate then rotate spins about the Y axis of the triangle.

I would be very pleased to have my code for gl-matrix corrected. If it cannot, gl-matrix is very broken.

Upvotes: 1

Related Questions