PDA

View Full Version : confused about push/pop/uniform



staticvoid
08-16-2011, 11:43 AM
I am new here so hello everybody! :)
I try to describe my problem even if my english skills are moderate. I am a bit confused about the matrix-functions in my project. I use mvPushMatrix, mvPopMatrix and setMatrixUniforms like seen in the "learning WebGL" lessons.


var mvMatrix = mat4.create();
var pMatrix = mat4.create();
var mvMatrixStack = [];

function mvPushMatrix() {
var copy = mat4.create();
mat4.set(mvMatrix, copy);
mvMatrixStack.push(copy);
}

function mvPopMatrix() {
if(mvMatrixStack.length == 0) {
throw "Invalid popMatrix!";
}
mvMatrix = mvMatrixStack.pop();
}

function setMatrixUniforms() {
gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, pMatrix);
gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, mvMatrix);
}


I like to draw a simple car and some tires. At first I draw the carriage of the car.
Then I translate the modelview-matrix to positioning the tires. As you can see in my example,
I dont realy understand how to call push, pop or uniform. Thats because I am not too familiar with these
methods. In my understanding I have to push a matrix for every tire, uniform it, translate it, draw it and pop it back.
Maybe I am wrong.






this.draw = function(){
// draw carriage
mvPushMatrix();
setMatrixUniforms();
mat4.translate(mvMatrix, [0,0,0]);
this.gl.bindBuffer(gl.ARRAY_BUFFER, this.carPositionBuffer);
this.gl.vertexAttribPointer(this.shaderProgram.ver texPositionAttribute, this.carPositionBuffer.itemSize, this.gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this.carColorBuffer);
this.gl.vertexAttribPointer(this.shaderProgram.ver texColorAttribute, this.carColorBuffer.itemSize, this.gl.FLOAT, false, 0, 0);
this.gl.drawArrays(gl.TRIANGLES, 0, this.carPositionBuffer.numItems);

// draw tires
var idx;
for(idx = 0; idx<4; idx++){
mvPushMatrix();
setMatrixUniforms();
if(idx==0) mat4.translate(mvMatrix, [1.4, 0, 1]);
if(idx==1) mat4.translate(mvMatrix, [2, 0, 2 ]);
if(idx==2) mat4.translate(mvMatrix, [3, 0, 3 ]);
if(idx==3) mat4.translate(mvMatrix, [4, 0, 4 ]);
this.gl.bindBuffer(gl.ARRAY_BUFFER, this.tirePositionBuffer);
this.gl.vertexAttribPointer(this.shaderProgram.ver texPositionAttribute, this.tirePositionBuffer.itemSize, this.gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this.tireColorBuffer);
this.gl.vertexAttribPointer(this.shaderProgram.ver texColorAttribute, this.tireColorBuffer.itemSize, this.gl.FLOAT, false, 0, 0);
this.gl.drawArrays(gl.TRIANGLES, 0, this.tirePositionBuffer.numItems);
mvPopMatrix();
}
mvPopMatrix();
};


Here is a link to my project: http://agrarkollektiv.com/WebGL/index.html
Could anybody try to explain what my missunderstanding is? Or does anybody have can tell me where I can find a tutorial about push/pop/uniform?
That would be to nice! Thank you!

LordAshes
01-28-2012, 08:33 AM
You do not need to push and pop the Matrix unless you need to return back to the previous matrix (position).

Consider your car example: You have the body and 4 tires. You could draw this by rendering the body then (without a push) moving to the first tire, rendering the first tire, moving from the first tire to the second tire, rendering the second tire, and so on through the third and fourth tire. If you do this then your tires are "linked" to each other. If you adjust the position of the first tire it will cause the other tires to also adjust. This may be fine for the tires but, for example, if your car spoiler was an individually rendered part then you would not want it linked to the tires because if the tires are moved then you don't necessarily want to move the spoiler. In that case you can use the Push and Pop matrix command. You would draw your car body, then push the matrix to basically store the position that you were at, then you would translate (move) to the position of the first tire and render it. Next, instead of continuing to the next tire, you Pop the matrix to return back to the position before you drew the first tire. Now you Push the matrix again (to store the position) and translate to the tire 2 position, render it and then Pop the matrix to return back to your default position. By doing this for each part the components (e.g. tires, spoiler, etc) become independent. If you now change the position of one tire (e.g change the translate amount before rendering the first tire) it will have no effect on the rest of the components.

Basically the Pop matrix allows you to remember the current position & rotation so that you can return back to it without having to issue reverse translations and reverse rotations. As such there is no hard fast rule on if you should use them or not...it depends on your implementation and if you want components to be independent of each other or not.

Another scenario with your car example. Say you are going to animate your car by spinning the tires. This will require a rotate command before each tire. If you use a push before each tire and a pop after each tire then all the tires will be independent so you can rotate each at will. If however you just translated between the 4 tires then rotating one tire would cause the other 3 tires to rotate out of place because they would be all rotating around the first tire axis. This, in some cases, may be desirable. I have a nice WebGL example on my webpage (http://webtable.byethost15.com/WebGL) which uses my Joint And Object Framework (basically some Javascript code to make loading object and bending them easier) to display a human figure. In such a case, when someone moves, for example, the shoulder joint then you want the rest of the arm to also rotate (and thus there would be no Pop matrix command to return back to the previous settings which would make the objects independent).

So you can see that depending on what you are trying to do, you either need to use the Push and Pop commands or you don't.