openvibers/openvibe.games Commits

Scraplandia: far avatars stand on their feet (the merged copy's parts went through their joints twice: a clone keeps its parent) (#120)

OP OpenVibers committed 24 days ago · 0aa7bca60b · 3 files, +14 −0

* Scraplandia: far avatars stand on their feet (a Babylon clone keeps its source's parent, so the merged copy's parts went through their joints twice and floated 0.4 m up, out of shape)

* avatarLod.test: refreshBoundingInfo(false, false) (an AbstractMesh's takes its arguments; the solution typecheck covers tests)

Changes

ddiff --git a/CHANGELOG.md b/CHANGELOG.md
iindex b619d08..3c33b59 100644
---- a/CHANGELOG.md
++++ b/CHANGELOG.md
@@@ -8,6 +8,10 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
### Fixed
++- **Far avatars floated, twisted.** The merged copy that stands in for an avatar past 18 m baked each part's world
++ position, but a Babylon clone keeps its source's parent, so the joint chain applied a second time: far NPCs hung
++ 0.4 m up, out of shape. Each copy now drops its parent before baking, and a test checks that the copy stands on its
++ feet at a person's height.
- **NPCs cost 150 draw calls in town.** Each avatar is about 14 meshes, so eleven townsfolk and wardens in view drew
150 times a frame. Past 18 m an avatar, NPC or remote player, now draws as one merged copy of itself in its rest
pose and skips the animation work. It switches back to the full rig inside 16 m. In town, NPC draws went from 150
ddiff --git a/apps/client/src/render/avatar/avatar.ts b/apps/client/src/render/avatar/avatar.ts
iindex e66dc4e..7dfd005 100644
---- a/apps/client/src/render/avatar/avatar.ts
++++ b/apps/client/src/render/avatar/avatar.ts
@@@ -82,6 +82,8 @@ export class Avatar {
if (!(part instanceof Mesh) || !part.getTotalVertices() || !material?.diffuseColor) continue
const copy = part.clone(`${this.name}:lodpart`, null, true)
copy.makeGeometryUnique()
++ // A clone keeps its source's parent (its joint), which would apply the joint chain again on top of the bake.
++ copy.parent = null
copy.position.setAll(0)
copy.rotationQuaternion = null
copy.rotation.setAll(0)
ddiff --git a/apps/client/src/render/avatar/avatarLod.test.ts b/apps/client/src/render/avatar/avatarLod.test.ts
iindex 883abb5..53e1445 100644
---- a/apps/client/src/render/avatar/avatarLod.test.ts
++++ b/apps/client/src/render/avatar/avatarLod.test.ts
@@@ -43,6 +43,14 @@ describe('avatar level of detail', () => {
const lod = lodOf()!
expect(lod).not.toBeNull()
expect(lod.isVerticesDataPresent(VertexBuffer.ColorKind)).toBe(true)
++ // It stands on its feet at its root, a person's height (each part placed once, not through its joints twice).
++ lod.refreshBoundingInfo(false, false)
++ const box = lod.getBoundingInfo().boundingBox
++ expect(box.minimumWorld.y).toBeGreaterThan(-0.05)
++ expect(box.minimumWorld.y).toBeLessThan(0.15)
++ expect(box.maximumWorld.y).toBeGreaterThan(1.5)
++ expect(box.maximumWorld.y).toBeLessThan(2.1)
++ expect(Math.abs(box.centerWorld.x)).toBeLessThan(0.2)
avatar.update(at(5))
expect(lod.isEnabled()).toBe(false)