This commit is contained in:
wass08
2026-01-27 09:25:40 +09:00
parent fd4c097d5b
commit e3e3602d91
19 changed files with 612 additions and 19 deletions
@@ -0,0 +1,32 @@
import { type CeilingNode, useRegistry } from '@pascal-app/core'
import { useRef } from 'react'
import { faceDirection, float, mix } from 'three/tsl'
import { DoubleSide, type Mesh, MeshStandardNodeMaterial } from 'three/webgpu'
import { useNodeEvents } from '../../../hooks/use-node-events'
// TSL material that renders differently based on face direction:
// - Back face (looking up at ceiling from below): solid
// - Front face (looking down at ceiling from above): 30% opacity
const ceilingMaterial = new MeshStandardNodeMaterial({
color: 0xffffff,
side: DoubleSide,
transparent: true,
})
// faceDirection is 1.0 for front face, -1.0 for back face
// We want: front face (top, looking down) = 0.3 opacity, back face (bottom, looking up) = 1.0 opacity
ceilingMaterial.opacityNode = mix(float(1.0), float(0.3), faceDirection.greaterThan(0.0))
export const CeilingRenderer = ({ node }: { node: CeilingNode }) => {
const ref = useRef<Mesh>(null!)
useRegistry(node.id, 'ceiling', ref)
const handlers = useNodeEvents(node, 'ceiling')
return (
<mesh ref={ref} material={ceilingMaterial} {...handlers}>
{/* CeilingSystem will replace this geometry in the next frame */}
<boxGeometry args={[0, 0, 0]} />
</mesh>
)
}
@@ -2,6 +2,7 @@
import { type AnyNode, useScene } from '@pascal-app/core'
import { BuildingRenderer } from './building/building-renderer'
import { CeilingRenderer } from './ceiling/ceiling-renderer'
import { ItemRenderer } from './item/item-renderer'
import { LevelRenderer } from './level/level-renderer'
import { SlabRenderer } from './slab/slab-renderer'
@@ -16,6 +17,7 @@ export const NodeRenderer = ({ nodeId }: { nodeId: AnyNode['id'] }) => {
return (
<>
{node.type === 'building' && <BuildingRenderer node={node} />}
{node.type === 'ceiling' && <CeilingRenderer node={node} />}
{node.type === 'level' && <LevelRenderer node={node} />}
{node.type === 'item' && <ItemRenderer node={node} />}
{node.type === 'slab' && <SlabRenderer node={node} />}
@@ -1,6 +1,6 @@
'use client'
import { SlabSystem, WallSystem } from '@pascal-app/core'
import { CeilingSystem, SlabSystem, WallSystem } from '@pascal-app/core'
import { Bvh, Environment } from '@react-three/drei'
import { Canvas, extend, type ThreeToJSXElements } from '@react-three/fiber'
import * as THREE from 'three/webgpu'
@@ -40,6 +40,7 @@ const Viewer: React.FC<ViewerProps> = ({ children }) => {
{/* Default Systems */}
<LevelSystem />
<CeilingSystem />
<SlabSystem />
<WallSystem />
<PostProcessing />
@@ -1,6 +1,8 @@
import {
type BuildingEvent,
type BuildingNode,
type CeilingEvent,
type CeilingNode,
type EventSuffix,
emitter,
type ItemEvent,
@@ -20,6 +22,7 @@ type NodeConfig = {
building: { node: BuildingNode; event: BuildingEvent }
zone: { node: ZoneNode; event: ZoneEvent }
slab: { node: SlabNode; event: SlabEvent }
ceiling: { node: CeilingNode; event: CeilingEvent }
}
type NodeType = keyof NodeConfig