简体   繁体   English

three.js-将对象悬停在其上时更改其颜色

[英]three.js - change colour of object when hovering over it

I am new to Three.js (and WebGL) and in my first project I am creating a model of an animal and animating it in various ways (ie it's head rotates to follow the mouse). 我是Three.js(和WebGL)的新手,在我的第一个项目中,我正在创建动物模型并以各种方式对其进行动画处理(即,头部旋转以跟随鼠标)。 The model is built up of lots of different geometries which are combined together in their own functions, for example: 该模型由许多不同的几何构造而成,它们在各自的功能中组合在一起,例如:

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);

};

These functions are then called in a master createAnimal() function which looks like this: 然后,在主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) }

I show you how the model is built mostly because I feel like this isn't the best way to do it and feel like it will be useful in finding the answer to my problem. 我向您展示了如何构建模型,主要是因为我觉得这不是实现模型的最佳方法,并且认为它对于找到问题的答案很有用。

The problem 问题

I would like for the Bottom Body section ( BodyBottom ) to change colour when I hover over it, however at the moment my current code only causes the shadow that is cast by the animalGroup to change colour. 我希望将“ Bottom Body”部分( BodyBottom )悬停在其上方时更改颜色,但是目前,我当前的代码仅使animalGroup投射的阴影更改了颜色。 I understand that the best way to do this is with the raycaster, however, the raycaster seems to not be detecting the individual objects or even the master animalGroup object. 我知道,执行此操作的最佳方法是使用光线投射器,但是光线投射器似乎没有检测到单个对象,甚至没有检测到animalGroup主对象。 I have created a detectMouseMove event listener, and inside that function I find the 3D position of the mouse with the following code: 我创建了一个detectMouseMove事件侦听器,并在该函数中使用以下代码找到了鼠标的3D位置:

mousePos3D = new THREE.Vector3(( event.clientX / window.innerWidth ) * 2 - 1, - ( event.clientY / window.innerHeight ) * 2 + 1, 0.5 );

The following code is my raycaster code that I copied from a Three.js example . 以下代码是我从Three.js示例复制的raycaster代码。 This code is also inside the detectMouseMove function, should it be? 此代码也位于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;
}

This code seems to only change the colour of the shadow of the Animal object which is cast onto the floor (code below) 此代码似乎仅更改投射到地板上的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);
}

My guess is that due to the way the animal is built, or perhaps when it is called, the raycaster is not intersecting with it, but I have no idea, hence why I am asking here. 我的猜测是,由于动物的构造方式,或者也许是当动物被调用时,光线投射器并未与之相交,但是我不知道,因此我为什么要在这里询问。

What I'm looking for: 我在寻找什么:

  • Fix to make the individual objects intersectable 修复以使单个对象可交叉
  • Make ONLY the BodyBottom intersectable 仅使BodyBottom相交

Thanks for the help, let me know if you need any more examples of my code or anything like that, this is my first SO question so go easy on me, but I'd also appreciate feedback on how to improve my questions! 感谢您的帮助,如果您需要我的代码示例或类似的示例,请让我知道,这是我的第一个SO问题,对我来说很轻松,但是我也希望获得有关如何改善问题的反馈! Thanks. 谢谢。

So it turns out that all I needed to do was change: 原来,我要做的就是更改:

var intersects = raycaster.intersectObjects( scene.children );

to: 至:

var intersects = raycaster.intersectObjects( scene.children, true );

Thank you to @WestLangley for the answer in the comments to my question, just posting it here so anyone finding this in the future can clearly see the answer. 感谢@WestLangley在对我的问题的评论中给出的答案,只需将其发布在此处,以便将来找到它的任何人都可以清楚地看到答案。

After doing some more research I found that this fixes my issue as the true parameter makes the intersect recursive, meaning it will intersect all of the descendants of the object, rather than just intersecting the object. 经过更多研究后,我发现这可以解决我的问题,因为true参数使相交递归,这意味着它将与对象的所有后代相交,而不仅仅是与对象相交。 I assume this works because I grouped all of my objects into one big "master" group, so without the intersect being recursive, it was just selecting that big group. 我认为这是可行的,因为我将所有对象都分组到一个大的“主”组中,因此,在不相交递归的情况下,只需选择该大组即可。 I'm still unsure why this made the shadow change colour and not the whole animal, so any thoughts on that would be appreciated in the comments. 我仍然不确定为什么这会使阴影改变颜色而不是整个动物,所以对此的任何想法都可以在评论中找到。 More info can be found here . 更多信息可以在这里找到。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM