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

Commit

Permalink
add scene placement and updates
Browse files Browse the repository at this point in the history
  • Loading branch information
HexaField committed Jun 24, 2024
1 parent e498d3a commit 8d3d376
Show file tree
Hide file tree
Showing 5 changed files with 193 additions and 18 deletions.
85 changes: 68 additions & 17 deletions src/examples/multipleScenes.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import { useLoadEngineWithScene, useNetwork } from '@etherealengine/client-core/src/components/World/EngineHooks'
import { Engine, EntityUUID, createEntity, getComponent, getMutableComponent, setComponent } from '@etherealengine/ecs'
import {
Engine,
EntityUUID,
UndefinedEntity,
createEntity,
getComponent,
getMutableComponent,
setComponent
} from '@etherealengine/ecs'
import { GLTFAssetState, GLTFSourceState } from '@etherealengine/engine/src/gltf/GLTFState'
import { getMutableState, useHookstate, useImmediateEffect } from '@etherealengine/hyperflux'
import { DirectionalLightComponent, TransformComponent } from '@etherealengine/spatial'
Expand All @@ -10,14 +18,11 @@ import { InputComponent } from '@etherealengine/spatial/src/input/components/Inp
import { RendererState } from '@etherealengine/spatial/src/renderer/RendererState'
import { SceneComponent } from '@etherealengine/spatial/src/renderer/components/SceneComponents'
import { VisibleComponent } from '@etherealengine/spatial/src/renderer/components/VisibleComponent'
import { computeTransformMatrix } from '@etherealengine/spatial/src/transform/systems/TransformSystem'
import { GLTF } from '@gltf-transform/core'
import React, { useEffect } from 'react'
import { Cache, Color, Euler, Quaternion, Vector3 } from 'three'

export const metadata = {
title: 'Avatar Test',
description: ''
}
import { Cache, Color, Euler, Matrix4, Quaternion, Vector3 } from 'three'
import { Transform } from './utils/transform'

// create scene with a rigidbody loaded offset from the origin
const createSceneGLTF = (id: string): GLTF.IGLTF => ({
Expand Down Expand Up @@ -54,8 +59,14 @@ const createSceneGLTF = (id: string): GLTF.IGLTF => ({
extensionsUsed: ['EE_uuid', 'EE_visible', 'EE_rigidbody', 'EE_collider', 'EE_primitive_geometry']
})

const SceneReactor = (props: { coord: Vector3 }) => {
const { coord } = props
const SceneReactor = (props: {
coord: Vector3
transform: { position: Vector3; rotation: Quaternion; scale: Vector3 }
}) => {
const { coord, transform } = props

const gltfEntityState = useHookstate(UndefinedEntity)

useEffect(() => {
const sceneID = `scene-${coord.x}-${coord.z}`
const gltf = createSceneGLTF(sceneID)
Expand All @@ -65,25 +76,56 @@ const SceneReactor = (props: { coord: Vector3 }) => {
Cache.add(sceneURL, gltf)

const gltfEntity = GLTFSourceState.load(sceneURL, sceneURL as EntityUUID)
setComponent(gltfEntity, TransformComponent, {
position: coord
.clone()
.sub(new Vector3(0.5, 0, 0.5))
.multiplyScalar(gridSpacing)
})
getMutableComponent(Engine.instance.viewerEntity, SceneComponent).scenes.merge([gltfEntity])
getMutableState(GLTFAssetState)[sceneURL].set(gltfEntity)

gltfEntityState.set(gltfEntity)

return () => {
GLTFSourceState.unload(gltfEntity)
getMutableState(GLTFAssetState)[sceneURL].set(gltfEntity)
}
}, [])

useEffect(() => {
const gltfEntity = gltfEntityState.value

// reset transform
setComponent(gltfEntity, TransformComponent, {
position: coord
.clone()
.sub(new Vector3(0.5, 0, 0.5))
.multiplyScalar(gridSpacing),
rotation: new Quaternion(),
scale: new Vector3(0.5, 0.5, 0.5)
})

// apply transform state
const transformComponent = getComponent(gltfEntity, TransformComponent)
const mat4 = new Matrix4()
transformComponent.matrix.multiply(mat4.compose(transform.position, transform.rotation, transform.scale))
transformComponent.matrix.decompose(
transformComponent.position,
transformComponent.rotation,
transformComponent.scale
)
computeTransformMatrix(gltfEntity)

console.log('position', transformComponent.position.x, transformComponent.position.y, transformComponent.position.z)
console.log(
'rotation',
transformComponent.rotation.x,
transformComponent.rotation.y,
transformComponent.rotation.z,
transformComponent.rotation.w
)
console.log('scale', transformComponent.scale.x, transformComponent.scale.y, transformComponent.scale.z)
}, [transform.position, transform.rotation, transform.scale])

return null
}

const gridCount = 10
const gridCount = 5
const gridSpacing = 10

export default function MultipleScenesEntry() {
Expand Down Expand Up @@ -118,11 +160,20 @@ export default function MultipleScenesEntry() {
coordsState.set(coords)
}, [])

const transformState = useHookstate({
position: new Vector3(),
rotation: new Quaternion(),
scale: new Vector3(1, 1, 1)
})

return (
<>
{coordsState.value.map((coord) => (
<SceneReactor key={`${coord.x}-${coord.z}`} coord={coord} />
<SceneReactor key={`${coord.x}-${coord.z}`} coord={coord} transform={transformState.value} />
))}
<div className="pointer-events-auto absolute right-0 w-fit flex flex-col flex-grid justify-start gap-1.5">
<Transform transformState={transformState} />
</div>
</>
)
}
72 changes: 72 additions & 0 deletions src/examples/scenePlacement.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { useLoadEngineWithScene, useNetwork } from '@etherealengine/client-core/src/components/World/EngineHooks'
import { Engine, getComponent, setComponent } from '@etherealengine/ecs'
import { getMutableState, useHookstate, useImmediateEffect } from '@etherealengine/hyperflux'
import { TransformComponent } from '@etherealengine/spatial'
import { CameraComponent } from '@etherealengine/spatial/src/camera/components/CameraComponent'
import { CameraOrbitComponent } from '@etherealengine/spatial/src/camera/components/CameraOrbitComponent'
import { InputComponent } from '@etherealengine/spatial/src/input/components/InputComponent'
import { RendererState } from '@etherealengine/spatial/src/renderer/RendererState'
import { updateWorldOriginFromScenePlacement } from '@etherealengine/spatial/src/transform/updateWorldOrigin'
import { XRState } from '@etherealengine/spatial/src/xr/XRState'
import React, { useEffect } from 'react'
import { Quaternion, Vector3 } from 'three'
import { useRouteScene } from '../sceneRoute'
import { Transform } from './utils/transform'

export default function ScenePlacement() {
const sceneEntity = useRouteScene('default-project', 'public/scenes/apartment.gltf')
useNetwork({ online: false })
useLoadEngineWithScene()

useImmediateEffect(() => {
getMutableState(RendererState).gridVisibility.set(true)
getMutableState(RendererState).physicsDebug.set(true)
const entity = Engine.instance.viewerEntity
setComponent(entity, CameraOrbitComponent)
setComponent(entity, InputComponent)
getComponent(entity, CameraComponent).position.set(0, 3, 4)
}, [])

/** Origin Transform */
const transformState = useHookstate({
position: new Vector3(),
rotation: new Quaternion(),
scale: new Vector3(1, 1, 1)
})

useEffect(() => {
const xrState = getMutableState(XRState)
xrState.scenePosition.value.copy(transformState.position.value)
xrState.sceneRotation.value.copy(transformState.rotation.value)
xrState.sceneScale.set(transformState.scale.value.x)
updateWorldOriginFromScenePlacement()
}, [transformState.position, transformState.rotation, transformState.scale])

/** Scene Transform */
const transformState2 = useHookstate({
position: new Vector3(2, 0, 2),
rotation: new Quaternion(),
scale: new Vector3().setScalar(0.1)
})

useEffect(() => {
if (!sceneEntity.value) return
setComponent(sceneEntity.value, TransformComponent, {
position: transformState2.position.value,
rotation: transformState2.rotation.value,
scale: transformState2.scale.value
})
}, [sceneEntity, transformState2.position, transformState2.rotation, transformState2.scale])

return (
<div className="pointer-events-auto absolute right-0 w-fit flex flex-col flex-grid justify-start gap-1.5">
<Transform title={'Origin'} transformState={transformState} />
<Transform title={'Scene'} transformState={transformState2} />
</div>
)
}

/**
* Scene placement
* -
*/
46 changes: 46 additions & 0 deletions src/examples/utils/transform.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { State } from '@etherealengine/hyperflux'
import EulerInput from '@etherealengine/ui/src/components/editor/input/Euler'
import InputGroup from '@etherealengine/ui/src/components/editor/input/Group'
import Vector3Input from '@etherealengine/ui/src/components/editor/input/Vector3'
import PropertyGroup from '@etherealengine/ui/src/components/editor/properties/group'
import React from 'react'
import { useTranslation } from 'react-i18next'
import { Euler, Quaternion, Vector3 } from 'three'

export const Transform = (props: {
title?: string
transformState: State<{ position: Vector3; rotation: Quaternion; scale: Vector3 }>
}) => {
const { transformState } = props
const { t } = useTranslation()

const { position, rotation, scale } = transformState.value

const onChangePosition = (value: Vector3) => transformState.position.set(new Vector3().copy(value))
const onChangeRotation = (value: Euler) => transformState.rotation.set(new Quaternion().setFromEuler(value))
const onChangeScale = (value: Vector3) => transformState.scale.set(new Vector3().copy(value))

return (
<PropertyGroup
minimizedDefault={false}
name={props.title ?? t('editor:properties.transform.title')}
>
<InputGroup name="Position" label={t('editor:properties.transform.lbl-position')}>
<Vector3Input smallStep={0.01} mediumStep={0.1} largeStep={1} value={position} onChange={onChangePosition} />
</InputGroup>
<InputGroup name="Rotation" label={t('editor:properties.transform.lbl-rotation')}>
<EulerInput quaternion={rotation} onChange={onChangeRotation} unit="°" />
</InputGroup>
<InputGroup name="Scale" label={t('editor:properties.transform.lbl-scale')}>
<Vector3Input
uniformScaling
smallStep={0.01}
mediumStep={0.1}
largeStep={1}
value={scale}
onChange={onChangeScale}
/>
</InputGroup>
</PropertyGroup>
)
}
6 changes: 6 additions & 0 deletions src/examplesRoute.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import ComponentExamplesRoute, { subComponentExamples } from './examples/compone
import GLTFViewer from './examples/gltf'
import Routes, { RouteData } from './sceneRoute'
import MultipleScenesEntry from './examples/multipleScenes'
import ScenePlacement from './examples/scenePlacement'

export const examples: RouteData[] = [
{
Expand Down Expand Up @@ -38,6 +39,11 @@ export const examples: RouteData[] = [
name: 'Multiple Scenes',
description: 'multiple scenes example',
entry: MultipleScenesEntry
},
{
name: 'Scene Placement',
description: 'place scenes relative to the origin example',
entry: ScenePlacement
}
]

Expand Down
2 changes: 1 addition & 1 deletion src/sceneRoute.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -209,8 +209,8 @@ const Routes = (props: { routes: RouteData[]; header: string }) => {
</div>
</div>
<div id="examples-panel" ref={ref} style={{ flexGrow: 1, pointerEvents: 'none' }} />
{Entry && <Entry {...subProps} />}
</div>
{Entry && <Entry {...subProps} />}
</>
)
}
Expand Down

0 comments on commit 8d3d376

Please sign in to comment.