Skip to content

Angular-based Level of Detail (LOD) implementation#82

Open
ericleib wants to merge 14 commits intoangular-threejs:mainfrom
ericleib:dev/angular-lod
Open

Angular-based Level of Detail (LOD) implementation#82
ericleib wants to merge 14 commits intoangular-threejs:mainfrom
ericleib:dev/angular-lod

Conversation

@ericleib
Copy link
Contributor

Implements Level of Detail (LOD) rendering. Automatically switches between different detail levels of child objects based on camera distance.

Unlike NgtsDetailed, this is an implementation based on Angular and angular-three APIs rather than Three's LOD class.
The component adds and remove objects from the scene graph rather than hiding them with visible = false.
This solves a number of issues such as avoid raycasting over hidden objects.

Usage:

<ngt-group lod>
  <ngt-mesh *lodLevel="{distance: 0}" />
  <ngt-mesh *lodLevel="{distance: 100}" />
  <ngt-mesh *lodLevel="{distance: 1000}" />
</ngt-group>

The [lodLevel] directive (NgtsLODLevel) supports the following options:

Property Description Default Value
distance Threshold above which to display the object 0
hysteresis Prevents rapid switching near distance thresholds 0

This directive may also be used with the following syntax:

<ngt-group lod>
  <ng-template [lodLevel]="{distance: 0}">
    <ngt-mesh />
    <ngt-mesh />
  </ng-template>
</ngt-group>

@netlify
Copy link

netlify bot commented Mar 16, 2026

Deploy Preview for angularthreedemo ready!

Name Link
🔨 Latest commit ba545e8
🔍 Latest deploy log https://app.netlify.com/projects/angularthreedemo/deploys/69b9cc725c2f53000898b5d6
😎 Deploy Preview https://deploy-preview-82--angularthreedemo.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify
Copy link

netlify bot commented Mar 16, 2026

Deploy Preview for angularthreesoba ready!

Name Link
🔨 Latest commit ba545e8
🔍 Latest deploy log https://app.netlify.com/projects/angularthreesoba/deploys/69b9cc7289e4980008d73923
😎 Deploy Preview https://deploy-preview-82--angularthreesoba.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@nartc
Copy link
Member

nartc commented Mar 16, 2026

See this issue in the deploy preview

ReferenceError: Cannot access 'lod_stories' before initialization
    at Module.default (https://deploy-preview-82--angularthreesoba.netlify.app/src-performances-lod-stories.4693c114.iframe.bundle.js:1:374)
    at processCSFFile (https://deploy-preview-82--angularthreesoba.netlify.app/sb-preview/runtime.js:34890:18)
    at StoryStore.memoizerific [as processCSFFileWithCache] (https://deploy-preview-82--angularthreesoba.netlify.app/sb-preview/runtime.js:10105:196)
    at StoryStore.loadCSFFileByStoryId (https://deploy-preview-82--angularthreesoba.netlify.app/sb-preview/runtime.js:35642:17)
    at async StoryStore.loadStory (https://deploy-preview-82--angularthreesoba.netlify.app/sb-preview/runtime.js:35671:19)
    at async https://deploy-preview-82--angularthreesoba.netlify.app/sb-preview/runtime.js:35904:20
    at async StoryRender.runPhase (https://deploy-preview-82--angularthreesoba.netlify.app/sb-preview/runtime.js:35893:21)
    at async StoryRender.prepare (https://deploy-preview-82--angularthreesoba.netlify.app/sb-preview/runtime.js:35903:9)
    at async PreviewWeb.renderSelection (https://deploy-preview-82--angularthreesoba.netlify.app/sb-preview/runtime.js:36784:7)

@ericleib
Copy link
Contributor Author

ericleib commented Mar 17, 2026

@nartc I've made some improvements to the API if that's ok with you.

  • I moved hysteresis in its own input so that the typical case becomes very simple: *lodLevel="100"
  • I added a maxDistance input, which removes the need to add empty levels to stop displaying anything above a certain distance (<ng-container *lodLevel="1000" /> can be replaced with [maxDistance]="1000").
  • Also added an event to the story book, and fixed the build.

Copy link
Member

@nartc nartc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The separate inputs are fine. However,

<ngt-mesh *lodLevel="100" [hysteresis]="0.1" />

won't work. the hysteresis here will be interpreted as a binding to ngt-mesh instead of the NgtsLODLevel directive here.

You have 2 options:

  • go back to an object input
lodLevel = input(defaultLodLevelOptions, { transform: mergeInputs(defaultLodLevelOptions) }); // mergeInputs is from ngxtension. This will type the lodLevel input correctly in a way that you can do `*lodLevel` without an empty {}
  • alias the hysteresis input with lodLevelHysteresis and usage with *lodLevel becomes:
<ngt-mesh *lodLevel="100; hysteresis: 0.1" />
<!-- this becomes -->
<ng-template [lodLevel]="100" [lodLevelHysteresis]="0.1">
  <ngt-mesh />
</ng-template>

Co-authored-by: Chau Tran <25516557+nartc@users.noreply.github.com>
@ericleib
Copy link
Contributor Author

Thank you, great catch! I was fooled as Angular did not complain about the [hysteresis] input, even though it went nowhere.
As you suggested, I went back to the object input + mergeInputs for the lean syntax.
Will commit shortly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants