Reputation: 23
I have a plane made of >10k squares and I want only the individual squares to change color that I hover my mouse above after click. But setColorAt isnt working.
let plane
let intersects
let color = new THREE.Color();
const geometry = new THREE.BoxGeometry(1, 1, .1);
//using instance method
function createInstancePlane(){
const material = new THREE.MeshBasicMaterial({
color: 0xffff00,
transparent: true,
opacity: 1,
});
plane = new THREE.InstancedMesh(geometry, material, 11856);
scene.add(plane);
//dummy
const dummy = new THREE.Object3D();
let mm = 0;
for (let i = 0; i < 152; i++) {
for (let j = 0; j < 78; j++) {
dummy.position.x = i - 76;
dummy.position.y = j - 39;
dummy.position.z = 0;
dummy.updateMatrix();
plane.setMatrixAt(mm, dummy.matrix);
mm++;
}
}
}
createInstancePlane()
console.log(plane)
//RAYCASTER
const rayCaster = new THREE.Raycaster();
let mouse = new Vector2();
window.addEventListener("mousemove", (e) => {
mouse.x = (e.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(e.clientY / window.innerHeight) * 2 + 1;
});
let funcWhileMouseMove = () => {
rayCaster.setFromCamera(mouse, camera);
intersects = rayCaster.intersectObject(plane);
for (let obj of intersects) {
console.log(obj.instanceId)
plane.setColorAt(obj.instanceId, color.set(0xff0000)); //THIS NOT WORKING
plane.instanceColor.needsUpdate = true;
}
};
//TICK FUNCTION
function tick() {
stats.begin();
//RAYCASTER obj test
window.addEventListener("mouseup", () => {
window.removeEventListener("mousemove", funcWhileMouseMove);
setTimeout(() => {
plane.material.color.set("pink");
}, 1000);
});
window.addEventListener("mousedown", () => {
window.addEventListener("mousemove", funcWhileMouseMove);
});
stats.end();
window.requestAnimationFrame(tick);
}
tick();
I get the desired plane made of >10k squares and when I click and move mouse I get instanceId too, but color stays the same.
I've tried different ways to implement color like-
plane.setColorAt(obj.instanceId, color.setHex(0xff0000)) plane.setColorAt(obj.instanceId, color.set('red'))
Upvotes: 1
Views: 521
Reputation: 31026
If you add color data after the InstancedMesh
has been rendered at least once, you have to set the needsUpdate
property of the respective material to true
. However, I recommend to setup an instanced color attribute with a default color right from the beginning like shown below:
let camera, scene, renderer;
let plane;
let color = new THREE.Color();
let mouse = new THREE.Vector2();
const rayCaster = new THREE.Raycaster();
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 100;
scene = new THREE.Scene();
createInstancePlane()
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
window.addEventListener("pointermove", onPointerMove);
}
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
function onPointerMove(e) {
mouse.x = (e.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(e.clientY / window.innerHeight) * 2 + 1;
rayCaster.setFromCamera(mouse, camera);
const intersects = rayCaster.intersectObject(plane);
for (let obj of intersects) {
plane.setColorAt(obj.instanceId, color.set(0xff0000));
plane.instanceColor.needsUpdate = true;
}
}
function createInstancePlane() {
const geometry = new THREE.BoxGeometry(1, 1, 0.1);
const material = new THREE.MeshBasicMaterial({
transparent: true,
opacity: 1,
});
plane = new THREE.InstancedMesh(geometry, material, 11856);
scene.add(plane);
//dummy
const dummy = new THREE.Object3D();
const defaultColor = new THREE.Color(0xffff00);
let mm = 0;
for (let i = 0; i < 152; i++) {
for (let j = 0; j < 78; j++) {
dummy.position.x = i - 76;
dummy.position.y = j - 39;
dummy.position.z = 0;
dummy.updateMatrix();
plane.setMatrixAt(mm, dummy.matrix);
plane.setColorAt(mm, defaultColor);
mm++;
}
}
}
body {
margin: 0;
}
<script src="https://cdn.jsdelivr.net/npm/[email protected]/build/three.min.js"></script>
Upvotes: 1