Skip to content

Commit

Permalink
Revert "Fix GLTF Export (#9483)"
Browse files Browse the repository at this point in the history
This reverts commit ec91819.
  • Loading branch information
HexaField committed Dec 22, 2023
1 parent 31df4b7 commit be1f68b
Show file tree
Hide file tree
Showing 12 changed files with 255 additions and 108 deletions.
149 changes: 149 additions & 0 deletions packages/editor/src/components/properties/LightmapBakerProperties.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/*
CPAL-1.0 License
The contents of this file are subject to the Common Public Attribution License
Version 1.0. (the "License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
https://github.com/EtherealEngine/etherealengine/blob/dev/LICENSE.
The License is based on the Mozilla Public License Version 1.1, but Sections 14
and 15 have been added to cover use of software over a computer network and
provide for limited attribution for the Original Developer. In addition,
Exhibit A has been modified to be consistent with Exhibit B.
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the
specific language governing rights and limitations under the License.
The Original Code is Ethereal Engine.
The Original Developer is the Initial Developer. The Initial Developer of the
Original Code is the Ethereal Engine team.
All portions of the code written by the Ethereal Engine team are Copyright © 2021-2023
Ethereal Engine. All Rights Reserved.
*/

import React, { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import { WebGLRenderer } from 'three'

import { ComponentType } from '@etherealengine/engine/src/ecs/functions/ComponentFunctions'
import { BoolArg, FloatArg } from '@etherealengine/engine/src/renderer/materials/constants/DefaultArgs'
import { ModelComponent } from '@etherealengine/engine/src/scene/components/ModelComponent'
import { useHookstate } from '@etherealengine/hyperflux'
import { State } from '@etherealengine/hyperflux/functions/StateFunctions'

import { Grid, Typography } from '@mui/material'

import { bakeLightmaps } from '../../lightmapper/lightmap'
import { WorkbenchSettings } from '../../lightmapper/workbench'
import { Button } from '../inputs/Button'
import ParameterInput from '../inputs/ParameterInput'
import CollapsibleBlock from '../layout/CollapsibleBlock'
import Well from '../layout/Well'

export default function LightmapBakerProperties({
modelState
}: {
modelState: State<ComponentType<typeof ModelComponent>>
}) {
const { t } = useTranslation()
const bakeProperties = useHookstate<WorkbenchSettings>(() => ({
ao: false,
aoDistance: 0.05,
bounceMultiplier: 1,
emissiveMultiplier: 1,
lightMapSize: 1024,
texelsPerUnit: 16,
samplerSettings: {
targetSize: 64,
offset: 0,
near: 0.05,
far: 50
}
}))

const baking = useHookstate(false)

const doLightmapBake = useCallback(async () => {
const scene = modelState.scene.value
if (!scene) throw Error('model has no scene')
baking.set(true)
const bakeRenderer = new WebGLRenderer()
const disposeRenderer = () => {
bakeRenderer.dispose()
baking.set(false)
}
try {
const lightmap = await bakeLightmaps(scene, bakeProperties.value, async () => bakeRenderer)
disposeRenderer()
return lightmap
} catch (e) {
disposeRenderer()
throw e
}
}, [modelState.scene])

return (
<>
<CollapsibleBlock label={'Bake Lightmaps'}>
<Well>
<ParameterInput
entity={modelState.src.value}
values={bakeProperties.value}
defaults={{
ao: BoolArg,
aoDistance: { ...FloatArg, default: 0.01 },
bounceMultiplier: { ...FloatArg, default: 1 },
emissiveMultiplier: { ...FloatArg, default: 1 },
lightMapSize: { ...FloatArg, default: 1024 },
texelsPerUnit: { ...FloatArg, default: 16 }
}}
onChange={(k: keyof WorkbenchSettings) => {
return (val) => {
bakeProperties[k].set(val)
}
}}
/>
<Grid
container
spacing={2}
style={{
alignItems: 'center',
justifyContent: 'flex-end',
outline: 'solid 1px #fff',
borderRadius: '0.5rem',
paddingBottom: '1rem',
width: 'auto',
margin: '1rem',
overflow: 'overlay'
}}
>
<Grid item xs={2}>
<Typography variant="subtitle1">Sampler Settings</Typography>
</Grid>
<Grid item xs>
<ParameterInput
entity={modelState.src.value}
values={bakeProperties.samplerSettings.value ?? {}}
defaults={{
targetSize: { ...FloatArg, default: 64 },
offset: FloatArg,
near: { ...FloatArg, default: 0.05 },
far: { ...FloatArg, default: 50 }
}}
onChange={(k: string) => {
return (val) => {
bakeProperties.samplerSettings[k].set(val)
}
}}
/>
</Grid>
</Grid>
</Well>
{!baking.value && <Button onClick={doLightmapBake}>Bake Lightmaps</Button>}
{baking.value && <Typography variant="subtitle1">Baking...</Typography>}
</CollapsibleBlock>
</>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export const LoopAnimationNodeEditor: EditorComponentType = (props) => {
{ label: 'None', value: -1 },
...animationComponent.animations.map((clip, index) => ({ label: clip.name, value: index }))
])
}, [modelComponent?.asset, loopAnimationComponent.hasAvatarAnimations])
}, [modelComponent?.scene, loopAnimationComponent.hasAvatarAnimations])

const onChangePlayingAnimation = (index) => {
commitProperties(LoopAnimationComponent, {
Expand Down
2 changes: 0 additions & 2 deletions packages/engine/src/assets/csm/CSM.ts
Original file line number Diff line number Diff line change
Expand Up @@ -417,9 +417,7 @@ export class CSM {
}

teardownMaterial(mesh: Mesh): void {
if (!mesh?.isMesh) return
const material = mesh.material as Material
if (!material) return
if (!material.userData) material.userData = {}
if (material.userData.CSMPlugin) {
removeOBCPlugin(material, material.userData.CSMPlugin)
Expand Down
3 changes: 1 addition & 2 deletions packages/engine/src/assets/functions/exportModelGLTF.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ Ethereal Engine. All Rights Reserved.

import { Entity } from '../../ecs/classes/Entity'
import { getComponent } from '../../ecs/functions/ComponentFunctions'
import { GroupComponent } from '../../scene/components/GroupComponent'
import { ModelComponent } from '../../scene/components/ModelComponent'
import createGLTFExporter from './createGLTFExporter'

Expand All @@ -39,7 +38,7 @@ export default async function exportModelGLTF(
embedImages: true
}
) {
const scene = getComponent(entity, ModelComponent).scene ?? getComponent(entity, GroupComponent)[0]
const scene = getComponent(entity, ModelComponent).scene!
const exporter = createGLTFExporter()
const modelName = options.relativePath.split('/').at(-1)!.split('.').at(0)!
const resourceURI = `model-resources/${modelName}`
Expand Down
15 changes: 6 additions & 9 deletions packages/engine/src/avatar/components/LoopAnimationComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,16 +126,15 @@ export const LoopAnimationComponent = defineComponent({
useEffect(() => {
if (!animComponent?.animations?.value) return
const clip = animComponent.animations.value[loopAnimationComponent.activeClipIndex.value]
const asset = modelComponent?.asset.get(NO_PROXY) ?? null
if (!modelComponent || !asset?.scene || !clip) {
if (!modelComponent?.scene?.value || !clip) {
loopAnimationComponent._action.set(null)
return
}
animComponent.mixer.time.set(0)
const assetObject = modelComponent.asset.get(NO_PROXY)
try {
const action = animComponent.mixer.value.clipAction(
assetObject instanceof VRM ? retargetMixamoAnimation(clip, asset.scene, assetObject) : clip
assetObject instanceof VRM ? retargetMixamoAnimation(clip, modelComponent.scene.value, assetObject) : clip
)
loopAnimationComponent._action.set(action)
return () => {
Expand Down Expand Up @@ -207,22 +206,20 @@ export const LoopAnimationComponent = defineComponent({
* A model is required for LoopAnimationComponent.
*/
useEffect(() => {
const asset = modelComponent?.asset.get(NO_PROXY) ?? null
if (!asset?.scene) return
if (!modelComponent?.scene?.value) return
const model = getComponent(entity, ModelComponent)

if (!hasComponent(entity, AnimationComponent)) {
setComponent(entity, AnimationComponent, {
mixer: new AnimationMixer(model.asset!.scene),
mixer: new AnimationMixer(model.scene!),
animations: []
})
}
}, [modelComponent?.asset, loopAnimationComponent.hasAvatarAnimations])
}, [modelComponent?.scene, loopAnimationComponent.hasAvatarAnimations])

useEffect(() => {
const asset = modelComponent?.asset.get(NO_PROXY) ?? null
if (
!asset?.scene ||
!modelComponent?.scene?.value ||
!animComponent ||
!loopAnimationComponent.animationPack.value ||
lastAnimationPack.value === loopAnimationComponent.animationPack.value
Expand Down
6 changes: 0 additions & 6 deletions packages/engine/src/avatar/functions/spawnAvatarReceptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,11 @@ import { AvatarCollisionMask, CollisionGroups } from '../../physics/enums/Collis
import { getInteractionGroups } from '../../physics/functions/getInteractionGroups'
import { PhysicsState } from '../../physics/state/PhysicsState'
import { EnvmapComponent } from '../../scene/components/EnvmapComponent'
import { addObjectToGroup } from '../../scene/components/GroupComponent'
import { NameComponent } from '../../scene/components/NameComponent'
import { ShadowComponent } from '../../scene/components/ShadowComponent'
import { UUIDComponent } from '../../scene/components/UUIDComponent'
import { VisibleComponent } from '../../scene/components/VisibleComponent'
import { EnvMapSourceType } from '../../scene/constants/EnvMapEnum'
import { proxifyParentChildRelationships } from '../../scene/functions/loadGLTFModel'
import { DistanceFromCameraComponent, FrustumCullCameraComponent } from '../../transform/components/DistanceComponents'
import { TransformComponent } from '../../transform/components/TransformComponent'
import { AnimationComponent } from '../components/AnimationComponent'
Expand Down Expand Up @@ -89,10 +87,6 @@ export const spawnAvatarReceptor = (entityUUID: EntityUUID) => {
const userName = userNames[entityUUID]
const shortId = ownerID.substring(0, 7)
setComponent(entity, NameComponent, 'avatar-' + (userName ? shortId + ' (' + userName + ')' : shortId))
const obj3d = new Object3D()
obj3d.entity = entity
addObjectToGroup(entity, obj3d)
proxifyParentChildRelationships(obj3d)

setComponent(entity, VisibleComponent, true)

Expand Down
2 changes: 1 addition & 1 deletion packages/engine/src/input/systems/ClientInputSystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,7 @@ const execute = () => {
if (hits.length && hits[0].distance < hitDistance) {
const object = hits[0].object
const parentObject = Object3DUtils.findAncestor(object, (obj) => obj.parent === Engine.instance.scene)
if (parentObject?.entity) {
if (parentObject.entity) {
assignedInputEntity = parentObject.entity
hitDistance = hits[0].distance
}
Expand Down
4 changes: 1 addition & 3 deletions packages/engine/src/scene/components/GroupComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,7 @@ export const GroupComponent = defineComponent({

onRemove: (entity, component) => {
for (const obj of component.value) {
if (obj.parent) {
obj.removeFromParent()
}
obj.removeFromParent()
}
}
})
Expand Down
63 changes: 45 additions & 18 deletions packages/engine/src/scene/components/ModelComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Ethereal Engine. All Rights Reserved.
*/

import { useEffect } from 'react'
import { Scene } from 'three'
import { Object3D, Scene } from 'three'

import { NO_PROXY, createState, getMutableState, getState, none, useHookstate } from '@etherealengine/hyperflux'

Expand All @@ -42,6 +42,7 @@ import { SceneState } from '../../ecs/classes/Scene'
import {
defineComponent,
getComponent,
getOptionalComponent,
hasComponent,
removeComponent,
serializeComponent,
Expand All @@ -51,6 +52,7 @@ import {
useQuery
} from '../../ecs/functions/ComponentFunctions'
import { useEntityContext } from '../../ecs/functions/EntityFunctions'
import { EntityTreeComponent } from '../../ecs/functions/EntityTree'
import { EngineRenderer } from '../../renderer/WebGLRendererSystem'
import { SourceType } from '../../renderer/materials/components/MaterialSource'
import { removeMaterialSource } from '../../renderer/materials/functions/MaterialLibraryFunctions'
Expand Down Expand Up @@ -143,11 +145,41 @@ function ModelReactor() {

const model = modelComponent.value
if (!model.src) {
// const dudScene = new Scene() as Scene & Object3D
// dudScene.entity = entity
// addObjectToGroup(entity, dudScene)
// proxifyParentChildRelationships(dudScene)
modelComponent.scene.set(null)
const dudScene = new Scene() as Scene & Object3D
dudScene.entity = entity
Object.defineProperties(dudScene, {
parent: {
get() {
if (EngineRenderer.instance?.rendering) return null
if (getComponent(entity, EntityTreeComponent)?.parentEntity) {
return (
getComponent(getComponent(entity, EntityTreeComponent).parentEntity!, GroupComponent)?.[0] ??
Engine.instance.scene
)
}
},
set(value) {
throw new Error('Cannot set parent of proxified object')
}
},
children: {
get() {
if (EngineRenderer.instance?.rendering) return []
return hasComponent(entity, EntityTreeComponent)
? getComponent(entity, EntityTreeComponent)
.children.filter((child) => getOptionalComponent(child, GroupComponent)?.length)
.flatMap((child) => getComponent(child, GroupComponent))
: []
},
set(value) {
throw new Error('Cannot set children of proxified object')
}
},
isProxified: {
value: true
}
})
modelComponent.scene.set(dudScene)
modelComponent.asset.set(null)
return
}
Expand All @@ -168,8 +200,7 @@ function ModelReactor() {
addError(entity, ModelComponent, 'INVALID_SOURCE', 'Invalid URL')
return
}
const boneMatchedAsset = autoconvertMixamoAvatar(loadedAsset) as GLTF
boneMatchedAsset.scene.animations = boneMatchedAsset.animations
const boneMatchedAsset = autoconvertMixamoAvatar(loadedAsset)
modelComponent.asset.set(boneMatchedAsset)
},
(onprogress) => {
Expand Down Expand Up @@ -200,12 +231,11 @@ function ModelReactor() {
if (!asset) return
removeError(entity, ModelComponent, 'INVALID_SOURCE')
removeError(entity, ModelComponent, 'LOADING_ERROR')
const sceneObj = getComponent(entity, GroupComponent)[0] as Scene

sceneObj.userData.src = model.src
sceneObj.userData.sceneID = getModelSceneID(entity)
//sceneObj.userData.type === 'glb' && delete asset.scene.userData.type
modelComponent.scene.set(sceneObj)
asset.scene.animations = asset.animations
asset.scene.userData.src = model.src
asset.scene.userData.sceneID = getModelSceneID(entity)
asset.scene.userData.type === 'glb' && delete asset.scene.userData.type
modelComponent.scene.set(asset.scene)
}, [modelComponent.asset])

// update scene
Expand All @@ -226,7 +256,7 @@ function ModelReactor() {
})
else removeComponent(entity, SceneAssetPendingTagComponent)

const loadedJsonHierarchy = parseGLTFModel(entity, asset.scene as Scene)
const loadedJsonHierarchy = parseGLTFModel(entity)
const uuid = getModelSceneID(entity)

SceneState.loadScene(uuid, {
Expand All @@ -244,9 +274,6 @@ function ModelReactor() {
return () => {
clearMaterials(src)
getMutableState(SceneState).scenes[uuid].set(none)
// for(const child of scene.children) {
// removeEntity(child.entity)
// }
}
}, [modelComponent.scene])

Expand Down

0 comments on commit be1f68b

Please sign in to comment.