ObjLoader Issues

Hi Speckle!

I’m trying to use the ObjLoader in my JS/React project where I’ve implemented a Speckle Viewer. PS, I’m not a very good dev (I’m an architect learning to be a dev) and I can’t seem to figure this error out. I get "Cannot load “resource” every time load() is called. The “resourceData” I’m loading is on OBJ string that looks like the following.

o mesh-0
v -8937581 5335397 0
v -8937576 5335389.5 0
v -8937572 5335392.5 0
v -8937568 5335388 0
v -8937562 5335411 0
v -8937554 5335398.5 0
vt 1 0.4032147228717804
vt 0.8017799258232117 0.07032811641693115
vt 0.6529126167297363 0.2002677172422409
vt 0.5339806079864502 0
vt 0.31755661964416504 1
vt 0 0.46684497594833374
vn 0 0 1
vn 0 0 1
vn 0 0 1
vn 0 0 1
vn 0 0 1
vn 0 0 1
f 3/3/3 6/6/6 5/5/5
f 4/4/4 6/6/6 3/3/3
f 1/1/1 2/2/2 3/3/3
f 5/5/5 1/1/1 3/3/3

I create this OBJ string in another process in my app, store it in global state, get it from that global state, and load it via objs[0]. My process
creates an array of OBJs, but for testing purposes I’m only selecting the first index. I know the OBJ isn’t a problem because I’ve replaced “public/d20.obj” in your Loaders example with the above string and it works.

Here’s my code. If there’s anything you notice that might be causing this problem I’d be forever grateful for you to point it out.

import {
  Viewer,
  DefaultViewerParams,
  CameraController,
  SelectionExtension,
  ObjLoader,
} from "@speckle/viewer";
import useStore from "../store/store";

function SpeckleViewer() {
  const { objs } = useStore();
  const containerRef = useRef(null);
  const viewerRef = useRef(null);

  // Initialize viewer

  useEffect(() => {
    if (viewerRef.current) return;

    const params = DefaultViewerParams;
    params.showStats = false;
    params.verbose = true;

    const viewer = new Viewer(containerRef.current, params);
    viewerRef.current = viewer;

    const run = async () => {
      await viewer.init();
      viewer.createExtension(CameraController);
      viewer.createExtension(SelectionExtension);
    };

    run();
  }, []);

  // Load objects

  useEffect(() => {
    const viewer = viewerRef.current;

    if (objs.length === 0) return;
1
    async function load() {
      const loader = new ObjLoader(viewer.getWorldTree(), "obj-0", objs[0]);
      await viewer.loadObject(loader, true);
    }

    load();
  }, [objs]);

  return <div ref={containerRef} id="speckle-container" />;
}

export default SpeckleViewer;

Been troubleshooting all day with no luck. I can get this to work.

    async function loadSpeckle() {
      const urls = await UrlHelper.getResourceUrls("https://app.speckle.systems/projects/7591c56179/models/32213f5381");
      for (const url of urls) {
        const loader = new SpeckleLoader(viewer.getWorldTree(), url, "");
        /** Load the speckle data */
        await viewer.loadObject(loader, true);
      }
    }
    loadSpeckle();

But not this (loading an OBJ).

    async function loadObj() {
      let i = 0;
      for (const obj of objs) {
        const loader = new ObjLoader(viewer.getWorldTree(), `${i}`, obj);
        await viewer.loadObject(loader, true);
        i++;
      }
    }
    loadObj();

Hi @aidannewsome

Welcome to the community! :partying_spockle: Feel free to introduce yourself!

I had a look at the issue you reported and indeed, the obj loader fell behind on some of our updates and is no longer properly working.
We’ll be sure to get it fixed! But so you don’t have to wait for the fix I’ll provide you with a patched obj loader that works, since loaders can be written and customized at application level, not only speckle library level.

Cheers

1 Like

OMG amazing! Thank you so much :folded_hands:

PS it would be an amazing piece of help if there was better documentation on making a custom loader or even a video. It’s a little trivial to understand from just the examples.

Hey Alex, just wondering how long a patch might take or if I should just copy out and use the old ObjLoader from one of those examples?

Hi @aidannewsome

We’ve just released 2.26.8 which fixes the ObjLoader issue

We’ve intentionally kept custom loader development loose and abstract. Data can come in from anywhere in any shape or form, that’s why we chose to not impose any specific structure. This part explains what any custom loader would need to do in order for the viewer library to be able to work with the data, but as far as how you implement the loader itself, that’s mostly up to you. For example, the ObjLoader we currently have implemented could work for most if not all of the other formats that three.js has loaders for, since it piggy backs on those loaders to actually parse data.

Cheers