Structure of my project 66% threejs model, 44% html (side control) using Bootstrap. I’m trying to make mouse picker, when pointing at an object so that it is shown on which object it is pointed. As I understand it, he sees the coordination of the mouse badly. Please help me figure out and set up the correct coordination mouse with Canvas.
Code:
export class CustomizerComponent implements OnInit {
public textureSrc: string;
public textureList = [
{ id: 1, name: 'Wood 2', src: '/assets/textures/wood2.jpg' },
{ id: 2, name: 'Wood 1', src: '/assets/textures/wood1.jpg' },
];
public selectedTexture(e): void {
let find = this.textureList.find((x) => x?.src === e.target.value);
// console.log(find?.src);
}
ngOnInit(): void {
let scene, kitchen, camera, renderer, canvas, controls, mouse, raycaster, loader, BACKGROUND_COLOR = 0xffffff;
// Scene
scene = new THREE.Scene();
scene.background = new THREE.Color(BACKGROUND_COLOR);
// Renderer with canvas
canvas = document.getElementById('canvas');
renderer = new THREE.WebGLRenderer({ canvas: canvas });
renderer.setSize(canvas.width * 3.5, canvas.height * 5);
console.log(canvas.clientWidth);
renderer.shadowMap.enabled = true;
// Set Camera
camera = new THREE.PerspectiveCamera(
75,
canvas.clientWidth / canvas.clientHeight,
0.1,
1000
);
camera.position.z = 5;
camera.position.x = 5;
camera.position.y = 1;
mouse = new THREE.Vector2();
raycaster = new THREE.Raycaster();
// Controls with options
controls = new OrbitControls(camera, renderer.domElement);
controls.maxPolarAngle = Math.PI / 2;
controls.minPolarAngle = Math.PI / 3;
controls.enableDamping = true;
controls.enablePan = false;
controls.target.set(5, 1, 0);
controls.maxAzimuthAngle = 0.8;
controls.minAzimuthAngle = -0.8;
controls.enableZoom = false;
controls.dampingFactor = 0.1;
controls.autoRotate = false;
controls.autoRotateSpeed = 0.2; // 30
loader = new GLTFLoader();
loader.load(
'assets/3d_models/kitch.glb',
(gltf) => {
kitchen = gltf.scene;
scene.add(kitchen);
console.log(kitchen);
},
undefined,
(err) => {
console.log(err);
}
);
function hoverPieces() {
const material = new THREE.MeshBasicMaterial({ color: 0xffff00 });
raycaster.setFromCamera(mouse, camera);
const intersects = raycaster.intersectObjects(scene.children);
// console.log(intersects);
for (let i = 0; i < intersects.length; i++) {
intersects[i].object.material = material;
}
console.log(intersects);
}
// Set Lights
setLights(scene);
function animate() {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
hoverPieces();
if (resizeRendererToDisplaySize(renderer)) {
const canvas = renderer.domElement;
camera.aspect = canvas.clientWidth / canvas.clientHeight;
camera.updateProjectionMatrix();
}
}
animate();
function onMouseMove(event) {
// calculate pointer position in normalized device coordinates
// (-1 to +1) for both components
mouse.x = ((event.clientX - 250) / canvas.clientWidth) * 2 - 1;
mouse.y = -(event.clientY / canvas.clientHeight) * 2 + 1;
}
window.addEventListener('mousemove', onMouseMove);
}
}
function setLights(scene) {
// Add lights
var hemiLight = new THREE.HemisphereLight(0xffffff, 0x444444, 0.61);
hemiLight.name = 'hemiLight';
hemiLight.position.set(0, 50, 0);
// Add hemisphere light to scene
scene.add(hemiLight);
var dirLight = new THREE.DirectionalLight(0xffffff, 0.54);
dirLight.name = 'dirLight';
dirLight.position.set(-8, 12, 8);
// dirLight.castShadow = true;
dirLight.shadow.mapSize = new THREE.Vector2(1024, 1024);
// Add directional Light to scene
scene.add(dirLight);
var light = new THREE.DirectionalLight(0xffffff, 3);
light.name = 'light';
light.position.set(10, 10, 10);
scene.add(light);
}
function resizeRendererToDisplaySize(renderer) {
const canvas = renderer.domElement;
var width = canvas.clientWidth;
var height = canvas.clientHeight;
var canvasPixelWidth = canvas.clientWidth / window.devicePixelRatio;
var canvasPixelHeight = canvas.clientHeight / window.devicePixelRatio;
const needResize = canvasPixelWidth !== width || canvasPixelHeight !== height;
if (needResize) {
renderer.setSize(width, height, false);
}
return needResize;
}
Gist link : https://gist.github.com/artur33s/e15abda28707231863ded08ccfe0887d
I suggest you use pointermove
instead of mousemove
and also use getBoundingClientRect()
in your event listener:
function onPointerMove(event) {
const rect = renderer.domElement.getBoundingClientRect();
mouse.x = ( ( event.clientX - rect.left ) / ( rect.right - rect.left ) ) * 2 - 1;
mouse.y = - ( ( event.clientY - rect.top ) / ( rect.bottom - rect.top) ) * 2 + 1;
}
window.addEventListener('pointermove', onPointerMove);