loading asset handler
This commit is contained in:
@@ -3,9 +3,10 @@ import { Clone } from '@react-three/drei/core/Clone'
|
|||||||
import { useGLTF } from '@react-three/drei/core/Gltf'
|
import { useGLTF } from '@react-three/drei/core/Gltf'
|
||||||
import { Suspense, useEffect, useMemo, useRef } from 'react'
|
import { Suspense, useEffect, useMemo, useRef } from 'react'
|
||||||
import type { Group, Material, Mesh } from 'three'
|
import type { Group, Material, Mesh } from 'three'
|
||||||
|
import { positionLocal, smoothstep, time } from 'three/tsl'
|
||||||
import { DoubleSide, MeshStandardNodeMaterial } from 'three/webgpu'
|
import { DoubleSide, MeshStandardNodeMaterial } from 'three/webgpu'
|
||||||
import { resolveCdnUrl } from '../../../lib/asset-url'
|
|
||||||
import { useNodeEvents } from '../../../hooks/use-node-events'
|
import { useNodeEvents } from '../../../hooks/use-node-events'
|
||||||
|
import { resolveCdnUrl } from '../../../lib/asset-url'
|
||||||
|
|
||||||
// Shared materials to avoid creating new instances for every mesh
|
// Shared materials to avoid creating new instances for every mesh
|
||||||
const defaultMaterial = new MeshStandardNodeMaterial({
|
const defaultMaterial = new MeshStandardNodeMaterial({
|
||||||
@@ -39,13 +40,35 @@ export const ItemRenderer = ({ node }: { node: ItemNode }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<group position={node.position} rotation={node.rotation} ref={ref} visible={node.visible}>
|
<group position={node.position} rotation={node.rotation} ref={ref} visible={node.visible}>
|
||||||
<Suspense>
|
<Suspense fallback={<PreviewModel node={node} />}>
|
||||||
<ModelRenderer node={node} />
|
<ModelRenderer node={node} />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</group>
|
</group>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const previewMaterial = new MeshStandardNodeMaterial({
|
||||||
|
color: '#cccccc',
|
||||||
|
roughness: 1,
|
||||||
|
metalness: 0,
|
||||||
|
depthTest: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
const previewOpacity = smoothstep(0.42, 0.55, positionLocal.y.add(time.mul(-0.2)).mul(10).fract())
|
||||||
|
|
||||||
|
previewMaterial.opacityNode = previewOpacity
|
||||||
|
previewMaterial.transparent = true
|
||||||
|
|
||||||
|
const PreviewModel = ({ node }: { node: ItemNode }) => {
|
||||||
|
return (
|
||||||
|
<mesh position-y={node.asset.dimensions[1] / 2} material={previewMaterial}>
|
||||||
|
<boxGeometry
|
||||||
|
args={[node.asset.dimensions[0], node.asset.dimensions[1], node.asset.dimensions[2]]}
|
||||||
|
/>
|
||||||
|
</mesh>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
const ModelRenderer = ({ node }: { node: ItemNode }) => {
|
const ModelRenderer = ({ node }: { node: ItemNode }) => {
|
||||||
const { scene, nodes } = useGLTF(resolveCdnUrl(node.asset.src) || '')
|
const { scene, nodes } = useGLTF(resolveCdnUrl(node.asset.src) || '')
|
||||||
|
|
||||||
|
|||||||
@@ -121,6 +121,7 @@ export const SiteRenderer = ({ node }: { node: SiteNode }) => {
|
|||||||
position={[edge.midX, 0.5, edge.midZ]}
|
position={[edge.midX, 0.5, edge.midZ]}
|
||||||
style={{ pointerEvents: 'none', userSelect: 'none' }}
|
style={{ pointerEvents: 'none', userSelect: 'none' }}
|
||||||
zIndexRange={[10, 0]}
|
zIndexRange={[10, 0]}
|
||||||
|
occlude
|
||||||
>
|
>
|
||||||
<div className="whitespace-nowrap rounded bg-black/75 px-1.5 py-0.5 font-mono text-white text-xs backdrop-blur-sm">
|
<div className="whitespace-nowrap rounded bg-black/75 px-1.5 py-0.5 font-mono text-white text-xs backdrop-blur-sm">
|
||||||
{edge.dist.toFixed(2)}m
|
{edge.dist.toFixed(2)}m
|
||||||
|
|||||||
Reference in New Issue
Block a user