added dissolve material
This commit is contained in:
20
app/package-lock.json
generated
20
app/package-lock.json
generated
@@ -48,6 +48,7 @@
|
||||
"sass": "^1.78.0",
|
||||
"socket.io-client": "^4.8.1",
|
||||
"three": "^0.168.0",
|
||||
"three-custom-shader-material": "^6.3.7",
|
||||
"three-viewport-gizmo": "^2.2.0",
|
||||
"typescript": "^4.9.5",
|
||||
"web-vitals": "^2.1.4",
|
||||
@@ -20675,6 +20676,25 @@
|
||||
"three-mesh-bvh": ">=0.6.6"
|
||||
}
|
||||
},
|
||||
"node_modules/three-custom-shader-material": {
|
||||
"version": "6.3.7",
|
||||
"resolved": "https://registry.npmjs.org/three-custom-shader-material/-/three-custom-shader-material-6.3.7.tgz",
|
||||
"integrity": "sha512-u+REZFLqjCTFgKrBu9nFomwcmLwGkuz//Hk8NezXBnC1rVb+0knyxsoFisoltQRJLg4CoB0pJda9iYItlX4IuQ==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@react-three/fiber": ">=8.0",
|
||||
"react": ">=18.0",
|
||||
"three": ">=0.159"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@react-three/fiber": {
|
||||
"optional": true
|
||||
},
|
||||
"react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/three-mesh-bvh": {
|
||||
"version": "0.6.8",
|
||||
"resolved": "https://registry.npmjs.org/three-mesh-bvh/-/three-mesh-bvh-0.6.8.tgz",
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
"sass": "^1.78.0",
|
||||
"socket.io-client": "^4.8.1",
|
||||
"three": "^0.168.0",
|
||||
"three-custom-shader-material": "^6.3.7",
|
||||
"three-viewport-gizmo": "^2.2.0",
|
||||
"typescript": "^4.9.5",
|
||||
"web-vitals": "^2.1.4",
|
||||
|
||||
108
app/src/modules/builder/wrappers/materials/dissolveMaterial.tsx
Normal file
108
app/src/modules/builder/wrappers/materials/dissolveMaterial.tsx
Normal file
@@ -0,0 +1,108 @@
|
||||
import * as React from "react";
|
||||
import * as THREE from "three";
|
||||
import { easing } from "maath";
|
||||
import { useFrame } from "@react-three/fiber";
|
||||
import CSM from "three-custom-shader-material";
|
||||
|
||||
const vertexShader = `
|
||||
varying vec2 vUv;
|
||||
varying vec3 vPosition;
|
||||
void main() {
|
||||
vUv = uv;
|
||||
vPosition = position;
|
||||
}
|
||||
`;
|
||||
|
||||
const fragmentShader = `
|
||||
varying vec2 vUv;
|
||||
varying vec3 vPosition;
|
||||
uniform float uThickness;
|
||||
uniform vec3 uColor;
|
||||
uniform float uProgress;
|
||||
|
||||
float hash(vec3 p) {
|
||||
p = fract(p * 0.3183099 + 0.1);
|
||||
p *= 17.0;
|
||||
return fract(p.x * p.y * p.z * (p.x + p.y + p.z));
|
||||
}
|
||||
|
||||
float noise(vec3 x) {
|
||||
vec3 i = floor(x);
|
||||
vec3 f = fract(x);
|
||||
f = f * f * (3.0 - 2.0 * f);
|
||||
|
||||
return mix(
|
||||
mix(mix(hash(i + vec3(0,0,0)), hash(i + vec3(1,0,0)), f.x),
|
||||
mix(hash(i + vec3(0,1,0)), hash(i + vec3(1,1,0)), f.x), f.y),
|
||||
mix(mix(hash(i + vec3(0,0,1)), hash(i + vec3(1,0,1)), f.x),
|
||||
mix(hash(i + vec3(0,1,1)), hash(i + vec3(1,1,1)), f.x), f.y), f.z);
|
||||
}
|
||||
|
||||
void main() {
|
||||
float noiseValue = noise(vPosition * 10.0);
|
||||
float progress = uProgress;
|
||||
|
||||
float visualFade = 1.0 - smoothstep(0.9, 1.0, progress);
|
||||
|
||||
float dissolveProgress = 1.0 - progress;
|
||||
|
||||
float alpha = step(noiseValue, dissolveProgress);
|
||||
|
||||
float border = step(noiseValue, dissolveProgress + uThickness) - alpha;
|
||||
border *= step(0.0, dissolveProgress);
|
||||
|
||||
alpha *= visualFade;
|
||||
border *= visualFade;
|
||||
|
||||
csm_DiffuseColor.rgb = border > 0.0 ? uColor : csm_DiffuseColor.rgb;
|
||||
csm_DiffuseColor.a = alpha + border;
|
||||
|
||||
if (progress >= 1.0) {
|
||||
csm_DiffuseColor.a = 0.0;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
interface DissolveMaterialProps {
|
||||
baseMaterial: THREE.ShaderMaterial | THREE.MeshStandardMaterial | THREE.MeshPhysicalMaterial;
|
||||
thickness?: number;
|
||||
color?: string;
|
||||
intensity?: number;
|
||||
duration?: number;
|
||||
fade?: boolean;
|
||||
fadedIn?: () => void;
|
||||
fadedOut?: () => void;
|
||||
}
|
||||
|
||||
export function DissolveMaterial({ baseMaterial, thickness = 0.1, color = "#0082b2", intensity = 50, duration = 1.2, fade = true, fadedIn, fadedOut }: DissolveMaterialProps) {
|
||||
const uniforms = React.useRef({
|
||||
uThickness: { value: thickness },
|
||||
uColor: { value: new THREE.Color(color).multiplyScalar(intensity) },
|
||||
uProgress: { value: fade ? 1 : 0 },
|
||||
});
|
||||
|
||||
const hasFadedIn = React.useRef(false);
|
||||
const hasFadedOut = React.useRef(false);
|
||||
|
||||
useFrame((_state, delta) => {
|
||||
easing.damp(uniforms.current.uProgress, "value", fade ? 0 : 1, duration, delta);
|
||||
|
||||
const p = uniforms.current.uProgress.value;
|
||||
|
||||
if (p <= 0.01) {
|
||||
if (!hasFadedIn.current) {
|
||||
fadedIn?.();
|
||||
hasFadedIn.current = true;
|
||||
hasFadedOut.current = false;
|
||||
}
|
||||
} else if (p >= 0.99) {
|
||||
if (!hasFadedOut.current) {
|
||||
fadedOut?.();
|
||||
hasFadedOut.current = true;
|
||||
hasFadedIn.current = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return <CSM baseMaterial={baseMaterial} vertexShader={vertexShader} fragmentShader={fragmentShader} uniforms={uniforms.current} toneMapped={false} transparent />;
|
||||
}
|
||||
@@ -1,44 +1,46 @@
|
||||
import { useGLTF } from '@react-three/drei'
|
||||
import { useMemo } from 'react';
|
||||
import * as THREE from 'three';
|
||||
import { useGLTF } from "@react-three/drei";
|
||||
import { useMemo } from "react";
|
||||
import * as THREE from "three";
|
||||
|
||||
import defaultMaterial from '../../../../../assets/gltf-glb/materials/default.glb';
|
||||
import material1 from '../../../../../assets/gltf-glb/materials/material1.glb';
|
||||
import material2 from '../../../../../assets/gltf-glb/materials/material2.glb';
|
||||
import material3 from '../../../../../assets/gltf-glb/materials/material3.glb';
|
||||
import defaultMaterial from "../../../../../assets/gltf-glb/materials/default.glb";
|
||||
import material1 from "../../../../../assets/gltf-glb/materials/material1.glb";
|
||||
import material2 from "../../../../../assets/gltf-glb/materials/material2.glb";
|
||||
import material3 from "../../../../../assets/gltf-glb/materials/material3.glb";
|
||||
// import { DissolveMaterial } from "../../../../builder/wrappers/materials/dissolveMaterial";
|
||||
|
||||
const modelPaths: Record<string, string> = {
|
||||
'Default material': defaultMaterial,
|
||||
'Material 1': material1,
|
||||
'Material 2': material2,
|
||||
'Material 3': material3,
|
||||
"Default material": defaultMaterial,
|
||||
"Material 1": material1,
|
||||
"Material 2": material2,
|
||||
"Material 3": material3,
|
||||
};
|
||||
|
||||
type ModelType = keyof typeof modelPaths;
|
||||
|
||||
interface ModelProps extends React.ComponentProps<'group'> {
|
||||
interface ModelProps extends React.ComponentProps<"group"> {
|
||||
materialId: string;
|
||||
materialType: ModelType;
|
||||
matRef: React.Ref<THREE.Group<THREE.Object3DEventMap>>
|
||||
matRef: React.Ref<THREE.Group<THREE.Object3DEventMap>>;
|
||||
}
|
||||
|
||||
export function MaterialModel({ materialId, materialType, matRef, ...props }: Readonly<ModelProps>) {
|
||||
const path = modelPaths[materialType] || modelPaths['Default material'];
|
||||
const path = modelPaths[materialType] || modelPaths["Default material"];
|
||||
const gltf = useGLTF(path);
|
||||
const cloned = useMemo(() => gltf?.scene.clone(), [gltf]);
|
||||
// const mat = useMemo(() => (gltf?.scene.clone().children[0] as THREE.Mesh).material as THREE.MeshStandardMaterial, [gltf]);
|
||||
|
||||
if (!cloned) return null;
|
||||
|
||||
return (
|
||||
<group uuid={materialId} ref={matRef} {...props} dispose={null}>
|
||||
<primitive
|
||||
object={cloned}
|
||||
scale={[0.4, 0.4, 0.4]}
|
||||
/>
|
||||
<primitive object={cloned} scale={[0.4, 0.4, 0.4]} />
|
||||
{/* <mesh scale={[0.2, 0.2, 0.2]} geometry={(cloned.children[0] as THREE.Mesh).geometry}>
|
||||
<DissolveMaterial baseMaterial={mat.clone()} color="blue"/>
|
||||
</mesh> */}
|
||||
</group>
|
||||
);
|
||||
}
|
||||
|
||||
Object.values(modelPaths).forEach((path) => {
|
||||
useGLTF.preload(path);
|
||||
});
|
||||
});
|
||||
|
||||
21
app/src/types/world/worldTypes.d.ts
vendored
21
app/src/types/world/worldTypes.d.ts
vendored
@@ -6,8 +6,6 @@ import { DragControls } from "three/examples/jsm/controls/DragControls";
|
||||
import { IntersectionEvent } from "@react-three/fiber/dist/declarations/src/core/events";
|
||||
import { ThreeEvent } from "@react-three/fiber/dist/declarations/src/core/events";
|
||||
import { RootState } from "@react-three/fiber";
|
||||
import { CSM } from "three/examples/jsm/csm/CSM";
|
||||
import { CSMHelper } from "three/examples/jsm/csm/CSMHelper";
|
||||
import { CameraControls } from "@react-three/drei";
|
||||
|
||||
/** Core THREE.js and React-Fiber Event Types **/
|
||||
@@ -129,13 +127,7 @@ export type Lines = Array<Line>;
|
||||
/** Wall and Room Types for 3D Space Management **/
|
||||
|
||||
// Defines a wall with its geometry, position, rotation, material, and layer information
|
||||
export type Wall = [
|
||||
THREE.ExtrudeGeometry,
|
||||
[number, number, number],
|
||||
[number, number, number],
|
||||
string,
|
||||
number
|
||||
];
|
||||
export type Wall = [THREE.ExtrudeGeometry, [number, number, number], [number, number, number], string, number];
|
||||
|
||||
// Collection of walls, useful in scene construction
|
||||
export type Walls = Array<Wall>;
|
||||
@@ -144,10 +136,10 @@ export type Walls = Array<Wall>;
|
||||
export type RefWalls = React.MutableRefObject<Walls>;
|
||||
|
||||
// Room type, containing coordinates and layer metadata for spatial management
|
||||
export type Rooms = Array<{ coordinates: Array<{ position: THREE.Vector3; uuid: string }>; layer: number; }>;
|
||||
export type Rooms = Array<{ coordinates: Array<{ position: THREE.Vector3; uuid: string }>; layer: number }>;
|
||||
|
||||
// Reference for room objects, enabling updates within React components
|
||||
export type RefRooms = React.MutableRefObject<Array<{ coordinates: Array<{ position: THREE.Vector3; uuid: string }>; layer: number; }>>;
|
||||
export type RefRooms = React.MutableRefObject<Array<{ coordinates: Array<{ position: THREE.Vector3; uuid: string }>; layer: number }>>;
|
||||
|
||||
// Reference for lines, supporting React-based state changes
|
||||
export type RefLines = React.MutableRefObject<Lines>;
|
||||
@@ -203,13 +195,13 @@ export type FloorItemType = {
|
||||
uuid: string;
|
||||
position: [number, number, number];
|
||||
rotation: [number, number, number];
|
||||
}
|
||||
};
|
||||
points?: {
|
||||
uuid: string;
|
||||
position: [number, number, number];
|
||||
rotation: [number, number, number];
|
||||
}[];
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// Array of floor items for managing multiple objects on the floor
|
||||
@@ -256,6 +248,3 @@ export type setRemoveLayerSetState = (layer: number | null) => void;
|
||||
export type setSelectedWallItemSetState = (item: THREE.Object3D | null) => void;
|
||||
export type setSelectedFloorItemSetState = (item: THREE.Object3D | null) => void;
|
||||
export type setSelectedItemsIndexSetState = (index: number | null) => void;
|
||||
|
||||
export type RefCSM = React.MutableRefObject<CSM>;
|
||||
export type RefCSMHelper = React.MutableRefObject<CSMHelper>;
|
||||
Reference in New Issue
Block a user