153 lines
3.7 KiB
Svelte
153 lines
3.7 KiB
Svelte
<script lang="ts">
|
|
import { Canvas } from "@threlte/core";
|
|
import Scene from "./Scene.svelte";
|
|
import {
|
|
BufferGeometry,
|
|
Float32BufferAttribute,
|
|
PerspectiveCamera,
|
|
Vector3,
|
|
} from "three";
|
|
import { decodeFloat } from "@nodes/utils";
|
|
import type { OrbitControls } from "three/examples/jsm/Addons.js";
|
|
|
|
export let result: Int32Array;
|
|
|
|
export let camera: PerspectiveCamera;
|
|
export let controls: OrbitControls;
|
|
export let center: Vector3;
|
|
|
|
let geometries: BufferGeometry[] = [];
|
|
let lines: Vector3[][] = [];
|
|
|
|
function createGeometryFromEncodedData(
|
|
encodedData: Int32Array,
|
|
): BufferGeometry {
|
|
const geometry = new BufferGeometry();
|
|
|
|
// Extract data from the encoded array
|
|
let index = 0;
|
|
const geometryType = encodedData[index++];
|
|
const vertexCount = encodedData[index++];
|
|
const faceCount = encodedData[index++];
|
|
|
|
// Indices
|
|
const indicesEnd = index + faceCount * 3;
|
|
const indices = encodedData.subarray(index, indicesEnd);
|
|
index = indicesEnd;
|
|
|
|
// Vertices
|
|
const vertices = new Float32Array(
|
|
encodedData.buffer,
|
|
index * 4,
|
|
vertexCount * 3,
|
|
);
|
|
index = index + vertexCount * 3;
|
|
|
|
const normals = new Float32Array(
|
|
encodedData.buffer,
|
|
index * 4,
|
|
vertexCount * 3,
|
|
);
|
|
index = index + vertexCount * 3;
|
|
|
|
// Add data to geometry
|
|
geometry.setIndex([...indices]);
|
|
geometry.setAttribute("position", new Float32BufferAttribute(vertices, 3));
|
|
geometry.setAttribute("normal", new Float32BufferAttribute(normals, 3));
|
|
geometry.computeVertexNormals();
|
|
|
|
return geometry;
|
|
}
|
|
|
|
function parse_args(input: Int32Array) {
|
|
let index = 0;
|
|
const length = input.length;
|
|
let res: Int32Array[] = [];
|
|
|
|
let nextBracketIndex = 0;
|
|
let argStartIndex = 0;
|
|
let depth = -1;
|
|
|
|
while (index < length) {
|
|
const value = input[index];
|
|
|
|
if (index === nextBracketIndex) {
|
|
nextBracketIndex = index + input[index + 1] + 1;
|
|
if (value === 0) {
|
|
depth++;
|
|
} else {
|
|
depth--;
|
|
}
|
|
|
|
if (depth === 1 && value === 0) {
|
|
// if opening bracket
|
|
argStartIndex = index + 2;
|
|
}
|
|
|
|
if (depth === 0 && value === 1) {
|
|
// if closing bracket
|
|
res.push(input.slice(argStartIndex, index));
|
|
argStartIndex = index + 2;
|
|
}
|
|
|
|
index = nextBracketIndex;
|
|
continue;
|
|
}
|
|
|
|
// we should not be here
|
|
|
|
index++;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
function createLineGeometryFromEncodedData(encodedData: Int32Array) {
|
|
const positions: Vector3[] = [];
|
|
|
|
const amount = (encodedData.length - 1) / 4;
|
|
|
|
for (let i = 0; i < amount; i++) {
|
|
const x = decodeFloat(encodedData[1 + i * 4 + 0]);
|
|
const y = decodeFloat(encodedData[1 + i * 4 + 1]);
|
|
const z = decodeFloat(encodedData[1 + i * 4 + 2]);
|
|
positions.push(new Vector3(x, y, z));
|
|
}
|
|
|
|
return positions;
|
|
}
|
|
|
|
$: if (result) {
|
|
const inputs = parse_args(result);
|
|
|
|
lines = inputs
|
|
.map((input) => {
|
|
if (input[0] === 0) {
|
|
return createLineGeometryFromEncodedData(input);
|
|
}
|
|
})
|
|
.filter(Boolean) as Vector3[][];
|
|
|
|
center = new Vector3();
|
|
|
|
geometries = inputs
|
|
.map((input) => {
|
|
if (input[0] === 1) {
|
|
const geo = createGeometryFromEncodedData(input);
|
|
geo?.computeBoundingSphere();
|
|
if (geo.boundingSphere) {
|
|
center.add(geo.boundingSphere.center);
|
|
}
|
|
return geo;
|
|
}
|
|
})
|
|
.filter(Boolean) as BufferGeometry[];
|
|
|
|
center = center.divideScalar(geometries.length);
|
|
}
|
|
</script>
|
|
|
|
<Canvas>
|
|
<Scene bind:camera bind:controls {geometries} {lines} />
|
|
</Canvas>
|