首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Raycasting不是处理导入的OBJ模型,而是处理用程序创建的对象。

Raycasting不是处理导入的OBJ模型,而是处理用程序创建的对象。
EN

Stack Overflow用户
提问于 2022-07-14 03:49:14
回答 1查看 41关注 0票数 1

我是three.js的新手,我正在尝试使用光线投射,我对光线投射在进口3d模型上的工作方式感到非常困惑。在这里,我导入了一个obj模型,当我试图检测我是否接触到导入的3D模型时,功能并没有像我预期的那样工作。但是,当我将其更改为检测我用three.js创建的box对象时,是否正像我所期望的那样,有人能帮助解决这个问题呢?

代码语言:javascript
复制
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);
});
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-07-14 15:19:54

问题是,从OBJLoader获得并分配给building变量的对象是THREE.Group的一个实例。群体没有自己的几何学或材料。它们或多或少是包含其他3D对象(如网格、点云、线条或其他组)的容器,并将它们表示为一个逻辑组。

这意味着它们永远不是光线投射评估的结果,这意味着if(intersects[0].object.id === building.id)总是失败。

我建议您在加载过程之后执行此操作,该过程标记您的对象:

代码语言:javascript
复制
building.traverse( function( object ) {

    object.userData.tag = 'building';

} );

然后,您可以在光线投射例程中使用tag属性来检测建筑物。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72974983

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档