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 { AppSettings } from "../settings/app-settings";
import localStore from "$lib/helpers/localStore";
import { onMount } from "svelte";
export let geometries: BufferGeometry[];
export let lines: Vector3[][];
let camera: PerspectiveCamera;
let controls: OrbitControlsType;
export let camera: PerspectiveCamera;
export let controls: OrbitControlsType;
const cameraTransform = localStore<{ camera: number[]; target: number[] }>(
"nodes.camera.transform",

View File

@ -1,11 +1,21 @@
<script lang="ts">
import { Canvas } from "@threlte/core";
import Scene from "./Scene.svelte";
import { BufferGeometry, Float32BufferAttribute, Vector3 } from "three";
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[][] = [];
@ -92,8 +102,6 @@
return res;
}
globalThis.parse_args = parse_args;
function createLineGeometryFromEncodedData(encodedData: Int32Array) {
const positions: Vector3[] = [];
@ -120,19 +128,25 @@
})
.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[];
console.log(lines);
center = center.divideScalar(geometries.length);
}
</script>
<Canvas>
<Scene {geometries} {lines} />
<Scene bind:camera bind:controls {geometries} {lines} />
</Canvas>

View File

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

View File

@ -15,6 +15,9 @@
import type { GraphManager } from "$lib/graph-interface/graph-manager";
import { setContext } from "svelte";
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 runtimeExecutor = new MemoryRuntimeExecutor(nodeRegistry);
@ -23,6 +26,9 @@
globalThis.encode = encodeNestedArray;
let res: Int32Array;
let viewerCamera: PerspectiveCamera;
let viewerControls: OrbitControls;
let viewerCenter: Vector3;
let graph = localStorage.getItem("graph")
? JSON.parse(localStorage.getItem("graph")!)
@ -38,6 +44,11 @@
function handleResult(event: CustomEvent<Graph>) {
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>) {
@ -117,7 +128,12 @@
<header></header>
<Grid.Row>
<Grid.Cell>
<Viewer result={res} />
<Viewer
bind:controls={viewerControls}
bind:center={viewerCenter}
bind:camera={viewerCamera}
result={res}
/>
</Grid.Cell>
<Grid.Cell>
{#key graph}

View File

@ -19,6 +19,12 @@
},
"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();
let args = get_args(input);
let plants = get_args(args[0]);
let scale = evaluate_float(args[1]);
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 px = Vector2::new(0.0, a * scale as f64);
let pz = Vector2::new(a * scale as f64, 0.0);
let nx = open_simplex_2d(px, &hasher) as f32 * strength * 0.1;
let nz = open_simplex_2d(pz, &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 * a as f32;
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);
}

View File

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

View File

@ -86,6 +86,8 @@ pub struct DefaultOptions {
pub setting: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
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)]

View File

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

View File

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

View File

@ -192,15 +192,6 @@ mod tests {
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);
println!("{:?}", args[0]);