2013-06-19 14 views
-4

我试图使星际争霸像three.js所游戏..三JS /在其Y轴网格面临方向的动画旋转

我有问题,它的Y轴旋转物体面对新的方向,然后改变立场。

并通过旋转我的意思是动画/所以请别再用蹩脚的lookAt()函数

,如果有人告诉我如何吐温一些魔术obj.MatrixRotationY(角度),我将不胜感激,我希望从的Vector3

计算,角度

这是我到目前为止有:

http://f.cl.ly/items/3J3R0X2q2R1h1J203C1V/drone.jpg

我从Vector3中获取了新的位置,如下所示。

// scene 
var container; 
var camera, scene, renderer; 

// intersect with objects in this array 
var intersectObjects = []; 

// materials 
var material = new THREE.MeshNormalMaterial(); 
var cristal_texture = new THREE.MeshLambertMaterial({ map: THREE.ImageUtils.loadTexture("models/JSON/textures/cristal.jpg") }); 
var destination; 

init(); 
animate(); 


function init() { 

    container = document.createElement('div'); 
    document.body.appendChild(container); 

    camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 1, 15000); 
    camera.rotation.x = - 90 * (Math.PI/180); 
    camera.position.set(800 , 1000 , 0); 

    scene = new THREE.Scene(); 

    plane = new THREE.Mesh(new THREE.PlaneGeometry(3000, 3000), new THREE.MeshBasicMaterial({ color: 0xe0e0e0 })); 
    plane.rotation.x = - 90 * (Math.PI/180); 
    plane.position.set(0,0,0); 
    plane.overdraw = true; 
    scene.add(plane); 
    intersectObjects.push(plane); 

    loader = new THREE.JSONLoader(); 
    loader.load("models/JSON/driller.js", function(geometry) { 
     driller = new THREE.Mesh(geometry, material); 
     driller.position.set(0,50,0); 
     matr = new THREE.Matrix4();  
     driller.matrixAutoUpdate = false; 
     driller.geometry.applyMatrix(matr.makeRotationY(0)); 
     driller.scale.set(0.5,0.5,0.5); 
     scene.add(driller); 
    }); 

    loade = new THREE.JSONLoader(); 
    loade.load("models/JSON/cristal.js", function(geometry) { 
     cristal = new THREE.Mesh(geometry, cristal_texture); 
     cristal.position.set(-1450,0,1450); 
     matre = new THREE.Matrix4();   
     cristal.matrixAutoUpdate = false; 
     cristal.geometry.applyMatrix(matre.makeRotationY(0)); 
     cristal.scale.set(0.5,0.5,0.5);   
     scene.add(cristal); 
     intersectObjects.push(plane); 
    }); 

    // lightning properties 
    var ambientLight = new THREE.AmbientLight(0xFFFFFF); 
    scene.add(ambientLight); 
    scene.matrixAutoUpdate = false; 

    // render engine 
    renderer = new THREE.WebGLRenderer({ antialias: true }); 
    renderer.setSize(window.innerWidth, window.innerHeight); 
    renderer.sortObjects = false; 
    container.appendChild(renderer.domElement); 

    // event listeners 
    document.addEventListener('mouseup', onMouseUp, false); 


} 

function onMouseUp(event) { 

    event.preventDefault();   
    x_pos = (event.clientX/window.innerWidth) * 2 - 1; 
    y_pos = -(event.clientY/window.innerHeight) * 2 + 1; 
    z_pos = 0.5; 

    var vector = new THREE.Vector3(x_pos , y_pos , z_pos); 

    var projector = new THREE.Projector(); 
    projector.unprojectVector(vector, camera); 
    var raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize()); 
    var intersects = raycaster.intersectObjects(intersectObjects); 

    if (intersects.length > 0) { 

     xp = intersects[0].point.x.toFixed(2); 
     yp = intersects[0].point.y.toFixed(2); 
     zp = intersects[0].point.z.toFixed(2); 
     destination = new THREE.Vector3(xp , 50 , zp); 

     var se23k = Math.random() * 4 * 4 ; 
     new TWEEN.Tween(driller.rotation).to({ y: se23k }, 1000).easing(TWEEN.Easing.Linear.None).start(); 

    } 

    else { 
     console.log('outside boundaries'); 
    } 

}; 

function update(){ 

    camera.lookAt(plane.position); 
    renderer.render(scene, camera); 
} 

function animate() { 

    requestAnimationFrame(animate);  
    update(); 
    render(); 
} 

function render() { 
    driller.updateMatrix(); 
    cristal.updateMatrix(); 

    TWEEN.update(); 
    renderer.render(scene, camera);  
} 
+0

如果通过旋转你的意思是动画,为什么不直接说,摆在首位?你是什​​么意思“所以请停下来一个糟糕的lookAt()函数”?看起来你需要结合使用补间lookAt()来获得你想要的效果。你是否试图在不使用lookAt()函数的情况下编写代码? –

+0

稍后会尝试并提供更大的答案,但它会涉及从欧拉角度创建两个Quaterions,以及它们之间的距离。 http://threejs.org/docs/58/#Reference/Math/Quaternion #slerp –

+0

此外,如果您删除关于lookAt的行,您将获得更少的downvotes - lookAt对于多种情况非常重要和有用的函数。虽然它不适合你的问题,但它肯定不是“蹩脚的”。 –

回答

0

我觉得这个问题听起来很熟悉 - 也许问题和答案在three.js parent child target tracking会有帮助吗?

+0

是的,我无法在任何地方找到适当的教程。 这只是没有提示任何地方这个简单的职位。我在这里粘贴了我的代码,以便每个人都可以看到我迄今为止所做的。 为了我的这个迷你项目,我需要能够声明单个实体及其属性,例如:drone.speed,drone.shield等。我发现如何使用class {}来做到这一点。但对我来说,最大的问题是如何动画整个东西。如果lookAt()可用于在其Y轴上旋转对象,则YES将使用它。 –

+0

而且由于无人机并非真的是场景中任何元素的孩子,所以很难使用你的提示。 –

+0

有人吗?有没有人有想法? –

1

下面是一些代码,它可以使指向Z轴的船舶顺利地指向X轴。

有一个在http://youtu.be/jBlDVSBv_m4

演示视频我已经修剪了渲染设置的巨大的部分,把重点只在四元数slerping。

以下代码位于咖啡脚本中,并使用S3age中的几个自定义类;我已经在可能的情况下评论了他们。如果这有问题,请在评论中提及它,然后我将它重写到VanillaJS。

# RequireJS preamble, not important. 
define ["util/stage", "game/clock"], 
    (Stage, Clock)-> 
     ### 
     # Ship is a constructor. 
     # It uses no ctor arguments, but does pass them to Object3D. 
     ### 
     Ship = (Object3DArgs)-> 
      # Ship directly extends Object3D 
      THREE.Object3D.apply @, arguments 
      @build() 

      # The critical piece - use the model's quaternion, not its rotation 
      @useQuaternion = yes 
      @ 

     # Finish subclassing, by creating a new prototype chain. 
     Ship:: = Object.create THREE.Object3D:: 
     ### 
     # Create some geometry, materials, etc. Not important, could be from 
     # Collada/JSON/etcLoader 
     # Important part is noticing the rotation and position are set relative to 
     # the Ship object itself; moving or rotating @ will move/rotate the 
     # geometry inside it implicitly. 
     ### 
     Ship::build = -> 
      geom = new THREE.CylinderGeometry 0, 3, 1.5, 20, 1 
      mat = new THREE.MeshLambertMaterial 
      @hull = new THREE.Mesh geom, mat 
      @hull.scale.set(0.3, 1, 0.1) 
      @hull.rotation.set(Math.PI/2, 0, 0) 
      @hull.position.set(0, 0, 0.33) 
      @add @hull 
      @ 


     ### 
     # An easing function, to go from ticks on a frame counter to some 
     # percentage between zero and one, over the course of some time. 
     ### 
     ease = do -> 
      seconds = 4 
      d = time = (seconds * 60) 
      b = 0.0 
      c = 1.0 
      #easeInOutQuad from http://www.robertpenner.com/easing/ 
      (t) -> 
       # Constrain `t` between `0` and the animation's duration 
       t %= d 
       if ((t /= d/2) < 1) 
        c/2*t*t + b 
       else 
        -c/2 * ((--t)*(t-2) - 1) + b 

     # Y is the axis to rotate through. In this instance, it is the Y axis. 
     # In general, it should be the "Up" vertex of the model. 
     # You will calculate this when the user clicks. 
     y = new THREE.Vector3(0, 1, 0) 

     # r0 is the initial direction when the animation starts; 
     # that is, the "up" vector at theta=0 
     r0 = new THREE.Quaternion() 
     r0.setFromAxisAngle(y, 0) 

     # r1 is the desired direction. Calculate theta from the dot product of the 
     # ship's normal with the vector pointing from the ship to the target (eg 
     # target.position - ship.position) 
     r1 = new THREE.Quaternion() 
     r1.setFromAxisAngle(y, Math.PI/2) 

     ### 
     # The update function will get called every physics update. 
     # Clock has time, delta, and frame. 
     # Frame is number of ticks, time is total time elapsed, 
     # delta is time since last update. 
     ### 
     Ship::update = (clock)-> 
      # Get the prct between zero and one of how far through 
      # the animation the clock is 
      prct = ease clock.frame 
      # Use the static slerp, storing the result directly 
      # in the ship's quaternion. 
      THREE.Quaternion.slerp r0, r1, @quaternion, prct 

     # A convention in my loader, not important. 
     # Creates a S3age, gets the scene, etc. 
     play: (selector)-> 
      stage = new Stage selector 
      stage.scene = new THREE.Scene() 

      stage.scene.add ship = new Ship() 

      # Some lights, controls, an axis. 
      stage.scene.add new THREE.AmbientLight 0x404040 
      stage.scene.add light = new THREE.PointLight 0xF0F0F0, 1, 100 
      light.position.set(20, 30, 50) 
      stage.controls = new THREE.Trackball stage.camera, stage.container 
      stage.camera.position.set(2, 5, -5) 
      stage.scene.add new THREE.AxisHelper(2) 
      # Call the update function every time the clock goes tick-tock 
      (new Clock()).addEventListener 'tick', (event)-> 
       clock = event.clock 
       ship.update clock 
      stage.start() 
+1

我想我会尝试并采取一些这一点,并将其添加到四元文档。 –

0

其实,我已经找到了更快的解决方案;)

 xp = intersects[0].point.x.toFixed(2); 
     yp = intersects[0].point.y.toFixed(2); 
     zp = intersects[0].point.z.toFixed(2); 
     destination = new THREE.Vector3(xp , yp , zp); 

     radians = Math.atan2((driller.position.x - xp) , (driller.position.z - zp)); 
     radians += 90 * (Math.PI/180); 

     var tween = new TWEEN.Tween(driller.rotation).to({ y : radians },200).easing(TWEEN.Easing.Linear.None).start(); 
+0

弧度+ = 90 *(Math。PI/180); <<这为钻机旋转设置了一个偏移量...... –

+0

我在一般情况下看不到这种情况......您正在从指向钻机的原点处的矢量获得旋转,指向原点处的矢量目标,而不是从向量指向司钻面向司钻向向目标的方向的旋转。 –

+0

嗯,我想那样。我能说什么 –