add theatre plugin, add route for theatre editor, build simple animation with a spotlight that follows animating object

This commit is contained in:
Silas 2024-05-01 02:34:07 -04:00
parent 47d13e7d6e
commit 2cf484aa46
Signed by: silentsilas
GPG Key ID: 4199EFB7DAA34349
14 changed files with 600 additions and 192 deletions

11
package-lock.json generated
View File

@ -9,11 +9,9 @@
"version": "0.0.1", "version": "0.0.1",
"dependencies": { "dependencies": {
"@dimforge/rapier3d-compat": "^0.11.2", "@dimforge/rapier3d-compat": "^0.11.2",
"@theatre/core": "^0.7.1",
"@threlte/core": "^7.3.0", "@threlte/core": "^7.3.0",
"@threlte/extras": "^8.11.2", "@threlte/extras": "^8.11.2",
"@threlte/rapier": "^2.0.0", "@threlte/rapier": "^2.0.0",
"@threlte/theatre": "^2.1.7",
"three": "^0.159.0", "three": "^0.159.0",
"three-inspect": "^0.4.5" "three-inspect": "^0.4.5"
}, },
@ -21,7 +19,9 @@
"@sveltejs/adapter-auto": "^3.0.0", "@sveltejs/adapter-auto": "^3.0.0",
"@sveltejs/kit": "^2.0.0", "@sveltejs/kit": "^2.0.0",
"@sveltejs/vite-plugin-svelte": "^3.0.0", "@sveltejs/vite-plugin-svelte": "^3.0.0",
"@theatre/core": "^0.7.1",
"@theatre/studio": "^0.7.1", "@theatre/studio": "^0.7.1",
"@threlte/theatre": "^2.1.7",
"@types/eslint": "^8.56.0", "@types/eslint": "^8.56.0",
"@types/three": "^0.159.0", "@types/three": "^0.159.0",
"@typescript-eslint/eslint-plugin": "^7.0.0", "@typescript-eslint/eslint-plugin": "^7.0.0",
@ -1814,6 +1814,7 @@
"version": "0.7.1", "version": "0.7.1",
"resolved": "https://registry.npmjs.org/@theatre/core/-/core-0.7.1.tgz", "resolved": "https://registry.npmjs.org/@theatre/core/-/core-0.7.1.tgz",
"integrity": "sha512-745IbKZURz5TlG9QQqtq3TClTlH2kfc1ZhIwP6sh4JAJW/XR4r5KEC2mZx0q2izWDLKMAz4ZrIs8URIdM6Km1w==", "integrity": "sha512-745IbKZURz5TlG9QQqtq3TClTlH2kfc1ZhIwP6sh4JAJW/XR4r5KEC2mZx0q2izWDLKMAz4ZrIs8URIdM6Km1w==",
"dev": true,
"dependencies": { "dependencies": {
"@theatre/dataverse": "0.7.1" "@theatre/dataverse": "0.7.1"
} }
@ -1822,6 +1823,7 @@
"version": "0.7.1", "version": "0.7.1",
"resolved": "https://registry.npmjs.org/@theatre/dataverse/-/dataverse-0.7.1.tgz", "resolved": "https://registry.npmjs.org/@theatre/dataverse/-/dataverse-0.7.1.tgz",
"integrity": "sha512-cl/uVuXQTYVfcdbBX/GYrZNNpJsvbXEwRaFHUj5zEnyLBuJMO+xCDl9bfRx6Sysdr6HcGJvFuekP0gdmTWK+bA==", "integrity": "sha512-cl/uVuXQTYVfcdbBX/GYrZNNpJsvbXEwRaFHUj5zEnyLBuJMO+xCDl9bfRx6Sysdr6HcGJvFuekP0gdmTWK+bA==",
"dev": true,
"dependencies": { "dependencies": {
"lodash-es": "^4.17.21" "lodash-es": "^4.17.21"
} }
@ -1830,6 +1832,7 @@
"version": "0.7.1", "version": "0.7.1",
"resolved": "https://registry.npmjs.org/@theatre/studio/-/studio-0.7.1.tgz", "resolved": "https://registry.npmjs.org/@theatre/studio/-/studio-0.7.1.tgz",
"integrity": "sha512-e2Of4XRjbq9ytyvYuC3pqn6QYTrOt3dRLTzzUFCMAefIIqbBN/mPUVtZElTDjHbTyNZMTRupRnL9AizAK7Afzw==", "integrity": "sha512-e2Of4XRjbq9ytyvYuC3pqn6QYTrOt3dRLTzzUFCMAefIIqbBN/mPUVtZElTDjHbTyNZMTRupRnL9AizAK7Afzw==",
"dev": true,
"dependencies": { "dependencies": {
"@theatre/dataverse": "0.7.1" "@theatre/dataverse": "0.7.1"
}, },
@ -1893,6 +1896,7 @@
"version": "2.1.7", "version": "2.1.7",
"resolved": "https://registry.npmjs.org/@threlte/theatre/-/theatre-2.1.7.tgz", "resolved": "https://registry.npmjs.org/@threlte/theatre/-/theatre-2.1.7.tgz",
"integrity": "sha512-VYNHsuwMKLrPcH0/gOW3FkYzPX/dXWXfedfamIt8C1DlpwfWn4c8sYdTMGyKqYah+a1hVQ1oQNu9pfTcj9c6qw==", "integrity": "sha512-VYNHsuwMKLrPcH0/gOW3FkYzPX/dXWXfedfamIt8C1DlpwfWn4c8sYdTMGyKqYah+a1hVQ1oQNu9pfTcj9c6qw==",
"dev": true,
"peerDependencies": { "peerDependencies": {
"@theatre/core": ">=0.6", "@theatre/core": ">=0.6",
"@theatre/studio": ">=0.6", "@theatre/studio": ">=0.6",
@ -4957,7 +4961,8 @@
"node_modules/lodash-es": { "node_modules/lodash-es": {
"version": "4.17.21", "version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==",
"dev": true
}, },
"node_modules/lodash.merge": { "node_modules/lodash.merge": {
"version": "4.6.2", "version": "4.6.2",

View File

@ -17,7 +17,9 @@
"@sveltejs/adapter-auto": "^3.0.0", "@sveltejs/adapter-auto": "^3.0.0",
"@sveltejs/kit": "^2.0.0", "@sveltejs/kit": "^2.0.0",
"@sveltejs/vite-plugin-svelte": "^3.0.0", "@sveltejs/vite-plugin-svelte": "^3.0.0",
"@theatre/core": "^0.7.1",
"@theatre/studio": "^0.7.1", "@theatre/studio": "^0.7.1",
"@threlte/theatre": "^2.1.7",
"@types/eslint": "^8.56.0", "@types/eslint": "^8.56.0",
"@types/three": "^0.159.0", "@types/three": "^0.159.0",
"@typescript-eslint/eslint-plugin": "^7.0.0", "@typescript-eslint/eslint-plugin": "^7.0.0",
@ -40,11 +42,9 @@
"type": "module", "type": "module",
"dependencies": { "dependencies": {
"@dimforge/rapier3d-compat": "^0.11.2", "@dimforge/rapier3d-compat": "^0.11.2",
"@theatre/core": "^0.7.1",
"@threlte/core": "^7.3.0", "@threlte/core": "^7.3.0",
"@threlte/extras": "^8.11.2", "@threlte/extras": "^8.11.2",
"@threlte/rapier": "^2.0.0", "@threlte/rapier": "^2.0.0",
"@threlte/theatre": "^2.1.7",
"three": "^0.159.0", "three": "^0.159.0",
"three-inspect": "^0.4.5" "three-inspect": "^0.4.5"
} }

View File

@ -1,17 +0,0 @@
<script lang="ts">
import { Canvas } from '@threlte/core'
import Home from '$lib/components/scenes/Home.svelte'
import { World } from '@threlte/rapier';
import { Inspector } from 'three-inspect';
import { dev } from '$app/environment';
</script>
<Canvas>
<World gravity={[0, 0, 0]}>
<Home />
</World>
{#if dev}
<Inspector />
{/if}
</Canvas>

View File

@ -1,109 +0,0 @@
<script
lang="ts"
context="module"
>
const geometry = new SphereGeometry(1, 8, 4)
const material = new MeshBasicMaterial({ color: '#339933' })
</script>
<script lang="ts">
import { T } from '@threlte/core'
import { HTML } from '@threlte/extras'
import { Attractor, Collider, RigidBody } from '@threlte/rapier'
import { MeshBasicMaterial, SphereGeometry, Vector3 } from 'three'
export let range: number = 10
export let position: [number, number, number] = [0, 0, 0]
let isHovering = false
let isPointerDown = false
let contactVec = new Vector3()
const bodyPositions = [
new Vector3(position[0] - range, position[0] - range, position[0] - range).toArray(),
new Vector3(position[1] + (range / 2), position[1] + range, position[1] + range).toArray(),
new Vector3(position[2] + range, position[2] - (range / 2), position[2] + range).toArray()
]
const getId = () => {
return Math.random().toString(16).slice(2)
}
const getRandomSize = (): number => {
return (Math.random() / 4) + 0.25
}
const generateBodies = (c: number) => {
return Array(c)
.fill('x')
.map((_, index) => {
return {
id: getId(),
position: bodyPositions[index],
size: getRandomSize()
}
})
}
const onClick = () => {
console.log('clicked')
}
$: bodies = generateBodies(2)
</script>
<HTML
position.x={position[0]}
position.y={position[1]}
position.z={position[2]}
>
<button
on:pointerenter={() => (isHovering = true)}
on:pointerleave={() => {
isPointerDown = false
isHovering = false
}}
on:pointerdown={() => (isPointerDown = true)}
on:pointerup={() => (isPointerDown = false)}
on:pointercancel={() => {
isPointerDown = false
isHovering = false
}}
on:click={onClick}
class="rounded-full bg-orange-500 px-3 text-white hover:opacity-90 active:opacity-70"
>
Hello!
</button>
</HTML>
<Attractor
position.x={position[0]}
position.y={position[1]}
position.z={position[2]}
range={200}
strength={isHovering ? 1 : 0.1}
gravityType={"linear"}
/>
{#each bodies as body (body.id)}
<T.Group position={body.position}>
<RigidBody>
<Collider
shape="ball"
args={[body.size]}
mass={body.size}
/>
<Attractor
range={50}
strength={1}
gravityType={"newtonian"}
/>
<T.Mesh
scale={[body.size, body.size, body.size]}
{geometry}
{material}
/>
</RigidBody>
</T.Group>
{/each}

View File

@ -1,56 +0,0 @@
<script lang="ts">
import { T } from '@threlte/core'
import { OrbitControls } from '@threlte/extras'
import OrbitingSpheres from '$lib/components/home/OrbitingSpheres.svelte';
const size = 100
const count = 500
const positions = new Float32Array(count * 3)
// randomly distribute points in a cube
for (let i = 0; i < count; i++) {
positions[i * 3 + 0] = (Math.random() - 0.5) * size
positions[i * 3 + 1] = (Math.random() - 0.5) * size
positions[i * 3 + 2] = (Math.random() - 0.5) * size
}
</script>
<T.PerspectiveCamera
position.y={15}
position.z={25}
makeDefault
fov={70}
far={10000}
>
<OrbitControls
enableZoom={false}
enablePan={false}
enableRotate={false}
enableDamping
target.y={0}
autoRotate
/>
</T.PerspectiveCamera>
<T.Points>
<T.BufferGeometry>
<T.BufferAttribute
args={[positions, 3]}
attach={(parent, self) => {
parent.setAttribute('position', self)
return () => {
// cleanup function called when ref changes or the component unmounts
// https://threlte.xyz/docs/reference/core/t#attach
}
}}
/>
</T.BufferGeometry>
<T.PointsMaterial size={0.1} />
</T.Points>
<OrbitingSpheres
position={[0, 0, 0]}
range={10}
/>

View File

@ -0,0 +1,12 @@
<script lang="ts">
import { dev } from '$app/environment';
import { Canvas } from '@threlte/core';
import Spinners from '$lib/components/scenes/editor/Spinners.svelte';
import { Studio } from '@threlte/theatre';
</script>
<Studio enabled={false} />
<Canvas>
<Spinners />
</Canvas>

View File

@ -0,0 +1,48 @@
<script lang="ts">
import { T } from '@threlte/core';
import { OrbitControls } from '@threlte/extras';
import { Project, Sequence, type SequenceController, Sheet, SheetObject } from '@threlte/theatre';
import { Vector3, type Mesh, type SpotLight } from 'three';
import spinnersJson from '$lib/components/scenes/editor/SpinnersState.json';
import { type IProjectConfig } from '@theatre/core';
let sequence: SequenceController;
let box: Mesh;
let spotlight: SpotLight;
let lastBoxPosition = new Vector3();
let currentBoxPosition = new Vector3();
let config = spinnersJson as IProjectConfig;
const boxMoved: any = (props: { position: { x: number; y: number; z: number } }) => {
if (box && spotlight) {
const { x, y, z } = props.position;
currentBoxPosition.set(x, y, z);
spotlight.lookAt(currentBoxPosition);
lastBoxPosition.copy(currentBoxPosition);
}
};
</script>
<Project name="Spinners" config={{ state: config }}>
<Sheet name="Spinners Sheet">
<T.PerspectiveCamera position={[0, 5, 10]} makeDefault>
<OrbitControls target={[0, 1.5, 0]} />
</T.PerspectiveCamera>
<!-- create a T.SpotLight that looks at box-->
<T.SpotLight position={[0, 5, 3]} intensity={10} bind:ref={spotlight}></T.SpotLight>
<SheetObject key="Box" let:Transform let:Sync on:change={boxMoved}>
<Transform>
<T.Mesh position.y={0.5} bind:ref={box}>
<T.BoxGeometry args={[1, 1, 1]} />
<T.MeshStandardMaterial color="#b00d03">
<Sync color roughness metalness />
</T.MeshStandardMaterial>
</T.Mesh>
</Transform>
</SheetObject>
<Sequence iterationCount={Infinity} direction="alternate" autoplay rate={1} bind:sequence />
</Sheet>
</Project>

View File

@ -0,0 +1,357 @@
{
"sheetsById": {
"Spinners Sheet": {
"staticOverrides": {
"byObject": {
"Box": {
"position": {
"x": 0,
"y": 0,
"z": 0
},
"rotation": {
"x": 0,
"y": 0,
"z": 0
},
"scale": {
"x": 1,
"y": 1,
"z": 1
}
},
"Camera": {
"position": {
"y": -3.4561481429695853,
"x": -0.1803637517299077,
"z": 0
},
"rotation": {
"x": 0,
"y": 0,
"z": 0
},
"scale": {
"x": 1,
"y": 1,
"z": 1
}
},
"Spotlight": {
"position": {
"x": 0,
"y": 0.34178271862927456,
"z": 0
},
"rotation": {
"x": 0,
"y": 0,
"z": 0
},
"scale": {
"x": 1,
"y": 1,
"z": 1
},
"intensity": 10
}
}
},
"sequence": {
"subUnitsPerUnit": 30,
"length": 4,
"type": "PositionalSequence",
"tracksByObject": {
"Box": {
"trackData": {
"SxW5NK1Z35": {
"type": "BasicKeyframedTrack",
"__debugName": "Box:[\"position\",\"x\"]",
"keyframes": [
{
"id": "mERu3kt0Xs",
"position": 0,
"connectedRight": true,
"handles": [
0.5,
1,
0.25,
0.46
],
"type": "bezier",
"value": 0
},
{
"id": "VBPb5E3B1C",
"position": 2,
"connectedRight": true,
"handles": [
0.45,
0.94,
0.55,
0.085
],
"type": "bezier",
"value": 1.9823485267067853
},
{
"id": "rfLGURCJkj",
"position": 4,
"connectedRight": true,
"handles": [
0.68,
0.53,
0.5,
0
],
"type": "bezier",
"value": 0.32792832756835955
}
]
},
"kOMLbXUiZO": {
"type": "BasicKeyframedTrack",
"__debugName": "Box:[\"position\",\"y\"]",
"keyframes": [
{
"id": "-A5U2JRANH",
"position": 0,
"connectedRight": true,
"handles": [
0.5,
1,
0.25,
0.46
],
"type": "bezier",
"value": 0
},
{
"id": "T-TNfaz7r4",
"position": 2,
"connectedRight": true,
"handles": [
0.45,
0.94,
0.55,
0.085
],
"type": "bezier",
"value": 2.240748284796251
},
{
"id": "KloOKSYvgL",
"position": 4,
"connectedRight": true,
"handles": [
0.68,
0.53,
0.5,
0
],
"type": "bezier",
"value": 3.6974259955062565
}
]
},
"pTB8Ik7IJ5": {
"type": "BasicKeyframedTrack",
"__debugName": "Box:[\"position\",\"z\"]",
"keyframes": [
{
"id": "5ik8ooLc9L",
"position": 0,
"connectedRight": true,
"handles": [
0.5,
1,
0.25,
0.46
],
"type": "bezier",
"value": 0
},
{
"id": "G1lA8oVdD6",
"position": 2,
"connectedRight": true,
"handles": [
0.45,
0.94,
0.55,
0.085
],
"type": "bezier",
"value": 2.245397305639063
},
{
"id": "cfuJSupHjD",
"position": 4,
"connectedRight": true,
"handles": [
0.68,
0.53,
0.5,
0
],
"type": "bezier",
"value": -0.37185537115063294
}
]
},
"Up7d7ZCZpA": {
"type": "BasicKeyframedTrack",
"__debugName": "Box:[\"rotation\",\"x\"]",
"keyframes": [
{
"id": "kVu_NY2i2n",
"position": 0,
"connectedRight": true,
"handles": [
0.5,
1,
0.25,
0.46
],
"type": "bezier",
"value": 0
},
{
"id": "L1BcPcoiNp",
"position": 2,
"connectedRight": true,
"handles": [
0.45,
0.94,
0.55,
0.085
],
"type": "bezier",
"value": -17
},
{
"id": "WeEOQ43olV",
"position": 4,
"connectedRight": true,
"handles": [
0.68,
0.53,
0.5,
0
],
"type": "bezier",
"value": 103
}
]
},
"RBXXUWXZPY": {
"type": "BasicKeyframedTrack",
"__debugName": "Box:[\"rotation\",\"y\"]",
"keyframes": [
{
"id": "4AEPToo_xo",
"position": 0,
"connectedRight": true,
"handles": [
0.5,
1,
0.25,
0.46
],
"type": "bezier",
"value": 0
},
{
"id": "WeFeWY1Ck0",
"position": 2,
"connectedRight": true,
"handles": [
0.45,
0.94,
0.55,
0.085
],
"type": "bezier",
"value": 83
},
{
"id": "aaBFIqYEFC",
"position": 4,
"connectedRight": true,
"handles": [
0.68,
0.53,
0.5,
0
],
"type": "bezier",
"value": 135
}
]
},
"4rTUFL8Rjv": {
"type": "BasicKeyframedTrack",
"__debugName": "Box:[\"rotation\",\"z\"]",
"keyframes": [
{
"id": "HYpJMJt8Dw",
"position": 0,
"connectedRight": true,
"handles": [
0.5,
1,
0.25,
0.46
],
"type": "bezier",
"value": 0
},
{
"id": "RLo4B-EMu3",
"position": 2,
"connectedRight": true,
"handles": [
0.45,
0.94,
0.55,
0.085
],
"type": "bezier",
"value": 43
},
{
"id": "P1hzyC7J7H",
"position": 4,
"connectedRight": true,
"handles": [
0.68,
0.53,
0.5,
0
],
"type": "bezier",
"value": 19
}
]
}
},
"trackIdByPropPath": {
"[\"position\",\"x\"]": "SxW5NK1Z35",
"[\"position\",\"y\"]": "kOMLbXUiZO",
"[\"position\",\"z\"]": "pTB8Ik7IJ5",
"[\"rotation\",\"x\"]": "Up7d7ZCZpA",
"[\"rotation\",\"y\"]": "RBXXUWXZPY",
"[\"rotation\",\"z\"]": "4rTUFL8Rjv"
}
}
}
}
}
},
"definitionVersion": "0.4.0",
"revisionHistory": [
"U-YSeMCq-p7is9Th",
"sCzKmBDPVWZIRTsi",
"BKd5QQO-QfV2Qu4-"
]
}

View File

@ -0,0 +1,32 @@
<script lang="ts">
import { Canvas, T } from '@threlte/core';
import { OrbitControls } from '@threlte/extras';
import OrbitingSpheres from '$lib/components/scenes/home/OrbitingSpheres.svelte';
import { World } from '@threlte/rapier';
import { Inspector } from 'three-inspect';
import { dev } from '$app/environment';
import SpaceSkysphere from './SpaceSkysphere.svelte';
</script>
<Canvas>
<World gravity={[0, 0, 0]}>
<T.PerspectiveCamera position.y={15} position.z={25} makeDefault fov={70} far={10000}>
<OrbitControls
enableZoom={false}
enablePan={false}
enableRotate={false}
enableDamping
target.y={0}
autoRotate
/>
</T.PerspectiveCamera>
<SpaceSkysphere size={100} count={500} />
<OrbitingSpheres position={[0, 0, 0]} range={10} />
</World>
{#if dev}
<Inspector />
{/if}
</Canvas>

View File

@ -0,0 +1,86 @@
<script lang="ts" context="module">
const geometry = new SphereGeometry(1, 8, 4);
const material = new MeshBasicMaterial({ color: '#339933' });
</script>
<script lang="ts">
import { T } from '@threlte/core';
import { HTML } from '@threlte/extras';
import { Attractor, Collider, RigidBody } from '@threlte/rapier';
import { MeshBasicMaterial, SphereGeometry, Vector3 } from 'three';
export let range: number = 10;
export let position: [number, number, number] = [0, 0, 0];
let isHovering = false;
let isPointerDown = false;
const bodyPositions = [
new Vector3(position[0] - range, position[0] - range, position[0] - range).toArray(),
new Vector3(position[1] + range / 2, position[1] + range, position[1] + range).toArray(),
new Vector3(position[2] + range, position[2] - range / 2, position[2] + range).toArray()
];
const getId = () => {
return Math.random().toString(16).slice(2);
};
const getRandomSize = (): number => {
return Math.random() / 4 + 0.25;
};
const generateBodies = (c: number) => {
return Array(c)
.fill('x')
.map((_, index) => {
return {
id: getId(),
position: bodyPositions[index],
size: getRandomSize()
};
});
};
const onClick = () => {
console.log('clicked');
};
$: bodies = generateBodies(2);
</script>
<HTML position.x={position[0]} position.y={position[1]} position.z={position[2]}>
<button
on:pointerenter={() => (isHovering = true)}
on:pointerleave={() => {
isPointerDown = false;
isHovering = false;
}}
on:pointerdown={() => (isPointerDown = true)}
on:pointerup={() => (isPointerDown = false)}
on:pointercancel={() => {
isPointerDown = false;
isHovering = false;
}}
on:click={onClick}
class="rounded-full bg-orange-500 px-3 text-white hover:opacity-90 active:opacity-70"
>
Hello!
</button>
</HTML>
<Attractor
position.x={position[0]}
position.y={position[1]}
position.z={position[2]}
range={200}
strength={isHovering ? 1 : 0.1}
gravityType={'linear'}
/>
{#each bodies as body (body.id)}
<T.Group position={body.position}>
<RigidBody>
<Collider shape="ball" args={[body.size]} mass={body.size} />
<Attractor range={50} strength={1} gravityType={'newtonian'} />
<T.Mesh scale={[body.size, body.size, body.size]} {geometry} {material} />
</RigidBody>
</T.Group>
{/each}

View File

@ -0,0 +1,30 @@
<script lang="ts">
import { T } from '@threlte/core';
export let size = 100;
export let count = 500;
const positions = new Float32Array(count * 3);
// randomly distribute points in a cube
for (let i = 0; i < count; i++) {
positions[i * 3 + 0] = (Math.random() - 0.5) * size;
positions[i * 3 + 1] = (Math.random() - 0.5) * size;
positions[i * 3 + 2] = (Math.random() - 0.5) * size;
}
</script>
<T.Points>
<T.BufferGeometry>
<T.BufferAttribute
args={[positions, 3]}
attach={(parent, self) => {
parent.setAttribute('position', self);
return () => {
// cleanup function called when ref changes or the component unmounts
// https://threlte.xyz/docs/reference/core/t#attach
};
}}
/>
</T.BufferGeometry>
<T.PointsMaterial size={0.1} />
</T.Points>

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import App from '$lib/components/App.svelte' import Home from '$lib/components/scenes/home/Home.svelte';
import type { PageData } from './$types'; import type { PageData } from './$types';
export let data: PageData; export let data: PageData;
</script> </script>
@ -8,10 +8,7 @@
{#each data.models as model} {#each data.models as model}
<span>{model.title}</span> <span>{model.title}</span>
{/each} {/each}
<App /> <Home />
<canvas>
</canvas>
</div> </div>
<style> <style>

View File

@ -0,0 +1,23 @@
<script lang="ts">
import Editor from '$lib/components/scenes/editor/Editor.svelte';
</script>
<div>
<Editor />
</div>
<style>
:global(body) {
margin: 0;
}
div {
width: 100vw;
height: 100vh;
background: rgb(0, 36, 6);
background: linear-gradient(180deg, rgba(0, 36, 6, 1) 0%, rgba(0, 0, 0, 1) 100%);
display: flex;
justify-content: center;
align-items: center;
}
</style>