add theatre plugin, add route for theatre editor, build simple animation with a spotlight that follows animating object
This commit is contained in:
parent
47d13e7d6e
commit
2cf484aa46
|
@ -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",
|
||||||
|
|
|
@ -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"
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
|
|
@ -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}
|
|
|
@ -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}
|
|
||||||
/>
|
|
|
@ -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>
|
|
@ -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>
|
|
@ -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-"
|
||||||
|
]
|
||||||
|
}
|
|
@ -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>
|
|
@ -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}
|
|
@ -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>
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
Loading…
Reference in New Issue