【问题标题】:rotating player camera on a sphere (javascript/three.js)在球体上旋转玩家相机 (javascript/three.js)
【发布时间】:2019-07-12 23:56:32
【问题描述】:

我正在尝试让玩家在三个.js / javascript 中以第一人称视角在行星上行走。在我正在编码的内容中,我想要两件事:

a) 玩家在行星周围正确移动,有两种移动类型:围绕自己旋转(左右和 A/D 按钮)和前后移动(W/S 按钮)。在此线程 https://gamedev.stackexchange.com/questions/59298/walking-on-a-sphere 的帮助下,我已经成功完成了这项工作。

b) 当玩家围绕自己旋转(A/D 按钮)时,连接到玩家的相机应该水平旋转(垂直于玩家所在的平面),并且相机应该从 0(最低点)移动到 180(天顶)度数 - 表示玩家向上和向下看,使用向上箭头/向下箭头按钮(最终使用鼠标,但稍后会出现)。

我遇到了 b 的问题,它最初可以正确旋转,但随着玩家继续前进,相机会跳到其他位置。

为了帮助我“调试”问题,我创建了一个 ArrowHelper 对象,它最终应该是我们的相机。

html:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">

        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
        <meta http-equiv="Cache-Control" content="no-cache"/>
        <meta http-equiv="Expires" content="-1"/>
        <meta http-equiv="Pragma" content="no-cache"/>
        <title>Planet</title>
        <link href="planet.css" rel="stylesheet" type="text/css"/>
        <script src="../three.js/build/three.js"></script>
        <script src="../three.js/examples/js/libs/stats.min.js"></script>
        <script src="planet.js"></script>
    </head>
    <body>
        <div id="divScreen">
        </div>
    </body>
</html>

var g_Game;
var g_Player;

window.onload = function () {
    initGame();
}

function initGame() {
    g_Game = new C_Game();

    g_Game.container = document.getElementById("divScreen");
    document.body.appendChild(g_Game.container);

    g_Game.scene = new THREE.Scene();

    g_Game.cameraPerspective = new THREE.PerspectiveCamera( 90, 1 * g_Game.aspect, 1, 10000 );
    g_Game.cameraPerspective.position.set(0.0, 0.0, g_Game.cameraDistance);

    //textures
    var earthTexture = new THREE.TextureLoader().load( 'https://i.ibb.co/vYh8tLY/land-ocean-ice-cloud-2048.jpg' );

    g_Game.earth = new THREE.Mesh(
        new THREE.SphereBufferGeometry( 100, 128, 64 ),
        new THREE.MeshBasicMaterial( { map: earthTexture } )
    );
    g_Game.earth.position.set(0.0, 0.0, 0.0);
    g_Game.scene.add(g_Game.earth);

    g_Game.cubePlayer = new THREE.Mesh(
        new THREE.BoxBufferGeometry( 10, 10, 10 ),
        new THREE.MeshBasicMaterial( { wireframe: true } )
    );
    g_Game.cubePlayer.position.set(0.0, 0.0, 105.0);
    //g_Game.cubePlayer.add(g_Game.cameraPerspective);
    //g_Game.cameraPerspective.position.z = 0;
    g_Game.scene.add(g_Game.cubePlayer);

    var matrix = new THREE.Matrix4();
    matrix.extractRotation(g_Game.cubePlayer.matrix);
    var direction = new THREE.Vector3( 0, 1, 0 );
    direction.applyMatrix4(matrix);
    var dir = direction.normalize();

    var origin = g_Game.cubePlayer.position; //new THREE.Vector3( 0, 0, 105 );
    var length = 10;
    var color = 0xff0000;
    arrowHelper = new THREE.ArrowHelper( dir, origin, length, color );
    g_Game.cubeaxis = dir;
    g_Game.scene.add(arrowHelper);

    g_Game.cameraPerspective.lookAt(g_Game.earth.position);

    g_Game.renderer = new THREE.WebGLRenderer( { antialias: true } );
    g_Game.renderer.setPixelRatio( window.devicePixelRatio );
    g_Game.renderer.setSize( g_Game.SCREEN_WIDTH, g_Game.SCREEN_HEIGHT );
    g_Game.container.appendChild( g_Game.renderer.domElement );
    g_Game.renderer.autoClear = false;

    //g_Game.stats = new Stats();
    //g_Game.stats.showPanel(0);
    //g_Game.container.appendChild(g_Game.stats.dom);

    g_Player = new C_Player();
    g_Player.setspeed(0.08, 0.8);

    jsSetEventHandlers();

    animate();
}

function jsSetEventHandlers() {
    window.addEventListener("resize", onWindowResize, false );

    window.addEventListener("keydown", onKeyDown, false);
    window.addEventListener("keyup", onKeyUp, false);
};

// Keyboard key down
function onKeyDown(e) {
    switch (e.keyCode) {
        case 37: // Left
        case 65: // A
            g_Player.keyleft = true;
            break;
        case 38: // Up
            g_Player.keyarrowup = true;
            break;
        case 87: // W
            g_Player.keyup = true;
            break;
        case 39: // Right
        case 68: // D
            g_Player.keyright = true;
            break;
        case 40: // Down
            g_Player.keyarrowdown = true;
            break;
        case 83: // S
            g_Player.keydown = true;
            break;  
    }
}

// Keyboard key up
function onKeyUp(e) {
    switch (e.keyCode) {
        case 37: // Left
        case 65: // A
            g_Player.keyleft = false;
            break;
        case 38: // Up
            g_Player.keyarrowup = false;
            break;
        case 87: // W
            g_Player.keyup = false;
            break;
        case 39: // Right
        case 68: // D
            g_Player.keyright = false;
            break;
        case 40: // Down
            g_Player.keyarrowdown = false;
            break;
        case 83: // S
            g_Player.keydown = false;
            break;  
    }
}

function onWindowResize() {
    g_Game.SCREEN_WIDTH = window.innerWidth;
    g_Game.SCREEN_HEIGHT = window.innerHeight;
    g_Game.aspect = g_Game.SCREEN_WIDTH / g_Game.SCREEN_HEIGHT;
    g_Game.renderer.setSize(g_Game.SCREEN_WIDTH, g_Game.SCREEN_HEIGHT);
    g_Game.cameraPerspective.aspect = 1 * g_Game.aspect;
    g_Game.cameraPerspective.updateProjectionMatrix();
}

function animate() {
    requestAnimationFrame(animate);
    //g_Game.stats.begin();

    render();

    //g_Game.stats.end();
}

function render() {
    g_Player.update();
    g_Game.renderer.render(g_Game.scene, g_Game.cameraPerspective);
}

//Classes
var C_Player = function() {
    this.ANGULAR_SPEED_MOVEMENT = 0.8;
    this.ANGULAR_SPEED_ROTATION = 0.08;

    this.keyleft = false;
    this.keyright = false;
    this.keyup = false;
    this.keydown = false;
    this.keyarrowup = false;
    this.keyarrowdown = false;
    this.QuatKeyU;
    this.QuatKeyD;
    this.QuatKeyL;
    this.QuatKeyR;

    this.setspeed = function(speedM, speedR) {
        this.ANGULAR_SPEED_MOVEMENT = speedM;
        this.ANGULAR_SPEED_ROTATION = speedR;
        this.QuatKeyU = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(1, 0, 0), -(this.ANGULAR_SPEED_MOVEMENT*Math.PI) / 180);
        this.QuatKeyD = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(1, 0, 0),  (this.ANGULAR_SPEED_MOVEMENT*Math.PI) / 180);
        this.QuatKeyL = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 0, 1),  (this.ANGULAR_SPEED_ROTATION*Math.PI) / 180);
        this.QuatKeyR = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 0, 1), -(this.ANGULAR_SPEED_ROTATION*Math.PI) / 180);
    }

    var qx;
    var qy;
    var qz;
    var qw;
    var rotWorldMatrix;

    this.update = function(seconds) {
        var rlud = false;

        if (this.keyup) {
            g_Game.cubePlayer.quaternion.multiply(this.QuatKeyU);
            g_Game.cameraPerspective.quaternion.multiply(this.QuatKeyU);
            arrowHelper.quaternion.multiply(this.QuatKeyU);
            rlud = true;
        } else if (this.keydown) {
            g_Game.cubePlayer.quaternion.multiply(this.QuatKeyD);
            g_Game.cameraPerspective.quaternion.multiply(this.QuatKeyD);
            arrowHelper.quaternion.multiply(this.QuatKeyD);
            rlud = true;
        };
        if (this.keyleft) {
            g_Game.cubePlayer.quaternion.multiply(this.QuatKeyL);
            g_Game.cameraPerspective.quaternion.multiply(this.QuatKeyL);
            arrowHelper.quaternion.multiply(this.QuatKeyL);
            rlud = true;
        } else if (this.keyright) {
            g_Game.cubePlayer.quaternion.multiply(this.QuatKeyR);
            g_Game.cameraPerspective.quaternion.multiply(this.QuatKeyR);
            arrowHelper.quaternion.multiply(this.QuatKeyR);
            rlud = true;
        };

        if (rlud == true) {
            qx = g_Game.cubePlayer.quaternion.x;
            qy = g_Game.cubePlayer.quaternion.y;
            qz = g_Game.cubePlayer.quaternion.z;
            qw = g_Game.cubePlayer.quaternion.w;
            g_Game.cubePlayer.position.x = 2 * (qy * qw + qz * qx) * 105;
            g_Game.cubePlayer.position.y = 2 * (qz * qy - qw * qx) * 105;
            g_Game.cubePlayer.position.z = ((qz * qz + qw * qw) - (qx * qx + qy * qy)) * 105;

            qx = g_Game.cameraPerspective.quaternion.x;
            qy = g_Game.cameraPerspective.quaternion.y;
            qz = g_Game.cameraPerspective.quaternion.z;
            qw = g_Game.cameraPerspective.quaternion.w;
            g_Game.cameraPerspective.position.x = 2 * (qy * qw + qz * qx) * g_Game.cameraDistance;
            g_Game.cameraPerspective.position.y = 2 * (qz * qy - qw * qx) * g_Game.cameraDistance;
            g_Game.cameraPerspective.position.z = ((qz * qz + qw * qw) - (qx * qx + qy * qy)) * g_Game.cameraDistance;

            qx = arrowHelper.quaternion.x;
            qy = arrowHelper.quaternion.y;
            qz = arrowHelper.quaternion.z;
            qw = arrowHelper.quaternion.w;
            arrowHelper.position.x = 2 * (qy * qw + qz * qx) * 105;
            arrowHelper.position.y = 2 * (qz * qy - qw * qx) * 105;
            arrowHelper.position.z = ((qz * qz + qw * qw) - (qx * qx + qy * qy)) * 105;
        }

        if (this.keyarrowup) {
            var q = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(1, 0, 0), -(this.ANGULAR_SPEED_MOVEMENT*Math.PI*10) / 180);
            arrowHelper.quaternion.multiply(q);
            // TRIAL AND ERRORS HERE
            //arrowHelper.rotateOnWorldAxis(new THREE.Vector3(1, 0, 0), -(this.ANGULAR_SPEED_MOVEMENT*Math.PI) / 180);
            //arrowHelper.rotateOnAxis(new THREE.Vector3(1, 0, 0), -(this.ANGULAR_SPEED_MOVEMENT*Math.PI) / 180);
            /*      
            var matrix = new THREE.Matrix4();
            matrix.extractRotation(g_Game.cubePlayer.matrix);
            var direction = new THREE.Vector3( 0, 1, 0 );
            direction.applyMatrix4(matrix);
            var dir = direction.normalize();

            rotWorldMatrix = new THREE.Matrix4();
            rotWorldMatrix.makeRotationAxis(dir,  (this.ANGULAR_SPEED_ROTATION*Math.PI) / 180);
            rotWorldMatrix.multiply(g_Game.cubePlayer.matrix);
            g_Game.cubePlayer.matrix = rotWorldMatrix;
            g_Game.cubePlayer.rotation.setFromRotationMatrix(g_Game.cubePlayer.matrix);
            */
        }
        if (this.keyarrowdown) {
            var q = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(1, 0, 0), (this.ANGULAR_SPEED_MOVEMENT*Math.PI*10) / 180);
            arrowHelper.quaternion.multiply(q);
        }
    }
}

function C_Game() {
    this.SCREEN_WIDTH = window.innerWidth;
    this.SCREEN_HEIGHT = window.innerHeight;
    this.aspect = this.SCREEN_WIDTH / this.SCREEN_HEIGHT;
    this.container;
    this.stats;
    this.scene;
    this.renderer;
    this.earth;
    this.cubePlayer;
    this.controls;
    this.cameraPerspective;
    this.cameraDistance = 125;
    this.cubeaxis = new THREE.Vector3(1, 0, 0);
}
#divScreen {
    position: absolute;
    left: 0%;
    top: 0%;
    width: 100%;
    height: 100%;
    overflow: auto;
    margin: 0px;
    padding: 0px;
    border: 0px;    
    background-color: #AACCFF;
    overflow: hidden;
}
<script src="https://threejs.org/build/three.min.js"></script>
<div id="divScreen"></div>

我做了一些努力——我不太擅长四元数——但似乎没有任何效果。此时您可以看到 // TRIAL AND ERRORS HERE 我的各种轮换工作已被注释掉,因为它们都不起作用(包括未注释掉的)。

jsfiddle:https://jsfiddle.net/z18ctvme/3/

感谢您帮助解决此问题。 提前谢谢你

【问题讨论】:

    标签: javascript three.js rotation quaternions


    【解决方案1】:

    解决方案是您问题中的编码:

    连接到播放器的摄像头 [...]

    简化事情并将arrowHelper附加到g_Game.cubePlayer。这意味着arrowHelper 必须是g_Game.cubePlayer 而不是THREE.Scene() 的孩子:

    arrowHelper = new THREE.ArrowHelper( dir, new THREE.Vector3( 0, 0, 0 ), length, color );
    g_Game.cubePlayer.add(arrowHelper);
    

    这导致arrowHelper 相对于g_Game.cubePlayer 始终位于相同的位置。在这种情况下,相对位置是THREE.Vector3( 0, 0, 0 )

    arrowHelper.quaternion 只包含arrowHelper 的相对方向。
    this.keyarrowupthis.keyarrowdown 的情况下更新arrowHelper.quaternion 就足够了:

    this.update = function(seconds) {
        var rlud = false;
    
        if (this.keyup) {
            g_Game.cubePlayer.quaternion.multiply(this.QuatKeyU);
            g_Game.cameraPerspective.quaternion.multiply(this.QuatKeyU);
            rlud = true;
        } else if (this.keydown) {
            g_Game.cubePlayer.quaternion.multiply(this.QuatKeyD);
            g_Game.cameraPerspective.quaternion.multiply(this.QuatKeyD);
            rlud = true;
        };
        if (this.keyleft) {
            g_Game.cubePlayer.quaternion.multiply(this.QuatKeyL);
            g_Game.cameraPerspective.quaternion.multiply(this.QuatKeyL);
            rlud = true;
        } else if (this.keyright) {
            g_Game.cubePlayer.quaternion.multiply(this.QuatKeyR);
            g_Game.cameraPerspective.quaternion.multiply(this.QuatKeyR);
            rlud = true;
        };
    
        if (rlud == true) {
            qx = g_Game.cubePlayer.quaternion.x;
            qy = g_Game.cubePlayer.quaternion.y;
            qz = g_Game.cubePlayer.quaternion.z;
            qw = g_Game.cubePlayer.quaternion.w;
            g_Game.cubePlayer.position.x = 2 * (qy * qw + qz * qx) * 105;
            g_Game.cubePlayer.position.y = 2 * (qz * qy - qw * qx) * 105;
            g_Game.cubePlayer.position.z = ((qz * qz + qw * qw) - (qx * qx + qy * qy)) * 105;
    
            qx = g_Game.cameraPerspective.quaternion.x;
            qy = g_Game.cameraPerspective.quaternion.y;
            qz = g_Game.cameraPerspective.quaternion.z;
            qw = g_Game.cameraPerspective.quaternion.w;
            g_Game.cameraPerspective.position.x = 2 * (qy * qw + qz * qx) * g_Game.cameraDistance;
            g_Game.cameraPerspective.position.y = 2 * (qz * qy - qw * qx) * g_Game.cameraDistance;
            g_Game.cameraPerspective.position.z = ((qz * qz + qw * qw) - (qx * qx + qy * qy)) * g_Game.cameraDistance;
        }
    
        if (this.keyarrowup) {
            var q = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(1, 0, 0), -(this.ANGULAR_SPEED_MOVEMENT*Math.PI*10) / 180);
            arrowHelper.quaternion.multiply(q);
        }
        if (this.keyarrowdown) {
            var q = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(1, 0, 0), (this.ANGULAR_SPEED_MOVEMENT*Math.PI*10) / 180);
            arrowHelper.quaternion.multiply(q);
        }
    }
    

    查看示例,我将更改应用于您的原始代码:

    var g_Game;
    var g_Player;
    
    window.onload = function () {
    	initGame();
    }
    
    function initGame() {
    	g_Game = new C_Game();
    
    	g_Game.container = document.getElementById("divScreen");
    	document.body.appendChild(g_Game.container);
    
    	g_Game.scene = new THREE.Scene();
    
    	g_Game.cameraPerspective = new THREE.PerspectiveCamera( 90, 1 * g_Game.aspect, 1, 10000 );
    	g_Game.cameraPerspective.position.set(0.0, 0.0, g_Game.cameraDistance);
    	
    	//textures
    	var earthTexture = new THREE.TextureLoader().load( 'https://i.ibb.co/vYh8tLY/land-ocean-ice-cloud-2048.jpg' );
    	
    	g_Game.earth = new THREE.Mesh(
    		new THREE.SphereBufferGeometry( 100, 128, 64 ),
    		new THREE.MeshBasicMaterial( { map: earthTexture } )
    	);
    	g_Game.earth.position.set(0.0, 0.0, 0.0);
    	g_Game.scene.add(g_Game.earth);
    	
    	g_Game.cubePlayer = new THREE.Mesh(
    		new THREE.BoxBufferGeometry( 10, 10, 10 ),
    		new THREE.MeshBasicMaterial( { wireframe: true } )
    	);
    	g_Game.cubePlayer.position.set(0.0, 0.0, 105.0);
    	//g_Game.cubePlayer.add(g_Game.cameraPerspective);
    	//g_Game.cameraPerspective.position.z = 0;
    	g_Game.scene.add(g_Game.cubePlayer);
    
    	var matrix = new THREE.Matrix4();
    	matrix.extractRotation(g_Game.cubePlayer.matrix);
    	var direction = new THREE.Vector3( 0, 1, 0 );
    	direction.applyMatrix4(matrix);
    	var dir = direction.normalize();
    
    	var origin = g_Game.cubePlayer.position; //new THREE.Vector3( 0, 0, 105 );
    	var length = 10;
    	var color = 0xff0000;
    	
      arrowHelper = new THREE.ArrowHelper( dir, new THREE.Vector3( 0, 0, 0 ), length, color );
      g_Game.cubePlayer.add(arrowHelper);
    
    	g_Game.cubeaxis = dir;
    
    
    	g_Game.cameraPerspective.lookAt(g_Game.earth.position);
    
    	g_Game.renderer = new THREE.WebGLRenderer( { antialias: true } );
    	g_Game.renderer.setPixelRatio( window.devicePixelRatio );
    	g_Game.renderer.setSize( g_Game.SCREEN_WIDTH, g_Game.SCREEN_HEIGHT );
    	g_Game.container.appendChild( g_Game.renderer.domElement );
    	g_Game.renderer.autoClear = false;
    
    	//g_Game.stats = new Stats();
    	//g_Game.stats.showPanel(0);
    	//g_Game.container.appendChild(g_Game.stats.dom);
    
    	g_Player = new C_Player();
    	g_Player.setspeed(0.08, 0.8);
    
    	jsSetEventHandlers();
    	
    	animate();
    }
    
    function jsSetEventHandlers() {
    	window.addEventListener("resize", onWindowResize, false );
    
    	window.addEventListener("keydown", onKeyDown, false);
    	window.addEventListener("keyup", onKeyUp, false);
    };
    
    // Keyboard key down
    function onKeyDown(e) {
    	switch (e.keyCode) {
    		case 37: // Left
    		case 65: // A
    			g_Player.keyleft = true;
    			break;
    		case 38: // Up
    			g_Player.keyarrowup = true;
    			break;
    		case 87: // W
    			g_Player.keyup = true;
    			break;
    		case 39: // Right
    		case 68: // D
    			g_Player.keyright = true;
    			break;
    		case 40: // Down
    			g_Player.keyarrowdown = true;
    			break;
    		case 83: // S
    			g_Player.keydown = true;
    			break;	
    	}
    }
    
    // Keyboard key up
    function onKeyUp(e) {
    	switch (e.keyCode) {
    		case 37: // Left
    		case 65: // A
    			g_Player.keyleft = false;
    			break;
    		case 38: // Up
    			g_Player.keyarrowup = false;
    			break;
    		case 87: // W
    			g_Player.keyup = false;
    			break;
    		case 39: // Right
    		case 68: // D
    			g_Player.keyright = false;
    			break;
    		case 40: // Down
    			g_Player.keyarrowdown = false;
    			break;
    		case 83: // S
    			g_Player.keydown = false;
    			break;	
    	}
    }
    
    function onWindowResize() {
    	g_Game.SCREEN_WIDTH = window.innerWidth;
    	g_Game.SCREEN_HEIGHT = window.innerHeight;
    	g_Game.aspect = g_Game.SCREEN_WIDTH / g_Game.SCREEN_HEIGHT;
    	g_Game.renderer.setSize(g_Game.SCREEN_WIDTH, g_Game.SCREEN_HEIGHT);
    	g_Game.cameraPerspective.aspect = 1 * g_Game.aspect;
    	g_Game.cameraPerspective.updateProjectionMatrix();
    }
    
    function animate() {
    	requestAnimationFrame(animate);
    	//g_Game.stats.begin();
    
    	render();
    
    	//g_Game.stats.end();
    }
    
    function render() {
    	g_Player.update();
    	g_Game.renderer.render(g_Game.scene, g_Game.cameraPerspective);
    }
    
    //Classes
    var C_Player = function() {
    	this.ANGULAR_SPEED_MOVEMENT = 0.8;
    	this.ANGULAR_SPEED_ROTATION = 0.08;
    
    	this.keyleft = false;
    	this.keyright = false;
    	this.keyup = false;
    	this.keydown = false;
    	this.keyarrowup = false;
    	this.keyarrowdown = false;
    	this.QuatKeyU;
    	this.QuatKeyD;
    	this.QuatKeyL;
    	this.QuatKeyR;
    	
    	this.setspeed = function(speedM, speedR) {
    		this.ANGULAR_SPEED_MOVEMENT = speedM;
    		this.ANGULAR_SPEED_ROTATION = speedR;
    		this.QuatKeyU = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(1, 0, 0), -(this.ANGULAR_SPEED_MOVEMENT*Math.PI) / 180);
    		this.QuatKeyD = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(1, 0, 0),  (this.ANGULAR_SPEED_MOVEMENT*Math.PI) / 180);
    		this.QuatKeyL = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 0, 1),  (this.ANGULAR_SPEED_ROTATION*Math.PI) / 180);
    		this.QuatKeyR = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 0, 1), -(this.ANGULAR_SPEED_ROTATION*Math.PI) / 180);
    	}
    
    	var qx;
    	var qy;
    	var qz;
    	var qw;
    	var rotWorldMatrix;
    
    	this.update = function(seconds) {
    		var rlud = false;
    
    		if (this.keyup) {
    			g_Game.cubePlayer.quaternion.multiply(this.QuatKeyU);
    			g_Game.cameraPerspective.quaternion.multiply(this.QuatKeyU);
    			rlud = true;
    		} else if (this.keydown) {
    			g_Game.cubePlayer.quaternion.multiply(this.QuatKeyD);
    			g_Game.cameraPerspective.quaternion.multiply(this.QuatKeyD);
    			rlud = true;
    		};
    		if (this.keyleft) {
    			g_Game.cubePlayer.quaternion.multiply(this.QuatKeyL);
    			g_Game.cameraPerspective.quaternion.multiply(this.QuatKeyL);
    			rlud = true;
    		} else if (this.keyright) {
    			g_Game.cubePlayer.quaternion.multiply(this.QuatKeyR);
    			g_Game.cameraPerspective.quaternion.multiply(this.QuatKeyR);
    			rlud = true;
    		};
    
    		if (rlud == true) {
    			qx = g_Game.cubePlayer.quaternion.x;
    			qy = g_Game.cubePlayer.quaternion.y;
    			qz = g_Game.cubePlayer.quaternion.z;
    			qw = g_Game.cubePlayer.quaternion.w;
    			g_Game.cubePlayer.position.x = 2 * (qy * qw + qz * qx) * 105;
    			g_Game.cubePlayer.position.y = 2 * (qz * qy - qw * qx) * 105;
    			g_Game.cubePlayer.position.z = ((qz * qz + qw * qw) - (qx * qx + qy * qy)) * 105;
    
    			qx = g_Game.cameraPerspective.quaternion.x;
    			qy = g_Game.cameraPerspective.quaternion.y;
    			qz = g_Game.cameraPerspective.quaternion.z;
    			qw = g_Game.cameraPerspective.quaternion.w;
    			g_Game.cameraPerspective.position.x = 2 * (qy * qw + qz * qx) * g_Game.cameraDistance;
    			g_Game.cameraPerspective.position.y = 2 * (qz * qy - qw * qx) * g_Game.cameraDistance;
    			g_Game.cameraPerspective.position.z = ((qz * qz + qw * qw) - (qx * qx + qy * qy)) * g_Game.cameraDistance;
        }
    		
    		if (this.keyarrowup) {
    			var q = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(1, 0, 0), -(this.ANGULAR_SPEED_MOVEMENT*Math.PI*10) / 180);
    			arrowHelper.quaternion.multiply(q);
    		}
    		if (this.keyarrowdown) {
    			var q = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(1, 0, 0), (this.ANGULAR_SPEED_MOVEMENT*Math.PI*10) / 180);
    			arrowHelper.quaternion.multiply(q);
    		}
    	}
    }
    
    function C_Game() {
    	this.SCREEN_WIDTH = window.innerWidth;
    	this.SCREEN_HEIGHT = window.innerHeight;
    	this.aspect = this.SCREEN_WIDTH / this.SCREEN_HEIGHT;
    	this.container;
    	this.stats;
    	this.scene;
    	this.renderer;
    	this.earth;
    	this.cubePlayer;
    	this.controls;
    	this.cameraPerspective;
    	this.cameraDistance = 125;
    	this.cubeaxis = new THREE.Vector3(1, 0, 0);
    }
    #divScreen {
    	position: absolute;
    	left: 0%;
    	top: 0%;
    	width: 100%;
    	height: 100%;
    	overflow: auto;
    	margin: 0px;
    	padding: 0px;
    	border: 0px;	
    	background-color: #AACCFF;
    	overflow: hidden;
    }
    <script src="https://threejs.org/build/three.min.js"></script>
    <div id="divScreen"></div>

    【讨论】:

    • 这就像哥伦布的蛋,就在我眼前。太感谢了。顺便说一句,有没有办法确定箭头助手是在 180 度(天顶)或 0 度(天底),这样我就可以在它到达这两个点时停止旋转?
    • 没关系,我想通了,每次触发事件时,我都会将旋转增量加到一个变量中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-22
    相关资源
    最近更新 更多