Are there any known pitfalls resulting in conflicting geometry ids (geometry.id)?

Hello!

We keep running into issues regarding conflicting geometry.id s resulting e.g. in Meshes being swapped / wrong and would like to know if there are any known pitfalls resulting in this behavior.

We assume it has something to do with:

  1. SubdivisionModifier :thinking:
  2. TextGeometry :thinking: (EDIT: not the problem!)

Our current workaround is to .clone() the geometries being generated by the SubdivisionModifier and the TextGeometry till the geometry.ids don’t conflict anymore. With the TextGeometry we have to do it even twice clone().clone() in order to push the geometry.id high enough and this feels very wrong so we would like to avoid it / fix it / do it the right way / find out why this is happening.

:point_right: We’re developing with the dev-branch using modules.

:point_right: SubdivisionModifier usage: We load .obj-Files (OBJLoader), extract / modify the geometry and then create new meshes from modified geometry.

:point_right: TextGeometry usage: standard / as described in the docs

Thank you! :slightly_smiling_face:

Any chances to demonstrate this issue with a live example? Without a test case, it’s hard to analyze the problem since I’ve never encountered something similar before.

1 Like

Hi, ok, we’ll try to reproduce in a simplified example and post it here.
Knowing there actually should be no such issues let’s us assume that the bug is probably produced by our project setup / structure … so thanks! :slightly_smiling_face::+1:

Hi @Mugen87!

We believe we’ve managed to identify the problem:

:point_right: Geometry from loaded OBJ-File gets conflicting id after being modified by SubdivisionModifier.
This seems to happen only if developing with modules / importing from source (dev-branch).

:face_with_monocle: Test 1 (IIFE) works as intended. No conflicting ids. :point_right: see console output.

:face_with_monocle: Test 2 (Modules) is basically the same as Test 1 but importing modules from source (dev-branch).
Here the SubdivisionModifier returns Geometries with conflicting ids after modification: one of the generated BoxGeometries (g1) with id:4 gets “overwritten” by the modified “ream”-Geometry (modified_geom1) initially loaded via OBJLoader :point_right: see console output. So when we try to add a Box using g1 (1000ms timeout), another “ream”-Mesh is being added instead of a Box. See also code of the class SubdivisionTest.ts

Thank you very much in advance for checking this issue + feedback! :grin::+1:

How are you including three.js into your project? It seems three.js gets loaded multiple times. Thus, you effectively have multiple ID counters (with non-unique results).

We’re using modules: TypeScript + Rollup setup. Basically we create (export) ts-classes and import all three-modules we need… :thinking:

All our TypeScript-classes look basically like this:

import { ... } from "three"; // "three" points to "Three.d.ts" inside "node_modules/three/src"
import { ... } from "three/examples/jsm/...";

export class Foo {
... }

Um, using classes from node_modules/three/src could probably be the root cause of the problem since all JSM modules rely on node_modules/three/build/three.module.js. It seems Three.d.ts points to the wrong place.

Can you please verify this by putting a console.log() in src/core/Geometry.js and logging the ID within the constructor. It will probably write only certain IDs to the console.

We did, but can see no such output at all in the console… :thinking:

function Geometry() {

	Object.defineProperty( this, 'id', { value: geometryId += 2 } );

	console.log("Log ID from Geometry constructor:" , this.id);

… an excerpt from Three.d.ts:

export * from './animation/AnimationAction';
export * from './core/Uniform';
export * from './core/InstancedBufferGeometry';
export * from './core/BufferGeometry';
export * from './core/Geometry';
export * from './core/InterleavedBufferAttribute';
export * from './core/InstancedInterleavedBuffer';
export * from './core/InterleavedBuffer';
export * from './core/InstancedBufferAttribute';
export * from './core/BufferAttribute';
export * from './core/Face3';
export * from './core/Object3D';

… and from package.json:

"_from": "github:mrdoob/three.js#dev",
"_id": "three@0.105.1",

Please try to put the mentioned console.log in all build files to see what code paths are actually taken. If always the same log is triggered, we might heading in the wrong direction.

Adding the log to three.min.js will be tricky but please give it a try.

Ok, can be done in about 2 hours…

:point_up:t2: though it’s a fact that we encounter this “offset” geometry.id issue only at this part of code where SubdivisionModifier is being used. We generate about 15 different geometries and over 60 Meshes in our project across multiple classes and these two geometries (ids) are the only ones “offset” / conflicting. I’m pointing this out, because we’ve looked at the issue really closely yesterday and finally came to the conclusion that the problem must be related to importing the SubdivisionModifier as module… :thinking:

Ok, done! :point_right: all being logged from three.module.js.

Even the “bad” ones:

Log ID from Geometry constructor (three.module.js): 2
Log ID from Geometry constructor (three.module.js): 4
C geometry after modification: 2
theR geometry after modification: 4

geometry.ids passed to SubdivisionModifier were:

C geometry before mofification: 7
theR geometry before mofification:: 11

Good to hear that!

Now I remember something: SubdivisionModifier does not modify the given geometry object but always creates a new one! Same for SimplifyModifier. This definitely explains the different IDs. However, that should always happen no matter of using ES6 modules from the JSM directory.

Here is the respective code section:

Yes, we were aware of that. :wink:
:point_up: The problem is that the new, subdivided geometry ids are not unique / “out of sync” with the others and are conflicting (could conflict) / are “overwriting” (could “overwrite”) other geometries.
:point_right: see Test 2 (Modules)

Are you aware that you have three.js included two times in your main2.js file? E.g. there is Geometry and Geometry$1. This would explain the wrong ids…

well… no. :man_shrugging:t3: :point_up:t2: it’s sure not supposed to be so. The question is: why is it? :thinking: Will have to take a closer look at it later… thanks!

… I assume the way we’re importing (from “three”) is wrong. :thinking:

I’m sorry but I have not programmed with TypeScript so far. We (the three.js dev team) just provide the type declaration files, that’s all.

1 Like

And you’re doing a great job with that! :+1::grin:

I now remember we were at this point already at the beginning of the project. We first imported everything directly from “three.module.js” than switched to “three” at some point later because it was functioning and “felt” right (correct IDE-labels, code completion etc.) and was constantly proposed like that by IntelliJ. At the end of the day it’s probably “just” setting the type-definitions, IDE etc. REALLY right. At least I hope so! :wink:

I will drop a word here when everything’s put straight again and we are sure there are no issues with the SubdivisionModifier. Thank you for your time! :+1::fist:

1 Like

Hi! I just wanted to let you know that:

  1. We’ll stick with our current three-modules importing (from “three”), it’s fine, not the problem.
  2. We still think there is an issue with the current SubdivisionModifier-Module. We’ve now tried our “old” (before you added it to jsm) self-modified Module and it is working as expected, the geometry-ids are being applied correctly. Here it is: SubdivisionModifier as Module.

:point_up: We could not confirm the issue concerning double running three you mentionend before. Are you sure? :thinking:

Thank you once again and have a nice weekend! :sunglasses:

Definitely. Classes like Geometry were located in the bundle two times. The $1 prefix is added by rollup in order to resolve a name conflict (meaning two classes or variables with the same name were added to the bundle in the same scope).

1 Like