簡體   English   中英

three.js-將對象懸停在其上時更改其顏色

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

我是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) }

我向您展示了如何構建模型,主要是因為我覺得這不是實現模型的最佳方法,並且認為它對於找到問題的答案很有用。

問題

我希望將“ Bottom Body”部分( BodyBottom )懸停在其上方時更改顏色,但是目前,我當前的代碼僅使animalGroup投射的陰影更改了顏色。 我知道,執行此操作的最佳方法是使用光線投射器,但是光線投射器似乎沒有檢測到單個對象,甚至沒有檢測到animalGroup主對象。 我創建了一個detectMouseMove事件偵聽器,並在該函數中使用以下代碼找到了鼠標的3D位置:

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

以下代碼是我從Three.js示例復制的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);
}

我的猜測是,由於動物的構造方式,或者也許是當動物被調用時,光線投射器並未與之相交,但是我不知道,因此我為什么要在這里詢問。

我在尋找什么:

  • 修復以使單個對象可交叉
  • 僅使BodyBottom相交

感謝您的幫助,如果您需要我的代碼示例或類似的示例,請讓我知道,這是我的第一個SO問題,對我來說很輕松,但是我也希望獲得有關如何改善問題的反饋! 謝謝。

原來,我要做的就是更改:

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

至:

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

感謝@WestLangley在對我的問題的評論中給出的答案,只需將其發布在此處,以便將來找到它的任何人都可以清楚地看到答案。

經過更多研究后,我發現這可以解決我的問題,因為true參數使相交遞歸,這意味着它將與對象的所有后代相交,而不僅僅是與對象相交。 我認為這是可行的,因為我將所有對象都分組到一個大的“主”組中,因此,在不相交遞歸的情況下,只需選擇該大組即可。 我仍然不確定為什么這會使陰影改變顏色而不是整個動物,所以對此的任何想法都可以在評論中找到。 更多信息可以在這里找到。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM