File size: 4,031 Bytes
6ce4ca6
 
 
 
 
 
 
 
3165745
 
6ce4ca6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
<script lang="ts">
	import { useCursor } from '@threlte/extras'
	import { T } from "@threlte/core";
	import { HTML, type IntersectionEvent } from "@threlte/extras";
	import { GLTF, useGltf } from "@threlte/extras";
	import Model from "./GPUModel.svelte";
	import { Shape, Path, ExtrudeGeometry, BoxGeometry } from "three";
	import { onMount } from "svelte";
	import type { VideoInstance } from "$lib/elements/video/VideoManager.svelte";
	import { videoManager } from "$lib/elements/video/VideoManager.svelte";

	// Props interface
	interface Props {
		// Transform props
		position?: [number, number, number];
		rotation?: [number, number, number];
		scale?: [number, number, number];
		rotating?: boolean;
	}

	// Props with defaults
	let { position = [0, 0, 0], rotation = [0, 0, 0], scale = [1, 1, 1], rotating = false }: Props = $props();

	// Create the TV frame geometry (outer rounded rectangle)
	function createTVFrame(
		tvWidth: number,
		tvHeight: number,
		tvDepth: number,
		tvFrameThickness: number,
		tvCornerRadius: number
	) {
		const shape = new Shape();
		const x = -tvWidth / 2;
		const y = -tvHeight / 2;
		const w = tvWidth;
		const h = tvHeight;
		const radius = tvCornerRadius;

		shape.moveTo(x, y + radius);
		shape.lineTo(x, y + h - radius);
		shape.quadraticCurveTo(x, y + h, x + radius, y + h);
		shape.lineTo(x + w - radius, y + h);
		shape.quadraticCurveTo(x + w, y + h, x + w, y + h - radius);
		shape.lineTo(x + w, y + radius);
		shape.quadraticCurveTo(x + w, y, x + w - radius, y);
		shape.lineTo(x + radius, y);
		shape.quadraticCurveTo(x, y, x, y + radius);

		// Create hole for screen (inner rectangle)
		const hole = new Path();
		const hx = x + tvFrameThickness;
		const hy = y + tvFrameThickness;
		const hwidth = w - tvFrameThickness * 2;
		const hheight = h - tvFrameThickness * 2;
		const hradius = tvCornerRadius * 0.5;

		hole.moveTo(hx, hy + hradius);
		hole.lineTo(hx, hy + hheight - hradius);
		hole.quadraticCurveTo(hx, hy + hheight, hx + hradius, hy + hheight);
		hole.lineTo(hx + hwidth - hradius, hy + hheight);
		hole.quadraticCurveTo(hx + hwidth, hy + hheight, hx + hwidth, hy + hheight - hradius);
		hole.lineTo(hx + hwidth, hy + hradius);
		hole.quadraticCurveTo(hx + hwidth, hy, hx + hwidth - hradius, hy);
		hole.lineTo(hx + hradius, hy);
		hole.quadraticCurveTo(hx, hy, hx, hy + hradius);

		shape.holes.push(hole);

		return new ExtrudeGeometry(shape, {
			depth: tvDepth,
			bevelEnabled: true,
			bevelThickness: 0.02,
			bevelSize: 0.02,
			bevelSegments: 8
		});
	}

	// Create the screen (video display area)
	function createScreen(tvWidth: number, tvHeight: number, tvFrameThickness: number) {
		const w = tvWidth - tvFrameThickness * 2;
		const h = tvHeight - tvFrameThickness * 2;

		// Create a very thin box for the screen area (only visible from front)
		return new BoxGeometry(w, h, 0.02);
	}

	const frameGeometry = createTVFrame(1, 1, 1, 0.2, 0.15);
	const screenGeometry = createScreen(1, 1, 0.2);

	const gltf = useGltf("/gpu/scene.gltf");

	let fan_rotation = $state(0);
	let rotationPerSeconds = $state(1); // 1 rotation per second by default
	
	onMount(() => {
		const interval = setInterval(() => {
			// Calculate angle increment per frame for desired rotations per second
			if (rotating) {
				const angleIncrement = (Math.PI * 2 * rotationPerSeconds) / 60;
				fan_rotation = fan_rotation + angleIncrement;
			}
		}, 1000/60); // Run at ~60fps

		return () => {
			clearInterval(interval);
		};
	});


</script>

<T.Group
	{position}
	{rotation}
	{scale}
>
	<!-- TV Frame -->
	<!-- <T.Mesh geometry={frameGeometry}>
		<T.MeshStandardMaterial
			color={"#374151"}
			metalness={0.05}
			roughness={0.4}
			envMapIntensity={0.3}
		/>
	</T.Mesh> -->
	<T.Group
		scale={[1, 1, 1]}
	>
		<Model fan_rotation={fan_rotation} />
	</T.Group>
	<!-- <GLTF castShadow receiveShadow gltf={$gltf} position={{ y: 1 }} scale={3} /> -->

	<!-- <T.Group scale={[1,1,1]}>
		{#if $gltf}
			<T is={$gltf.nodes['Sketchfab_model']} />
		{/if}
	</T.Group> -->
</T.Group>