I'm trying to implement a first person movement using the mouse.
I do have it working with keyboard yet I'm having difficulties implementing it using mouse since movement to a specific side isn't that clear (i.e moving left can include moving up or down).
I want to use the matrix3d
in order to receive changed values of the position.
EDIT #2 Here is a jsfiddle.
EDIT I've pasted the new code I've managed to resolve:
$(document).on('mousemove', function (e) {
var MOVE = 10; // how much to move
var XTURN = 1; // how much to rotate
var YTURN = 1; // how much to rotate
var transformer, origMat, translationMatrix, result;
transformer = document.getElementById("transformer");
if ($.browser.webkit)
origMat = new WebKitCSSMatrix(window.getComputedStyle(transformer).webkitTransform);
//turn left
if (e.pageX < xPrev) {
if (XTURN < 0) {
XTURN *= -1;
}
xPrev = e.pageX;
//turn right
} else {
if (XTURN > 0) {
XTURN *= -1;
}
xPrev = e.pageX;
}
//look up
if (e.pageY < yPrev) {
if (YTURN < 0) {
YTURN *= -1;
}
yPrev = e.pageY;
//look down
} else {
if (YTURN > 0) {
YTURN *= -1;
}
yPrev = e.pageY;
}
translationMatrix = new WebKitCSSMatrix("matrix3d(" + cos(XTURN).toFixed(10) + ",0," + sin(XTURN).toFixed(10) + ",0,0,"+ cos(-YTURN).toFixed(10) +","+ sin(YTURN).toFixed(10) +",0, " + sin(-XTURN).toFixed(10) + ","+ sin(-YTURN).toFixed(10) +"," + cos(XTURN).toFixed(10) + ",0,0,0,0,1)");
transformer.style.webkitTransform = translationMatrix.multiply(origMat).toString();
});
As you can see (Sorry for the one line matrix) I'm stating the changes of the X and Y rotations on the same matrix change and then committing it, the issue now is with the cos(XTURN).toFixed(10)
which can be related to the X and Y rotations, so you can see it works but not perfect.
Would appreciate any tips/ideas.
P.S I don't want to use the Pointer Lock API, even though it's great, since I want it to support maximal number of browsers.
Pure JavaScript is mostly better than libraries (unless it's a "Code less do more" thing),
since you can understand what your code really does.
This is my entire JavaScript code:
var velocity = 0.5;
document.onmousemove = function(e) {
var angleX = e.pageY * velocity * Math.PI / 180;
var angleY = e.pageX * velocity * Math.PI / 180;
document.getElementById('transformer').style.webkitTransform = 'matrix3d(' + Math.cos(-angleY) + ',0,' + Math.sin(-angleY) + ',0,' + (Math.sin(angleX)*Math.sin(-angleY)) + ',' + Math.cos(angleX) + ',' + (-Math.sin(angleX)*Math.cos(-angleY)) + ',0,' + (-Math.cos(angleX)*Math.sin(-angleY)) + ',' + Math.sin(angleX) + ',' + (Math.cos(angleX)*Math.cos(-angleY)) + ',0,0,0,0,1)';
};
And this is the fiddle.
It works!
(I even made an example of this using the Pointer Lock API: fiddle (click the square to begin)
Explanation:
First, a velocity variable to easily set the rotation speed.
Then, a mousemove
event which has the two rotation variabls set.
The last line is to convert from rotateX
and rotateY
transformations, to matrix3d
as requested.
This Stackoverflow question helped me get to the following solution.
rotateX(angleX)
is equal to the following matrix:
1 0 0 0
0 cos(angleX) -sin(angleX) 0
0 sin(angleX) cos(angleX) 0
0 0 0 1
rotateY(angleY)
is equal to the following matrix:
cos(angleY) 0 sin(angleY) 0
0 1 0 0
-sin(angleY) 0 cos(angleY) 0
0 0 0 1
And to use them both together, you need to multiply the two matrices. So I wrote a small JavaScript tool to give me the calculation I need to do to get the result of this multiplication.
The result:
cos(angleY) sin(angleX)*sin(angleY) cos(angleX)*sin(angleY) 0
0 cos(angleX) -sin(angleX) 0
-sin(angleY) sin(angleX)*cos(angleY) cos(angleX)*cos(angleY) 0
0 0 0 1
And that's the way to convert rotateX
and rotateY
to matrix3d
.
Hope it helps :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With