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",
|
||||
"dependencies": {
|
||||
"@dimforge/rapier3d-compat": "^0.11.2",
|
||||
"@theatre/core": "^0.7.1",
|
||||
"@threlte/core": "^7.3.0",
|
||||
"@threlte/extras": "^8.11.2",
|
||||
"@threlte/rapier": "^2.0.0",
|
||||
"@threlte/theatre": "^2.1.7",
|
||||
"three": "^0.159.0",
|
||||
"three-inspect": "^0.4.5"
|
||||
},
|
||||
|
@ -21,7 +19,9 @@
|
|||
"@sveltejs/adapter-auto": "^3.0.0",
|
||||
"@sveltejs/kit": "^2.0.0",
|
||||
"@sveltejs/vite-plugin-svelte": "^3.0.0",
|
||||
"@theatre/core": "^0.7.1",
|
||||
"@theatre/studio": "^0.7.1",
|
||||
"@threlte/theatre": "^2.1.7",
|
||||
"@types/eslint": "^8.56.0",
|
||||
"@types/three": "^0.159.0",
|
||||
"@typescript-eslint/eslint-plugin": "^7.0.0",
|
||||
|
@ -1814,6 +1814,7 @@
|
|||
"version": "0.7.1",
|
||||
"resolved": "https://registry.npmjs.org/@theatre/core/-/core-0.7.1.tgz",
|
||||
"integrity": "sha512-745IbKZURz5TlG9QQqtq3TClTlH2kfc1ZhIwP6sh4JAJW/XR4r5KEC2mZx0q2izWDLKMAz4ZrIs8URIdM6Km1w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@theatre/dataverse": "0.7.1"
|
||||
}
|
||||
|
@ -1822,6 +1823,7 @@
|
|||
"version": "0.7.1",
|
||||
"resolved": "https://registry.npmjs.org/@theatre/dataverse/-/dataverse-0.7.1.tgz",
|
||||
"integrity": "sha512-cl/uVuXQTYVfcdbBX/GYrZNNpJsvbXEwRaFHUj5zEnyLBuJMO+xCDl9bfRx6Sysdr6HcGJvFuekP0gdmTWK+bA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"lodash-es": "^4.17.21"
|
||||
}
|
||||
|
@ -1830,6 +1832,7 @@
|
|||
"version": "0.7.1",
|
||||
"resolved": "https://registry.npmjs.org/@theatre/studio/-/studio-0.7.1.tgz",
|
||||
"integrity": "sha512-e2Of4XRjbq9ytyvYuC3pqn6QYTrOt3dRLTzzUFCMAefIIqbBN/mPUVtZElTDjHbTyNZMTRupRnL9AizAK7Afzw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@theatre/dataverse": "0.7.1"
|
||||
},
|
||||
|
@ -1893,6 +1896,7 @@
|
|||
"version": "2.1.7",
|
||||
"resolved": "https://registry.npmjs.org/@threlte/theatre/-/theatre-2.1.7.tgz",
|
||||
"integrity": "sha512-VYNHsuwMKLrPcH0/gOW3FkYzPX/dXWXfedfamIt8C1DlpwfWn4c8sYdTMGyKqYah+a1hVQ1oQNu9pfTcj9c6qw==",
|
||||
"dev": true,
|
||||
"peerDependencies": {
|
||||
"@theatre/core": ">=0.6",
|
||||
"@theatre/studio": ">=0.6",
|
||||
|
@ -4957,7 +4961,8 @@
|
|||
"node_modules/lodash-es": {
|
||||
"version": "4.17.21",
|
||||
"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": {
|
||||
"version": "4.6.2",
|
||||
|
|
|
@ -17,7 +17,9 @@
|
|||
"@sveltejs/adapter-auto": "^3.0.0",
|
||||
"@sveltejs/kit": "^2.0.0",
|
||||
"@sveltejs/vite-plugin-svelte": "^3.0.0",
|
||||
"@theatre/core": "^0.7.1",
|
||||
"@theatre/studio": "^0.7.1",
|
||||
"@threlte/theatre": "^2.1.7",
|
||||
"@types/eslint": "^8.56.0",
|
||||
"@types/three": "^0.159.0",
|
||||
"@typescript-eslint/eslint-plugin": "^7.0.0",
|
||||
|
@ -40,11 +42,9 @@
|
|||
"type": "module",
|
||||
"dependencies": {
|
||||
"@dimforge/rapier3d-compat": "^0.11.2",
|
||||
"@theatre/core": "^0.7.1",
|
||||
"@threlte/core": "^7.3.0",
|
||||
"@threlte/extras": "^8.11.2",
|
||||
"@threlte/rapier": "^2.0.0",
|
||||
"@threlte/theatre": "^2.1.7",
|
||||
"three": "^0.159.0",
|
||||
"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">
|
||||
import App from '$lib/components/App.svelte'
|
||||
import Home from '$lib/components/scenes/home/Home.svelte';
|
||||
import type { PageData } from './$types';
|
||||
export let data: PageData;
|
||||
</script>
|
||||
|
@ -8,10 +8,7 @@
|
|||
{#each data.models as model}
|
||||
<span>{model.title}</span>
|
||||
{/each}
|
||||
<App />
|
||||
<canvas>
|
||||
|
||||
</canvas>
|
||||
<Home />
|
||||
</div>
|
||||
|
||||
<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