-
-
Notifications
You must be signed in to change notification settings - Fork 3.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
I want to improve the method of orbitControl () that translates the camera #6107
Comments
here is sample code. |
I think this change makes sense! it makes right-click-dragging more intuitive when the view has been rotated, and makes the interaction more consistent with other tools. |
Thanks for reply! I would like to raise a pull request based on this suggestion. |
Thanks! I'll assign this to you. |
After that, I found a bug in ortho() and frustum() that doesn't behave well when the absolute values of the left and right arguments are different, so I fixed it (even when the absolute values of top and bottom are different). I ended up with code like this: else if (this.mouseButton === this.RIGHT) {
var local = cam._getLocalAxes();
const diffX = cam.eyeX - cam.centerX;
const diffY = cam.eyeY - cam.centerY;
const diffZ = cam.eyeZ - cam.centerZ;
// get spherical coorinates for current camera position about origin
const viewZ = Math.sqrt(diffX * diffX + diffY * diffY + diffZ * diffZ);
// position vector of the center
let cv = createVector(cam.centerX, cam.centerY, cam.centerZ);
const cMat = cam.cameraMatrix.mat4;
const uP = this._renderer.uPMatrix.mat4;
// Calculate the normalized device coordinates of the center
cv = _applyMatrixToVector3(cMat, cv);
cv = _applyMatrixToVector3(uP, cv, true);
// Normalize mouse movement distance
const ndcX = (this.mouseX - this.pmouseX)*2/this.width;
const ndcY = -(this.mouseY - this.pmouseY)*2/this.height;
// Move the center by this distance
// in the normalized device coordinate system
cv.x -= ndcX;
cv.y -= ndcY;
// Calculate the translation vector
// in the direction perpendicular to the line of sight of center
let dx, dy;
if(uP[15] === 0){
dx = ((uP[8] + cv.x)/uP[0]) * viewZ;
dy = ((uP[9] + cv.y)/uP[5]) * viewZ;
}else{
dx = (cv.x - uP[12])/uP[0];
dy = (cv.y - uP[13])/uP[5];
}
cam.setPosition(
cam.eyeX + dx * local.x[0] + dy * local.y[0],
cam.eyeY + dx * local.x[1] + dy * local.y[1],
cam.eyeZ + dx * local.x[2] + dy * local.y[2]
);
}
/* ------------------------------ */
function _applyMatrixToVector3(m, v, divideFlag=false){
const a = m[0]*v.x + m[4]*v.y + m[8]*v.z + m[12];
const b = m[1]*v.x + m[5]*v.y + m[9]*v.z + m[13];
const c = m[2]*v.x + m[6]*v.y + m[10]*v.z + m[14];
const d = m[3]*v.x + m[7]*v.y + m[11]*v.z + m[15];
if(divideFlag){
return createVector(a/d,b/d,c/d);
}else{
return createVector(a,b,c);
}
} At that time, there was no function to apply a matrix to a vector, so I prepared a global function because the processing is complicated even though it is only used here. Is it permissible to write like this? |
Maybe it's worth making it a method on p5.Matrix instead of a global function so that we make that class more useful as a nice side effect? It's inconvenient that p5.Vector doesn't have a
|
I tried to write it by imitating what I saw, but is it like this...? /**
* apply a matrix to a vector with x,y,z,w components
* get the results in the form of an array
* @method multiplyVec4
* @param {Number}
* @return {Number[]}
*/
multiplyVec4(x, y, z, w) {
const result = new Array(4);
result[0] = this.mat4[0] * x + this.mat4[4] * y + this.mat4[8] * z + this.mat4[12] * w;
result[1] = this.mat4[1] * x + this.mat4[5] * y + this.mat4[9] * z + this.mat4[13] * w;
result[2] = this.mat4[2] * x + this.mat4[6] * y + this.mat4[10] * z + this.mat4[14] * w;
result[3] = this.mat4[3] * x + this.mat4[7] * y + this.mat4[11] * z + this.mat4[15] * w;
return result;
} |
I also tried the rest of the methods. /**
* Applies a matrix to a vector.
* The fourth component is set to 1.
* Returns a vector consisting of the first
* through third components of the result.
*
* @method multiplyPoint
* @param {p5.Vector}
* @return {p5.Vector}
*/
multiplyPoint(v) {
const array = this.multiplyVec4(v.x, v.y, v.z, 1);
return new p5.Vector(array[0], array[1], array[2]);
}
/**
* Applies a matrix to a vector.
* The fourth component is set to 1.
* Returns the result of dividing the 1st to 3rd components
* of the result by the 4th component as a vector.
*
* @method multiplyAndNormalizePoint
* @param {p5.Vector}
* @return {p5.Vector}
*/
multiplyAndNormalizePoint(v) {
const array = this.multiplyVec4(v.x, v.y, v.z, 1);
array[0] /= array[3];
array[1] /= array[3];
array[2] /= array[3];
return new p5.Vector(array[0], array[1], array[2]);
};
/**
* Applies a matrix to a vector.
* The fourth component is set to 0.
* Returns a vector consisting of the first
* through third components of the result.
*
* @method multiplyDirection
* @param {p5.Vector}
* @return {p5.Vector}
*/
multiplyDirection(v) {
const array = this.multiplyVec4(v.x, v.y, v.z, 0);
return new p5.Vector(array[0], array[1], array[2]);
} Also, when I introduced this as a method of p5.Matrix in the sample and rewrote it, I was able to confirm that it worked properly. |
Looks good! |
Increasing Access
In the current specification, you can move the camera parallel by pressing the right mouse button while using orbitControl().
However, I think this is difficult to understand intuitively. This is because the movement range of the fixation point is limited to the direction parallel to the XZ plane. Therefore, when moving vertically, it moves backwards and forwards instead of vertically.
For example, blender's default behavior is to hold down the shift key and press the middle mouse button to move the camera so that the object moves in the direction the mouse is moving. So I think it should be done that way.
Another issue is that the distance traveled is specified along the default camera, so it doesn't behave well at different scales. At small scales it moves too much and at large scales it moves very little.
This is also no problem in blender. Also, the above problem does not occur with easyCam.js.
2023-04-19.00-14-07.mp4
The video below demonstrates how the current right button translation method works. At the end, if you use the right button on a small scale, the object will fly away.
Most appropriate sub-area of p5.js?
Feature enhancement details
The idea is to first find the view coordinates of a point in the view coordinate system that is at the same depth as the gaze point, corresponding to the position moved on the canvas by the mouse movement vector.
Translate this into a global position change using the camera's coordinate system.
Finally, use setPosition() to add this vector to each of the viewpoint and gaze point, and you're done.
At that time, we want the object to move in the direction of the mouse movement, so we reverse the obtained vector in the direction of the camera movement.
The result of applying this patch is below: (Note that I have applied a patch that makes scaling smooth with the mouse wheel, because it is easier to verify. This has not been merged yet.)
2023-04-19.00-33-50.mp4
I don't know if there are any disadvantages due to moving the gaze point not parallel to the XZ plane. I would like to leave it to the user's judgment after implementing this. I feel I should do this.
If such a disadvantage exists, I am considering withdrawing this proposal.
The text was updated successfully, but these errors were encountered: