Skip to content

Commit 14e9b51

Browse files
authored
Merge pull request #6116 from inaridarkfox4231/improve-cameraMove
Align the method of moving the camera with the right button in orbitControl() to the movement of the mouse
2 parents c27002c + 08a3b7d commit 14e9b51

File tree

2 files changed

+109
-22
lines changed

2 files changed

+109
-22
lines changed

src/webgl/interaction.js

Lines changed: 42 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -119,33 +119,53 @@ p5.prototype.orbitControl = function(sensitivityX, sensitivityY, sensitivityZ) {
119119
sensitivityY * (this.mouseY - this.pmouseY) / scaleFactor;
120120
this._renderer._curCamera._orbit(deltaTheta, deltaPhi, 0);
121121
} else if (this.mouseButton === this.RIGHT) {
122-
// PANNING BEHAVIOR along X/Z camera axes and restricted to X/Z plane
123-
// in world space
122+
// Translate the camera so that the entire object moves
123+
// perpendicular to the line of sight when the mouse is moved
124124
const local = cam._getLocalAxes();
125125

126-
// normalize portions along X/Z axes
127-
const xmag = Math.sqrt(local.x[0] * local.x[0] + local.x[2] * local.x[2]);
128-
if (xmag !== 0) {
129-
local.x[0] /= xmag;
130-
local.x[2] /= xmag;
126+
// Calculate the z coordinate in the view coordinates of
127+
// the center, that is, the distance to the view point.
128+
const diffX = cam.eyeX - cam.centerX;
129+
const diffY = cam.eyeY - cam.centerY;
130+
const diffZ = cam.eyeZ - cam.centerZ;
131+
const viewZ = Math.sqrt(diffX * diffX + diffY * diffY + diffZ * diffZ);
132+
133+
// position vector of the center
134+
let cv = createVector(cam.centerX, cam.centerY, cam.centerZ);
135+
136+
// Calculate the normalized device coordinates of the center
137+
cv = cam.cameraMatrix.multiplyPoint(cv);
138+
cv = this._renderer.uPMatrix.multiplyAndNormalizePoint(cv);
139+
140+
// Normalize mouse movement distance
141+
const ndcX = (this.mouseX - this.pmouseX) * 2 / this.width;
142+
const ndcY = -(this.mouseY - this.pmouseY) * 2 / this.height;
143+
144+
// Move the center by this distance
145+
// in the normalized device coordinate system
146+
cv.x -= ndcX;
147+
cv.y -= ndcY;
148+
149+
// Calculate the translation vector
150+
// in the direction perpendicular to the line of sight of center
151+
let dx, dy;
152+
const uP = this._renderer.uPMatrix.mat4;
153+
// When calculating the view coordinates, the calculation method is
154+
// different depending on whether ortho() or not, so separate the cases.
155+
// uP[15] is non-zero only for ortho().
156+
if (uP[15] === 0) {
157+
dx = ((uP[8] + cv.x) / uP[0]) * viewZ;
158+
dy = ((uP[9] + cv.y) / uP[5]) * viewZ;
159+
} else {
160+
dx = (cv.x - uP[12]) / uP[0];
161+
dy = (cv.y - uP[13]) / uP[5];
131162
}
132163

133-
// normalize portions along X/Z axes
134-
const ymag = Math.sqrt(local.y[0] * local.y[0] + local.y[2] * local.y[2]);
135-
if (ymag !== 0) {
136-
local.y[0] /= ymag;
137-
local.y[2] /= ymag;
138-
}
139-
140-
// move along those vectors by amount controlled by mouseX, pmouseY
141-
const dx = -1 * sensitivityX * (this.mouseX - this.pmouseX);
142-
const dz = -1 * sensitivityY * (this.mouseY - this.pmouseY);
143-
144-
// restrict movement to XZ plane in world space
164+
// translate the camera
145165
cam.setPosition(
146-
cam.eyeX + dx * local.x[0] + dz * local.z[0],
147-
cam.eyeY,
148-
cam.eyeZ + dx * local.x[2] + dz * local.z[2]
166+
cam.eyeX + dx * local.x[0] + dy * local.y[0],
167+
cam.eyeY + dx * local.x[1] + dy * local.y[1],
168+
cam.eyeZ + dx * local.x[2] + dy * local.y[2]
149169
);
150170
}
151171
}

src/webgl/p5.Matrix.js

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -720,6 +720,73 @@ p5.Matrix = class {
720720
return this;
721721
}
722722

723+
/**
724+
* apply a matrix to a vector with x,y,z,w components
725+
* get the results in the form of an array
726+
* @method multiplyVec4
727+
* @param {Number}
728+
* @return {Number[]}
729+
*/
730+
multiplyVec4(x, y, z, w) {
731+
const result = new Array(4);
732+
const m = this.mat4;
733+
734+
result[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w;
735+
result[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w;
736+
result[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w;
737+
result[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w;
738+
739+
return result;
740+
}
741+
742+
/**
743+
* Applies a matrix to a vector.
744+
* The fourth component is set to 1.
745+
* Returns a vector consisting of the first
746+
* through third components of the result.
747+
*
748+
* @method multiplyPoint
749+
* @param {p5.Vector}
750+
* @return {p5.Vector}
751+
*/
752+
multiplyPoint(v) {
753+
const array = this.multiplyVec4(v.x, v.y, v.z, 1);
754+
return new p5.Vector(array[0], array[1], array[2]);
755+
}
756+
757+
/**
758+
* Applies a matrix to a vector.
759+
* The fourth component is set to 1.
760+
* Returns the result of dividing the 1st to 3rd components
761+
* of the result by the 4th component as a vector.
762+
*
763+
* @method multiplyAndNormalizePoint
764+
* @param {p5.Vector}
765+
* @return {p5.Vector}
766+
*/
767+
multiplyAndNormalizePoint(v) {
768+
const array = this.multiplyVec4(v.x, v.y, v.z, 1);
769+
array[0] /= array[3];
770+
array[1] /= array[3];
771+
array[2] /= array[3];
772+
return new p5.Vector(array[0], array[1], array[2]);
773+
}
774+
775+
/**
776+
* Applies a matrix to a vector.
777+
* The fourth component is set to 0.
778+
* Returns a vector consisting of the first
779+
* through third components of the result.
780+
*
781+
* @method multiplyDirection
782+
* @param {p5.Vector}
783+
* @return {p5.Vector}
784+
*/
785+
multiplyDirection(v) {
786+
const array = this.multiplyVec4(v.x, v.y, v.z, 0);
787+
return new p5.Vector(array[0], array[1], array[2]);
788+
}
789+
723790
/**
724791
* PRIVATE
725792
*/

0 commit comments

Comments
 (0)