Scenario:
- Multiple obj file meshes loaded with ObjLoader2 are present in the scene
Issue:
- After moving objects with transformControls, their position is not getting updated
Minimal Reproducible Code:
-
Unzip the file minRepro.zip (3.3 KB) inside three.js/examples directory
-
Open demo_objload.html in chrome browser.
-
Click on any of the objects and move around using the gizmo. In console logs, notice that the object positions are not getting updated.
-
Pasting the code here as well for a quick look:
// transform controls const transformControls = new TransformControls(camera, canvas); transformControls.addEventListener("dragging-changed", function (event) { orbitControl.enabled = !event.value; }); scene.add(transformControls); // objects let objects = []; function callbackOnLoad(obj) { const p = [0.5 * Math.random(), 0.5 * Math.random(), 0.5 * Math.random()]; obj.position.set(p[0], p[1], p[2]); scene.add(obj); objects.push(obj); } let files = ["4.obj", "5.obj"] for (var i=0; i<files.length; i++) { const objLoader = new OBJLoader2(); objLoader.load(files[i], callbackOnLoad, null, null, null); } document.addEventListener("click", function(event) { let mouse = new THREE.Vector2( (event.clientX / window.innerWidth) * 2 - 1, -(event.clientY / window.innerHeight) * 2 + 1 ); let raycaster = new THREE.Raycaster(); raycaster.setFromCamera(mouse, camera); let intersections = raycaster.intersectObjects(objects, true); if (intersections.length > 0) { let object = intersections[0].object; transformControls.attach(object); } }); function render() { if (resizeRendererToDisplaySize(renderer)) { const canvas = renderer.domElement; camera.aspect = canvas.clientWidth / canvas.clientHeight; camera.updateProjectionMatrix(); } for (var i=0; i<objects.length; i++) { let p = objects[i].position; console.log(`-- ${p.x} ${p.y} ${p.z}`); } console.log("======"); renderer.render(scene, camera); requestAnimationFrame(render); } requestAnimationFrame(render); }
More details
I tried manually creating objects using THREE’s Mesh function (instead of loading via ObjLoader2) and it worked perfectly fine with TransformControls. Following is the code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TransformControl Issue</title>
<style>
html,
body,
#three_canvas {
width: 100%;
height: 100%;
margin: 0px;
}
</style>
</head>
<body>
<canvas id="three_canvas"></canvas>
<script type="module">
import * as THREE from "../build/three.module.js"
import { OrbitControls } from './jsm/controls/OrbitControls.js';
import { TransformControls } from './jsm/controls/TransformControls.js';
function resizeRendererToDisplaySize(renderer) {
const canvas = renderer.domElement;
const width = canvas.clientWidth;
const height = canvas.clientHeight;
const needResize = canvas.width != width || canvas.height != height;
if (needResize) {
renderer.setSize(width, height, false);
}
return needResize;
}
function main() {
// renderer
const canvas = document.querySelector("#three_canvas")
const renderer = new THREE.WebGLRenderer({
canvas
});
// camera
const camera = new THREE.PerspectiveCamera(75, 2, 0.1, 100);
camera.position.set(0, 3, 3);
// control
const orbitControl = new OrbitControls(camera, canvas);
orbitControl.target.set(0, 0, 0);
orbitControl.update();
// scene
const scene = new THREE.Scene();
scene.add(new THREE.GridHelper(5, 50));
// transform controls
const transformControls = new TransformControls(camera, canvas);
transformControls.addEventListener("dragging-changed", function (event) {
orbitControl.enabled = !event.value;
});
scene.add(transformControls);
// lights
{
const light = new THREE.HemisphereLight();
scene.add(light);
} {
const light = new THREE.DirectionalLight();
light.position.set(0, 10, 0);
light.target.position.set(0, 0, 0);
scene.add(light);
scene.add(light.target);
}
// objects
let objects = [];
// - cube 1
const cubeGeometry = new THREE.BoxGeometry(0.5, 0.5, 0.5);
const redMaterial = new THREE.MeshBasicMaterial({color: 0xf56342});
const cube1 = new THREE.Mesh(cubeGeometry, redMaterial);
cube1.position.x = 2;
scene.add(cube1);
objects.push(cube1);
// - cube 2
const greenMaterial = new THREE.MeshBasicMaterial({color: 0x025711});
const cube2 = new THREE.Mesh(cubeGeometry, greenMaterial);
cube2.position.y = 2;
scene.add(cube2);
objects.push(cube2);
transformControls.attach(cube2);
document.addEventListener("click", function(event) {
let mouse = new THREE.Vector2(
(event.clientX / window.innerWidth) * 2 - 1,
-(event.clientY / window.innerHeight) * 2 + 1
);
let raycaster = new THREE.Raycaster();
raycaster.setFromCamera(mouse, camera);
let intersections = raycaster.intersectObjects(objects, true);
if (intersections.length > 0) {
let object = intersections[0].object;
transformControls.attach(object);
}
});
function render() {
if (resizeRendererToDisplaySize(renderer)) {
const canvas = renderer.domElement;
camera.aspect = canvas.clientWidth / canvas.clientHeight;
camera.updateProjectionMatrix();
}
for (var i=0; i<objects.length; i++) {
let p = objects[i].position;
console.log(`-- ${p.x} ${p.y} ${p.z}`);
}
console.log("======");
renderer.render(scene, camera);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
}
main();
</script>
</body>
</html>
I appreciate any help. Thanks.