Tresjs / tres

Declarative ThreeJS using Vue Components
https://tresjs.org
MIT License
2.27k stars 107 forks source link

BufferGeometry as <primitive> component throws an error #363

Closed jaekong closed 5 months ago

jaekong commented 1 year ago

Describe the bug

I was trying to load an OBJ file and get the geometry out to make it a TresLine instead of TresMesh, but it kept failed. And every BufferGeometry I've tried has failed the same thing, including empty new one (new BufferGeometry()).

Uncaught (in promise) TypeError: Spread syntax requires ...iterable[Symbol.iterator] to be a function
    at patchProp (chunk-JZH6BBMB.js:1084:11)
    at mountElement (chunk-BVQHDTV7.js:6605:11)
    at processElement (chunk-BVQHDTV7.js:6552:7)
    at patch (chunk-BVQHDTV7.js:6424:11)
    at mountChildren (chunk-BVQHDTV7.js:6680:7)
    at mountElement (chunk-BVQHDTV7.js:6587:7)
    at processElement (chunk-BVQHDTV7.js:6552:7)
    at patch (chunk-BVQHDTV7.js:6424:11)
    at mountChildren (chunk-BVQHDTV7.js:6680:7)
    at processFragment (chunk-BVQHDTV7.js:6897:7)

I could bypass this by changing the nodeOps part of compiled tres.js file, by wrapping the setAttribute call in patchProps method with try-catch, and it seems to work. But it feels kinda hacky and I am assuming there would be some data lost during this process.

스크린샷 2023-08-11 오후 11 01 59
patchProp(node, prop, _prevValue, nextValue) {
  if (node) {
    let root = node
    let key = prop
    let finalKey = kebabToCamel(key)
    let target = root?.[finalKey]

    if (root.type === 'BufferGeometry') {
      if (key === 'args') return
      try { // added to bypass error
        root.setAttribute(
          kebabToCamel(key),
          new BufferAttribute(...(nextValue as ConstructorParameters<typeof BufferAttribute>)),
        )
      } catch {} // added to bypass error
      return
    }
// ...

https://github.com/Tresjs/tres/blob/211c3e172726a4cb339a02333ac596fcf3bb7793/src/core/nodeOps.ts#L187C7-L187C7

Reproduction

https://stackblitz.com/edit/tresjs-basic-yrhocm?file=src%2Fcomponents%2FTheExperience.vue

Steps to reproduce

  1. Create a TresCanvas and include a TresMesh or any other component that utilises a geometry.
  2. Create a BufferGeometry in <script> section. (ex. const geometry = new BufferGeometry())
  3. Refer to the BufferGeometry with <primitive :object="geometry"> tag.
  4. Run the code.

System Info

System:
  OS: macOS 14.0
  CPU: (10) arm64 Apple M1 Max
  Memory: 114.36 MB / 32.00 GB
  Shell: 5.9 - /bin/zsh
Binaries:
  Node: 18.14.0 - ~/.nvm/versions/node/v18.14.0/bin/node
  npm: 9.3.1 - ~/.nvm/versions/node/v18.14.0/bin/npm
Browsers:
  Safari: 17.0
npmPackages:
  @tresjs/cientos: ^3.0.1 => 3.0.1
  @tresjs/nuxt: ^1.1.3 => 1.1.3

Note: I also have ran this on Firefox (116.0.2) and Arc (Version 1.3.0 (40706) / Chromium Engine Version 115.0.5790.170)

Used Package Manager

npm

Code of Conduct

alvarosabu commented 1 year ago

Hey @jtodaone thanks for opening this ticket

@Tinoooo maybe we need to add a conditional for the nextValue inside the if?

andretchen0 commented 5 months ago

I'm working on primitive. Will attempt to address this with the same patch.

dghez commented 4 months ago

Confirmed i'm having the same issue image

Not happening if I'm creating the mesh new Mesh(bufferGeometry,....) and use that mesh as primitive <primitive :object="mesh">,