21 Sep 2024 |
3dlirious |
- Enhancements to nearly all of the operators, including
move , rotate , reflect , stretch , shear , local_taper , bend , repeat , mirror , slice , and loft . New about and align operators. Many operators now include "dot axis" shortcuts, where you can select the applicable axis or direction of the operator by by adding e.g. .x , .y or .z to the end of the operator. More examples added to the documentation.
For example, here's an infinite ladder created from only 2 cylinders, using the 'dot axis' shortcuts:
let width = 4; in
union [ cylinder {d:0.5, h:inf} >> move.x (width/2) >> mirror.x,
cylinder {d:0.25, h:width} >> rotate.y (tau/4) >> repeat.z 1 ]
This is shorter (and more readable IMO) than the equivalent:
union [ cylinder {d:0.5, h:inf} >> move [width/2, 0] >> mirror X_axis,
cylinder {d:0.25, h:width} >> rotate {axis=Y_axis, angle=tau/4} >> repeat.z 1 ]
And if you give this shape a twist, you have an infinite strand of DNA (constructed very inexpensively).
| 18:32:05 |
3dlirious | Docs:
https://codeberg.org/doug-moen/curv/src/branch/master/docs/shapes/Transformations.rst | 18:32:29 |
3dlirious | https://codeberg.org/doug-moen/curv/src/branch/master/docs/shapes/Repetition.rst | 18:32:34 |
3dlirious |
- Lots of bug fixes, and a few language enhancements as well (such as equality pattern matching). Doug's been great about squashing bugs almost as soon as I find them. This also means that you will need to recompile in order to use these new features, as some depend on these fixes.
- The project homepage has been migrated to Codeberg and is now hosted directly from within the main repository. It is also now the permanent home of the [Cheat Sheet]https://curv3d.org/cheatsheet/), which is up to date with all the latest changes, and in many cases now links directly to the shape or operator documentation. Not much else has changed on the homepage yet, but future improvements are planned.
| 18:34:35 |
3dlirious | *
- Over 40 (I lost count) new primitives, mostly 2D and mostly exact distance fields. Some are in std.curv, but most are in the new lib.shapes2d library. Shapes include stars, a moon, heart, stroke arc, and exact quadratic bezier curves! All are documented with examples.
| 18:35:39 |
3dlirious | COMING SOON!: more features are actively in development, here's a sneak peak: | 18:37:03 |
3dlirious | Download text_preview_1.png | 18:37:33 |
3dlirious | Text support | 18:37:44 |
3dlirious | Download screenshot.1718676494.png | 18:38:47 |
3dlirious | Many new blending kernels and enhancements; here's an associative blend of three shapes, with colour mixing! | 18:39:10 |
1 Oct 2024 |
3dlirious | Hmm, is there anybody out there? | 12:42:42 |
4 Oct 2024 |
3dlirious | Download screenshot.1728004611.jpg | 01:20:21 |
3dlirious | Work in progress. Anyone need a parametric pumpkin? | 01:21:43 |
krzno | In reply to @3dlirious:matrix.org Work in progress. Anyone need a parametric pumpkin? I will take s e v e n | 07:25:20 |
krzno | * I will take exactly s e v e n | 07:26:01 |
5 Oct 2024 |
3dlirious | Download screenshot.1728141585.jpg | 15:24:41 |
3dlirious | Is that a reference to the storybook? Here's another, this one is intersected with a C(D) triply periodic minimal surface (polar form). | 15:25:30 |
3dlirious | parametric dia :: slider [2,20] = 12; height :: slider [2,20] = 10; rib_width :: slider [0.1,5] = 4; centre_height :: slider [0,0.999] = 0.6; rib_num :: int_slider [10,30] = 16; in let
pumpkin {d, height, centre_height, rib_width, rib_num} = let R = d/2; dx = rib_width; c = dx/2; dz = height; b = dz/2; ctr_h = centre_height*height/2; //mz
// Find dy based on centre_height
a = R/(1 + sqrt(b*b - ctr_h*ctr_h)/b);
dy = 2*a;
my = R - a;
// Find inner radius of ribs so we can hollow the pumpkin without cutting through
angle = pi/rib_num;
tan_a = tan angle;
a2tan2 = a*a*tan_a*tan_a;
// Solve quadratic equation
qa = a2tan2 + c*c;
qb = 2*a2tan2*my;
qc = a2tan2*my*my - a*a*c*c;
ny = (-qb + sqrt(qb*qb - 4*qa*qc))/(2*qa);
ridge_inner_rad = (my + ny)/cos angle;
// Minimum wall thickness of the pumpkin.
shell_min_thickness = 0.2;
pumpkin_body = ellipsoid [dx, dy, dz]
>> colour orange //(lib.web_colour.DarkOrange)
>> move.y (-my) >> repeat_radial rib_num
;
pumpkin_inside = spheroid.exact [2*(ridge_inner_rad - shell_min_thickness),
2*(ctr_h - shell_min_thickness)]
>> colour yellow;
// Stem
stem_out_dia = 2; //outer diameter
stem_ridge_dia = stem_out_dia/2;
stem_h = 4;
stem_bend_dia = 2*stem_h;
stem_bend_ang = 50*deg;
stem = circle stem_ridge_dia >> colour (lib.web_colour.DarkGreen)
>> move.y ((stem_ridge_dia - stem_out_dia)/2)
>> repeat_radial 7
>> reflect.y
>> extrude stem_h
>> local_taper {scale:[[1, 1], [0.5, 0.5]], range:[-stem_h/2,stem_h/2]}
>> about X_axis (bend {d:stem_bend_dia, angle:stem_bend_ang})
>> rotate.x (-stem_bend_ang/2)
>> move.y (stem_bend_dia/2 + stem_out_dia/2)
>> twist 0.3
>> move.z ctr_h
// Fix bbox!
;
whole = difference2.cmix [pumpkin_body, pumpkin_inside] >> into union [stem];
in whole;
face = union [ triangle [1,1] >> move.x 1.5 >> mirror.x >> move.y 1.5, triangle [1,1], lib.shapes2d.moon {d:4, dx:1} >> rotate (pi/2) >> move.y (-0.5) ] >> colour (lib.web_colour.Goldenrod) >> extrude (dia) >> rotate.x (pi/2) >> bend {d:0, angle:55*deg} ;
// Intersection and difference with colour mixing intersection2 = let _intersection3 mix list = reduce[everything, _intersection3b mix] list; _intersection3b mix [s1,s2] = make_shape { dist p : max[s1.dist p, s2.dist p], colour p : if mix ( let d1 = s1.dist p; d2 = s2.dist p; in if (d2 <= 0 || d2 <= d1) s1.colour p else s2.colour p ) else s1.colour p, bbox : [max[s1.bbox.[MIN], s2.bbox.[MIN]], min[s1.bbox.[MAX], s2.bbox.[MAX]]], is_2d : s1.is_2d && s2.is_2d, is_3d : s1.is_3d && s2.is_3d, }; in { call : _intersection3 false, cmix : _intersection3 true, };
difference2 = let _difference2 [s1,s2] = intersection2 [s1, complement s2]; _difference2_col [s1,s2] = intersection2.cmix [s1, complement s2]; in { call : _difference2, cmix : _difference2_col, };
in
difference2.cmix [ pumpkin {d:dia, height:height, centre_height:centre_height, rib_width:rib_width, rib_num:rib_num}, face, ]
rotate (10deg) >> rotate.x (10deg) lib.utilities.face_camera //>> show_axes
| 16:41:57 |
3dlirious | * dia :: slider \[2,20\] = 12;
height :: slider \[2,20\] = 10;
rib\_width :: slider \[0.1,5\] = 4;
centre\_height :: slider \[0,0.999\] = 0.6;
rib\_num :: int\_slider \[10,30\] = 16;
in
let
pumpkin {d, height, centre\_height, rib\_width, rib\_num} =
let
R = d/2;
dx = rib\_width;
c = dx/2;
dz = height;
b = dz/2;
ctr\_h = centre\_height\*height/2; //mz
// Find dy based on centre_height
a = R/(1 + sqrt(b*b - ctr_h*ctr_h)/b);
dy = 2*a;
my = R - a;
// Find inner radius of ribs so we can hollow the pumpkin without cutting through
angle = pi/rib_num;
tan_a = tan angle;
a2tan2 = a*a*tan_a*tan_a;
// Solve quadratic equation
qa = a2tan2 + c*c;
qb = 2*a2tan2*my;
qc = a2tan2*my*my - a*a*c*c;
ny = (-qb + sqrt(qb*qb - 4*qa*qc))/(2*qa);
ridge_inner_rad = (my + ny)/cos angle;
// Minimum wall thickness of the pumpkin.
shell_min_thickness = 0.2;
pumpkin_body = ellipsoid [dx, dy, dz]
>> colour orange //(lib.web_colour.DarkOrange)
>> move.y (-my) >> repeat_radial rib_num
;
pumpkin_inside = spheroid.exact [2*(ridge_inner_rad - shell_min_thickness),
2*(ctr_h - shell_min_thickness)]
>> colour yellow;
// Stem
stem_out_dia = 2; //outer diameter
stem_ridge_dia = stem_out_dia/2;
stem_h = 4;
stem_bend_dia = 2*stem_h;
stem_bend_ang = 50*deg;
stem = circle stem_ridge_dia >> colour (lib.web_colour.DarkGreen)
>> move.y ((stem_ridge_dia - stem_out_dia)/2)
>> repeat_radial 7
>> reflect.y
>> extrude stem_h
>> local_taper {scale:[[1, 1], [0.5, 0.5]], range:[-stem_h/2,stem_h/2]}
>> about X_axis (bend {d:stem_bend_dia, angle:stem_bend_ang})
>> rotate.x (-stem_bend_ang/2)
>> move.y (stem_bend_dia/2 + stem_out_dia/2)
>> twist 0.3
>> move.z ctr_h
// Fix bbox!
;
whole = difference2.cmix [pumpkin_body, pumpkin_inside] >> into union [stem];
in whole;
face = union \[
triangle \[1,1\] >> move.x 1.5 >> mirror.x >> move.y 1.5,
triangle \[1,1\],
lib.shapes2d.moon {d:4, dx:1} >> rotate (pi/2) >> move.y (-0.5)
\]
\>> colour (lib.web\_colour.Goldenrod)
\>> extrude (dia)
\>> rotate.x (pi/2)
\>> bend {d:0, angle:55\*deg}
;
// Intersection and difference with colour mixing
intersection2 =
let
\_intersection3 mix list = reduce\[everything, \_intersection3b mix\] list;
\_intersection3b mix \[s1,s2\] =
make\_shape {
dist p : max\[s1.dist p, s2.dist p\],
colour p : if mix (
let d1 = s1.dist p;
d2 = s2.dist p;
in if (d2 \<= 0 || d2 \<= d1) s1.colour p else s2.colour p
)
else s1.colour p,
bbox : \[max\[s1.bbox.\[MIN\], s2.bbox.\[MIN\]\], min\[s1.bbox.\[MAX\], s2.bbox.\[MAX\]\]\],
is\_2d : s1.is\_2d && s2.is\_2d,
is\_3d : s1.is\_3d && s2.is\_3d,
};
in {
call : \_intersection3 false,
cmix : \_intersection3 true,
};
difference2 =
let
\_difference2 \[s1,s2\] = intersection2 \[s1, complement s2\];
\_difference2\_col \[s1,s2\] = intersection2.cmix \[s1, complement s2\];
in {
call : \_difference2,
cmix : \_difference2\_col,
};
in
difference2.cmix \[
pumpkin {d:dia, height:height, centre\_height:centre\_height, rib\_width:rib\_width, rib\_num:rib\_num},
face,
\]
> > rotate (10_deg) >> rotate.x (10_deg)
> > lib.utilities.face\_camera
> > //>> show\_axes
| 16:42:36 |
3dlirious | * dia :: slider \[2,20\] = 12;
height :: slider \[2,20\] = 10;
rib\_width :: slider \[0.1,5\] = 4;
centre\_height :: slider \[0,0.999\] = 0.6;
rib\_num :: int\_slider \[10,30\] = 16;
in
let
pumpkin {d, height, centre\_height, rib\_width, rib\_num} =
let
R = d/2;
dx = rib\_width;
c = dx/2;
dz = height;
b = dz/2;
ctr\_h = centre\_height\*height/2; //mz
// Find dy based on centre_height
a = R/(1 + sqrt(b*b - ctr_h*ctr_h)/b);
dy = 2*a;
my = R - a;
// Find inner radius of ribs so we can hollow the pumpkin without cutting through
angle = pi/rib_num;
tan_a = tan angle;
a2tan2 = a*a*tan_a*tan_a;
// Solve quadratic equation
qa = a2tan2 + c*c;
qb = 2*a2tan2*my;
qc = a2tan2*my*my - a*a*c*c;
ny = (-qb + sqrt(qb*qb - 4*qa*qc))/(2*qa);
ridge_inner_rad = (my + ny)/cos angle;
// Minimum wall thickness of the pumpkin.
shell_min_thickness = 0.2;
pumpkin_body = ellipsoid [dx, dy, dz]
>> colour orange //(lib.web_colour.DarkOrange)
>> move.y (-my) >> repeat_radial rib_num
;
pumpkin_inside = spheroid.exact [2*(ridge_inner_rad - shell_min_thickness),
2*(ctr_h - shell_min_thickness)]
>> colour yellow;
// Stem
stem_out_dia = 2; //outer diameter
stem_ridge_dia = stem_out_dia/2;
stem_h = 4;
stem_bend_dia = 2*stem_h;
stem_bend_ang = 50*deg;
stem = circle stem_ridge_dia >> colour (lib.web_colour.DarkGreen)
>> move.y ((stem_ridge_dia - stem_out_dia)/2)
>> repeat_radial 7
>> reflect.y
>> extrude stem_h
>> local_taper {scale:[[1, 1], [0.5, 0.5]], range:[-stem_h/2,stem_h/2]}
>> about X_axis (bend {d:stem_bend_dia, angle:stem_bend_ang})
>> rotate.x (-stem_bend_ang/2)
>> move.y (stem_bend_dia/2 + stem_out_dia/2)
>> twist 0.3
>> move.z ctr_h
// Fix bbox!
;
whole = difference2.cmix [pumpkin_body, pumpkin_inside] >> into union [stem];
in whole;
face = union \[
triangle \[1,1\] >> move.x 1.5 >> mirror.x >> move.y 1.5,
triangle \[1,1\],
lib.shapes2d.moon {d:4, dx:1} >> rotate (pi/2) >> move.y (-0.5)
\]
\>> colour (lib.web\_colour.Goldenrod)
\>> extrude (dia)
\>> rotate.x (pi/2)
\>> bend {d:0, angle:55\*deg}
;
// Intersection and difference with colour mixing
intersection2 =
let
\_intersection3 mix list = reduce\[everything, \_intersection3b mix\] list;
\_intersection3b mix \[s1,s2\] =
make\_shape {
dist p : max\[s1.dist p, s2.dist p\],
colour p : if mix (
let d1 = s1.dist p;
d2 = s2.dist p;
in if (d2 \<= 0 || d2 \<= d1) s1.colour p else s2.colour p
)
else s1.colour p,
bbox : \[max\[s1.bbox.\[MIN\], s2.bbox.\[MIN\]\], min\[s1.bbox.\[MAX\], s2.bbox.\[MAX\]\]\],
is\_2d : s1.is\_2d && s2.is\_2d,
is\_3d : s1.is\_3d && s2.is\_3d,
};
in {
call : \_intersection3 false,
cmix : \_intersection3 true,
};
difference2 =
let
\_difference2 \[s1,s2\] = intersection2 \[s1, complement s2\];
\_difference2\_col \[s1,s2\] = intersection2.cmix \[s1, complement s2\];
in {
call : \_difference2,
cmix : \_difference2\_col,
};
in
difference2.cmix \[
pumpkin {d:dia, height:height, centre\_height:centre\_height, rib\_width:rib\_width, rib\_num:rib\_num},
face,
\]
> > rotate (10_deg) >> rotate.x (10_deg)
> > lib.utilities.face\_camera
> > //>> show\_axes
| 16:43:15 |
3dlirious | * parametric
dia :: slider [2,20] = 12;
height :: slider [2,20] = 10;
rib_width :: slider [0.1,5] = 4;
centre_height :: slider [0,0.999] = 0.6;
rib_num :: int_slider [10,30] = 16;
in
let
pumpkin {d, height, centre_height, rib_width, rib_num} =
let
R = d/2;
dx = rib_width;
c = dx/2;
dz = height;
b = dz/2;
ctr_h = centre_height*height/2; //mz
// Find dy based on centre_height
a = R/(1 + sqrt(b*b - ctr_h*ctr_h)/b);
dy = 2*a;
my = R - a;
// Find inner radius of ribs so we can hollow the pumpkin without cutting through
angle = pi/rib_num;
tan_a = tan angle;
a2tan2 = a*a*tan_a*tan_a;
// Solve quadratic equation
qa = a2tan2 + c*c;
qb = 2*a2tan2*my;
qc = a2tan2*my*my - a*a*c*c;
ny = (-qb + sqrt(qb*qb - 4*qa*qc))/(2*qa);
ridge_inner_rad = (my + ny)/cos angle;
// Minimum wall thickness of the pumpkin.
shell_min_thickness = 0.2;
pumpkin_body = ellipsoid [dx, dy, dz]
>> colour orange //(lib.web_colour.DarkOrange)
>> move.y (-my) >> repeat_radial rib_num
;
pumpkin_inside = spheroid.exact [2*(ridge_inner_rad - shell_min_thickness),
2*(ctr_h - shell_min_thickness)]
>> colour yellow;
// Stem
stem_out_dia = 2; //outer diameter
stem_ridge_dia = stem_out_dia/2;
stem_h = 4;
stem_bend_dia = 2*stem_h;
stem_bend_ang = 50*deg;
stem = circle stem_ridge_dia >> colour (lib.web_colour.DarkGreen)
>> move.y ((stem_ridge_dia - stem_out_dia)/2)
>> repeat_radial 7
>> reflect.y
>> extrude stem_h
>> local_taper {scale:[[1, 1], [0.5, 0.5]], range:[-stem_h/2,stem_h/2]}
>> about X_axis (bend {d:stem_bend_dia, angle:stem_bend_ang})
>> rotate.x (-stem_bend_ang/2)
>> move.y (stem_bend_dia/2 + stem_out_dia/2)
>> twist 0.3
>> move.z ctr_h
// Fix bbox!
;
whole = difference2.cmix [pumpkin_body, pumpkin_inside] >> into union [stem];
in whole;
face = union [
triangle [1,1] >> move.x 1.5 >> mirror.x >> move.y 1.5,
triangle [1,1],
lib.shapes2d.moon {d:4, dx:1} >> rotate (pi/2) >> move.y (-0.5)
]
>> colour (lib.web_colour.Goldenrod)
>> extrude (dia)
>> rotate.x (pi/2)
>> bend {d:0, angle:55*deg}
;
// Intersection and difference with colour mixing
intersection2 =
let
_intersection3 mix list = reduce[everything, _intersection3b mix] list;
_intersection3b mix [s1,s2] =
make_shape {
dist p : max[s1.dist p, s2.dist p],
colour p : if mix (
let d1 = s1.dist p;
d2 = s2.dist p;
in if (d2 <= 0 || d2 <= d1) s1.colour p else s2.colour p
)
else s1.colour p,
bbox : [max[s1.bbox.[MIN], s2.bbox.[MIN]], min[s1.bbox.[MAX], s2.bbox.[MAX]]],
is_2d : s1.is_2d && s2.is_2d,
is_3d : s1.is_3d && s2.is_3d,
};
in {
call : _intersection3 false,
cmix : _intersection3 true,
};
difference2 =
let
_difference2 [s1,s2] = intersection2 [s1, complement s2];
_difference2_col [s1,s2] = intersection2.cmix [s1, complement s2];
in {
call : _difference2,
cmix : _difference2_col,
};
in
difference2.cmix [
pumpkin {d:dia, height:height, centre_height:centre_height, rib_width:rib_width, rib_num:rib_num},
face,
]
>> rotate (10*deg) >> rotate.x (10*deg)
>> lib.utilities.face_camera
//>> show_axes
| 16:44:00 |
3dlirious | Download screenshot.1728146340.jpg | 16:44:31 |
3dlirious | Still a work in progress, but figure I better go ahead and share, since it won't be October for long. | 16:59:24 |
3dlirious | Download screenshot.1728157440.jpg | 19:57:54 |
3dlirious | Seven pumpkins, fresh from the parametric patch:
row 2 [
difference2.cmix [
pumpkin {d:12, height:10, centre_height:0.6, rib_width:4, rib_num:16},
face,
] >> align.min.z,
pumpkin {d:13, height:19, centre_height:0.8, rib_width:4.2, rib_num:17} >> align.min.z,
pumpkin {d:16, height:7, centre_height:0.6, rib_width:4, rib_num:18} >> align.min.z,
pumpkin {d:14, height:10, centre_height:0.6, rib_width:4, rib_num:15} >> align.min.z,
pumpkin {d:15, height:15, centre_height:0.8, rib_width:3.5, rib_num:16} >> align.min.z,
pumpkin {d:11, height:8, centre_height:0.6, rib_width:3.5, rib_num:12} >> align.min.z,
pumpkin {d:13, height:9, centre_height:0.5, rib_width:4.2, rib_num:15} >> align.min.z,
]
| 19:58:02 |
6 Oct 2024 |
3dlirious | Download screenshot.1728218694.jpg | 12:47:20 |
3dlirious | Today's varietal is intersected with the F surface, lib.tpms.tpms_f . It reminds me of Yayoi Kusama's dotted pumpkins, and so I coloured it gold in homage. | 12:47:45 |
krzno | In reply to @3dlirious:matrix.org
Seven pumpkins, fresh from the parametric patch:
row 2 [
difference2.cmix [
pumpkin {d:12, height:10, centre_height:0.6, rib_width:4, rib_num:16},
face,
] >> align.min.z,
pumpkin {d:13, height:19, centre_height:0.8, rib_width:4.2, rib_num:17} >> align.min.z,
pumpkin {d:16, height:7, centre_height:0.6, rib_width:4, rib_num:18} >> align.min.z,
pumpkin {d:14, height:10, centre_height:0.6, rib_width:4, rib_num:15} >> align.min.z,
pumpkin {d:15, height:15, centre_height:0.8, rib_width:3.5, rib_num:16} >> align.min.z,
pumpkin {d:11, height:8, centre_height:0.6, rib_width:3.5, rib_num:12} >> align.min.z,
pumpkin {d:13, height:9, centre_height:0.5, rib_width:4.2, rib_num:15} >> align.min.z,
]
Yummy, thank | 18:23:40 |
15 Oct 2024 |
| @pedocepe:matrix.org left the room. | 08:35:04 |
4 Nov 2024 |
| Adroit joined the room. | 10:22:30 |