Giter Site home page Giter Site logo

Comments (14)

alvarosabu avatar alvarosabu commented on August 23, 2024 4

Hi @darkvertex the event issue with dynamic components should be fixed with #763, hasn't being released yet. Probably today

from tres.

darkvertex avatar darkvertex commented on August 23, 2024 1

Also to be clear, I don't believe this is an issue with threejs as there is an official example showing dynamically changing instance counts on the same InstancedMesh working no problem:

https://threejs.org/examples/?q=inst#webgl_instancing_dynamic

from tres.

alvarosabu avatar alvarosabu commented on August 23, 2024 1

Hey buddy @Neosoulink, not yet, but it would be great if you could help us with it.

from tres.

darkvertex avatar darkvertex commented on August 23, 2024 1

Thanks for taking a look, @Neosoulink!

You are indeed right that "count" cannot go higher than the value fed to the constructor. I missed that in the docs, my bad. -- It turns out that the "count" property is editable however, so as long it is a lower or equal value than what was given to the constructor.

With this corrected knowledge, I forked my bug repro stackblitz and got it working given the "count" prop never exceeds the value of the constructor. I give it a higher number (10) at consturction and track the desired count separate from the max (initial) count, and ensure my desired count does not exceed the initial.

This works reasonably well now:
https://stackblitz.com/edit/tresjs-instanced-mesh-vwhmkx?file=src%2Fcomponents%2FTheExperience.vue
(click on the monkey idling in the center, and it will add up to 10 instances.)

Now, what if the stuff fed to ":args=..." (constructor) changes? Would it be a crazy expectation that if constructor (":args=...") change because the given props changed upstream, the old threejs InstancedMesh object ought to be cleanly disposed of and a new one recreated in its place?

If you hold the Shift key while clicking on the monkey in the middle in my example above, it will attempt to set the "maxCount" to a higher number (1000 instead of 10), which was passed to the ":args", so I would have thought TresJS would handle re-syncing, but instead you will see this error below:

image

I can kinda work around my issues by setting a very high initial count, but it would be nice if TresJS could autorecreate the InstancedMesh should the constructor's reactive values change.

Thoughts?

from tres.

Neosoulink avatar Neosoulink commented on August 23, 2024 1

@darkvertex, nice to know you partially solved the issue!

But this issue is more about ThreeJs itself,

If you want to increase the max-count, you have to recreate a new InstancedMesh

See my Tres examples integration
https://stackblitz.com/edit/tresjs-instanced-mesh-pwbt4l?file=src%2Fcomponents%2FTheExperience.vue

from tres.

Neosoulink avatar Neosoulink commented on August 23, 2024

Hey @alvarosabu, is someone working on this?

I can Investigate and work on this

from tres.

Neosoulink avatar Neosoulink commented on August 23, 2024

@darkvertex it's important you understand that the count of instancedMesh can not be resized to a higher level

As mugen87 mentionned it here: https://discourse.threejs.org/t/modified-three-instancedmesh-dynamically-instancecount/18124/10

Keep in mind that InstancedMesh.count represents the maximum count of instances. You need to init the mesh with this number but can then alter the property to a lower value.
Buffers can not be resized!

From the Doc InstancedMesh.count

You can change the number of instances at runtime to an integer value in the range [0, count].
If you need more instances than the original count value, you have to create a new InstancedMesh.


With that said, why are you getting the error:

"Cannot assign to read only property position of object #<InstancedMesh>"

I'm unsure, but the error is triggered after the count is modified. count being an argument of an instance, it can not be modified again.


Now let's see alternatives,
Understand that even if the count was working, you wouldn't be able to increase the count like that.

Here I've created an alternative solution to increase InstancedMesh in Tres

const material = new MeshNormalMaterial();
const count = shallowRef(1);
const instancedMesh = shallowRef();

const createPrimitiveInstance = () =>
  h('primitive', {
    ref: instancedMesh,
    object: new InstancedMesh(susane, material, count.value ?? 1),
  });

const InstancedComponent = shallowRef(() => createPrimitiveInstance());

const resetInstancedComp = () => {
  instancedMesh.value?.dispose();
  InstancedComponent.value = () => createPrimitiveInstance();
};

onLoop(({ elapsed }) => {
 // codes ...
});

onMounted(() => {
  setInterval(() => {
    if (count.value < 100) {
      count.value++;
      resetInstancedComp();
      console.log('instancedMesh updated', count.value);
    }
  }, 3000);
});

//////////

<template>
  <TresCanvas v-bind="stateCanvas">
    <InstancedComponent />
  </TresCanvas>
</template>

The above code will add each 3 sec a new instance to the scene.
See the complete example here: https://stackblitz.com/edit/tresjs-instanced-mesh-pwbt4l?file=src%2Fcomponents%2FTheExperience.vue


@alvarosabu, I don't think it's related to Tres didn't find anything

Error coming from patchProp property of nodeOps precisely in the root Object.assign.

from tres.

darkvertex avatar darkvertex commented on August 23, 2024

@Neosoulink Ah, I get what you did now. Okay.

With your approach of having a swapable "component", do you know how could I get @click events working again on the <InstancedComponent>? -- I incorporated your technique but they do not appear to trigger anymore (and they did when it was on the direct <TresInstancedMesh> component.)

from tres.

darkvertex avatar darkvertex commented on August 23, 2024

@alvarosabu Oh, que bueno! ❤️

Will I need to do any code gymnastics to make the raycast click stuff detect the instanceid under the click, given that this is a dynamic component? Or does TresJS figure it out by the threejs object type?

from tres.

darkvertex avatar darkvertex commented on August 23, 2024

I don't have a bug repro stackblitz for you at this time, but I wanted to share some oddities:

I tried to update my real app code to 4.2.0 and it goes into an infinite loop of recreating the InstancedMesh, whereas 4.0.2 works fine but had no working click events in my component.

The trick of using a function to return a primitive seems to be the culprit somehow, as when I change directly to having a <primitive :object="myInstancedMesh" /> in my <template> instead of referencing a dynamic component then I can point it to a mesh almost the same way and the infinite creation loop goes away.

When I test with static data it seems I have click events with it, but when I have the whole thing hooked up, my instances are updating nicely, and on-demand rendering is working nicely too, but I cannot get any click events to fire at all... I'm stumped. 🤔

Is there a special debug verbosity flag or something I can enable to get more visibility on what's happening inside Tres?

from tres.

alvarosabu avatar alvarosabu commented on August 23, 2024

Is there a special debug verbosity flag or something I can enable to get more visibility on what's happening inside Tres?

Hi @darkvertex have you tried checking the scene graph on the vue devtools?

Screenshot 2024-07-15 at 20 09 50

from tres.

darkvertex avatar darkvertex commented on August 23, 2024

Yes.

When I was having the issue of the instancedmesh being regenerated in perpetuity the devtools for Tres showed the mesh in question flickering in the Scene breakdown, which was probably from being trashed and recreated over and over.

Now with my functional but unclickable setup there's no flickering of the mesh and there does seem to have the click event attached:
image
but the click event is not firing.

from tres.

darkvertex avatar darkvertex commented on August 23, 2024

Ok, I think I found my issue with click events not firing.

Calling .computeBoundingSphere() on the InstancedMesh after doing all my instances matrix updates (.setMatrixAt(...)) seems to make clicking work again. I didn't know this was necessary.

Curiously, doing .computeBoundingBox() does not help, only .computeBoundingSphere() fixes it. Odd.

from tres.

darkvertex avatar darkvertex commented on August 23, 2024

When I tested just manually setting two instances at the root of the component without anything dynamic, click events worked without having to recompute any bounding volumes.

It's as if the bounding spheres are computed the very very first render and then that's it.

from tres.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.