Been able to figure out a bunch of stuff looking through examples and the forum, but I am stuck right now and looking for some help.
I have imported a 3d model of a skull into 3js. The skull has 2 objects that I modeled in blender, the skull and jaw.
What I am trying to do is attach transformcontrols to just the jaw part. I confirmed that the object’s name is jaw through the console.
What ends up happening right now is that the controls looks like its just attached to the scene instead. I can interact and manipulate the controls when it’s in rotate, but nothing happens. When it’s on scale mode, I can interact with it (all the axes highlight when I mouse over them), but I can’t scale the model as if it was locked. If I use transform, the code just breaks. These errors I get:
Uncaught TypeError: this.picker[this.mode] is undefined
Uncaught TypeError: object is undefined
So I have no idea what the controls is even attached to even though I specified the jaw.
Here’s the code I’m using right now and doesn’t give me any errors, but it’s not working as intended:
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
import { TransformControls } from 'three/addons/controls/TransformControls.js';
import WebGL from 'three/addons/capabilities/WebGL.js';
import GUI from 'lil-gui';
let skull;
const scene = new THREE.Scene( );
scene.background = new THREE.Color( 0xdddddd );
scene.add( new THREE.GridHelper( 1000, 1000, 0x888888, 0x444444 ) );
const camera = new THREE.OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, 1, 1000 );
const hlight = new THREE.AmbientLight ( 0x404040, 10 );
scene.add( hlight );
const directionalLight = new THREE.DirectionalLight( 0xffffff, 10 );
directionalLight.position.set( 0, 1, 0 );
directionalLight.castShadow = true;
scene.add( directionalLight );
const renderer = new THREE.WebGLRenderer( );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setAnimationLoop( animate );
document.body.appendChild( renderer.domElement );
const loader = new GLTFLoader( );
loader.load( 'skull.glb', function ( gltf ) {
skull = gltf.scene;
skull.traverse( function( object ) {
if ( object.isMesh ) console.log( object );
} );
scene.add( skull );
}, undefined, function ( error ) {
console.error( error );
} );
const controls = new OrbitControls( camera, renderer.domElement );
controls.update( );
controls.addEventListener( 'change', animate );
const tcontrols = new TransformControls( camera, renderer.domElement );
tcontrols.setMode( 'rotate' );
tcontrols.addEventListener( 'change', animate );
tcontrols.addEventListener( 'dragging-changed', function ( event ) {
controls.enabled = ! event.value;
} );
tcontrols.size = 1;
tcontrols.space = 'local';
const Jaw = new THREE.Mesh( skull );
scene.add( Jaw );
tcontrols.attach( Jaw );
scene.add ( tcontrols );
camera.position.x = 157;
camera.position.y = -245;
camera.position.z = 127;
const gui = new GUI( );
const myObject = {
myBoolean: true,
myFunction: function( ) { alert( 'hi') },
myString: 'lil-gui',
myNumber: 1
};
gui.add( myObject, 'myBoolean' ); // Checkbox
gui.add( myObject, 'myFunction' ); // Button
gui.add( myObject, 'myString' ); // Text Field
gui.add( myObject, 'myNumber' ); // Number Field
// Add sliders to number fields by passing min and max
gui.add( myObject, 'myNumber', 0, 1 );
gui.add( myObject, 'myNumber', 0, 100, 2 ); // snap to even numbers
// Create dropdowns by passing an array or object of named values
gui.add( myObject, 'myNumber', [ 0, 1, 2 ] );
gui.add( myObject, 'myNumber', { Label1: 0, Label2: 1, Label3: 2 } );
// Create color pickers for multiple color formats
const colorFormats = {
string: '#ffffff',
int: 0xffffff,
object: { r: 1, g: 1, b: 1 },
array: [ 1, 1, 1 ]
};
gui.addColor( colorFormats, 'string' );
function animate( ) {
renderer.render( scene, camera );
}
I am able to attach the controls to just a regular geometric shape when I use this based off the examples:
orbit = new OrbitControls( currentCamera, renderer.domElement );
orbit.update();
orbit.addEventListener( 'change', render );
control = new TransformControls( currentCamera, renderer.domElement );
control.setMode( 'rotate' );
control.addEventListener( 'change', render );
control.addEventListener( 'dragging-changed', function ( event ) {
orbit.enabled = ! event.value;
} );
const mesh = new THREE.Mesh( geometry );
scene.add( mesh );
control.attach( mesh );
scene.add( control );
But trying to get the controls on the imported object is confusing me. Maybe it’s the placement of some of the parts in the code?
Any help would be greatly appreciated.
