2012-10-09 140 views
2

我有一個簡單的three.js場景,其中包含一個3D Homer Simpson,在一架飛機上。我希望能夠用自己的Y軸旋轉他,使用鼠標。圍繞自己的y軸旋轉Collada模型

以下代碼是差不多那裏。這是我從一些地方拼湊起來的,還有我自己的一點點。問題在於,我無法繞着他的Y軸旋轉他,他的核心正好穿過他的中軸。

在包含的代碼中,如果我使用該框架作爲參考,他將圍繞一個圓圈旋轉。其中的圓周(在這個例子中是偶然的)大約是他站在飛機上的大小。

如果我刪除幀,而是使用模型旋轉,然後他幾乎打轉他的Y軸 - 除了我軸線只是他的身邊。我正在使用以下model。事實上,我希望他旋轉的方式就像他在3D模型庫中所做的那樣。如果你點擊3D查看並旋轉他,你會看到我想要實現的。

// nasty globals, but this is just a sandbox. 
var camera; 
var frame; 
var loader = new THREE.ColladaLoader(); 
var model; 
var plane; 
var renderer; 
var scene; 

var mouseX = 0; 
var mouseXOnMouseDown = 0; 
var targetRotation = 0; 
var targetRotationOnMouseDown = 0; 
var windowHalfX = 800/2; 

loader.load('Homer/models/body.dae', function(collada) { 
    model = collada.scene; 

    model.position.x = 0; 
    model.position.y = 0; 
    model.position.z = 100; 

    model.rotation.x = - Math.PI/2;  // stand Homer upright and facing the camera. 

    init(); 
    animate(); 
}); 

function init() 
{ 
    renderer = new THREE.WebGLRenderer(); 
    renderer.setSize(800, 800); 

    document.body.appendChild(renderer.domElement); 

    camera = new THREE.PerspectiveCamera(45, 1, 100, 10000); 

    camera.position.x = 50; 
    camera.position.y = 120; 
    camera.position.z = 600; 

    scene = new THREE.Scene(); 
    scene.add(model); 

    // Do I need a frame of reference to get Homer to spin on his own Y-axis instead of the scene's? 
    frame = new THREE.Object3D(); 
    frame.add(model); 
    scene.add(frame); 

    plane = new THREE.Mesh(new THREE.PlaneGeometry(400, 400), new THREE.MeshBasicMaterial({ color: 0xe0e0e0 })); 
    plane.geometry.applyMatrix(new THREE.Matrix4().makeRotationX(- Math.PI/2)); 
    scene.add(plane); 

    var light = new THREE.SpotLight(); 
    light.position.set(200, 500, 4000); 
    scene.add(light); 

    renderer.render(scene, camera); 

    // Spin Homer around when moving the mouse around 
    document.addEventListener('mousedown', onDocumentMouseDown, false); 
    document.addEventListener('touchstart', onDocumentTouchStart, false); 
    document.addEventListener('touchmove', onDocumentTouchMove, false); 
} 


function onDocumentMouseDown(event) { 
    event.preventDefault(); 
    document.addEventListener('mousemove', onDocumentMouseMove, false); 
    document.addEventListener('mouseup', onDocumentMouseUp, false); 
    document.addEventListener('mouseout', onDocumentMouseOut, false); 

    mouseXOnMouseDown = event.clientX - windowHalfX; 
    targetRotationOnMouseDown = targetRotation; 
} 

function onDocumentMouseMove() { 
    mouseX = event.clientX - windowHalfX; 
    targetRotation = targetRotationOnMouseDown + (mouseX - mouseXOnMouseDown) * 0.02; 
} 

function onDocumentMouseUp() { 
    document.removeEventListener('mousemove', onDocumentMouseMove, false); 
    document.removeEventListener('mouseup', onDocumentMouseUp, false); 
    document.removeEventListener('mouseout', onDocumentMouseOut, false); 
} 

function onDocumentMouseOut() { 
    document.removeEventListener('mousemove', onDocumentMouseMove, false); 
    document.removeEventListener('mouseup', onDocumentMouseUp, false); 
    document.removeEventListener('mouseout', onDocumentMouseOut, false); 
} 

function onDocumentTouchStart(event) { 
    if (event.touches.length === 1) { 
     event.preventDefault(); 
     mouseXOnMouseDown = event.touches[ 0 ].pageX - windowHalfX; 
     targetRotationOnMouseDown = targetRotation; 
    } 
} 

function onDocumentTouchMove(event) { 
    if (event.touches.length === 1) { 
     event.preventDefault(); 
     mouseX = event.touches[ 0 ].pageX - windowHalfX; 
     targetRotation = targetRotationOnMouseDown + (mouseX - mouseXOnMouseDown) * 0.05; 
    } 
} 

// Spin Homer around the Y-Axis 
function animate() { 
    requestAnimationFrame(animate); 

    // When we add the frame, he spins in a circle, about the size of the plane (that's spin size if coincidence) 
    frame.rotation.y += (targetRotation - frame.rotation.y) * 0.03; 

    // If we remove the frame from the scene, and use this line instead, Homer spins around the y-axis. 
    // But, the y-axis is along the outside of his leg and arm, not through his vertical center, which is what I want. 
    // model.rotation.z += (targetRotation - model.rotation.z) * 0.03; 
    renderer.render(scene, camera); 
} 

回答

6

這很棘手。問題在於荷馬的幾何讓他站在他的局部座標系中,右腳靠近原點。

,你會在這樣的情況下normallly做的是叫

geometry.applyMatrix(new THREE.Matrix4().makeTranslation(-distance, 0, 0)); 

和翻譯沿本地x軸的幾何形狀。那會讓荷馬居中,你就完成了。

如果你能弄清楚Collada數據結構,你可以這樣做。

另一個解決方案是這招:(1)使模型中的父母的孩子,(2)使母體另一對象的子,(3),然後通過一段距離偏移父:

在你init()功能,做到這一點

scene = new THREE.Scene(); 

renderer = new THREE.WebGLRenderer(); 
renderer.setSize(800, 800); 
document.body.appendChild(renderer.domElement); 

camera = new THREE.PerspectiveCamera(45, 1, 100, 10000); 
camera.position.x = 50; 
camera.position.y = 120; 
camera.position.z = 600; 
scene.add(camera); // don't forget this 

scene.add(new THREE.AxisHelper()); // frame of reference 

// ////////////////////////////////////////////////// 
// trick to accommodate geometry offset 
object = new THREE.Object3D(); 
scene.add(object); 

parent = new THREE.Object3D(); 
parent.position.x = -39; 
object.add(parent); 

parent.add(model); 
// ////////////////////////////////////////////////// 

,然後在animate()功能:

object.rotation.y += (targetRotation - object.rotation.y) * 0.03; 
+0

這工作。做得好。 – Muers

+0

工作完美,謝謝。 – dbarros