Open virtualritz opened 1 year ago
This is somewhat sneaky: there is already a function named circle, and it's getting called instead of your function. In addition, it's already set up to return a lamda function, so you'd invoke it like
draw(circle(0, 0, 1)) // center x, center y, r -> (Fn(x, y) -> f32)
It works if you rename your function to not collide with the existing function:
fn length(x, y) {
sqrt(x*x + y*y)
}
fn my_circle(x, y, r) {
length(x, y) - r
}
draw(|x, y| my_circle(x, y, 1));
However, this violates the search order in the Rhai docs (and is confusing!), so let's leave this issue open.
However, this violates the search order in the Rhai docs (and is confusing!), so let's leave this issue open.
Shall I report this upstream to the rhai
peeps?
It works if you rename your function to not collide with the existing function:
fn length(x, y) { sqrt(x*x + y*y) } fn my_circle(x, y, r) { length(x, y) - r } draw(|x, y| my_circle(x, y, 1));
When I try this with viewer
in the current main
branch, I get:
❯ cargo run -- test.rhai
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.09s
Running `/home/moritz/code/crates/fidget/target/debug/viewer test.rhai`
[2024-04-09T11:58:18Z ERROR viewer] render thread got error "Rhai error: Function not found: draw (Fn) (line 9, position 1)"; forwarding
[...]
Ah, I see, it doesn't take a closure any more. Sorry about the noise, kindly ignore!
Docs say there is a draw_rgb
function in Rhai but I get an error when trying to call this. Also: what's the signature of this function?
Yes, #67 switched to using the new Tree
type in scripts (instead of closures).
The new signature is draw_rgb(Tree, f32, f32, f32)
, e.g. this works for me:
draw_rgb(circle(0, 1, 2), 1.0, 0.0, 0.0)
Cheers, it was a typo.
Is there a list of built-ins somewhere? It seems e.g. Rhai is missing e.g. abs
? Docs say one needs to include ArithmeticPackage but the docs also say Engine::new()
would include that. What am I missing?
I can not get a simple box in the viewer. Whatever function I try, except for the circle, I only get the positive part of the axes, i.e.
fn abs(x) {
if x < 0 {
-x
} else {
x
}
}
fn box(x, y, radius_x, radius_y)
{
let p_x = abs(x) - radius_x;
let p_y = abs(y) - radius_y;
max(p_x, p_y)
}
draw(box(x, y, 1, 1))
I get:
Zooming out:
I also tried move(box(...),...)
but no luck. What am I missing?
Here's the issue:
fn abs(x) {
if x < 0 {
-x
} else {
x
}
}
During script evaluation, x
is a Tree
handle. Normally, trees capture operations through operator overloading, e.g. x + 1
will return a new Tree
. For some reason, Rhai comparisons of different types always return false
, so x < 0
is evaluated during script evaluation and returns a new Tree
that is always -x
.
fn box(radius_x, radius_y)
{
let ax = axes();
let p_x = abs(ax.x) - radius_x;
let p_y = abs(ax.y) - radius_y;
max(p_x, p_y)
}
draw(box(1, 1))
(I'm still figuring out best practices, but using axes()
within a function seems cleaner than passing x, y
as arguments)
(I'm still figuring out best practices, but using axes() within a function seems cleaner than passing x, y as arguments)
Speaking of which: writing the functions in Rhai, doing each operation for each coordinate, is very verbose because of the lack of tuple types. Most functions from e.g. here almost double in code length. For 3D cases it will be even more verbose.
What is the performance hit if one used arrays of two (or three) elements to represent vectors?
Of course then one would need to write the entire shebang of basics like mul
, add
, div
etc. that work on those arrays.
And the code of the kind of expressions used in SDFs would still look more like Lisp than math. :grin:.
I.e. best would probably be some language extension that supports vectors (and possible matrices) inside Rhai? Not sure this possible.
EDIT: I just saw this, so it seems this is possible and likely axes()
does something like this already?
https://github.com/mkeeter/fidget/pull/70 (merging soon) adds overloaded operators to ban these comparisons, so that it will fail at script evaluation instead of returning a misleading result. This PR also adds missing opcodes, [...]
Cheers! :smiley:
So I have something like:
fn rounded_box(
height_x, height_y,
radius_top_right,
radius_bottom_right,
radius_top_left,
radius_bottom_left)
{
let ax = axes();
let x = ax.x;
let y = ax.y;
let r_x = if 0.0 < x { radius_top_right } else { radius_top_left };
let r_y = if 0.0 < x { radius_bottom_right } else { radius_bottom_left };
let r_x = if 0.0 < y { r_x } else { r_y };
let q_x = abs(x)- height_x + r_x;
let q_y = abs(y)- height_y + r_x;
min(max(q_x, q_y), 0) + length(max(q_x, 0.0), max(q_y, 0)) - r_x
}
And that gives me an error for the comparisons in the if a < b
s:
cannot compare Tree types during function tracing
I tried rewriting the resp. expressions with compare(a, b)
but this:
let r_x = if compare(0, x) == -1 { radius_top_right } else { radius_top_left };
let r_y = if compare(0, x) == -1 { radius_bottom_right } else { radius_bottom_left };
let r_x = if compare(0, y) == -1 { r_x } else { r_y };
results in the same error.
What is the workaround here?
EDIT: thinking back of my days as a VFX shader writer (where conditionals were a no-no): step()
/filteredstep()
would be the alternative(s). And re. the latter: will there be access to filter size(s)/derivatives?
And another one. A simple rounding op, i.e.
fn round(shape, radius) {
shape - radius
}
Only grows my shape by radius
but there is no rounding. This is obviously somehow possible as visible in the viewer for the gradient 2D SDF
view mode.
What am I missing/what is the workaround?
So I just started playing around with the
viewer
.This Rhai script
works as expected.
However
Yields: