Rich-Harris/svelte-cubed

Primitive does not attach children to a passed-in object

camjackson opened this issue · 4 comments

My code:

I'm trying to create an Object3D manually, and then attach children to it via the svelte component hierarchy:

<script>
  import { Object3D } from 'three';

  const myObject = new Object3D();
  myObject.name = 'expectedParent';
<script>

<Primitive object={myObject}>
  <Mesh />
</Primitive>

Expected scene graph

The mesh should be a child of the object that we created, named, and passed in:

  • Scene
    • expectedParent
      • Mesh

Actual scene graph

Instead, <Primitive> creates a new Object3D of its own, and attaches both our named object and the child mesh to it. So our object ends up as a sibling of the mesh instead of as its parent.

  • Scene
    • Object3D
      • expectedParent
      • Mesh

Why is this a problem?

Firstly, it's just plain useful to be able to take a primitive object and make something else a child of it. And it's surprising that <Primitive> does not allow this. I did not expect it to create its own Object3Das a middle-layer parent.

What I'm really trying to do though, is work around the fact that svelte-cubed does not expose bindings for the three.js objects that it creates. I'm trying to use the three.js Raycaster and it needs an Object3D to test against. Luckily it can do so recursively, so I thought "I'll just stick my own primitive object into the root of the scene and search downwards from there". With the current behaviour though it doesn't work.

My workaround to the workaround was to do the above, and then when I call the raycaster instead of passing in myObject, I pass in myObject.parent. That works but it's pretty gross.

the Primitive html is the object3D, thats why when you create a new one within the script it adds it as a child. if you removed that you'd get what you're expecting.

you'll need to adjust your thinking towards how svelte does things. in this instance, if you'd like to do something to the primitive object within the script - you'll need to use the bind keyword from svelte

Yeah I understand that now, it's just not how I expected it to work 🙂 I expected that the <Primitive> component would do something like:

// Only create a new object if one was not supplied
const { root, self } = setup(object || new THREE.Object3D());

Rather than its current behaviour which is basically:

const { root, self } = setup(new THREE.Object3D());

if (object) {
  self.add(object);
}

Keen to hear your thoughts on my first snippet above. If you think it makes sense I'd be happy to put a PR together.

Also, yes, bind is exactly what I would like to use, to get the primitive object. But none of current svelte-cubed components export self, so AFAICT there's no way to get at the underlying objects, meshes, groups etc that svelte-cubed creates. Am I mistaken?

I can see that things like position, rotation, scale, material etc are exported, which is great. So if I just want to move an object then I can. But if I want to do rayCaster.intersectObject(someMesh) then that's not possible as I can't get the mesh. The only Object3D that is exported is the Primitive object, hence my example code above.

Also, yes, bind is exactly what I would like to use, to get the primitive object. But none of current svelte-cubed components export self, so AFAICT there's no way to get at the underlying objects, meshes, groups etc that svelte-cubed creates. Am I mistaken?

I can see that things like position, rotation, scale, material etc are exported, which is great. So if I just want to move an object then I can. But if I want to do rayCaster.intersectObject(someMesh) then that's not possible as I can't get the mesh. The only Object3D that is exported is the Primitive object, hence my example code above.

for some of them yes. This piece of software couldn't even be considered in alpha. Rich released it to us as part of a demonstration of svelte-kit as a tool for wrapping around other libraries. Figuring out what kind of an api there'll be is entirely your own discretion within your own fork until such a time as Rich or someone else within the community takes the project under their wing.

Doing so within your own fork would help out future discussions when it comes to it.

Yeah for sure, I totally understand that this whole thing is in its infancy. I'm just excited to be playing with it. My comments above are intended as feedback and ideas for future development, not criticism per se 🙂

I may end up forking the library at some point, but for now I will forge on with my user-space workarounds which are doing the job so far. Cheers.

Feel free to close this if you like!