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

Unify Material Handling #6426

Merged
merged 1 commit into from
Jun 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 4 additions & 8 deletions packages/engine/src/scene/functions/loaders/ModelFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ import { EntityNodeComponent } from '../../components/EntityNodeComponent'
import { MaterialOverrideComponentType } from '../../components/MaterialOverrideComponent'
import { ModelComponent, ModelComponentType } from '../../components/ModelComponent'
import { Object3DComponent } from '../../components/Object3DComponent'
import { SimpleMaterialTagComponent } from '../../components/SimpleMaterialTagComponent'
import cloneObject3D from '../cloneObject3D'
import { addError, removeError } from '../ErrorFunctions'
import { overrideTexture, parseGLTFModel } from '../loadGLTFModel'
import { initializeOverride } from './MaterialOverrideFunctions'
import { useSimpleMaterial, useStandardMaterial } from './SimpleMaterialFunctions'

export const SCENE_COMPONENT_MODEL = 'gltf-model'
export const SCENE_COMPONENT_MODEL_DEFAULT_VALUE = {
Expand Down Expand Up @@ -69,13 +69,8 @@ export const updateModel: ComponentUpdateFunction = (entity: Entity, properties:
overrideTexture(entity)
}

if (properties.useBasicMaterial !== undefined) {
const obj3d = getComponent(entity, Object3DComponent).value
obj3d.traverseVisible((child: Mesh) => {
if (child.isMesh) {
properties.useBasicMaterial ? useSimpleMaterial(child as any) : useStandardMaterial(child as any)
}
})
if (properties.useBasicMaterial !== undefined && properties.useBasicMaterial) {
addComponent(entity, SimpleMaterialTagComponent, true)
}
}

Expand Down Expand Up @@ -103,6 +98,7 @@ export const serializeModel: ComponentSerializeFunction = (entity) => {
textureOverride: component.textureOverride,
materialOverrides: overrides,
matrixAutoUpdate: component.matrixAutoUpdate,
useBasicMaterial: component.useBasicMaterial,
isUsingGPUInstancing: component.isUsingGPUInstancing,
isDynamicObject: component.isDynamicObject
}
Expand Down
53 changes: 39 additions & 14 deletions packages/engine/src/scene/systems/SceneObjectSystem.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Not } from 'bitecs'
import { Material, Mesh, Vector3 } from 'three'

import { loadDRACODecoder } from '../../assets/loaders/gltf/NodeDracoLoader'
Expand Down Expand Up @@ -58,17 +59,12 @@ const processObject3d = (entity: Entity) => {
obj.receiveShadow = shadowComponent.receiveShadow
obj.castShadow = shadowComponent.castShadow
}

if (Engine.instance.simpleMaterials || Engine.instance.isHMD) {
useSimpleMaterial(obj as any)
} else {
useStandardMaterial(obj)
}
})
}

const sceneObjectQuery = defineQuery([Object3DComponent])
const simpleMaterialsQuery = defineQuery([SimpleMaterialTagComponent])
const simpleMaterialsQuery = defineQuery([Object3DComponent, SimpleMaterialTagComponent])
const standardMaterialsQuery = defineQuery([Object3DComponent, Not(SimpleMaterialTagComponent)])
const persistQuery = defineQuery([Object3DComponent, PersistTagComponent])
const visibleQuery = defineQuery([VisibleComponent])
const updatableQuery = defineQuery([Object3DComponent, UpdatableComponent])
Expand Down Expand Up @@ -151,17 +147,46 @@ export default async function SceneObjectSystem(world: World) {
obj?.update(world.fixedDeltaSeconds)
}

for (const _ of simpleMaterialsQuery.enter()) {
Engine.instance.simpleMaterials = true
Engine.instance.currentWorld.scene.traverse((obj) => {
/**
* If a SimpleMaterialTagComponent is attached to the root node, this acts as a global to override all materials
* It can also be used to selectively convert individual objects to use simple materials
*/
for (const entity of simpleMaterialsQuery.enter()) {
const object3DComponent = getComponent(entity, Object3DComponent)
if (object3DComponent.value === world.scene) {
Engine.instance.simpleMaterials = true
}
object3DComponent.value.traverse((obj) => {
useSimpleMaterial(obj as any)
})
}

for (const _ of simpleMaterialsQuery.exit()) {
Engine.instance.simpleMaterials = false
Engine.instance.currentWorld.scene.traverse((obj) => {
useStandardMaterial(obj as Mesh<any, Material>)
/**
* As we iterative down the scene hierarchy, we don't want to override entities that have a SimpleMaterialTagComponent
*/
for (const entity of simpleMaterialsQuery.exit()) {
const object3DComponent = getComponent(entity, Object3DComponent)
if (object3DComponent.value === world.scene) {
Engine.instance.simpleMaterials = false
}
object3DComponent.value.traverse((obj: Object3DWithEntity) => {
const shouldUseSimpleMaterial =
(typeof obj.entity !== 'undefined' && !hasComponent(obj.entity, SimpleMaterialTagComponent)) ||
Engine.instance.simpleMaterials
shouldUseSimpleMaterial ? useSimpleMaterial(obj as any) : useStandardMaterial(obj as any)
})
}

/**
* This is needed as the inverse case of the previous query to ensure objects that are created without a simple material still have the standard material logic applied
*/
for (const entity of standardMaterialsQuery.enter()) {
const object3DComponent = getComponent(entity, Object3DComponent)
object3DComponent.value.traverse((obj: Object3DWithEntity) => {
const shouldUseSimpleMaterial =
(typeof obj.entity !== 'undefined' && !hasComponent(obj.entity, SimpleMaterialTagComponent)) ||
Engine.instance.simpleMaterials
shouldUseSimpleMaterial ? useSimpleMaterial(obj as any) : useStandardMaterial(obj as any)
})
}
}
Expand Down