feat: yyyess, got extrude_path working

This commit is contained in:
max_richter 2024-04-23 17:26:05 +02:00
parent 3af7ebb672
commit 6ea4afa012
11 changed files with 105 additions and 65 deletions

View File

@ -6,13 +6,12 @@
import { OrbitControls } from "@threlte/extras"; import { OrbitControls } from "@threlte/extras";
import { AppSettings } from "../settings/app-settings"; import { AppSettings } from "../settings/app-settings";
import localStore from "$lib/helpers/localStore"; import localStore from "$lib/helpers/localStore";
import { onMount } from "svelte";
export let geometries: BufferGeometry[]; export let geometries: BufferGeometry[];
export let lines: Vector3[][]; export let lines: Vector3[][];
let camera: PerspectiveCamera; export let camera: PerspectiveCamera;
let controls: OrbitControlsType; export let controls: OrbitControlsType;
const cameraTransform = localStore<{ camera: number[]; target: number[] }>( const cameraTransform = localStore<{ camera: number[]; target: number[] }>(
"nodes.camera.transform", "nodes.camera.transform",

View File

@ -1,11 +1,21 @@
<script lang="ts"> <script lang="ts">
import { Canvas } from "@threlte/core"; import { Canvas } from "@threlte/core";
import Scene from "./Scene.svelte"; import Scene from "./Scene.svelte";
import { BufferGeometry, Float32BufferAttribute, Vector3 } from "three"; import {
BufferGeometry,
Float32BufferAttribute,
PerspectiveCamera,
Vector3,
} from "three";
import { decodeFloat } from "@nodes/utils"; import { decodeFloat } from "@nodes/utils";
import type { OrbitControls } from "three/examples/jsm/Addons.js";
export let result: Int32Array; export let result: Int32Array;
export let camera: PerspectiveCamera;
export let controls: OrbitControls;
export let center: Vector3;
let geometries: BufferGeometry[] = []; let geometries: BufferGeometry[] = [];
let lines: Vector3[][] = []; let lines: Vector3[][] = [];
@ -92,8 +102,6 @@
return res; return res;
} }
globalThis.parse_args = parse_args;
function createLineGeometryFromEncodedData(encodedData: Int32Array) { function createLineGeometryFromEncodedData(encodedData: Int32Array) {
const positions: Vector3[] = []; const positions: Vector3[] = [];
@ -120,19 +128,25 @@
}) })
.filter(Boolean) as Vector3[][]; .filter(Boolean) as Vector3[][];
center = new Vector3();
geometries = inputs geometries = inputs
.map((input) => { .map((input) => {
if (input[0] === 1) { if (input[0] === 1) {
const geo = createGeometryFromEncodedData(input); const geo = createGeometryFromEncodedData(input);
geo?.computeBoundingSphere();
if (geo.boundingSphere) {
center.add(geo.boundingSphere.center);
}
return geo; return geo;
} }
}) })
.filter(Boolean) as BufferGeometry[]; .filter(Boolean) as BufferGeometry[];
console.log(lines); center = center.divideScalar(geometries.length);
} }
</script> </script>
<Canvas> <Canvas>
<Scene {geometries} {lines} /> <Scene bind:camera bind:controls {geometries} {lines} />
</Canvas> </Canvas>

View File

@ -34,6 +34,11 @@ export const AppSettingTypes = {
label: "Show Grid", label: "Show Grid",
value: true, value: true,
}, },
centerCamera: {
type: "boolean",
label: "Center Camera",
value: true
},
nodeInterface: { nodeInterface: {
__title: "Node Interface", __title: "Node Interface",
showNodeGrid: { showNodeGrid: {

View File

@ -15,6 +15,9 @@
import type { GraphManager } from "$lib/graph-interface/graph-manager"; import type { GraphManager } from "$lib/graph-interface/graph-manager";
import { setContext } from "svelte"; import { setContext } from "svelte";
import { decodeNestedArray, encodeNestedArray } from "@nodes/utils"; import { decodeNestedArray, encodeNestedArray } from "@nodes/utils";
import type { PerspectiveCamera, Vector3 } from "three";
import type { OrbitControls } from "three/examples/jsm/Addons.js";
import GraphView from "$lib/graph-interface/graph/GraphView.svelte";
const nodeRegistry = new RemoteNodeRegistry(""); const nodeRegistry = new RemoteNodeRegistry("");
const runtimeExecutor = new MemoryRuntimeExecutor(nodeRegistry); const runtimeExecutor = new MemoryRuntimeExecutor(nodeRegistry);
@ -23,6 +26,9 @@
globalThis.encode = encodeNestedArray; globalThis.encode = encodeNestedArray;
let res: Int32Array; let res: Int32Array;
let viewerCamera: PerspectiveCamera;
let viewerControls: OrbitControls;
let viewerCenter: Vector3;
let graph = localStorage.getItem("graph") let graph = localStorage.getItem("graph")
? JSON.parse(localStorage.getItem("graph")!) ? JSON.parse(localStorage.getItem("graph")!)
@ -38,6 +44,11 @@
function handleResult(event: CustomEvent<Graph>) { function handleResult(event: CustomEvent<Graph>) {
res = runtimeExecutor.execute(event.detail, get(settings?.graph?.settings)); res = runtimeExecutor.execute(event.detail, get(settings?.graph?.settings));
if ($AppSettings.centerCamera && viewerCamera && viewerCenter) {
viewerControls.target.copy(viewerCenter);
viewerControls.update();
}
} }
function handleSave(event: CustomEvent<Graph>) { function handleSave(event: CustomEvent<Graph>) {
@ -117,7 +128,12 @@
<header></header> <header></header>
<Grid.Row> <Grid.Row>
<Grid.Cell> <Grid.Cell>
<Viewer result={res} /> <Viewer
bind:controls={viewerControls}
bind:center={viewerCenter}
bind:camera={viewerCamera}
result={res}
/>
</Grid.Cell> </Grid.Cell>
<Grid.Cell> <Grid.Cell>
{#key graph} {#key graph}

View File

@ -19,6 +19,12 @@
}, },
"seed": { "seed": {
"type": "seed" "type": "seed"
},
"fixBottom": {
"type": "float",
"hidden": true,
"min": 0,
"max": 1
} }
} }
} }

View File

@ -12,6 +12,7 @@ pub fn execute(input: &[i32]) -> Vec<i32> {
set_panic_hook(); set_panic_hook();
let args = get_args(input); let args = get_args(input);
let plants = get_args(args[0]); let plants = get_args(args[0]);
let scale = evaluate_float(args[1]); let scale = evaluate_float(args[1]);
let strength = evaluate_float(args[2]); let strength = evaluate_float(args[2]);
@ -32,8 +33,8 @@ pub fn execute(input: &[i32]) -> Vec<i32> {
let a = i as f64 / (points - 1) as f64; let a = i as f64 / (points - 1) as f64;
let px = Vector2::new(0.0, a * scale as f64); let px = Vector2::new(0.0, a * scale as f64);
let pz = Vector2::new(a * scale as f64, 0.0); let pz = Vector2::new(a * scale as f64, 0.0);
let nx = open_simplex_2d(px, &hasher) as f32 * strength * 0.1; let nx = open_simplex_2d(px, &hasher) as f32 * strength * 0.1 * a as f32;
let nz = open_simplex_2d(pz, &hasher) as f32 * strength * 0.1; let nz = open_simplex_2d(pz, &hasher) as f32 * strength * 0.1 * a as f32;
plant[3 + i * 4] = encode_float(decode_float(plant[3 + i * 4]) + nx); plant[3 + i * 4] = encode_float(decode_float(plant[3 + i * 4]) + nx);
plant[5 + i * 4] = encode_float(decode_float(plant[5 + i * 4]) + nz); plant[5 + i * 4] = encode_float(decode_float(plant[5 + i * 4]) + nz);
} }

View File

@ -1,10 +1,5 @@
use glam::{Mat4, Vec3};
use macros::include_definition_file; use macros::include_definition_file;
use utils::{ use utils::{concat_args, evaluate_int, geometry::extrude_path, get_args, log};
concat_args, evaluate_int,
geometry::{extrude_path, transform_geometry},
get_args, log,
};
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
include_definition_file!("src/inputs.json"); include_definition_file!("src/inputs.json");

View File

@ -86,6 +86,8 @@ pub struct DefaultOptions {
pub setting: Option<String>, pub setting: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub label: Option<serde_json::Value>, // To handle both String and false pub label: Option<serde_json::Value>, // To handle both String and false
#[serde(skip_serializing_if = "Option::is_none")]
pub hidden: Option<bool>,
} }
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]

View File

@ -1,5 +1,7 @@
use crate::log;
use super::{create_geometry_data, wrap_geometry_data}; use super::{create_geometry_data, wrap_geometry_data};
use glam::{Mat4, Quat, Vec3}; use glam::{Mat4, Vec3};
fn create_circle(res: usize) -> Vec<f32> { fn create_circle(res: usize) -> Vec<f32> {
let angle = (2.0 * std::f32::consts::PI) / res as f32; let angle = (2.0 * std::f32::consts::PI) / res as f32;
@ -11,7 +13,6 @@ fn create_circle(res: usize) -> Vec<f32> {
circle circle
} }
#[rustfmt::skip]
pub fn extrude_path(input_path: &[i32], res_x: usize) -> Vec<i32> { pub fn extrude_path(input_path: &[i32], res_x: usize) -> Vec<i32> {
let point_amount = input_path.len() / 4; let point_amount = input_path.len() / 4;
let face_amount = (point_amount - 1) * res_x * 2; let face_amount = (point_amount - 1) * res_x * 2;
@ -33,35 +34,45 @@ pub fn extrude_path(input_path: &[i32], res_x: usize) -> Vec<i32> {
} }
for i in 0..point_amount { for i in 0..point_amount {
let index_offset = i * res_x * 6; let index_offset = i * res_x * 6;
let position_offset = i * res_x; let position_offset = i * res_x;
let point = Vec3::from_slice(&path[i*4..i*4+3]); let pos = Vec3::new(path[i * 4], path[i * 4 + 1], path[i * 4 + 2]);
let thickness = path[i * 4 + 3]; let thickness = path[i * 4 + 3];
let next_point = if i == point_amount - 1 { point } else { Vec3::from_slice(&path[(i+1)*4..(i+1)*4+3]) };
let prev_point = if i == 0 { point } else { Vec3::from_slice(&path[(i-1)*4..(i-1)*4+3]) };
let mut v = if i == 0 { // Get direction of the current segment
point - next_point let segment_dir = (if i == 0 {
Vec3::new(
pos[0] - path[i * 4 + 4],
pos[1] - path[i * 4 + 5],
pos[2] - path[i * 4 + 6],
)
} else if i == point_amount - 1 { } else if i == point_amount - 1 {
prev_point - point Vec3::new(
path[i * 4 - 4] - pos[0],
path[i * 4 - 3] - pos[1],
path[i * 4 - 2] - pos[2],
)
} else { } else {
prev_point - next_point Vec3::new(
}; path[i * 4 - 4] - path[i * 4 + 4],
v = v.normalize(); path[i * 4 - 3] - path[i * 4 + 5],
path[i * 4 - 2] - path[i * 4 + 6],
)
})
.normalize();
let n = Vec3::new(0.0, -1.0, 0.0); // Assuming 'n' is the up vector or similar // In our case the up vector is always the Y axis
let axis = n.cross(v); let up_vector = Vec3::NEG_Y;
let angle = n.dot(v).acos();
let quat = Quat::from_axis_angle(axis, angle).normalize(); let binormal = up_vector.cross(segment_dir);
let mat = Mat4::IDENTITY * Mat4::from_quat(quat);
let rotation_angle = up_vector.dot(segment_dir).acos();
let rotation_matrix = Mat4::from_axis_angle(binormal, rotation_angle);
for j in 0..res_x { for j in 0..res_x {
if i < point_amount - 1 { if i < point_amount - 1 {
let i_index_offset = index_offset + j * 6; let i_index_offset = index_offset + j * 6;
let i_position_offset = position_offset + j; let i_position_offset = position_offset + j;
@ -71,6 +82,7 @@ pub fn extrude_path(input_path: &[i32], res_x: usize) -> Vec<i32> {
indices[i_index_offset] = (i_position_offset + 1) as i32; indices[i_index_offset] = (i_position_offset + 1) as i32;
indices[i_index_offset + 1] = (i_position_offset + 1 - res_x) as i32; indices[i_index_offset + 1] = (i_position_offset + 1 - res_x) as i32;
indices[i_index_offset + 2] = (i_position_offset) as i32; indices[i_index_offset + 2] = (i_position_offset) as i32;
indices[i_index_offset + 3] = (i_position_offset) as i32; indices[i_index_offset + 3] = (i_position_offset) as i32;
indices[i_index_offset + 4] = (i_position_offset + res_x) as i32; indices[i_index_offset + 4] = (i_position_offset + res_x) as i32;
indices[i_index_offset + 5] = (i_position_offset + 1) as i32; indices[i_index_offset + 5] = (i_position_offset + 1) as i32;
@ -78,6 +90,7 @@ pub fn extrude_path(input_path: &[i32], res_x: usize) -> Vec<i32> {
indices[i_index_offset] = (i_position_offset + res_x + 1) as i32; indices[i_index_offset] = (i_position_offset + res_x + 1) as i32;
indices[i_index_offset + 1] = (i_position_offset + 1) as i32; indices[i_index_offset + 1] = (i_position_offset + 1) as i32;
indices[i_index_offset + 2] = (i_position_offset) as i32; indices[i_index_offset + 2] = (i_position_offset) as i32;
indices[i_index_offset + 3] = (i_position_offset) as i32; indices[i_index_offset + 3] = (i_position_offset) as i32;
indices[i_index_offset + 4] = (i_position_offset + res_x) as i32; indices[i_index_offset + 4] = (i_position_offset + res_x) as i32;
indices[i_index_offset + 5] = (i_position_offset + res_x + 1) as i32; indices[i_index_offset + 5] = (i_position_offset + res_x + 1) as i32;
@ -88,23 +101,20 @@ pub fn extrude_path(input_path: &[i32], res_x: usize) -> Vec<i32> {
let idx = i * res_x * 3 + j * 3; let idx = i * res_x * 3 + j * 3;
let circle_x = circle[j * 2] * thickness; let circle_x = circle[j * 2] * thickness;
let circle_y = circle[j * 2 + 1] * thickness; let circle_z = circle[j * 2 + 1] * thickness;
let _pt = Vec3::new( let point = rotation_matrix.transform_point3(Vec3::new(circle_x, 0.0, circle_z)) + pos;
point[0] + circle_x, let normal = rotation_matrix
point[1], .transform_vector3(Vec3::new(circle_x, 0.0, circle_z))
point[2] + circle_y, .normalize();
);
let pt = Mat4::transform_vector3(&mat, _pt) + point; normals[idx] = normal[0];
normals[idx + 1] = normal[1];
normals[idx + 2] = normal[2];
normals[idx ] = circle_x; positions[idx] = point[0];
normals[idx + 1] = 0.0; positions[idx + 1] = point[1];
normals[idx + 2] = circle_y; positions[idx + 2] = point[2];
positions[idx ] = pt[0];
positions[idx + 1] = pt[1];
positions[idx + 2] = pt[2];
} }
} }

View File

@ -1,7 +1,7 @@
use utils::get_args; use utils::get_args;
#[rustfmt::skip] #[rustfmt::skip]
fn main() { fn test_split_args(){
let inputs = vec![ let inputs = vec![
vec![0, 1, 0, 4, 1056964608, 1065353216, 1056964608, 1, 4, 1080872141, 1054951342, 32, 1, 1 ], vec![0, 1, 0, 4, 1056964608, 1065353216, 1056964608, 1, 4, 1080872141, 1054951342, 32, 1, 1 ],
vec![0, 4, 1056964608, 1065353216, 1056964608, 1, 4], vec![0, 4, 1056964608, 1065353216, 1056964608, 1, 4],
@ -14,5 +14,6 @@ fn main() {
for input in inputs { for input in inputs {
println!("RESULT: {:?}", get_args(&input)); println!("RESULT: {:?}", get_args(&input));
} }
} }
fn main() {}

View File

@ -192,15 +192,6 @@ mod tests {
1053609165, 54, 1053609165, 54,
]; ];
// this should be the output
/* [
[ 0, 28, 0, 2, 1048576000, 0, 20, 0, 4, 0, 0, 1073741824, 0, 9, 0, 5, 0, 0, 1073741824, 1073741824, 1, 1, 1, 0, 1, 1, 1, 4, 1041865114 ],
1086324736,
1053609165,
54
] */
let args = get_args(&input); let args = get_args(&input);
println!("{:?}", args[0]); println!("{:?}", args[0]);