我是three.js的新手,我正在尝试使用光线投射,我对光线投射在进口3d模型上的工作方式感到非常困惑。在这里,我导入了一个obj模型,当我试图检测我是否接触到导入的3D模型时,功能并没有像我预期的那样工作。但是,当我将其更改为检测我用three.js创建的box对象时,是否正像我所期望的那样,有人能帮助解决这个问题呢?
import * as THREE from 'https://unpkg.com/three@0.126.1/build/three.module.js';
import { OrbitControls } from 'https://unpkg.com/three@0.126.1/examples/jsm/controls/OrbitControls.js';
import {OBJLoader} from "https://unpkg.com/three@0.126.1/examples/jsm/loaders/OBJLoader.js";
import {MTLLoader} from "https://unpkg.com/three@0.126.1/examples/jsm/loaders/MTLLoader.js";
import * as GUI from "https://unpkg.com/dat.gui@0.7.7/build/dat.gui.module.js";
//Set Up Enviroment for 3D model
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth,window.innerHeight);
document.body.appendChild(renderer.domElement);
const scene = new THREE.Scene();
//Set up Lighting
var keyLight = new THREE.DirectionalLight(new THREE.Color('hsl(30,100%,75%)'),1.0);
var fillLight = new THREE.DirectionalLight(new THREE.Color('hsl(240,100%,75%)'),0.75);
var backLight = new THREE.DirectionalLight(0xffffff,1.0);
keyLight.position.set(-100,0,100);
fillLight.position.set(100,0,100);
backLight.position.set(100,0,-100).normalize();
scene.add(keyLight);
scene.add(fillLight);
scene.add(backLight);
//Set up Camera
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth/window.innerHeight,
0.1,
1000
);
const orbit = new OrbitControls(camera,renderer.domElement);
camera.position.set(0,2,7.5);
orbit.update();
//Set up base
const planeGeometry = new THREE.PlaneGeometry(100,100);
const planeMaterial = new THREE.MeshBasicMaterial({
color: 0xffffff,
wireframe: false,
side: THREE.DoubleSide
});
var plane = new THREE.Mesh(planeGeometry,planeMaterial);
scene.add(plane);
plane.rotation.x = -0.5 * Math.PI;
//Model for testing
const boxGeometry = new THREE.BoxGeometry(10,10,10);
const boxMaterial = new THREE.MeshBasicMaterial({color: 0x0000ff})
var box = new THREE.Mesh(boxGeometry,boxMaterial);
scene.add(box);
box.position.x += 20;
//Set up GUI for controlling base
const gridHelper = new THREE.GridHelper(100);
scene.add(gridHelper);
const gui = new GUI.GUI();
const options = {
planeColor: '#ffea00',
wireframe: false
};
gui.addColor(options,'planeColor').onChange(function(e){
plane.material.color.set(e);
});
gui.add(options,'wireframe').onChange(function(e){
plane.material.wireframe = e;
});
//Set up Background image
const textureLoader = new THREE.TextureLoader();
textureLoader.load(
'../img/doge.jpg',
function ( texture ) {
scene.background = texture;
},
undefined,
function ( err ) {
console.error( 'An error happened.' );
}
);
//Import obj and mtl file to build 3D model
var building;
const mtlLoader = new MTLLoader();
mtlLoader.load(
'../source/building_04.mtl',
(materials)=>{
materials.preload();
console.log(materials);
const objLoader = new OBJLoader()
objLoader.setMaterials(materials)
objLoader.load(
'../source/building_04.obj',
(object)=>{
scene.add(object)
building = object;
object.position.y +=1;
},
(xhr) => {
console.log((xhr.loaded / xhr.total) * 100 + '% loaded')
},
(error) => {
console.log("Object error")
}
)
},
(xhr) => {
console.log((xhr.loaded / xhr.total) * 100 + '% loaded')
},
(error) => {
console.log("Material Eror")
}
)
//Set up raycasting environment
const raycaster = new THREE.Raycaster();
const mousePosition = new THREE.Vector2();
window.addEventListener('mousemove', function(e){
mousePosition.x = (e.clientX/this.window.innerWidth)*2 - 1;
mousePosition.y = -(e.clientY/this.window.innerHeight)*2 + 1;
});
//Function making sure everything to be up to date
function animate(){
//Raycasting
raycaster.setFromCamera( mousePosition, camera );
const intersects = raycaster.intersectObjects( scene.children,true);
if(intersects.length > 0){
for ( let i = 0; i < intersects.length; i ++ ) {
if(building != undefined){
if(intersects[0].object.id === building.id){
console.log("Touched!");
}
else{
console.log("did not touch!");
}
}
else{
console.log("Not reeady!");
}
console.log(intersects[i].object.id);
}
}
else{
console.log("did not touched")
}
console.log("finished")
renderer.render(scene,camera);
}
renderer.setAnimationLoop(animate);
//Make the screen to resize following the browser size
window.addEventListener('resize',function(){
camera.aspect = window.innerWidth/this.window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth,window.innerHeight);
});发布于 2022-07-14 15:19:54
问题是,从OBJLoader获得并分配给building变量的对象是THREE.Group的一个实例。群体没有自己的几何学或材料。它们或多或少是包含其他3D对象(如网格、点云、线条或其他组)的容器,并将它们表示为一个逻辑组。
这意味着它们永远不是光线投射评估的结果,这意味着if(intersects[0].object.id === building.id)总是失败。
我建议您在加载过程之后执行此操作,该过程标记您的对象:
building.traverse( function( object ) {
object.userData.tag = 'building';
} );然后,您可以在光线投射例程中使用tag属性来检测建筑物。
https://stackoverflow.com/questions/72974983
复制相似问题