javascript - three.js - 为什么光线投射器无法识别加载的对象?
问题描述
我是 THREE.js 的新手。我想点击鼠标在场景中选择一个加载的 .obj 对象,然后突出显示它(变成半透明),然后移动鼠标,移动的对象跟随鼠标。当我再次单击鼠标时。对象颜色再次变回纯色,并停留在单击的位置。
我编写了以下代码,但光线投射器无法识别我单击了加载的对象,尽管它们已添加到对象数组中。
代码:
<html>
<head includeDefault="true">
<script src="js/three.js"></script>
<script src="js/PointerLockControls.js"></script>
<script src="js/OBJLoader.js"></script>
<script src="js/MTLLoader.js"></script>
<script src="js/dat.gui.min.js"></script>
<script src="js/stats.min.js"></script>
<script src="js/OrbitControls.js"></script>
</head>
<body>
<script>
var camera, scene, renderer, controls, ambient, cube, wuyun11, tempMateria11;
var stats = initStats();
var controlsEnabled=true;
var step = 0;
var speed = 10;
var matArrayA=[];
var moveForward=false;
var moveBackward=false;
var moveLeft=false;
var moveRight=false;
var group = new THREE.Group();
var prevTime=performance.now();
var velocity=new THREE.Vector3();
var direction=new THREE.Vector3();
var color=new THREE.Color();
var params = {exposure: 1,};
var Smogs111 = [];
var SmogGeometry11;
var SWtrue2 = false;
var params1 = {
wather3: function () {
wather33();
},
}
var Basic_material = new THREE.MeshStandardMaterial();
//the following variables are for moving objects
var isSelected=false;
var objects=[];
var selectedObject;
var newPosition;
init();
animate();
function initGui() {
gui = {
ambientLight:"#111111",
directionalLight:"#ffffff",
intensity:1,
debug:false,
time:0,
pause:false,
speed:10
};
var datGui = new dat.GUI();
datGui.add(gui,"time",0 ,1440).onChange(function (e) {
time = e;
});
datGui.add(gui,"speed",0 ,100).onChange(function (e) {
speed = e;
});
datGui.add(gui,"pause").onChange(function (e) {
if(e){
cancelAnimationFrame(id);
}
else{
requestAnimationFrame(animate);
}
});
datGui.addColor(gui,"ambientLight").onChange(function (e) {
ambientLight.color = new THREE.Color(e);
});
datGui.addColor(gui,"directionalLight").onChange(function (e) {
directionalLight.color = new THREE.Color(e);
});
datGui.add(gui,"intensity",0,5).onChange(function (e) {
directionalLight.intensity = e;
});
}
function init(){
var ratio=window.innerWidth/window.innerHeight;
//camera=new THREE.PerspectiveCamera(60,ratio,0.1,100000);
var Pos=new THREE.Vector3(0,0,0);
//camera.position.set(Pos.x,Pos.y,Pos.z);
var Dir=new THREE.Vector3(0,0,1);
//camera.lookAt(Dir.x,Dir.y,Dir.z);
scene=new THREE.Scene();
scene.fog = new THREE.Fog( scene.background, 3000, 5000 );
renderer = new THREE.WebGLRenderer({antialias:true});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor(0x4682B4,1);
renderer.shadowMapEnabled = true;
renderer.shadowMapSoft = true;
document.body.appendChild( renderer.domElement );
initCamera();
initGui();
loadHouse();
//loadTree();
loadTrees();
//loadFountain();
loadFences();
//loadChar();
initLight();
createFloor();
createWallMaterail();
createCubeWall(10, 50, 1000, 0, matArrayA, -500, 25, 0, "Wall");
createCubeWall(10, 50, 1000, 0, matArrayA, 500, 25, 0, "Wall");
createCubeWall(10, 50, 1000, 0.5, matArrayA, 0, 25, -500, "Wall");
createCubeWall(10, 50, 1000, 0.5, matArrayA, 0, 25, 500, "Wall");
initControls();
window.addEventListener('resize',onWindowResize,false);
gui2 = new dat.GUI( { width: 350 } );
gui2.add( params, 'exposure', 0, 1 );
gui2.domElement.style = 'position:absolute;top:20px;left:0px;height: 350px';
var generationFolder111 = gui2.addFolder('Wather');
generationFolder111.close();
var genBtn333 = generationFolder111.add(params1, 'wather3');
genBtn333.name("winter");
}
function createFloor(){
var loader = new THREE.TextureLoader();
loader.load("img/grass-texture2.jpg",function(texture){
texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set( 16, 16 );
var floorGeometry = new THREE.PlaneGeometry(1000, 1000);
var floorMaterial = new THREE.MeshLambertMaterial( { map: texture } );// side: THREE.DoubleSide
var floor = new THREE.Mesh(floorGeometry, floorMaterial);
floor.receiveShadow = true;
floor.castShadow = true;
floor.position.y = 0;
floor.rotation.x = -Math.PI / 2;
floor.name = "floor";
scene.add(floor);
});
}
function initStats() {
var stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
document.body.appendChild(stats.domElement);
return stats;
}
function onWindowResize(){
camera.aspect=window.innerWidth/window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth,window.innerHeight);
}
function animate(){
//requestAnimationFrame(animate);
id = requestAnimationFrame(animate);
movnigSun(directionalLight,speed * 0.0002);
if(controlsEnabled==true){
var time=performance.now();
var delta=(time-prevTime)/1000;
velocity.x-=velocity.x*10.0*delta;
velocity.z-=velocity.z*10.0*delta;
direction.z=Number(moveForward)-Number(moveBackward);
direction.x=Number(moveLeft)-Number(moveRight);
direction.normalize();
if(moveForward || moveBackward) velocity.z-=direction.z*400.0*delta;
if(moveLeft || moveRight) velocity.x-=direction.x*400.0*delta;
//controls.getObject().translateX(velocity.x*delta);
//controls.getObject().translateZ(velocity.z*delta);
prevTime=time;
stats.update();
}
if(cube){
for (var i = 0; i < cube.material.length; i++) {
cube.material[i].color.setRGB(params.exposure,params.exposure,params.exposure);
}
//ambientLight.intensity = params.exposure
}
renderer.render(scene,camera);
}
function ItRains(){
requestAnimationFrame( ItRains );
for( var i=0; i<Smogs111.length; i++ ){
var ii = i+1;
if( ii > 3 ){ ii = i/4; }
if( ii < 10 ){ ii = 10*i; }
Smogs111[i].position.y -= ii*0.0002;
Smogs111[i].lookAt(camera.position);
if( Smogs111[i].position.y < -40 ){
Smogs111[i].position.y = 140;
}
}
}
function initCamera() {
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000);
//camera.shadowCameraVisible = true;
camera.position.set(0, 800, 1500);
camera.lookAt(new THREE.Vector3(0, 0, 0));
}
function initControls() {
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.enableDamping = true;
controls.dampingFactor = 0.5;
controls.minDistance = 100;
controls.maxDistance = 2000;
controls.maxPolarAngle = Math.PI/2.2;
//controls.enablePan = true;
}
function wather33(){
if( SWtrue2 == false ){
for( var i=0; i<Smogs111.length; i++ ){
Smogs111[i].visible = true;
}
SWtrue2 = true;
}else{
for( var i=0; i<Smogs111.length; i++ ){
Smogs111[i].visible = false;
}
SWtrue2 = false;
}
}
function loadSkyBox(){
const geometry=new THREE.CubeGeometry(10000,100,10000);
const manager = new THREE.LoadingManager();
const loader = new THREE.TextureLoader(manager);
const tex1 = loader.load( 'img/sky2.jpg' );
const tex2 = loader.load( 'img/sky2_new.jpg' );
var texture = loader.load( 'img/grass-texture4.jpg' );
const tex3 = loader.load( 'img/sky1.jpg' );
texture.wrapS=THREE.RepeatWrapping;
texture.wrapT=THREE.RepeatWrapping;
texture.repeat.set(128,128);
manager.onLoad = function() {
const cubeMaterials= [
new THREE.MeshBasicMaterial({map:tex1, side:THREE.DoubleSide}), //left
new THREE.MeshBasicMaterial({map:tex1, side:THREE.DoubleSide}), //right
new THREE.MeshBasicMaterial({map:tex3, side:THREE.DoubleSide}), //up
new THREE.MeshBasicMaterial({map:texture, side:THREE.DoubleSide}), //down
new THREE.MeshBasicMaterial({map:tex2, side:THREE.DoubleSide}), //front
new THREE.MeshBasicMaterial({map:tex2, side:THREE.DoubleSide}) //back
];
cube=new THREE.Mesh(geometry,cubeMaterials);
scene.add(cube);
}
SmogGeometry11 = new THREE.PlaneBufferGeometry( 5, 5 );
wuyun11 = new THREE.TextureLoader().load( "img/snowflake1.png" );
tempMateria11 = new THREE.MeshBasicMaterial({map: wuyun11, transparent: true, opacity: 0.9, blending: THREE.AdditiveBlending, depthWrite: false, side: THREE.DoubleSide })
for ( var i = 0; i < 200; i++ ) {
for ( var j = 0; j < 200; j++ ) {
Smogs11 = new THREE.Mesh( SmogGeometry11, tempMateria11 );
Smogs11.position.set( -50 + Math.random()*1080 * Math.sin( i * 0.4 ),70,-50 + Math.random()*1080 * Math.cos( j * 0.25 ));
Smogs11.scale.set(0.1,0.1,0.1);
Smogs11.visible=false;
scene.add( Smogs11 );
Smogs111.push(Smogs11);
}
}
ItRains();
}
function loadHouse(){
var mtlLoader=new THREE.MTLLoader();
//mtlLoader.setTexturePath("model/house/");
//mtlLoader.setPath("model/house/");
mtlLoader.load(
"model/house/house_10.mtl", function(materials){
materials.preload();
materials.materials["grass_ground"].transparent = true;
materials.materials["grass_ground"].opacity = 0;
materials.materials["roof_01"].color = new THREE.Color(0, 0.5, 1)
var objLoader=new THREE.OBJLoader();
objLoader.setMaterials(materials);
objLoader.load(
//resource url
"model/house/house_10.obj",
//called when resource is loaded
function(object){
object.traverse( function( child ) {
if ( child instanceof THREE.Mesh ) {
//child.material = Basic_material;
child.castShadow = true;
child.receiveShadow = true;
}
});
object.position.y=4;
object.position.z=-100;
object.scale.set(25,25,25);
scene.add(object);
objects.push(object);
},
//called when loading is in progresses
function(xhr){
console.log((xhr.loaded/xhr.total*100)+'% loaded');
},
//called when loading has errors
function (error){
console.log('An error happened'+error);
}
);
}
);
}
function loadTrees(){
createTree(200,25,50);
createTree(100,25,20);
createTree(-100,25,30);
createTree(50,25,100);
createTree(-100,25,-200);
}
function createTree(x,y,z){
var mtlLoader=new THREE.MTLLoader();
mtlLoader.load(
"model/tree1/shu.mtl", function(materials){
materials.preload();
materials.materials["dashuzhi"].transparent = true;
materials.materials["dashuzhi"].alphaTest = 0.7;
var objLoader=new THREE.OBJLoader();
objLoader.setMaterials(materials);
objLoader.load(
"model/tree1/shu.obj",
function(object){
object.traverse( function( child ) {
if ( child instanceof THREE.Mesh ) {
//child.material = Basic_material;
child.castShadow = true;
child.receiveShadow = true;
}
});
object.scale.set(0.1,0.1,0.1);
object.position.set(x,y,z);
scene.add(object);
objects.push(object);
},
);
}
);
}
function loadFences(){
//左侧栅栏
createFence(-300,0,-360,0);
createFence(-300,0,-270,0);
createFence(-300,0,-180,0);
createFence(-300,0,-90,0);
createFence(-300,0,0,0);
createFence(-300,0,90,0);
//右侧栅栏
createFence(300,0,-360,0);
createFence(300,0,-270,0);
createFence(300,0,-180,0);
createFence(300,0,-90,0);
createFence(300,0,0,0);
createFence(300,0,90,0);
//前面栅栏
createFence(-311.5,0,206,Math.PI/2);
createFence(-221.5,0,206,Math.PI/2);
// createFence(0,0,206,Math.PI/2);
createFence(100,0,206,Math.PI/2);
createFence(189.75,0,206,Math.PI/2);
// createFence(0,0,180,Math.PI/2);
//后面栅栏
createFence(-311.5,0,-340,Math.PI/2);
createFence(-221.5,0,-340,Math.PI/2);
createFence(100,0,-340,Math.PI/2);
createFence(189.75,0,-340,Math.PI/2);
}
function createFence(positionX,positionY,positionZ,rotationAngle){
var mtlLoader=new THREE.MTLLoader();
mtlLoader.load(
"model/white-fence/Fence_White.mtl",function(materials){
materials.preload();
var objLoader=new THREE.OBJLoader();
objLoader.setMaterials(materials);
objLoader.load(
"model/white-fence/Fence_White.obj",function(object){
object.scale.set(1,1,1);
object.rotation.y=rotationAngle;
object.position.set(positionX,positionY,positionZ);
scene.add(object);
}
)
}
)
}
function loadChar(){
var mtlLoader=new THREE.MTLLoader();
//mtlLoader.setTexturePath("model/house/");
//mtlLoader.setPath("model/house/");
mtlLoader.load(
"model/char/Doll_for_fafa.mtl", function(materials){
materials.preload();
materials.setMaterials('blinn7SG');
//materials.materials["grass_ground"].opacity = 0;
//materials.materials["grass_ground"].color = new THREE.Color(0x00000, 1.0)
var objLoader=new THREE.OBJLoader();
objLoader.setMaterials(materials);
objLoader.load(
//resource url
"model/char/Doll_for_fafa.obj",
//called when resource is loaded
function(object){
object.traverse( function( child ) {
if ( child instanceof THREE.Mesh ) {
//child.material = Basic_material;
child.castShadow = true;
child.receiveShadow = true;
}
});
object.position.set(0,0,0)
object.scale.set(10,10,10);
scene.add(object);
},
);
}
);
}
function createCubeWall(width, height, depth, angle, material, x, y, z, name){
var cubeGeometry = new THREE.BoxGeometry(width, height, depth );
var cube = new THREE.Mesh( cubeGeometry, material );
cube.castShadow = true;
cube.receiveShadow = true;
cube.position.x = x;
cube.position.y = y;
cube.position.z = z;
cube.rotation.y += angle*Math.PI;
cube.name = name;
scene.add(cube);
}
function createWallMaterail(){
matArrayA.push(new THREE.MeshPhongMaterial({color: 0xafc0ca})); //前 0xafc0ca :灰色
matArrayA.push(new THREE.MeshPhongMaterial({color: 0x9cb2d1})); //后 0x9cb2d1:淡紫
matArrayA.push(new THREE.MeshPhongMaterial({color: 0xd6e4ec})); //上 0xd6e4ec: 偏白色
matArrayA.push(new THREE.MeshPhongMaterial({color: 0xd6e4ec})); //下
matArrayA.push(new THREE.MeshPhongMaterial({color: 0xafc0ca})); //左 0xafc0ca :灰色
matArrayA.push(new THREE.MeshPhongMaterial({color: 0xafc0ca})); //右
}
function initLight() {
directionalLight = new THREE.DirectionalLight( 0xffffff, 0.9 );//模拟远处类似太阳的光源
var target = new THREE.Object3D();
target.position.set(0, 0, 0);
scene.add(target);
directionalLight.position.set( 500, 500, 0);
directionalLight.castShadow = true;
directionalLight.color.setHSL( 0.1, 1, 0.95 );
directionalLight.shadow.camera.near = 10;
directionalLight.shadow.camera.far = 1500;
directionalLight.shadow.camera.left = -500;
directionalLight.shadow.camera.right = 500;
directionalLight.shadow.camera.top = 600;
directionalLight.shadow.camera.bottom = -600;
directionalLight.shadowCameraVisible = true;
directionalLight.target = target;
directionalLight.shadow.mapSize.height = 4096;
directionalLight.shadow.mapSize.width = 4096;
scene.add( directionalLight) ;
var helper = new THREE.CameraHelper(directionalLight.shadow.camera);
scene.add(helper);
ambientLight = new THREE.AmbientLight( 0xFFFFFF, 0.1 ); //AmbientLight,影响整个场景的光源
ambientLight.position.set(0,0,0);
scene.add( ambientLight );
}
function movnigSun(obj,speed){
step += speed;
obj.position.x = 750*(Math.cos(step));
obj.position.y = 750*(Math.sin(step));
//obj.target.updateMatrixWorld();
}
document.addEventListener('mousedown',onDocumentMouseDown);
function onDocumentMouseDown(e){
e.preventDefault();
var vector=new THREE.Vector3((e.clientX/window.innerWidth)*2-1,-(e.clientY/window.innerHeight)*2+1,0.5).unproject(camera);
var raycaster=new THREE.Raycaster(camera.position,vector.sub(camera.position).normalize());
var intersects=raycaster.intersectObjects(objects);
console.log('imtersrcts'+intersects);
if(intersects.length>0)
{
if(isSelected==false)
{
console.log(isSelected);
selectedObject=intersects[0].object;
selectedObject.material.color=new THREE.Color(0xff0000);
console.log(selectedObject);
console.log(selectedObject.position);
isSelected=true;
}
else if(isSelected==true)
{
console.log(selectedObject);
console.log(isSelected);
selectedObject.material.color=new THREE.Color(0x00ff00);
selectedObject.position.set(-10,0,1);
isSelected=false;
}
// selectedObject.position.x-=10;
//selectedObject.position.set(50,0,0);
}
}
</script>
</body>
</html>
解决方案
我建议在 three.js 中尝试这种更常见的光线投射语法
var mouse = new THREE.Vector2();
var raycaster = new THREE.RayCaster();
mouse.x = (e.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(e.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
var intersects = raycaster.intersectObjects(objects);
如果您仍然遇到问题,请确保您的所有网格都可见,因为 three.js 光线投射不会检测到具有 visible=false 的网格
推荐阅读
- python - Generating graphs for given degree sequence in Python or R
- python - 我试图在循环中找到一个数字到 number+1 的乘法持久性。那么我应该怎么做才能修复hte代码?
- c# - 如何使用 LibVlcSharp 去除 videoView 中的视频黑带?
- ruby-on-rails - 带有 Cocoon 的动态表单 - NilClass:Class 的未定义方法“reflect_on_association”:
- android - 无法使用 RobolectricTestRunner 和 Koin 运行单元测试
- jquery-ui - Jqueryui datepicker change class onselect doesn´t work
- pytorch - 在pytorch中实现将旋转矩阵转换为旋转向量
- amazon-web-services - 将弹性 IP 与 AWS 负载均衡器结合使用
- python - Python 另一个嵌套列表
- python-3.x - 在python中提取两个列表之间的最长公共路径