How to move GLB file via Dragcontrols

2 weeks ago 21
ARTICLE AD BOX
Three issues here. 1. Typo - you define moveModel but pass moveMiku to DragControls. That throws a ReferenceError. 2. Async timing - GLTFLoader is asynchronous. When this line runs: const moveModel = [model]; the loader callback hasn't fired yet, so model is still undefined. You're passing [undefined] to DragControls. You need to initialize DragControls inside the loader callback: let dragControls; const loader2 = new GLTFLoader(); loader2.load('assets/blendmodel.glb', function(glb){ model = glb.scene; scene2.add(model); dragControls = new DragControls([model], camera2, renderer.domElement); dragControls.transformGroup = true; }); 3. Wrong tool for what you want - you said you want the model to follow the cursor without clicking. DragControls requires click-and-drag interaction. For cursor tracking you need to handle mousemove directly: window.addEventListener('mousemove', (event) => { if (!model) return; const mouse = new THREE.Vector2( (event.clientX / sizes.width) * 2 - 1, -(event.clientY / sizes.height) * 2 + 1 ); const vector = new THREE.Vector3(mouse.x, mouse.y, 0.5).unproject(camera2); const dir = vector.sub(camera2.position).normalize(); const dist = -camera2.position.z / dir.z; const pos = camera2.position.clone().add(dir.multiplyScalar(dist)); model.position.x = pos.x; model.position.y = pos.y; }); This projects the 2D mouse position into 3D space at the model's z-depth and updates position every frame.

Here is how i would approach it
--JS--

import * as THREE from 'three'; import { GLTFLoader } from 'three/examples/jsm/Addons.js'; const canvas = document.querySelector('.gamescreen'); const scene1 = new THREE.Scene(); const scene2 = new THREE.Scene(); const sizes = { width: 1270, height: 853, }; const loader1 = new GLTFLoader(); loader1.load('assets/Background.glb', function(glb){ const stage = glb.scene; for (let i = -20; i <= 20; i++){ for (let j = -20; j <= 20; j++){ const instance = stage.clone(); instance.position.set(i * 0, 0, j * 200); scene1.add(instance); } } scene1.add(stage); }); let model; const loader2 = new GLTFLoader(); loader2.load('assets/blendmodel.glb', function(glb){ model = glb.scene; scene2.add(model); }); const light1 = new THREE.DirectionalLight(0xffffff, 1); light1.position.set(2, 2, 5); scene1.add(light1); const light2 = new THREE.DirectionalLight(0xffffff, 1); light2.position.set(2, 2, 5); scene2.add(light2); const camera1 = new THREE.PerspectiveCamera(160, sizes.width/sizes.height, 0.1, 100); camera1.position.set(0, 0, 5); scene1.add(camera1); const camera2 = new THREE.PerspectiveCamera(160, sizes.width/sizes.height, 0.1, 100); camera2.position.set(0, 0, 5); scene2.add(camera2); const renderer = new THREE.WebGLRenderer({ canvas: canvas }); renderer.setSize(sizes.width, sizes.height, true); renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); renderer.shadowMap.enabled = true; renderer.gammaOutput = true; // cursor following without clicking window.addEventListener('mousemove', (event) => { if (!model) return; const rect = canvas.getBoundingClientRect(); const mouse = new THREE.Vector2( ((event.clientX - rect.left) / sizes.width) * 2 - 1, -((event.clientY - rect.top) / sizes.height) * 2 + 1 ); const vector = new THREE.Vector3(mouse.x, mouse.y, 0.5).unproject(camera2); const dir = vector.sub(camera2.position).normalize(); const dist = -camera2.position.z / dir.z; const pos = camera2.position.clone().add(dir.multiplyScalar(dist)); model.position.x = pos.x; model.position.y = pos.y; }); function animate(){ requestAnimationFrame(animate); renderer.autoClear = false; camera1.position.z -= 0.1; renderer.render(scene1, camera1); renderer.render(scene2, camera2); } animate();

--HTML--

<!DOCTYPE html> <html lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Project</title> <script type="importmap"> { "imports": { "three": "https://unpkg.com/[email protected]/build/three.module.js", "three/examples/jsm/Addons.js": "https://unpkg.com/[email protected]/examples/jsm/Addons.js" } } </script> <link rel="stylesheet" href="src/style.css"> <script type="module" src="src/threeeditor.js"></script> </head> <body> <canvas class="gamescreen"></canvas> <div class="backgroundborder"> <div class="songdetails"> <p class="gametitle">Game</p> <p class="score">Score: 0</p> <p class="songname">Song name</p> <p class="artist">Artist</p> </div> <div class="buttons_time"> <button class="prev" title="PreviousButton">⏮</button> <button class="play" title="PlayButton">▶</button> <button class="next" title="NextButton">⏭</button> <span class="time" title="CurrentTime">00:00</span> <span class="divider" title="CurrentTime-SongLength-Diver">/</span> <span class="length" title="SongLength">00:00</span> <button class="showhide">☰</button> </div> </div> </body> <script src="src/songlist.js"></script> <script src="src/main.js"></script> </html>
Read Entire Article