Skip to content
This repository has been archived by the owner on Aug 21, 2024. It is now read-only.

Commit

Permalink
Skinned mesh ECS bounding box frustum culling (#8733)
Browse files Browse the repository at this point in the history
* disable bvh on models with skinned meshes

* bvh disable

* set up skinned mesh frustum culling components

* bounding box culling

---------

Co-authored-by: Gheric Speiginer <[email protected]>
  • Loading branch information
AidanCaruso and speigg authored Sep 13, 2023
1 parent 6351680 commit d9b5dc2
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 19 deletions.
15 changes: 10 additions & 5 deletions packages/engine/src/scene/components/ModelComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,10 @@ import {
useOptionalComponent
} from '../../ecs/functions/ComponentFunctions'
import { entityExists, useEntityContext } from '../../ecs/functions/EntityFunctions'
import { BoundingBoxComponent } from '../../interaction/components/BoundingBoxComponents'
import { SourceType } from '../../renderer/materials/components/MaterialSource'
import { removeMaterialSource } from '../../renderer/materials/functions/MaterialLibraryFunctions'
import { FrustumCullCameraComponent } from '../../transform/components/DistanceComponents'
import { ObjectLayers } from '../constants/ObjectLayers'
import { addError, removeError } from '../functions/ErrorFunctions'
import { generateMeshBVH } from '../functions/bvhWorkerPool'
Expand Down Expand Up @@ -208,20 +210,23 @@ function ModelReactor() {

if (groupComponent?.value?.find((group: any) => group === scene)) return
parseGLTFModel(entity)
// setComponent(entity, BoundingBoxComponent)
setComponent(entity, BoundingBoxComponent)

let active = true

const skinnedMeshSearch = iterateObject3D(
scene,
() => true,
(ob: SkinnedMesh) => ob.isSkinnedMesh,
false,
true
(skinnedMesh) => skinnedMesh,
(ob: SkinnedMesh) => ob.isSkinnedMesh
)

if (skinnedMeshSearch[0]) {
modelComponent.hasSkinnedMesh.set(true)
modelComponent.generateBVH.set(false)
for (const skinnedMesh of skinnedMeshSearch) {
skinnedMesh.frustumCulled = false
}
setComponent(entity, FrustumCullCameraComponent)
}

if (model.generateBVH) {
Expand Down
10 changes: 3 additions & 7 deletions packages/engine/src/scene/systems/SceneObjectSystem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ import { defineQuery, getComponent, hasComponent, useOptionalComponent } from '.
import { defineSystem } from '../../ecs/functions/SystemFunctions'
import { RendererState } from '../../renderer/RendererState'
import { registerMaterial, unregisterMaterial } from '../../renderer/materials/functions/MaterialLibraryFunctions'
import { DistanceFromCameraComponent, FrustumCullCameraComponent } from '../../transform/components/DistanceComponents'
import { FrustumCullCameraComponent } from '../../transform/components/DistanceComponents'
import { isMobileXRHeadset } from '../../xr/XRState'
import { CallbackComponent } from '../components/CallbackComponent'
import { GroupComponent, GroupQueryReactor, Object3DWithEntity } from '../components/GroupComponent'
Expand Down Expand Up @@ -195,12 +195,8 @@ const execute = () => {
/**
* do frustum culling here, but only if the object is more than 5 units away
*/
const visible =
hasComponent(entity, VisibleComponent) &&
!(
FrustumCullCameraComponent.isCulled[entity] &&
DistanceFromCameraComponent.squaredDistance[entity] > minimumFrustumCullDistanceSqr
)
const visible = hasComponent(entity, VisibleComponent) && !FrustumCullCameraComponent.isCulled[entity]

for (const obj of group) obj.visible = visible
}

Expand Down
14 changes: 7 additions & 7 deletions packages/engine/src/transform/systems/TransformSystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -402,13 +402,13 @@ const execute = () => {
_projScreenMatrix.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse)
_frustum.setFromProjectionMatrix(_projScreenMatrix)

for (const entity of frustumCulledQuery())
FrustumCullCameraComponent.isCulled[entity] = _frustum.containsPoint(
getComponent(entity, TransformComponent).position
)
? 0
: 1

for (const entity of frustumCulledQuery()) {
const boundingBox = getOptionalComponent(entity, BoundingBoxComponent)?.box
const cull = boundingBox
? _frustum.intersectsBox(boundingBox)
: _frustum.containsPoint(getComponent(entity, TransformComponent).position)
FrustumCullCameraComponent.isCulled[entity] = cull ? 0 : 1
}
if (localClientEntity) {
const localClientPosition = getOptionalComponent(localClientEntity, TransformComponent)?.position
if (localClientPosition) {
Expand Down

0 comments on commit d9b5dc2

Please sign in to comment.