Add roof material targets and UV mapping
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
import { type AnyNodeId, type RoofNode, type RoofSegmentNode, useRegistry, useScene } from '@pascal-app/core'
|
||||
import { useMemo, useRef } from 'react'
|
||||
import type * as THREE from 'three'
|
||||
import { useEffect, useMemo, useRef } from 'react'
|
||||
import * as THREE from 'three'
|
||||
import { useNodeEvents } from '../../../hooks/use-node-events'
|
||||
import { createMaterial, createMaterialFromPresetRef } from '../../../lib/materials'
|
||||
import useViewer from '../../../store/use-viewer'
|
||||
import { getRoofMaterialArray } from '../../../systems/roof/roof-materials'
|
||||
import { roofDebugMaterials, roofMaterials } from '../roof/roof-materials'
|
||||
|
||||
export const RoofSegmentRenderer = ({ node }: { node: RoofSegmentNode }) => {
|
||||
@@ -16,16 +16,22 @@ export const RoofSegmentRenderer = ({ node }: { node: RoofSegmentNode }) => {
|
||||
const debugColors = useViewer((s) => s.debugColors)
|
||||
const parentNode =
|
||||
node.parentId ? (nodes[node.parentId as AnyNodeId] as RoofNode | undefined) : undefined
|
||||
const placeholderGeometry = useMemo(() => {
|
||||
const geometry = new THREE.BufferGeometry()
|
||||
geometry.setAttribute('position', new THREE.Float32BufferAttribute([], 3))
|
||||
geometry.addGroup(0, 0, 0)
|
||||
geometry.addGroup(0, 0, 1)
|
||||
geometry.addGroup(0, 0, 2)
|
||||
geometry.addGroup(0, 0, 3)
|
||||
return geometry
|
||||
}, [])
|
||||
|
||||
const customMaterial = useMemo(() => {
|
||||
const effectiveMaterialPreset = node.materialPreset ?? parentNode?.materialPreset
|
||||
const effectiveMaterial = node.material ?? parentNode?.material
|
||||
if (node.material !== undefined || typeof node.materialPreset === 'string') {
|
||||
return null
|
||||
}
|
||||
|
||||
const presetMaterial = createMaterialFromPresetRef(effectiveMaterialPreset)
|
||||
if (presetMaterial) return presetMaterial
|
||||
const mat = effectiveMaterial
|
||||
if (!mat) return null
|
||||
return createMaterial(mat)
|
||||
return parentNode ? getRoofMaterialArray(parentNode) : null
|
||||
}, [
|
||||
node.materialPreset,
|
||||
node.material,
|
||||
@@ -37,21 +43,31 @@ export const RoofSegmentRenderer = ({ node }: { node: RoofSegmentNode }) => {
|
||||
parentNode?.material?.preset,
|
||||
parentNode?.material?.properties,
|
||||
parentNode?.material?.texture,
|
||||
parentNode?.topMaterial,
|
||||
parentNode?.topMaterialPreset,
|
||||
parentNode?.edgeMaterial,
|
||||
parentNode?.edgeMaterialPreset,
|
||||
parentNode?.wallMaterial,
|
||||
parentNode?.wallMaterialPreset,
|
||||
])
|
||||
|
||||
const material = debugColors ? roofDebugMaterials : customMaterial || roofMaterials
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
placeholderGeometry.dispose()
|
||||
}
|
||||
}, [placeholderGeometry])
|
||||
|
||||
return (
|
||||
<mesh
|
||||
geometry={placeholderGeometry}
|
||||
material={material}
|
||||
position={node.position}
|
||||
ref={ref}
|
||||
rotation-y={node.rotation}
|
||||
visible={node.visible}
|
||||
{...handlers}
|
||||
>
|
||||
{/* RoofSystem will replace this geometry in the next frame */}
|
||||
<boxGeometry args={[0, 0, 0]} />
|
||||
</mesh>
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { type RoofNode, useRegistry } from '@pascal-app/core'
|
||||
import { useMemo, useRef } from 'react'
|
||||
import type * as THREE from 'three'
|
||||
import { useEffect, useMemo, useRef } from 'react'
|
||||
import * as THREE from 'three'
|
||||
import { useNodeEvents } from '../../../hooks/use-node-events'
|
||||
import { createMaterial, createMaterialFromPresetRef } from '../../../lib/materials'
|
||||
import useViewer from '../../../store/use-viewer'
|
||||
import { getRoofMaterialArray } from '../../../systems/roof/roof-materials'
|
||||
import { NodeRenderer } from '../node-renderer'
|
||||
import { roofDebugMaterials, roofMaterials } from './roof-materials'
|
||||
|
||||
@@ -14,17 +14,41 @@ export const RoofRenderer = ({ node }: { node: RoofNode }) => {
|
||||
|
||||
const handlers = useNodeEvents(node, 'roof')
|
||||
const debugColors = useViewer((s) => s.debugColors)
|
||||
const placeholderGeometry = useMemo(() => {
|
||||
const geometry = new THREE.BufferGeometry()
|
||||
geometry.setAttribute('position', new THREE.Float32BufferAttribute([], 3))
|
||||
geometry.addGroup(0, 0, 0)
|
||||
geometry.addGroup(0, 0, 1)
|
||||
geometry.addGroup(0, 0, 2)
|
||||
geometry.addGroup(0, 0, 3)
|
||||
return geometry
|
||||
}, [])
|
||||
|
||||
const customMaterial = useMemo(() => {
|
||||
const presetMaterial = createMaterialFromPresetRef(node.materialPreset)
|
||||
if (presetMaterial) return presetMaterial
|
||||
const mat = node.material
|
||||
if (!mat) return null
|
||||
return createMaterial(mat)
|
||||
}, [node.materialPreset, node.material, node.material?.preset, node.material?.properties, node.material?.texture])
|
||||
const customMaterial = useMemo(
|
||||
() => getRoofMaterialArray(node),
|
||||
[
|
||||
node.materialPreset,
|
||||
node.material,
|
||||
node.material?.preset,
|
||||
node.material?.properties,
|
||||
node.material?.texture,
|
||||
node.topMaterial,
|
||||
node.topMaterialPreset,
|
||||
node.edgeMaterial,
|
||||
node.edgeMaterialPreset,
|
||||
node.wallMaterial,
|
||||
node.wallMaterialPreset,
|
||||
],
|
||||
)
|
||||
|
||||
const material = debugColors ? roofDebugMaterials : customMaterial || roofMaterials
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
placeholderGeometry.dispose()
|
||||
}
|
||||
}, [placeholderGeometry])
|
||||
|
||||
return (
|
||||
<group
|
||||
position={node.position}
|
||||
@@ -33,9 +57,13 @@ export const RoofRenderer = ({ node }: { node: RoofNode }) => {
|
||||
visible={node.visible}
|
||||
{...handlers}
|
||||
>
|
||||
<mesh castShadow material={material} name="merged-roof" receiveShadow>
|
||||
<boxGeometry args={[0, 0, 0]} />
|
||||
</mesh>
|
||||
<mesh
|
||||
castShadow
|
||||
geometry={placeholderGeometry}
|
||||
material={material}
|
||||
name="merged-roof"
|
||||
receiveShadow
|
||||
/>
|
||||
<group name="segments-wrapper" visible={false}>
|
||||
{(node.children ?? []).map((childId) => (
|
||||
<NodeRenderer key={childId} nodeId={childId} />
|
||||
|
||||
Reference in New Issue
Block a user