10

マウスを使用して一人称の動きを実装しようとしています。キーボードで動作していますが、特定の側への移動が明確ではないため、マウスを使用して実装するのは困難です (つまり、左に移動すると上下に移動する可能性があります)。matrix3d位置の変更された値を受け取るために使用したい。

EDIT #2ここにjsfiddleがあります。

EDIT私が解決した新しいコードを貼り付けました:

$(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();
    });

ご覧のとおり (1 行のマトリックスで申し訳ありません) 私は同じマトリックスの変更で X と Y の回転の変更を述べてから、それをコミットしています。問題はcos(XTURN).toFixed(10)、X と Y の回転に関連している可能性があることです。であるため、機能していることがわかりますが、完全ではありません。ヒントやアイデアをいただければ幸いです。

PS Pointer Lock APIは使用したくありませんが、最大数のブラウザーをサポートする必要があるためです。

4

3 に答える 3

3

純粋な JavaScript は、コードが実際に何をするかを理解できるため、ほとんどの場合、ライブラリよりも優れています (「コードが少なくて済む」ものでない限り) 。

これは私の JavaScript コード全体です。

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)';
};

そして、これがフィドルです。

できます!

(私は Pointer Lock API を使用してこの例を作成しました:フィドル(四角をクリックして開始)


説明:

まず、回転速度を簡単に設定できる速度変数。
次に、mousemove2 つの回転変数が設定されたイベント。
最後の行は、要求に応じ て変換元rotateXrotateY変換先を変換することです。この Stackoverflow の質問は、次の解決策にたどり着くのに役立ちました。matrix3d


rotateX(angleX)は次の行列と同じです。

1               0               0               0


0               cos(angleX)     -sin(angleX)    0


0               sin(angleX)     cos(angleX)     0


0               0               0               1

rotateY(angleY)は次の行列と同じです。

cos(angleY)     0               sin(angleY)     0


0               1               0               0


-sin(angleY)    0               cos(angleY)     0


0               0               0               1

両方を一緒に使用するには、2 つの行列を乗算する必要があります。そこで、この乗算の結果を得るために必要な計算を行う小さな JavaScript ツールを作成しました。

結果:

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

そして、それが と に変換するrotateX方法rotateYですmatrix3d

それが役に立てば幸い :)

于 2013-08-23T20:09:46.073 に答える
2

クォータニオンを使用すると、非常に簡単になります。Googleクロージャーライブラリで実装を見つけたので、例を作成しました(また、jsFiddleを確認してください):

goog.require('goog.vec.Quaternion');

var velocity = 0.5;

var lastX = null;
var lastY = null;
var angleX = 0;
var angleY = 0;

$(document).on('mousemove', function (e) {
    if (lastX == null) lastX = e.pageX;
    if (lastY == null) lastY = e.pageY;

    angleX += (e.pageX - lastX) * velocity * Math.PI / 180;
    angleY += (e.pageY - lastY) * velocity * Math.PI / 180;

    lastX = e.pageX;
    lastY = e.pageY;

    var quat = goog.vec.Quaternion.concat(
        goog.vec.Quaternion.fromAngleAxis(angleX, [0, 1, 0], []),
        goog.vec.Quaternion.fromAngleAxis(-angleY, [1, 0, 0], []), []);

    var matrix = goog.vec.Quaternion.toRotationMatrix4(quat, []);

    $("#transformer").css({
        webkitTransform: "matrix3d(" + matrix.join(",") + ")"
    });
});
于 2013-08-23T14:02:13.103 に答える