2016-04-15 77 views
0

我有一個雙擊功能,允許用戶雙擊汽車模型,並顯示哪些對象已相交;例如刮水器,格柵,輪胎等,並且該功能將它們顯示在具有雙擊相交的項目數量的列表中。JavaScript雙擊功能Three.js

但是,我現在試圖弄清楚,當點擊某個部分的汽車時,例如輪胎,它會顯示一段關於它們的信息。我可以看到這只是檢查相交對象的名稱,然後顯示相關文本(如果它與它相交)的情況,但是每次我去做我認爲正確的事情時,它就會將已有的函數打破爲指出整個事情不會運行的地方。

我不完全是一個JavaScript或Three.js專業版,但試圖進一步推進我的功能證明是相當困難的。

有什麼建議嗎?我已經包括了整個雙擊功能,但是它是在檢查底部附近是否有交叉點,這是需要進行改變的地方。

// On Mouse double click event function 
function onDoubleClick(event) { 
// Set the mouse down flag to false 
mouseDown = false; 

// Canvas x (left) and y (top) position 
var canvasLeft = 0; 
var canvasTop = 0; 

// "event.clientX" is the mouse x position. "event.clientY" is the mouse y position 
var tempX = event.clientX - canvasLeft; 
var tempY = event.clientY - canvasTop; 
// Create a normalised vector in 2d space 
var vector = new THREE.Vector3((tempX/window.innerWidth) * 2 - 1, - (tempY/innerHeight) * 2 + 1, 0.5); 

// Unproject a 2D point into the 3D word 
// Use the camera projection matrix to transform the vector to the 3D world space 
vector.unproject(camera); 

// Send a ray in the direction the user has clicked from the cameras position 
var raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize()); 

// Check if the ray has intersected with any objects and get intersections 
var intersects = raycaster.intersectObjects(objects, true); 

// Check if intersected with objects 
if (intersects.length > 0) { 
    var tempStr = "Number of items: " + intersects.length + " "; 
    // List the items that were hit 
    for(var i=0; i < intersects.length; i++){ 
     if(intersects[i].object.name != ""){ 
      // The mesh name set above 
      tempStr += " | Name: " + intersects[i].object.name; 
     } else { 
      // The names inside the model 
      tempStr += " | Name: " + intersects[i].object.parent.name; 
     } 
    } 

    //Debug information 
    document.getElementById("debugInfo").innerHTML = tempStr + ".<br>"; 
    //END 
} 

}

編輯: 這是javascript文件全代碼,改變雙擊功能的元素似乎停止加載頁面。

window.onload = init; 

// declare variables  
var scene,camera,renderer, container; 
var controls, guiControls, datGUI; 
var grid, color; 
var cube, cubeGeometry, cubeMaterial; 
var plane, planeGeometry, planeMaterial; 
var skyBoxMesh, texture_placeholder; 
var spotLight; 
var stats; 

// Handles the mouse events. 
var mouseOverCanvas; 
var mouseDown; 
// An array of objects that can be clicked on 
var objects = []; 

//DAE models 
var showroom ,carOld, carNew; 

var daeObject; 

var animations; 
var kfAnimations = []; 
var kfAnimationsLength = 0; 
var lastFrameCurrentTime = []; 

var clock = new THREE.Clock(); 

var mouseOverCanvas, mouseDown; 
var objectsClick=[]; 

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

    //creates empty scene 
    scene = new THREE.Scene(); 

    //camera 
    camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, .1, 500); 
    camera.position.x = 40; 
    camera.position.y = 40; 
    camera.position.z = 40; 
    camera.lookAt(scene.position); 

    //renderer 
    renderer = new THREE.WebGLRenderer({antialias:true}); 
    renderer.setClearColor(0xe6f2ff); 
    renderer.setSize(window.innerWidth, window.innerHeight); 
    renderer.shadowMap.enabled = true; 
    renderer.shadowMapSoft = true; 
    container.appendChild(renderer.domElement); 

    // Add an event to set if the mouse is over our canvas 
    renderer.domElement.onmouseover=function(e){ mouseOverCanvas = true; } 
    renderer.domElement.onmousemove=function(e){ mouseOverCanvas = true; } 
    renderer.domElement.onmouseout=function(e){ mouseOverCanvas = false; } 

    renderer.domElement.onmousedown=function(e){ mouseDown = true; } 
    renderer.domElement.onmouseup=function(e){ mouseDown = false; } 

    // Double Click Event. Set a function called "onDoubleClick" 
    renderer.domElement.ondblclick=onDoubleClick; 

    // stats 
    stats = new Stats(); 
    stats.domElement.style.position = 'absolute'; 
    stats.domElement.style.left = '0px'; 
    stats.domElement.style.top = '0px'; 
    container.appendChild(stats.domElement); 

    //adds controls 
    controls = new THREE.OrbitControls(camera, renderer.domElement); 
    controls.addEventListener('change', render); 

    var ambient = new THREE.AmbientLight(0xadad85); 
    scene.add(ambient); 

    //---------- creates grid --------------- 
    grid = new THREE.GridHelper(50,5); 
    color= new THREE.Color("rgb(255,0,0)"); 
    grid.setColors(0x000000); 
    scene.add(grid); 

    //----------- creates cube -------------- 
    cubeGeometry = new THREE.BoxGeometry(5,5,5); 
    cubeMaterial = new THREE.MeshPhongMaterial({color: 0xff3300}); 
    cube = new THREE.Mesh(cubeGeometry, cubeMaterial); 
    cube.position.x = 0; 
    cube.position.y = 6; 
    cube.position.z = 2.5; 
    cube.castShadow = true; 

    scene.add(cube); 

    //----------- creates plane --------------- 
    planeGeomenty= new THREE.PlaneGeometry(100,100,100); 
    planeMaterial = new THREE.MeshLambertMaterial({color: 0x00cc00}); 
    plane = new THREE.Mesh(planeGeomenty, planeMaterial); 
    //position the add objects to the scene 
    plane.rotation.x = -.5*Math.PI; 
    plane.receiveShadow = true; 
    scene.add(plane); 

    //------------- skyBox -------------- 
    texture_placeholder = document.createElement('canvas'); 
    texture_placeholder.width = 128; 
    texture_placeholder.height = 128; 

    var context = texture_placeholder.getContext('2d'); 
    context.fillStyle = 'rgb(200,200, 200)'; 
    context.fillRect(0, 0,texture_placeholder.width, texture_placeholder.height); 

    var materials = [ 
     loadTexture('images/skybox/posX.jpg'), 
     loadTexture('images/skybox/negX.jpg'), 
     loadTexture('images/skybox/posY.jpg'), 
     loadTexture('images/skybox/negY.jpg'), 
     loadTexture('images/skybox/posZ.jpg'), 
     loadTexture('images/skybox/negZ.jpg') 
     ]; 
    skyBoxMesh = new THREE.Mesh(new THREE.BoxGeometry(500,500,500,7,7,7), 
           new THREE.MeshFaceMaterial(materials)); 
    skyBoxMesh.scale.x = -1; 
    scene.add(skyBoxMesh); 

    //---------- loads collada files ----------- 
    loadCollada(); 

    daeObject = cube; 
    // initialise datGUI controls values 
    guiControls = new function() { 
     this.rotationY = 0.0; 

     this.positionX = 0.0; 
     this.positionY = 0.0; 
     this.positionZ = -10; 

     this.lightX = 20; 
     this.lightY = 35; 
     this.lightZ = 40; 

     this.intensity = 1; 
     this.distance = 0; 
     this.angle = 1.570; 
     this.target = cube; 
    } 

    //add spotLight with starting parameters 
    spotLight = new THREE.SpotLight(0xffffff); 
    spotLight.castShadow = true; 
    spotLight.position.set(20,35,40); 
    spotLight.intensity = guiControls.intensity; 
    spotLight.distance = guiControls.distance; 
    spotLight.angle = guiControls.angle; 
    scene.add(spotLight); 

    //adds controls on the scene 
    datGUI = new dat.GUI(); 
    // datGUI.add(guiControls, 'positionZ', 0, 1); 
    datGUI.add(guiControls, 'positionZ', -10, 25, 0.5). name("Move the car"); 
    datGUI.add(guiControls, 'rotationY', 0, 1).name('Rotate the car'); 

    datGUI.add(guiControls, 'lightX', -60, 180); 
    datGUI.add(guiControls, 'lightY', 0, 180); 
    datGUI.add(guiControls, 'lightZ', -60, 180); 

    datGUI.add(guiControls, 'target',[ 'cube','Modern Mini', 'Classic Mini']).onChange(function() { 
     if(guiControls.target == 'cube'){ 
      spotLight.target = cube; 
      daeObject = cube; 
     } 
     else if(guiControls.target == 'Classic Mini'){ 
      spotLight.target = carOld; 
      daeObject = carOld; 
     } 
     else if(guiControls.target = 'Modern Mini'){ 
      spotLight.target = carNew; 
      daeObject = carNew; 
     }   
    }); 

    datGUI.add(guiControls, 'intensity', 0.01, 5).onChange(function (value){ 
     spotLight.intensity = value; 
    }); 
    datGUI.add(guiControls, 'distance', 0, 1000).onChange(function (value){ 
     spotLight.distance = value; 
    }); 
    datGUI.add(guiControls, 'angle', 0.001, 1.570).onChange(function (value){ 
     spotLight.angle = value; 
    }); 

    datGUI.close(); 
    container.appendChild(renderer.domElement); 

    window.addEventListener('resize', onWindowResize, false); 
}  
//------------------------- END INIT() ---------------------------- 

function onWindowResize() { 
    camera.aspect = window.innerWidth/window.innerHeight; 
    camera.updateProjectionMatrix(); 
    renderer.setSize(window.innerWidth, window.innerHeight); 

} 

function loadCollada() { 
    //--- Loads the Classic Mini --- 
    colladaLoader = new THREE.ColladaLoader(); 
    colladaLoader.options.convertUpAxis = true; 
    colladaLoader.load('dae_files/ClassicMini.dae', function (collada) { 
     carOld = collada.scene; // stores dae file to a global variable 

     carOld.position.set(14.5, 1.8, -10);   
     carOld.scale.set(0.04, 0.04, 0.04);   

     carOld.traverse(function (child) { 
      child.castShadow = true; 
      child.receiveShadow = true; 
      }); 

     carOld.updateMatrix(); 
     carOld.name = "Classic"; 
     scene.add(carOld); 
     objects.push(carOld); 
    }); 

    //--- loads Modern Mini --- 
    colladaLoader = new THREE.ColladaLoader(); 
    colladaLoader.options.convertUpAxis = true; 
    colladaLoader.load('dae_files/ModernMini.dae', function (collada) { 
     carNew = collada.scene; 

     carNew.position.set(-14.5, 6.3, -10); 
     carNew.scale.set(0.06, 0.06, 0.06); 

     // creates shadow 
     carNew.traverse(function (child) { 
     child.castShadow = true; 
     child.receiveShadow = true; 
     }); 

     carNew.updateMatrix(); 
     carNew.name = "Modern"; 
     scene.add(carNew); 
     objects.push(carNew); 
    }); 

    //--- loads the Showroom ---  
    colladaLoader = new THREE.ColladaLoader(); 
    colladaLoader.options.convertUpAxis = true; 
    colladaLoader.load('dae_files/roomAnim2.dae', function collada(collada) { 
     showroom = collada.scene; 
     animations = collada.animations; 

     kfAnimationsLength = animations.length; 
     // Initialise last frame current time. 
     for (var i = 0; i < kfAnimationsLength; i++) { 
      lastFrameCurrentTime[i] = 0; 
     } 
     // Get all the key frame animations. 
     for (var i = 0; i < kfAnimationsLength; i++) { 
      var anim = animations[ i ]; 
      var keyFrameAnim = new THREE.KeyFrameAnimation(anim); 
      keyFrameAnim.timeScale = 1; 
      keyFrameAnim.loop = false; 
      kfAnimations.push(keyFrameAnim); 

      anim = kfAnimations[i]; 
      anim.play(); 
     } 

     showroom.position.set(0, 0, -20); 
     showroom.scale.set(0.06, 0.06, 0.06); 

     showroom.traverse(function (child) { 
      child.castShadow = true; 
      child.receiveShadow = true; 
      }); 

     showroom.updateMatrix(); 
     scene.add(showroom); 
     animate(); 
    });  
} 

// On Mouse double click event function 
function onDoubleClick(event) { 
    // Set the mouse down flag to false 
    mouseDown = false; 

    // Canvas x (left) and y (top) position 
    var canvasLeft = 0; 
    var canvasTop = 0; 

    // "event.clientX" is the mouse x position. "event.clientY" is the mouse y position 
    var tempX = event.clientX - canvasLeft; 
    var tempY = event.clientY - canvasTop; 
    // Create a normalised vector in 2d space 
    var vector = new THREE.Vector3((tempX/window.innerWidth) * 2 - 1, - (tempY/innerHeight) * 2 + 1, 0.5); 

    // Unproject a 2D point into the 3D word 
    // Use the camera projection matrix to transform the vector to the 3D world space 
    vector.unproject(camera); 

    // Send a ray in the direction the user has clicked from the cameras position 
    var raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize()); 

    // Check if the ray has intersected with any objects and get intersections 
    var intersects = raycaster.intersectObjects(objects, true); 

    // Check if intersected with objects 
    if (intersects.length > 0) { 
     var tempStr = "Number of items: " + intersects.length + " "; 
     // List the items that were hit 
     for(var i=0; i < intersects.length; i++){ 
      if(intersects[i].object.name != ""){ 
       // The mesh name set above 
       tempStr += " | Name: " + intersects[i].object.name; 
      } else { 
       // The names inside the model 
       tempStr += " | Name: " + intersects[i].object.parent.name; 
      } 
     } 

     //Debug information 
     document.getElementById("debugInfo").innerHTML = tempStr + ".<br>"; 
     //END 
    } 
} 

function loopAnimations(){ 
    // Loop through all animations 
    for (var i = 0; i < kfAnimationsLength; i++) { 
     // Check if the animation is player and not paused. 
     if(kfAnimations[i].isPlaying && !kfAnimations[i].isPaused){ 
      if(kfAnimations[i].currentTime == lastFrameCurrentTime[i]) { 
       kfAnimations[i].stop(); 
       //kfAnimations[i].play(); 
       lastFrameCurrentTime[i] = 0; 
      } 
     } 
    } 
} 

function play_pauseAnim() { 
    //checks is there animation and is it paused  
    if(kfAnimationsLength > 0) { 
     if(kfAnimations[0].isPlaying) { 
      for(i = 0; i < kfAnimationsLength; i++){ 
       kfAnimations[i].stop(); 
      } 
     }else { 
      for(i = 0; i < kfAnimationsLength; i++) { 
       lastFrameCurrentTime[i] = 0; 
       //kfAnimations[i].play(kfAnimations[i].currentTime); 
       kfAnimations[i].play(0); 
      } 
     } 
    } 
} 

function checkTime(){ 
    if(kfAnimationsLength > 0) { 
     if(kfAnimations[0].isPlaying) { 
      if(kfAnimations[0].currentTime > 3){ 
       play_pauseAnim(); 
      } 
     } 
    } 
} 

// create a render loop to draw the scene 60 times per second 
function render() { 
    //checkTime(); 

    daeObject.rotation.y += guiControls.rotationY; 

    //if (daeObject.position.z < 25) { 
    daeObject.position.z = guiControls.positionZ; 
    //} 

    spotLight.rotation.x += guiControls.rotationX; 
    spotLight.rotation.y += guiControls.rotationY; 
    spotLight.rotation.z += guiControls.rotationZ; 

    stats.update(); 
} 

function animate() { 
    var deltaTime = clock.getDelta(); 
    for (var i = 0; i < kfAnimationsLength; i++) { 
     // Get a key frame animation. 
     var anim = kfAnimations[i]; 
     anim.update(deltaTime); 
    } 
    loopAnimations(); 
    requestAnimationFrame(animate); 
     // Update last frame current time. 
    for (var i = 0; i < kfAnimationsLength; i++) { 
     lastFrameCurrentTime[i] = kfAnimations[i].currentTime; 
    } 
    render(); 
    renderer.render(scene, camera); 
} 

// Loads skybox texture 
function loadTexture(path) { 
    var texture = new THREE.Texture(texture_placeholder); 
    var material = new THREE.MeshBasicMaterial({ 
       map: texture, 
       overdraw: 0.5 
    }); 
    var image = new Image(); 
    image.onload = function() { 
     texture.image = this; 
     texture.needsUpdate = true; 
    }; 
    image.src = path; 
    return material;  
} 

回答

1

Macast,

請檢查您是否已經不在你的代碼被遺忘:

var objets = []; 
var raycaster = new THREE.Raycaster(); 

而且對汽車的各部分這一行:

objects.push(mesh); 

例如:

var geometry = new THREE.RingGeometry(1, 5, 32); 
var material = new THREE.MeshBasicMaterial({ color: 0xff0000, side: THREE.DoubleSide }); 
var simpleTire = new THREE.Mesh(geometry, material); 
simpleTire.name = 'tire'; 
objects.push(simpleTire); 
scene.add(simpleTire); 

然後,很簡單:

if (intersects.length > 0) { 
    switch(intersects[0].object.name){ 
     case 'tire': 
      console.log('A pretty red tire'); 
     break; 
     case 'motor': 
      console.log('An electric motor'); 
     break; 
     } 
} 
+0

恐怕它不工作:/中的COLLADA 3D的出口是一個模型,但是當你在對象上雙擊它顯示的個別型號的名稱父母模型。當我添加此代碼時,它不允許加載頁面。我將在上面添加整個JavaScript文件以顯示實際發生的情況,因爲代碼中可能存在衝突。 – Macast