Accessing mesh property outside of THREE.Fontloader()

Hey guys,

I was carefully following this thread (Accessing font mesh outside of THREE.Fontloader?) in order to rotate my 3D text mesh and although I have the exact same problem it doesn’t seem to be working for me :expressionless:

Here’s my code, the text is properly displaying but when I’m trying to change the position I get this error message (Uncaught TypeError: Cannot read property ‘position’ of undefined)

const fontLoader = new THREE.FontLoader();

let text;

fontLoader.load("/fonts/Gar-A-MondTall_Light.json", (font) => {
const textGeometry = new THREE.TextBufferGeometry(“HELLO WORLD”, {
font: font,
size: 1,
height: 0.1,
curveSegments: 32,
bevelEnabled: true,
bevelThickness: 0.03,
bevelSize: 0.02,
bevelOffset: 0,
bevelSegments: 4,
});

textGeometry.center();

const material = new THREE.MeshMatcapMaterial({
matcap: matcapTexture,
color: “#ACE1FF”,
});

text = new THREE.Mesh(textGeometry, material);
scene.add(text);
});

let waitForLoad = () => {
if (text === undefined) {
window.requestAnimationFrame(waitForLoad);
} else {
scene.add(text);
}
};

If you have any clues, thank you so much in advance :grinning_face_with_smiling_eyes:

no offense, but this looks a little fragile to me. waitForLoad is … polled? your problem might just be a race condition, that code is kind of asking for it. you can have some order either with callback hell (executing everything in the outmost onion layer) or async await, which in your case i’d suggest you use.

async function run() {
  // some loaders also have loadAsync inbuilt
  const font = await new Promise(res => new FontLoader().load(url, res))
  const geo = new TextGeometry("hello", { font, size: 1, ... })
  ...
  const mesh = new Mesh(geo, new MeshBasicMaterial())
  const scene = new Scene()
  scene.add(mesh)

  function loop() {
    requestAnimationFrame(loop)
    gl.render(scene, camera)
  }

  loop()
}

run()

ps “#ACE1FF”, “HELLO WORLD” imo is not valid javascript.
pps executing loaders one after the other is very inefficient, so you’ll want to optimize this later on by using something like Promise.all which would allow you to fetch all the assets that you need in one spot, but in parallel!

const [font, texture, model] = await Promise.all([
  new Promise(res => new FontLoader().load(url, res)),
  new Promise(res => new TextureLoader().load(url, res)),
  new Promise(res => new GLTFLoader().load(url, res)),
  ...
])

Sorry for not specifying it, but I’m also a hugo noob in javascript and coding in general :sweat: so what you’re suggesting is like Chinese to me :grinning_face_with_smiling_eyes:

But thanks for you answer ! I’ll look into it and try to understand the pieces i’m missing :+1:

no worries, it’s not that much, you could go through a quick refresh of js semantics. babel has a good article on es2015 Learn ES2015 · Babel and mozilla has a good one that teaches you promises and async/await Making asynchronous programming easier with async and await - Learn web development | MDN generally loaders in three are always async, you need to be familiar with callbacks, promises and/or async/await. polling data can otherwise easily turn into a nightmare.