File size: 3,370 Bytes
6ce4ca6
 
3cdf7b9
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
<script lang="ts">
	import { T } from "@threlte/core";
	import { useGltf } from "@threlte/extras";
	import Model from "./GPUModel.svelte";
	import { Shape, Path, ExtrudeGeometry, BoxGeometry } from "three";
	import { onMount } from "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}
>
	<T.Group
		scale={[1, 1, 1]}
	>
		<Model fan_rotation={fan_rotation} />
	</T.Group>
</T.Group>