【问题标题】:Three.js raycaster not selecting right objectThree.js raycaster 没有选择正确的对象
【发布时间】:2015-02-21 03:01:24
【问题描述】:

大家好,我正在尝试使用 raycaster 选择一个对象,我希望它可以更改第一个选择的对象的材质。在我选择对象之前,一切都很顺利。如果我选择第一个元素,则只有一个对象会发生变化。

如果我遍历列表大部分更改,但有时即使我单击空白部分也会更改部分

我的假设是我加载模型的方式或光线投射器获取错误的点位置

我已经在下面发布了代码帮助,不胜感激。

var camera, scene, renderer, loader, controls, play;
var jetEngine = [];
var x = 0;
var texture = THREE.ImageUtils.loadTexture('images/metal2.jpg');
texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set(10, 10);
var play = false;
var container;
var $container;
var _this;

function Jet($con) {

  $container = $con;
  _this = this;
  width = $con.width();
  height = $con.height();


  renderer = new THREE.WebGLRenderer({alpha: true});
  renderer.setClearColor(0xffffff, 1);
  renderer.setSize(width, height);
  $container.append(renderer.domElement);
  raycaster = new THREE.Raycaster();
  camera = new THREE.PerspectiveCamera(60, width / height, 1, 2000);
  camera.position.z = 200;
  camera.position.y = 0;
  camera.position.x = 30;
  controls = new THREE.TrackballControls(camera,renderer.domElement );
  controls.rotateSpeed = 1.0;
  controls.zoomSpeed = 1.2;
  controls.panSpeed = 0.8;
  controls.noZoom = false;
  controls.noPan = false;
  controls.staticMoving = true;
  controls.dynamicDampingFactor = 0.3;
  controls.keys = [65, 83, 68];
  scene = new THREE.Scene();
  loader = new THREE.JSONLoader();

  loader.load("jetengine/fan.json", _this.addmodel);
  loader.load("jetengine/shaft.json", _this.addmodel);
  loader.load("jetengine/nose.json", _this.addmodel);
  loader.load("jetengine/compressor.json", _this.addmodel);
  loader.load("jetengine/compressor2.json", _this.addmodel);
  loader.load("jetengine/combustion.json", _this.addmodel);

  var directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
  directionalLight.position.set(0, 1, 0);
  scene.add(directionalLight);
  var light = new THREE.AmbientLight(0x404040); // soft white light
  scene.add(light);
  window.addEventListener('resize', _this.onWindowResize, false);
  window.addEventListener( 'click', _this.onMouseMove, false );

  _this.animate();
}

Jet.prototype.changeColor = function () {
  for (i = 0; i < jetEngine.length; i++) {
    jetEngine[i].material = new THREE.MeshPhongMaterial({
      // light
      map: texture,
      // dark
      shininess: 50
    });

  }
};

Jet.prototype.playPause = function (btn) {

  play = !play;
  if(play){$(playbtn).html('Puase');}else{$(playbtn).html('Play');}
};

Jet.prototype.reset = function () {
  play = false;
  for (i = 0; i < jetEngine.length; i++) {
    jetEngine[i].material = new THREE.MeshNormalMaterial()
  }

  camera.position.z = 200;
  camera.position.y = 0;
  camera.position.x = 30;
  camera.lookAt(new THREE.Vector3(0,0,0));
};


Jet.prototype.addmodel = function (geometry, materials) {
  var obj = new THREE.Mesh(geometry, new THREE.MeshNormalMaterial());
  obj.scale.set(15, 15, 15);
  jetEngine[x] = obj;
  scene.add(jetEngine[x]);
  x++;
};

Jet.prototype.onWindowResize = function () {

  width = container.width();
  height = container.height();
  renderer.setSize(width, height);
  camera.aspect = width / height;
  camera.updateProjectionMatrix();
  controls.handleResize();
};

Jet.prototype.animate = function () {
  if (play) {
    if (jetEngine[0] != null) {
      try{
        jetEngine[0].rotateZ(1);
        jetEngine[1].rotateZ(1);
        jetEngine[2].rotateZ(10);
        jetEngine[3].rotateZ(0);
        jetEngine[4].rotateZ(1);
        jetEngine[5].rotateZ(30);
      }catch (err){

      }

    }
  }
  requestAnimationFrame(_this.animate);
  renderer.render(scene, camera);
  controls.update();
};

Jet.prototype.onMouseMove = function( e ) {

  var isHovered = $container.is(":hover");
  console.log(isHovered);
  if (isHovered) {
    mouseVector = new THREE.Vector3();
    mouseVector.x = 2 * (e.clientX / width ) - 1;
    mouseVector.y = 1 - 2 * ( e.clientY / height );
    var vector = mouseVector.clone().unproject(camera);
    var direction = new THREE.Vector3(0, 0, -1).transformDirection(camera.matrixWorld);
    raycaster.set(vector, direction);
    var intersects = raycaster.intersectObjects(jetEngine);
    var intersection = intersects[0];
    obj = intersection.object;
    obj.material = new THREE.MeshPhongMaterial({
        // light
        map: texture,
        // dark
        shininess: 50
      });
  }
}

更新 尽管感谢 Almaz Vildanov 提供的非常有用的 eventControl 脚本。我决定再看一遍代码来找出问题所在。

问题在于渲染器在嵌套的div中,光线初始坐标的计算计算不正确。为了解决这个问题,将鼠标向量替换为:

var mouse = { x: 0, y: 0 };
mouse.x = ((event.clientX - $container.offset().left) /$container.width() ) * 2 - 1;
mouse.y =  -(((event.clientY - $container.offset().top) / $container.innerHeight() ) * 2 - 1);
console.log('x: ' + mouse.x+ '|    y:'+ mouse.y);

vector.set( mouse.x, mouse.y, 0.5 );
vector.unproject( camera );

raycaster.set( camera.position, vector.sub( camera.position ).normalize() );

其中 $container 是渲染器所在的嵌套 div。

【问题讨论】:

  • 也许this 会有所帮助
  • 感谢 Almaz 这似乎工作得很好,感谢您的帮助。
  • 好吧,如果答案对您投票有帮助,请为它投票 =)

标签: javascript jquery three.js raycasting


【解决方案1】:

尝试通过这个example。查看控制台中的消息。

<script src="js/controls/EventsControls.js"></script>

EventsControls = new EventsControls( camera, renderer.domElement );
EventsControls.draggable = false;

EventsControls.onclick = function() {

   console.log( this.focused.name );

}

var jsonLoader = new THREE.JSONLoader();
jsonLoader.load( "models/Tux.js", addModelToScene ); 


function addModelToScene( geometry, materials ) {

   var material = new THREE.MeshFaceMaterial( materials );
   model = new THREE.Mesh( geometry, material );
   model.scale.set( 10, 10, 10 ); model.name = 'Tux';
   model.rotation.x = -Math.PI/2; 
   model.position.set( 175, 45, 125 );
   scene.add( model ); 
   EventsControls.attach( model );

}

【讨论】:

    猜你喜欢
    • 2014-11-30
    • 1970-01-01
    • 2021-11-16
    • 2017-01-04
    • 2020-07-28
    • 2015-08-07
    • 2015-12-26
    • 1970-01-01
    • 2015-12-25
    相关资源
    最近更新 更多