Skip to content

Commit

Permalink
Merge pull request #6761 from deveshidwivedi/model-view
Browse files Browse the repository at this point in the history
Separate Model and View Matrices.
  • Loading branch information
Qianqianye committed May 25, 2024
2 parents f62fc6d + 9f2cdd1 commit 3c7a094
Show file tree
Hide file tree
Showing 12 changed files with 78 additions and 47 deletions.
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 12 additions & 12 deletions src/webgl/3d_primitives.js
Original file line number Diff line number Diff line change
Expand Up @@ -2481,7 +2481,7 @@ p5.RendererGL.prototype.triangle = function(args) {
// this matrix multiplication transforms those two unit vectors
// onto the required vector prior to rendering, and moves the
// origin appropriately.
const uMVMatrix = this.uMVMatrix.copy();
const uModelMatrix = this.uModelMatrix.copy();
try {
// triangle orientation.
const orientation = Math.sign(x1*y2-x2*y1 + x2*y3-x3*y2 + x3*y1-x1*y3);
Expand All @@ -2490,13 +2490,13 @@ p5.RendererGL.prototype.triangle = function(args) {
x3 - x1, y3 - y1, 0, 0, // the resulting unit Y-axis
0, 0, orientation, 0, // the resulting unit Z-axis (Reflect the specified order of vertices)
x1, y1, 0, 1 // the resulting origin
]).mult(this.uMVMatrix);
]).mult(this.uModelMatrix);

this.uMVMatrix = mult;
this.uModelMatrix = mult;

this.drawBuffers(gId);
} finally {
this.uMVMatrix = uMVMatrix;
this.uModelMatrix = uModelMatrix;
}

return this;
Expand Down Expand Up @@ -2618,15 +2618,15 @@ p5.RendererGL.prototype.arc = function(...args) {
this.createBuffers(gId, arcGeom);
}

const uMVMatrix = this.uMVMatrix.copy();
const uModelMatrix = this.uModelMatrix.copy();

try {
this.uMVMatrix.translate([x, y, 0]);
this.uMVMatrix.scale(width, height, 1);
this.uModelMatrix.translate([x, y, 0]);
this.uModelMatrix.scale(width, height, 1);

this.drawBuffers(gId);
} finally {
this.uMVMatrix = uMVMatrix;
this.uModelMatrix = uModelMatrix;
}

return this;
Expand Down Expand Up @@ -2678,14 +2678,14 @@ p5.RendererGL.prototype.rect = function(args) {
// opposite corners at (0,0) & (1,1).
//
// before rendering, this square is scaled & moved to the required location.
const uMVMatrix = this.uMVMatrix.copy();
const uModelMatrix = this.uModelMatrix.copy();
try {
this.uMVMatrix.translate([x, y, 0]);
this.uMVMatrix.scale(width, height, 1);
this.uModelMatrix.translate([x, y, 0]);
this.uModelMatrix.scale(width, height, 1);

this.drawBuffers(gId);
} finally {
this.uMVMatrix = uMVMatrix;
this.uModelMatrix = uModelMatrix;
}
} else {
// Use Immediate mode to round the rectangle corner,
Expand Down
8 changes: 4 additions & 4 deletions src/webgl/GeometryBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class GeometryBuilder {
this.renderer = renderer;
renderer._pInst.push();
this.identityMatrix = new p5.Matrix();
renderer.uMVMatrix = new p5.Matrix();
renderer.uModelMatrix = new p5.Matrix();
this.geometry = new p5.Geometry();
this.geometry.gid = `_p5_GeometryBuilder_${GeometryBuilder.nextGeometryId}`;
GeometryBuilder.nextGeometryId++;
Expand All @@ -25,7 +25,7 @@ class GeometryBuilder {
transformVertices(vertices) {
if (!this.hasTransform) return vertices;

return vertices.map(v => this.renderer.uMVMatrix.multiplyPoint(v));
return vertices.map(v => this.renderer.uModelMatrix.multiplyPoint(v));
}

/**
Expand All @@ -46,11 +46,11 @@ class GeometryBuilder {
* transformations.
*/
addGeometry(input) {
this.hasTransform = !this.renderer.uMVMatrix.mat4
this.hasTransform = !this.renderer.uModelMatrix.mat4
.every((v, i) => v === this.identityMatrix.mat4[i]);

if (this.hasTransform) {
this.renderer.uNMatrix.inverseTranspose(this.renderer.uMVMatrix);
this.renderer.uNMatrix.inverseTranspose(this.renderer.uModelMatrix);
}

let startIdx = this.geometry.vertices.length;
Expand Down
4 changes: 2 additions & 2 deletions src/webgl/interaction.js
Original file line number Diff line number Diff line change
Expand Up @@ -813,7 +813,7 @@ p5.prototype._grid = function(size, numDivs, xOff, yOff, zOff) {
this._renderer.curStrokeColor[1] * 255,
this._renderer.curStrokeColor[2] * 255
);
this._renderer.uMVMatrix.set(this._renderer._curCamera.cameraMatrix);
this._renderer.uModelMatrix.reset();

// Lines along X axis
for (let q = 0; q <= numDivs; q++) {
Expand Down Expand Up @@ -860,7 +860,7 @@ p5.prototype._axesIcon = function(size, xOff, yOff, zOff) {

return function() {
this.push();
this._renderer.uMVMatrix.set(this._renderer._curCamera.cameraMatrix);
this._renderer.uModelMatrix.reset();

// X axis
this.strokeWeight(2);
Expand Down
10 changes: 5 additions & 5 deletions src/webgl/p5.Camera.js
Original file line number Diff line number Diff line change
Expand Up @@ -2915,7 +2915,8 @@ p5.Camera = class Camera {
this.cameraMatrix.translate([tx, ty, tz]);

if (this._isActive()) {
this._renderer.uMVMatrix.set(this.cameraMatrix);
this._renderer.uModelMatrix.reset();
this._renderer.uViewMatrix.set(this.cameraMatrix);
}
return this;
}
Expand Down Expand Up @@ -3242,13 +3243,12 @@ p5.Camera = class Camera {
this.cameraMatrix = cam.cameraMatrix.copy();
this.projMatrix = cam.projMatrix.copy();

// If the target camera is active, update uMVMatrix and uPMatrix.
if (this._isActive()) {
this._renderer.uMVMatrix.mat4 = this.cameraMatrix.mat4.slice();
this._renderer.uPMatrix.mat4 = this.projMatrix.mat4.slice();
this._renderer.uModelMatrix.reset();
this._renderer.uViewMatrix.set(this.cameraMatrix);
this._renderer.uPMatrix.set(this.projMatrix);
}
}

/**
* Sets the camera’s position and orientation to values that are in-between
* those of two other cameras.
Expand Down
7 changes: 4 additions & 3 deletions src/webgl/p5.Framebuffer.js
Original file line number Diff line number Diff line change
Expand Up @@ -1176,9 +1176,10 @@ class Framebuffer {
// RendererGL.reset() does, but this does not try to clear any buffers;
// it only sets the camera.
this.target.setCamera(this.defaultCamera);
this.target._renderer.uMVMatrix.set(
this.target._renderer._curCamera.cameraMatrix
);
this.target.resetMatrix();
this.target._renderer.uViewMatrix
.set(this.target._renderer._curCamera.cameraMatrix);
this.target._renderer.uModelMatrix.reset();
this.target._renderer._applyStencilTestIfClipping();
}

Expand Down
9 changes: 9 additions & 0 deletions src/webgl/p5.Matrix.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,15 @@ p5.Matrix = class {
return this;
}

reset() {
if (this.mat3) {
this.mat3.set([1, 0, 0, 0, 1, 0, 0, 0, 1]);
} else if (this.mat4) {
this.mat4.set([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
}
return this;
}

/**
* Replace the entire contents of a 4x4 matrix.
* If providing an array or a p5.Matrix, the values will be copied without
Expand Down
9 changes: 5 additions & 4 deletions src/webgl/p5.RendererGL.Retained.js
Original file line number Diff line number Diff line change
Expand Up @@ -195,15 +195,16 @@ p5.RendererGL.prototype.drawBuffersScaled = function(
scaleY,
scaleZ
) {
const uMVMatrix = this.uMVMatrix.copy();
let originalModelMatrix = this.uModelMatrix.copy();
try {
this.uMVMatrix.scale(scaleX, scaleY, scaleZ);
this.uModelMatrix.scale(scaleX, scaleY, scaleZ);

this.drawBuffers(gId);
} finally {
this.uMVMatrix = uMVMatrix;

this.uModelMatrix = originalModelMatrix;
}
};

p5.RendererGL.prototype._drawArrays = function(drawMode, gId) {
this.GL.drawArrays(
drawMode,
Expand Down
21 changes: 13 additions & 8 deletions src/webgl/p5.RendererGL.js
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,8 @@ p5.RendererGL = class RendererGL extends p5.Renderer {
* model view, projection, & normal
* matrices
*/
this.uModelMatrix = new p5.Matrix();
this.uViewMatrix = new p5.Matrix();
this.uMVMatrix = new p5.Matrix();
this.uPMatrix = new p5.Matrix();
this.uNMatrix = new p5.Matrix('mat3');
Expand Down Expand Up @@ -894,7 +896,8 @@ p5.RendererGL = class RendererGL extends p5.Renderer {
_update() {
// reset model view and apply initial camera transform
// (containing only look at info; no projection).
this.uMVMatrix.set(this._curCamera.cameraMatrix);
this.uModelMatrix.reset();
this.uViewMatrix.set(this._curCamera.cameraMatrix);

// reset light data for new frame.

Expand Down Expand Up @@ -1528,9 +1531,9 @@ p5.RendererGL = class RendererGL extends p5.Renderer {

applyMatrix(a, b, c, d, e, f) {
if (arguments.length === 16) {
p5.Matrix.prototype.apply.apply(this.uMVMatrix, arguments);
p5.Matrix.prototype.apply.apply(this.uModelMatrix, arguments);
} else {
this.uMVMatrix.apply([
this.uModelMatrix.apply([
a, b, 0, 0,
c, d, 0, 0,
0, 0, 1, 0,
Expand All @@ -1554,7 +1557,7 @@ p5.RendererGL = class RendererGL extends p5.Renderer {
y = x.y;
x = x.x;
}
this.uMVMatrix.translate([x, y, z]);
this.uModelMatrix.translate([x, y, z]);
return this;
}

Expand All @@ -1567,15 +1570,15 @@ p5.RendererGL = class RendererGL extends p5.Renderer {
* @chainable
*/
scale(x, y, z) {
this.uMVMatrix.scale(x, y, z);
this.uModelMatrix.scale(x, y, z);
return this;
}

rotate(rad, axis) {
if (typeof axis === 'undefined') {
return this.rotateZ(rad);
}
p5.Matrix.prototype.rotate.apply(this.uMVMatrix, arguments);
p5.Matrix.prototype.rotate.apply(this.uModelMatrix, arguments);
return this;
}

Expand All @@ -1601,7 +1604,8 @@ p5.RendererGL = class RendererGL extends p5.Renderer {
// add webgl-specific style properties
const properties = style.properties;

properties.uMVMatrix = this.uMVMatrix.copy();
properties.uModelMatrix = this.uModelMatrix.copy();
properties.uViewMatrix = this.uViewMatrix.copy();
properties.uPMatrix = this.uPMatrix.copy();
properties._curCamera = this._curCamera;

Expand Down Expand Up @@ -1688,7 +1692,8 @@ p5.RendererGL = class RendererGL extends p5.Renderer {
}
}
resetMatrix() {
this.uMVMatrix.set(this._curCamera.cameraMatrix);
this.uModelMatrix.reset();
this.uViewMatrix.set(this._curCamera.cameraMatrix);
return this;
}

Expand Down
10 changes: 6 additions & 4 deletions src/webgl/p5.Shader.js
Original file line number Diff line number Diff line change
Expand Up @@ -577,9 +577,11 @@ p5.Shader = class {
}

_setMatrixUniforms() {
const viewMatrix = this._renderer._curCamera.cameraMatrix;
const modelMatrix = this._renderer.uModelMatrix;
const viewMatrix = this._renderer.uViewMatrix;
const projectionMatrix = this._renderer.uPMatrix;
const modelViewMatrix = this._renderer.uMVMatrix;
const modelViewMatrix = (modelMatrix.copy()).mult(viewMatrix);
this._renderer.uMVMatrix = modelViewMatrix;

const modelViewProjectionMatrix = modelViewMatrix.copy();
modelViewProjectionMatrix.mult(projectionMatrix);
Expand All @@ -589,6 +591,7 @@ p5.Shader = class {
}
this.setUniform('uViewMatrix', viewMatrix.mat4);
this.setUniform('uProjectionMatrix', projectionMatrix.mat4);
this.setUniform('uModelMatrix', modelMatrix.mat4);
this.setUniform('uModelViewMatrix', modelViewMatrix.mat4);
this.setUniform(
'uModelViewProjectionMatrix',
Expand All @@ -599,8 +602,7 @@ p5.Shader = class {
this.setUniform('uNormalMatrix', this._renderer.uNMatrix.mat3);
}
if (this.uniforms.uCameraRotation) {
this._renderer.curMatrix.inverseTranspose(this._renderer.
_curCamera.cameraMatrix);
this._renderer.curMatrix.inverseTranspose(this._renderer.uViewMatrix);
this.setUniform('uCameraRotation', this._renderer.curMatrix.mat3);
}
}
Expand Down
2 changes: 1 addition & 1 deletion test/unit/webgl/p5.Camera.js
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ suite('p5.Camera', function() {
// the renderer's matrix will also change.
assert.deepEqual(
copyCam.cameraMatrix.mat4,
myp5._renderer.uMVMatrix.mat4
myp5._renderer.uViewMatrix.mat4
);
assert.deepEqual(
copyCam.projMatrix.mat4,
Expand Down
19 changes: 16 additions & 3 deletions test/unit/webgl/p5.RendererGL.js
Original file line number Diff line number Diff line change
Expand Up @@ -593,13 +593,26 @@ suite('p5.RendererGL', function() {
suite('push() and pop() work in WEBGL Mode', function() {
test('push/pop and translation works as expected in WEBGL Mode', function(done) {
myp5.createCanvas(100, 100, myp5.WEBGL);
var modelView = myp5._renderer.uMVMatrix.copy();
var modelMatrixBefore = myp5._renderer.uModelMatrix.copy();
var viewMatrixBefore = myp5._renderer.uViewMatrix.copy();

myp5.push();
// Change view
myp5.camera(0, 0, -500);
// Change model
myp5.rotateX(Math.random(0, 100));
myp5.translate(20, 100, 5);
assert.notEqual(modelView.mat4, myp5._renderer.uMVMatrix.mat4);
// Check if the model matrix has changed
assert.notDeepEqual(modelMatrixBefore.mat4,
myp5._renderer.uModelMatrix.mat4);
// Check if the view matrix has changed
assert.notDeepEqual(viewMatrixBefore.mat4,
myp5._renderer.uViewMatrix.mat4);
myp5.pop();
assert.deepEqual(modelView.mat4, myp5._renderer.uMVMatrix.mat4);
// Check if both the model and view matrices are restored after popping
assert.deepEqual(modelMatrixBefore.mat4,
myp5._renderer.uModelMatrix.mat4);
assert.deepEqual(viewMatrixBefore.mat4, myp5._renderer.uViewMatrix.mat4);
done();
});

Expand Down

0 comments on commit 3c7a094

Please sign in to comment.