我是Three.js(和WebGL)的新手,在我的第一个项目中,我创建了一个动物模型并以各种方式设置动画(即它的头部旋转以跟随鼠标)。该模型由许多不同的几何构成,这些几何在它们自己的功能中组合在一起,例如:
var BodyFunc = function(){
this.mesh = new THREE.Object3D();
this.mesh.name = "body";
// Body
var geomBody = new THREE.SphereGeometry( 100, 150, 150 );
geomBody.applyMatrix( new THREE.Matrix4().makeScale( 1.0, 1.3, 1.0 ) );
var matBody = new THREE.MeshPhongMaterial({color:Colors.black, shading:THREE.FlatShading});
var Body = new THREE.Mesh(geomBody, matBody);
Body.castShadow = true;
Body.receiveShadow = true;
this.mesh.add(Body);
// Body (bottom)
var geomBodyBottom = new THREE.SphereGeometry( 95, 150, 150 );
geomBodyBottom.applyMatrix( new THREE.Matrix4().makeScale( 1.0, 1.0, 1.0 ) );
var matBodyBottom = new THREE.MeshPhongMaterial({color:pantsColour, shading:THREE.FlatShading});
var BodyBottom = new THREE.Mesh(geomBodyBottom, matBodyBottom);
BodyBottom.position.set(0,-40,0);
BodyBottom.castShadow = true;
BodyBottom.receiveShadow = true;
this.mesh.add(BodyBottom);
// Body (base)
var geomBodyBase = new THREE.SphereGeometry( 92, 150, 150 );
geomBodyBase.applyMatrix( new THREE.Matrix4().makeScale( 1.0, 1.0, 1.0 ) );
var matBodyBase = new THREE.MeshPhongMaterial({color:Colors.black, shading:THREE.FlatShading});
var BodyBase = new THREE.Mesh(geomBodyBase, matBodyBase);
BodyBase.position.set(0,-50,0);
BodyBase.castShadow = true;
BodyBase.receiveShadow = true;
this.mesh.add(BodyBase);
};
然后在主createAnimal()
函数中调用这些函数,如下所示:
function createAnimal(){
animalBodyGroup = new THREE.Object3D();
animalGroup = new THREE.Object3D();
head = new HeadFunc();
head.mesh.scale.set(.25,.25,.25);
head.mesh.position.y = 0;
animalGroup.add(head.mesh);
body = new BodyFunc();
body.mesh.scale.set(.25,.25,.25);
body.mesh.position.y = 0;
animalBodyGroup.add(body.mesh);
armRight = new armRightFunc();
armRight.mesh.scale.set(.25,.25,.25);
armRight.mesh.position.y = 0;
animalBodyGroup.add(armRight.mesh);
armLeft = new armLeftFunc();
armLeft.mesh.scale.set(.25,.25,.25);
armLeft.mesh.position.y = 0;
animalBodyGroup.add(armLeft.mesh);
footRight = new footRightFunc();
footRight.mesh.scale.set(.25,.25,.25);
footRight.mesh.position.y = 0;
animalBodyGroup.add(footRight.mesh);
footLeft = new footLeftFunc();
footLeft.mesh.scale.set(.25,.25,.25);
footLeft.mesh.position.y = 0;
animalBodyGroup.add(footLeft.mesh);
// master group that is added to the scene (whole animal)
animalGroup.add(animalBodyGroup);
animalGroup.position.y = -40;
animalGroup.castShadow = true;
animalGroup.receiveShadow = true;
scene.add(animalGroup) }
我向您展示了如何构建模型主要是因为我觉得这不是最好的方法,并且觉得它有助于找到问题的答案。
问题
我希望底部正文部分(BodyBottom
)在我将鼠标悬停在其上时更改颜色,但目前我的当前代码只会导致由animalGroup
投射的阴影发生变化颜色。我知道最好的方法是使用raycaster,然而,raycaster似乎没有检测到单个对象甚至是主animalGroup
对象。我创建了一个detectMouseMove
事件监听器,在该函数内部,我使用以下代码找到鼠标的3D位置:
mousePos3D = new THREE.Vector3(( event.clientX / window.innerWidth ) * 2 - 1, - ( event.clientY / window.innerHeight ) * 2 + 1, 0.5 );
以下代码是我从Three.js example复制的raycaster代码。这段代码也在detectMouseMove
函数内,是不是?
var raycaster = new THREE.Raycaster();
raycaster.setFromCamera( mousePos3D, camera );
var intersects = raycaster.intersectObjects( scene.children );
console.info(INTERSECTED);
if ( intersects.length > 0 ) {
if ( INTERSECTED != intersects[ 0 ].object ) {
if ( INTERSECTED ) INTERSECTED.material.emissive.setHex( INTERSECTED.currentHex );
INTERSECTED = intersects[ 0 ].object;
INTERSECTED.currentHex = INTERSECTED.material.emissive.getHex();
INTERSECTED.material.emissive.setHex( 0xff0000 );
}
} else {
if ( INTERSECTED ) INTERSECTED.material.emissive.setHex( INTERSECTED.currentHex );
INTERSECTED = null;
}
此代码似乎只改变投射到地板上的Animal对象阴影的颜色(下面的代码)
function createFloor(){
var geomFloor = new THREE.PlaneGeometry(350,350);
var matFloor = new THREE.MeshPhongMaterial({color: 0xffffff});
var Floor = new THREE.Mesh(geomFloor, matFloor);
Floor.rotation.x = -Math.PI/2;
Floor.position.y = -72.5;
// allows shadow to be cast on floor (same for all objects)
Floor.receiveShadow = true;
scene.add(Floor);
}
我的猜测是,由于动物的建立方式,或者可能是它被召唤的时候,raycaster与它没有相交,但我不知道,因此我在这里问。
我正在寻找的内容:
BodyBottom
可交叉感谢您的帮助,如果您需要我的代码或类似内容的更多示例,请告诉我,这是我的第一个问题,所以对我很轻松,但我也很感激有关如何改进的反馈我的问题!感谢。
答案 0 :(得分:0)
事实证明,我需要做的就是改变:
var intersects = raycaster.intersectObjects( scene.children );
为:
var intersects = raycaster.intersectObjects( scene.children, true );
感谢@WestLangley对我的问题的评论中的答案,只是在此发布,以便将来发现这一点的任何人都可以清楚地看到答案。
在做了一些研究后,我发现这解决了我的问题,因为true
参数使交叉递归,这意味着它将与对象的所有后代相交,而不是仅仅交叉对象。我认为这是有效的,因为我将所有对象组合成一个大的“主”组,因此如果没有交叉是递归的,那只是选择那个大组。我仍然不确定为什么这会使阴影改变颜色而不是整个动物,因此在评论中会有任何想法。可以找到更多信息here。