mirror of
https://github.com/revarbat/BOSL2.git
synced 2025-08-16 23:14:10 +02:00
add vnf_vertex_array() module
texture code cleanup doc fixes
This commit is contained in:
@@ -3475,6 +3475,35 @@ Access to the derivative smoothing parameter?
|
|||||||
// attach(RIGHT,"root")
|
// attach(RIGHT,"root")
|
||||||
// join_prism(circle(r=8,$fn=32),
|
// join_prism(circle(r=8,$fn=32),
|
||||||
// l=10, base="plane", fillet=4);
|
// l=10, base="plane", fillet=4);
|
||||||
|
// Example(3D,NoScales,VPR=[47.3,0,14.5],VPT=[-2.8467,-2.05938,-10.6999],VPD=220): Two join_prism objects are placed on the parent cylinder using anchors, and then their descriptions are used to contruct a curved handle with a bezier.
|
||||||
|
// $fs=.5; $fa=4;
|
||||||
|
// vspace=25;
|
||||||
|
// bezlen=40;
|
||||||
|
// cylr=20;
|
||||||
|
// straightlen=10;
|
||||||
|
// circ = circle(r=6);
|
||||||
|
// cyl(r=cylr,h=50, rounding=3)
|
||||||
|
// let(cyl=parent())
|
||||||
|
// down(vspace/2)
|
||||||
|
// attach(RIGHT+FWD, "root", spin=90)
|
||||||
|
// join_prism(circ, base="cyl", base_r=20, height=straightlen, fillet=4)
|
||||||
|
// let(base1=parent())
|
||||||
|
// restore(cyl)
|
||||||
|
// up(vspace/2)
|
||||||
|
// attach(LEFT+FWD, "root", spin=90)
|
||||||
|
// join_prism(circ, base="cyl", base_r=20, height=straightlen, fillet=4)
|
||||||
|
// let(base2=parent())
|
||||||
|
// let(
|
||||||
|
// avg_dir = desc_dir(base1,anchor=TOP)+desc_dir(base2,anchor=TOP),
|
||||||
|
// bez=[
|
||||||
|
// desc_point(base1,anchor=TOP),
|
||||||
|
// desc_point(base1,anchor=TOP)+bezlen*desc_dir(base1,anchor=TOP),
|
||||||
|
// (cylr+straightlen+bezlen)*avg_dir,
|
||||||
|
// desc_point(base2,anchor=TOP)+bezlen*desc_dir(base2,anchor=TOP),
|
||||||
|
// desc_point(base2,anchor=TOP)]
|
||||||
|
// )
|
||||||
|
// path_sweep(circ,bezier_curve(bez,40));
|
||||||
|
|
||||||
module join_prism(polygon, base, base_r, base_d, base_T=IDENT,
|
module join_prism(polygon, base, base_r, base_d, base_T=IDENT,
|
||||||
scale=1, prism_end_T=IDENT, short=false,
|
scale=1, prism_end_T=IDENT, short=false,
|
||||||
length, l, height, h,
|
length, l, height, h,
|
||||||
@@ -4045,6 +4074,9 @@ function _prism_fillet_prism(name, basepoly, bot, top, d, k, N, overlap, uniform
|
|||||||
// n = number of facets to use for the fillets. Default: 15
|
// n = number of facets to use for the fillets. Default: 15
|
||||||
// n1 = number of facets at object1
|
// n1 = number of facets at object1
|
||||||
// n2 = number of facets at object2
|
// n2 = number of facets at object2
|
||||||
|
// fillet = fillet for both ends of the prism. Default: 0
|
||||||
|
// fillet1 = fillet for the joint at object1
|
||||||
|
// fillet2 = fillet for the joint at object2
|
||||||
// k = fillet curvature parameter for both ends. Default: 0.7
|
// k = fillet curvature parameter for both ends. Default: 0.7
|
||||||
// k1 = fillet curvature parameter at object1
|
// k1 = fillet curvature parameter at object1
|
||||||
// k2 = fillet curvature parameter at object2
|
// k2 = fillet curvature parameter at object2
|
||||||
@@ -4513,8 +4545,8 @@ module prism_connector(profile, desc1, anchor1, desc2, anchor2, shift1=0, shift2
|
|||||||
smooth_normals, smooth_normals1, smooth_normals2,
|
smooth_normals, smooth_normals1, smooth_normals2,
|
||||||
debug=false, debug_pos=false)
|
debug=false, debug_pos=false)
|
||||||
{
|
{
|
||||||
base_fillet = default(fillet1,fillet);
|
base_fillet = first_defined([fillet1,fillet,0]);
|
||||||
aux_fillet = default(fillet2,fillet);
|
aux_fillet = first_defined([fillet2,fillet,0]);
|
||||||
|
|
||||||
base_overlap = first_defined([overlap1,overlap,1]);
|
base_overlap = first_defined([overlap1,overlap,1]);
|
||||||
aux_overlap = first_defined([overlap2,overlap,1]);
|
aux_overlap = first_defined([overlap2,overlap,1]);
|
||||||
|
@@ -1218,12 +1218,12 @@ function regular_prism(n,
|
|||||||
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
|
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
|
||||||
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
|
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
|
||||||
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
|
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
|
||||||
// Example(3D,NoScale,VPT=[-0.257402,0.467403,-0.648606],VPR=[46.6,0,16.6],VPD=29.2405): Basic textured tile
|
// Example(3D,NoScales,VPT=[-0.257402,0.467403,-0.648606],VPR=[46.6,0,16.6],VPD=29.2405): Basic textured tile
|
||||||
// textured_tile("trunc_diamonds", 10, tex_reps=[5,5]);
|
// textured_tile("trunc_diamonds", 10, tex_reps=[5,5]);
|
||||||
// Example(3D,NoScale,VPT=[-0.0852782,0.259593,0.139667],VPR=[58.5,0,345.1],VPD=36.0994): Attaching a tile to a cube
|
// Example(3D,NoAxes,VPT=[-0.0852782,0.259593,0.139667],VPR=[58.5,0,345.1],VPD=36.0994): Attaching a tile to a cube
|
||||||
// cuboid([12,12,4]) attach(TOP,BOT)
|
// cuboid([12,12,4]) attach(TOP,BOT)
|
||||||
// textured_tile("trunc_pyramids", 10, tex_reps=[5,5], style="convex");
|
// textured_tile("trunc_pyramids", 10, tex_reps=[5,5], style="convex");
|
||||||
// Example(3D,NoScale,VPT = [-0.0788193, 0.10015, -0.0938629], VPR = [57.8, 0, 34.1], VPD = 29.2405): This inset texture doesn't look obviously different, but you can see that the object is below the XY plane.
|
// Example(3D,NoScales,VPT = [-0.0788193, 0.10015, -0.0938629], VPR = [57.8, 0, 34.1], VPD = 29.2405): This inset texture doesn't look obviously different, but you can see that the object is below the XY plane.
|
||||||
// textured_tile("trunc_pyramids_vnf", 10, tex_reps=[5,5], tex_inset=true);
|
// textured_tile("trunc_pyramids_vnf", 10, tex_reps=[5,5], tex_inset=true);
|
||||||
// Example(3D,NoAxes,VPT=[0.242444,0.170054,-0.0714754],VPR=[67.6,0,33.4],VPD=36.0994): Here we use the `diff` option combined with {{diff()}} to attach the inset texture to the front of a parent cuboid.
|
// Example(3D,NoAxes,VPT=[0.242444,0.170054,-0.0714754],VPR=[67.6,0,33.4],VPD=36.0994): Here we use the `diff` option combined with {{diff()}} to attach the inset texture to the front of a parent cuboid.
|
||||||
// diff()
|
// diff()
|
||||||
@@ -1233,17 +1233,17 @@ function regular_prism(n,
|
|||||||
// Example(3D,NoAxes,VPT=[5.86588,-0.107082,-0.311155],VPR=[17.2,0,9.6],VPD=32.4895): Tile shaped like a rhombic prism
|
// Example(3D,NoAxes,VPT=[5.86588,-0.107082,-0.311155],VPR=[17.2,0,9.6],VPD=32.4895): Tile shaped like a rhombic prism
|
||||||
// textured_tile("ribs", w1=10, w2=10, shift=4,ysize=7);
|
// textured_tile("ribs", w1=10, w2=10, shift=4,ysize=7);
|
||||||
// Example(3D,NoAxes,VPT=[-0.487417,-0.398897,-0.143258],VPR=[10.2,0,12.4],VPD=26.3165): A tile shaped like a trapezoidal prism. Note that trapezoidal tiles will always distort the texture, resulting in curves
|
// Example(3D,NoAxes,VPT=[-0.487417,-0.398897,-0.143258],VPR=[10.2,0,12.4],VPD=26.3165): A tile shaped like a trapezoidal prism. Note that trapezoidal tiles will always distort the texture, resulting in curves
|
||||||
// textured_tile("diamonds", w1=10, w2=7, ysize=7) show_anchors(2);
|
// textured_tile("diamonds", w1=10, w2=7, ysize=7);
|
||||||
// Example(3D,NoAxes,VPT=[-0.0889877,-0.31974,0.554444],VPR=[22.1,0,22.2],VPD=32.4895): An inset trapezoidal tile placed into a cube
|
// Example(3D,NoAxes,VPT=[-0.0889877,-0.31974,0.554444],VPR=[22.1,0,22.2],VPD=32.4895): An inset trapezoidal tile placed into a cube
|
||||||
// diff()cuboid([10,10,2])
|
// diff()cuboid([10,10,2])
|
||||||
// attach(TOP,BOT)
|
// attach(TOP,BOT)
|
||||||
// textured_tile("trunc_diamonds", tex_reps=[5,5], tex_inset=true,
|
// textured_tile("trunc_diamonds", tex_reps=[5,5], tex_inset=true,
|
||||||
// w1=8, w2=4, ysize=8, diff=true);
|
// w1=8, w2=4, ysize=8, diff=true);
|
||||||
// Example(3D,NoScales,VPT=[-0.0889877,-0.31974,0.554444],VPR=[58.5,0,21.5],VPD=32.4895): This example shows what happens if you set `extra` to zero for the "pyramids" texture. Note that the texture doesn't finish. The default of `extra=1` produces the correct result.
|
// Example(3D,NoAxes,VPT=[-0.0889877,-0.31974,0.554444],VPR=[58.5,0,21.5],VPD=32.4895): This example shows what happens if you set `extra` to zero for the "pyramids" texture. Note that the texture doesn't finish. The default of `extra=1` produces the correct result.
|
||||||
// textured_tile("pyramids", 10, tex_reps=[5,5], extra=0);
|
// textured_tile("pyramids", 10, tex_reps=[5,5], extra=0);
|
||||||
// Example(3D,NoScales,VPT=[-0.212176,-0.651766,0.124004],VPR=[58.5,0,21.5],VPD=29.2405): This texture has an asymmetry even with the default `extra=1`.
|
// Example(3D,NoAxes,VPT=[-0.212176,-0.651766,0.124004],VPR=[58.5,0,21.5],VPD=29.2405): This texture has an asymmetry even with the default `extra=1`.
|
||||||
// textured_tile("trunc_ribs", 10, tex_reps=[5,2]);
|
// textured_tile("trunc_ribs", 10, tex_reps=[5,1]);
|
||||||
// Example(3D,NoScales,VPT=[-0.212176,-0.651766,0.124004],VPR=[58.5,0,21.5],VPD=29.2405): It could be fixed by setting `extra=2`, which would place an extra flat strip on the right. But another option is to use the `skip` parameter to trim the flat part from the left. Note that we are also skipping in the y direction, but it doesn't make a difference for this texture, except that you need to have enough texture tiles to accommodate the skip. You can also set `skip` to a vector.
|
// Example(3D,NoAxes,VPT=[-0.212176,-0.651766,0.124004],VPR=[58.5,0,21.5],VPD=29.2405): It could be fixed by setting `extra=2`, which would place an extra flat strip on the right. But another option is to use the `skip` parameter to trim the flat part from the left. Note that we are also skipping in the y direction, but it doesn't make a difference for this texture, except that you need to have enough texture tiles to accommodate the skip, so we increased the Y reps value to 2. You can also set `skip` to a vector.
|
||||||
// textured_tile("trunc_ribs", 10, tex_reps=[5,2], skip=1);
|
// textured_tile("trunc_ribs", 10, tex_reps=[5,2], skip=1);
|
||||||
|
|
||||||
|
|
||||||
|
156
skin.scad
156
skin.scad
@@ -651,7 +651,7 @@ function skin(profiles, slices, refine=1, method="direct", sampling, caps, close
|
|||||||
// linear_sweep(path, texture=tex, tex_size=[5,5], h=40);
|
// linear_sweep(path, texture=tex, tex_size=[5,5], h=40);
|
||||||
// Example: Textured with twist and scale.
|
// Example: Textured with twist and scale.
|
||||||
// linear_sweep(regular_ngon(n=3, d=50),
|
// linear_sweep(regular_ngon(n=3, d=50),
|
||||||
// texture="rough", h=100, tex_depth=2,
|
// texture="rough", h=100, tex_depth=.4,
|
||||||
// tex_size=[20,20], style="min_edge",
|
// tex_size=[20,20], style="min_edge",
|
||||||
// convexity=10, scale=0.2, twist=120);
|
// convexity=10, scale=0.2, twist=120);
|
||||||
// Example: As Function
|
// Example: As Function
|
||||||
@@ -717,7 +717,7 @@ function skin(profiles, slices, refine=1, method="direct", sampling, caps, close
|
|||||||
// [24, 25, 35, 33], [33, 35, 34], [24, 33, 6, 31], [34, 35, 11, 7],
|
// [24, 25, 35, 33], [33, 35, 34], [24, 33, 6, 31], [34, 35, 11, 7],
|
||||||
// [35, 25, 32, 11], [30, 32, 25, 23]]
|
// [35, 25, 32, 11], [30, 32, 25, 23]]
|
||||||
// ];
|
// ];
|
||||||
// front_half(y=3){
|
// front_half(y=33){
|
||||||
// cyl(d=14.5,h=1,anchor=BOT,rounding=1/3,$fa=1,$fs=.5);
|
// cyl(d=14.5,h=1,anchor=BOT,rounding=1/3,$fa=1,$fs=.5);
|
||||||
// linear_sweep(circle(d=12), h=12, scale=1.3, texture=diag_weave_vnf,
|
// linear_sweep(circle(d=12), h=12, scale=1.3, texture=diag_weave_vnf,
|
||||||
// tex_size=[5,5], convexity=12);
|
// tex_size=[5,5], convexity=12);
|
||||||
@@ -1041,7 +1041,7 @@ function linear_sweep(
|
|||||||
// path = [for(y=[-30:30]) [ 20-3*(1-cos((y+30)/60*360)),y]];
|
// path = [for(y=[-30:30]) [ 20-3*(1-cos((y+30)/60*360)),y]];
|
||||||
// rotate_sweep(path, closed=false, texture=tile, tex_rot=90,
|
// rotate_sweep(path, closed=false, texture=tile, tex_rot=90,
|
||||||
// tex_size=[12,8], tex_depth=9, angle=360);
|
// tex_size=[12,8], tex_depth=9, angle=360);
|
||||||
// Example(3D,Med,NoAxes: A basket weave texture, here only half way around the circle to avoid clutter.
|
// Example(3D,Med,NoAxes,VPR=[78.1,0,199.3],VPT=[-4.55445,1.37814,-4.39897],VPD=192.044): A basket weave texture, here only half way around the circle to avoid clutter.
|
||||||
// diag_weave_vnf = [
|
// diag_weave_vnf = [
|
||||||
// [[0.2, 0, 0], [0.8, 0, 0], [1, 0.2, 0.5], [1, 0.8, 0.5], [0.7, 0.5, 0.5],
|
// [[0.2, 0, 0], [0.8, 0, 0], [1, 0.2, 0.5], [1, 0.8, 0.5], [0.7, 0.5, 0.5],
|
||||||
// [0.5, 0.3, 0], [0.2, 0, 0.5], [0.8, 0, 0.5], [1, 0.2, 1], [1, 0.8, 1],
|
// [0.5, 0.3, 0], [0.2, 0, 0.5], [0.8, 0, 0.5], [1, 0.2, 1], [1, 0.8, 1],
|
||||||
@@ -4016,7 +4016,6 @@ function _validate_texture(texture) =
|
|||||||
min_xy = point2d(bounds[0]),
|
min_xy = point2d(bounds[0]),
|
||||||
max_xy = point2d(bounds[1])
|
max_xy = point2d(bounds[1])
|
||||||
)
|
)
|
||||||
//assert(min_xy==[0,0] && max_xy==[1,1],"VNF tiles must span exactly from [0,0] to [1,1] in the X and Y components."))
|
|
||||||
assert(all_nonnegative(concat(min_xy,[1,1]-max_xy)), "VNF tile X and Y components must be between 0 and 1.")
|
assert(all_nonnegative(concat(min_xy,[1,1]-max_xy)), "VNF tile X and Y components must be between 0 and 1.")
|
||||||
let(
|
let(
|
||||||
verts = texture[0],
|
verts = texture[0],
|
||||||
@@ -4059,8 +4058,8 @@ function _textured_linear_sweep(
|
|||||||
frac = pos-ind,
|
frac = pos-ind,
|
||||||
texh = scale<0 ? -(1-tilez - inset) * scale
|
texh = scale<0 ? -(1-tilez - inset) * scale
|
||||||
: (tilez - inset) * scale,
|
: (tilez - inset) * scale,
|
||||||
base = lerp(bases[ind], select(bases,ind+1), frac),
|
base = lerp(select(bases,ind), select(bases,ind+1), frac),
|
||||||
norm = unit(lerp(norms[ind], select(norms,ind+1), frac))
|
norm = unit(lerp(select(norms,ind), select(norms,ind+1), frac))
|
||||||
)
|
)
|
||||||
base + norm * texh,
|
base + norm * texh,
|
||||||
|
|
||||||
@@ -4083,38 +4082,36 @@ function _textured_linear_sweep(
|
|||||||
samples = !is_vnf(texture)? len(texture[0]) :
|
samples = !is_vnf(texture)? len(texture[0]) :
|
||||||
is_num(samples)? samples : 8,
|
is_num(samples)? samples : 8,
|
||||||
check_tex = _validate_texture(texture),
|
check_tex = _validate_texture(texture),
|
||||||
sorted_tile =
|
vnf_tile =
|
||||||
!is_vnf(texture)? texture :
|
!is_vnf(texture) || samples==1 ? texture
|
||||||
|
:
|
||||||
let(
|
let(
|
||||||
s = 1 / max(1, samples),
|
s = 1 / max(1, samples),
|
||||||
vnf = samples<=1? texture :
|
slice_us = list([s:s:1-s/2]),
|
||||||
let(
|
vnft1 = vnf_slice(texture, "X", slice_us),
|
||||||
slice_us = list([s:s:1-s/2]),
|
vnft = twist? vnf_slice(vnft1, "Y", slice_us) : vnft1,
|
||||||
vnft1 = vnf_slice(texture, "X", slice_us),
|
zvnf = [
|
||||||
vnft = twist? vnf_slice(vnft1, "Y", slice_us) : vnft1,
|
[
|
||||||
zvnf = [
|
for (p=vnft[0]) [
|
||||||
[
|
|
||||||
for (p=vnft[0]) [
|
|
||||||
approx(p.x,0)? 0 : approx(p.x,1)? 1 : p.x,
|
approx(p.x,0)? 0 : approx(p.x,1)? 1 : p.x,
|
||||||
approx(p.y,0)? 0 : approx(p.y,1)? 1 : p.y,
|
approx(p.y,0)? 0 : approx(p.y,1)? 1 : p.y,
|
||||||
p.z
|
p.z
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
vnft[1]
|
vnft[1]
|
||||||
]
|
]
|
||||||
) zvnf
|
) zvnf,
|
||||||
) _vnf_sort_vertices(vnf, idx=[1,0]),
|
edge_paths = is_vnf(texture) ? _tile_edge_path_list(vnf_tile,1) : undef,
|
||||||
vertzs = !is_vnf(sorted_tile)? undef :
|
|
||||||
group_sort(sorted_tile[0], idx=1),
|
|
||||||
edge_paths = is_vnf(sorted_tile) ? _tile_edge_path_list(sorted_tile,1) : undef,
|
|
||||||
tpath = is_def(edge_paths)
|
tpath = is_def(edge_paths)
|
||||||
? len(edge_paths[0])==0 ? [] : hstack([column(edge_paths[0][0],0), column(edge_paths[0][0],2)])
|
? len(edge_paths[0])==0 ? [] : hstack([column(edge_paths[0][0],0), column(edge_paths[0][0],2)])
|
||||||
: let(
|
: let(
|
||||||
row = sorted_tile[0],
|
row = texture[0],
|
||||||
rlen = len(row)
|
rlen = len(row)
|
||||||
) [for (i = [0:1:rlen]) [i/rlen, row[i%rlen]]],
|
) [for (i = [0:1:rlen]) [i/rlen, row[i%rlen]]],
|
||||||
edge_closed_paths = is_def(edge_paths) ? edge_paths[1] : [],
|
edge_closed_paths = is_def(edge_paths) ? edge_paths[1] : [],
|
||||||
tmat = scale(scale) * zrot(twist) * up(h/2),
|
tmat = scale(scale) * zrot(twist) * up(h/2),
|
||||||
|
texcnt = is_vnf(texture) ? undef
|
||||||
|
: [len(texture[0]), len(texture)],
|
||||||
pre_skew_vnf = vnf_join([
|
pre_skew_vnf = vnf_join([
|
||||||
for (rgn = regions) let(
|
for (rgn = regions) let(
|
||||||
walls_vnf = vnf_join([
|
walls_vnf = vnf_join([
|
||||||
@@ -4125,19 +4122,16 @@ function _textured_linear_sweep(
|
|||||||
is_vector(tex_size,2)
|
is_vector(tex_size,2)
|
||||||
? [round(plen/tex_size.x), max(1,round(h/tex_size.y)), ]
|
? [round(plen/tex_size.x), max(1,round(h/tex_size.y)), ]
|
||||||
: [ceil(6*plen/h), 6],
|
: [ceil(6*plen/h), 6],
|
||||||
obases = resample_path(path, n=counts.x * samples, closed=true),
|
bases = resample_path(path, n=counts.x * samples, closed=true),
|
||||||
onorms = path_normals(obases, closed=true),
|
norms = path_normals(bases, closed=true),
|
||||||
bases = list_wrap(obases),
|
|
||||||
norms = list_wrap(onorms),
|
|
||||||
vnf = is_vnf(texture)
|
vnf = is_vnf(texture)
|
||||||
? vnf_join( // VNF tile texture
|
? vnf_join( // VNF tile texture
|
||||||
let(
|
let(
|
||||||
row_vnf = vnf_join([
|
row_vnf = vnf_join([
|
||||||
for (i = [0:1:(scale==1?0:counts.y-1)], j = [0:1:counts.x-1]) [
|
for (i = [0:1:(scale==1?0:counts.y-1)], j = [0:1:counts.x-1]) [
|
||||||
[
|
[
|
||||||
for (group = vertzs)
|
for (vert=vnf_tile[0])
|
||||||
each [
|
let(
|
||||||
for (vert = group) let(
|
|
||||||
xy = transform_pt(j,vert.x,vert.z,samples, inset, tex_scale, bases, norms),
|
xy = transform_pt(j,vert.x,vert.z,samples, inset, tex_scale, bases, norms),
|
||||||
pt = point3d(xy,vert.y),
|
pt = point3d(xy,vert.y),
|
||||||
v = vert.y / counts.y,
|
v = vert.y / counts.y,
|
||||||
@@ -4149,9 +4143,8 @@ function _textured_linear_sweep(
|
|||||||
zrot(twist*(v+vv)) *
|
zrot(twist*(v+vv)) *
|
||||||
zscale(h/counts.y)
|
zscale(h/counts.y)
|
||||||
) apply(mat, pt)
|
) apply(mat, pt)
|
||||||
]
|
|
||||||
],
|
],
|
||||||
sorted_tile[1]
|
vnf_tile[1]
|
||||||
]
|
]
|
||||||
])
|
])
|
||||||
) [
|
) [
|
||||||
@@ -4168,7 +4161,6 @@ function _textured_linear_sweep(
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
: let( // Heightfield texture
|
: let( // Heightfield texture
|
||||||
texcnt = [len(texture[0]), len(texture)],
|
|
||||||
tile_rows = [
|
tile_rows = [
|
||||||
for (ti = [0:1:texcnt.y-1])
|
for (ti = [0:1:texcnt.y-1])
|
||||||
path3d([
|
path3d([
|
||||||
@@ -4204,10 +4196,8 @@ function _textured_linear_sweep(
|
|||||||
is_vector(tex_size,2)
|
is_vector(tex_size,2)
|
||||||
? [round(plen/tex_size.x), max(1,round(h/tex_size.y)), ]
|
? [round(plen/tex_size.x), max(1,round(h/tex_size.y)), ]
|
||||||
: [ceil(6*plen/h), 6],
|
: [ceil(6*plen/h), 6],
|
||||||
obases = resample_path(path, n=counts.x * samples, closed=true),
|
bases = resample_path(path, n=counts.x * samples, closed=true),
|
||||||
onorms = path_normals(obases, closed=true),
|
norms = path_normals(bases, closed=true),
|
||||||
bases = list_wrap(obases),
|
|
||||||
norms = list_wrap(onorms),
|
|
||||||
nupath = [
|
nupath = [
|
||||||
for (j = [0:1:counts.x-1], vert = tpath)
|
for (j = [0:1:counts.x-1], vert = tpath)
|
||||||
transform_pt(j,vert.x,vert.y,samples,inset,tex_scale,bases,norms)
|
transform_pt(j,vert.x,vert.y,samples,inset,tex_scale,bases,norms)
|
||||||
@@ -4224,10 +4214,8 @@ function _textured_linear_sweep(
|
|||||||
is_vector(tex_size,2)
|
is_vector(tex_size,2)
|
||||||
? [round(plen/tex_size.x), max(1,round(h/tex_size.y)), ]
|
? [round(plen/tex_size.x), max(1,round(h/tex_size.y)), ]
|
||||||
: [ceil(6*plen/h), 6],
|
: [ceil(6*plen/h), 6],
|
||||||
obases = resample_path(path, n=counts.x * samples, closed=true),
|
bases = resample_path(path, n=counts.x * samples, closed=true),
|
||||||
onorms = path_normals(obases, closed=true),
|
norms = path_normals(bases, closed=true),
|
||||||
bases = list_wrap(obases),
|
|
||||||
norms = list_wrap(onorms),
|
|
||||||
modpaths = [for (j = [0:1:counts.x-1], cpath = edge_closed_paths)
|
modpaths = [for (j = [0:1:counts.x-1], cpath = edge_closed_paths)
|
||||||
[for(vert = cpath)
|
[for(vert = cpath)
|
||||||
transform_pt(j,vert.x,vert.z,samples,inset,tex_scale,bases, norms)]
|
transform_pt(j,vert.x,vert.z,samples,inset,tex_scale,bases, norms)]
|
||||||
@@ -4382,28 +4370,24 @@ function _textured_revolution(
|
|||||||
maxy = bounds[1].y,
|
maxy = bounds[1].y,
|
||||||
h = maxy - miny,
|
h = maxy - miny,
|
||||||
circumf = 2 * PI * maxx,
|
circumf = 2 * PI * maxx,
|
||||||
tile = !is_vnf(texture)? texture :
|
tile = !is_vnf(texture) || samples==1 ? texture :
|
||||||
let(
|
let(
|
||||||
utex = samples<=1? texture :
|
s = 1 / samples,
|
||||||
let(
|
slices = list([s : s : 1-s/2]),
|
||||||
s = 1 / samples,
|
vnfx = vnf_slice(texture, "X", slices),
|
||||||
slices = list([s : s : 1-s/2]),
|
vnfy = inhibit_y_slicing? vnfx : vnf_slice(vnfx, "Y", slices),
|
||||||
vnfx = vnf_slice(texture, "X", slices),
|
vnft = vnf_triangulate(vnfy),
|
||||||
vnfy = inhibit_y_slicing? vnfx : vnf_slice(vnfx, "Y", slices),
|
zvnf = [
|
||||||
vnft = vnf_triangulate(vnfy),
|
[
|
||||||
zvnf = [
|
for (p=vnft[0]) [
|
||||||
[
|
approx(p.x,0)? 0 : approx(p.x,1)? 1 : p.x,
|
||||||
for (p=vnft[0]) [
|
approx(p.y,0)? 0 : approx(p.y,1)? 1 : p.y,
|
||||||
approx(p.x,0)? 0 : approx(p.x,1)? 1 : p.x,
|
p.z
|
||||||
approx(p.y,0)? 0 : approx(p.y,1)? 1 : p.y,
|
|
||||||
p.z
|
|
||||||
]
|
|
||||||
],
|
|
||||||
vnft[1]
|
|
||||||
]
|
]
|
||||||
) zvnf
|
],
|
||||||
) _vnf_sort_vertices(utex, idx=[0,1]),
|
vnft[1]
|
||||||
vertzs = is_vnf(texture)? group_sort(tile[0], idx=0) : undef,
|
]
|
||||||
|
) zvnf,
|
||||||
edge_paths = is_vnf(tile) ? _tile_edge_path_list(tile,1) : undef,
|
edge_paths = is_vnf(tile) ? _tile_edge_path_list(tile,1) : undef,
|
||||||
bpath = is_def(edge_paths)
|
bpath = is_def(edge_paths)
|
||||||
? len(edge_paths[0])==0 ? [] : hstack([column(edge_paths[0][0],0), column(edge_paths[0][0],2)])
|
? len(edge_paths[0])==0 ? [] : hstack([column(edge_paths[0][0],0), column(edge_paths[0][0],2)])
|
||||||
@@ -4436,8 +4420,8 @@ function _textured_revolution(
|
|||||||
part = tileind * samples,
|
part = tileind * samples,
|
||||||
ind = floor(part),
|
ind = floor(part),
|
||||||
frac = part - ind,
|
frac = part - ind,
|
||||||
base = lerp(bases[ind], select(bases,ind+1), frac),
|
base = lerp(select(bases,ind), select(bases,ind+1), frac),
|
||||||
norm = unit(lerp(norms[ind], select(norms,ind+1), frac)),
|
norm = unit(lerp(select(norms,ind), select(norms,ind+1), frac)),
|
||||||
scale = tex_scale * lookup(tileind/counts_y, taper_lup) * base.x/maxx,
|
scale = tex_scale * lookup(tileind/counts_y, taper_lup) * base.x/maxx,
|
||||||
texh = scale<0 ? -(1-tilez - inset) * scale
|
texh = scale<0 ? -(1-tilez - inset) * scale
|
||||||
: (tilez - inset) * scale
|
: (tilez - inset) * scale
|
||||||
@@ -4452,26 +4436,21 @@ function _textured_revolution(
|
|||||||
is_vector(tex_size,2)? max(1,round(plen/tex_size.y)) : 6,
|
is_vector(tex_size,2)? max(1,round(plen/tex_size.y)) : 6,
|
||||||
obases = resample_path(path, n=counts_y * samples + (closed?0:1), closed=closed),
|
obases = resample_path(path, n=counts_y * samples + (closed?0:1), closed=closed),
|
||||||
onorms = path_normals(obases, closed=closed),
|
onorms = path_normals(obases, closed=closed),
|
||||||
rbases = closed? list_wrap(obases) : obases,
|
bases = xrot(90, p=path3d(obases)),
|
||||||
rnorms = closed? list_wrap(onorms) : onorms,
|
norms = xrot(90, p=path3d(onorms)),
|
||||||
bases = xrot(90, p=path3d(rbases)),
|
|
||||||
norms = xrot(90, p=path3d(rnorms)),
|
|
||||||
vnf = is_vnf(texture)
|
vnf = is_vnf(texture)
|
||||||
? vnf_join([ // VNF tile texture
|
? vnf_join([ // VNF tile texture
|
||||||
for (j = [0:1:counts_y-1])
|
for (j = [0:1:counts_y-1])
|
||||||
[
|
[
|
||||||
[
|
[
|
||||||
for (group = vertzs) each [
|
for (vert = tile[0])
|
||||||
for (vert = group)
|
|
||||||
let(xyz = transform_point(j + (1-vert.y),vert.z,counts_y,bases, norms))
|
let(xyz = transform_point(j + (1-vert.y),vert.z,counts_y,bases, norms))
|
||||||
zrot(vert.x*angle/counts_x, p=xyz)
|
zrot(vert.x*angle/counts_x, p=xyz)
|
||||||
]
|
|
||||||
],
|
],
|
||||||
tile[1]
|
tile[1]
|
||||||
]
|
]
|
||||||
])
|
])
|
||||||
: let( // Heightfield texture
|
: let( // Heightfield texture
|
||||||
texcnt = [len(texture[0]), len(texture)],
|
|
||||||
tiles = transpose([
|
tiles = transpose([
|
||||||
for (j = [0,1], tj = [0:1:texcnt.x-1])
|
for (j = [0,1], tj = [0:1:texcnt.x-1])
|
||||||
if (j == 0 || tj == 0)
|
if (j == 0 || tj == 0)
|
||||||
@@ -4502,23 +4481,18 @@ function _textured_revolution(
|
|||||||
plen = path_length(path, closed=closed),
|
plen = path_length(path, closed=closed),
|
||||||
counts_y = is_vector(counts,2)? counts.y :
|
counts_y = is_vector(counts,2)? counts.y :
|
||||||
is_vector(tex_size,2)? max(1,round(plen/tex_size.y)) : 6,
|
is_vector(tex_size,2)? max(1,round(plen/tex_size.y)) : 6,
|
||||||
obases = resample_path(path, n=counts_y * samples + (closed?0:1), closed=closed),
|
bases = resample_path(path, n=counts_y * samples + (closed?0:1), closed=closed),
|
||||||
onorms = path_normals(obases, closed=closed),
|
norms = path_normals(bases, closed=closed),
|
||||||
bases = closed? list_wrap(obases) : obases,
|
|
||||||
norms = closed? list_wrap(onorms) : onorms,
|
|
||||||
ppath = is_vnf(texture)
|
ppath = is_vnf(texture)
|
||||||
? [ // VNF tile texture
|
? [ // VNF tile texture
|
||||||
for (j = [0:1:counts_y-1])
|
for (j = [0:1:counts_y-1], vert=side_open_path)
|
||||||
//for (group = vertzs, vert = reverse(group))
|
|
||||||
for(vert=side_open_path)
|
|
||||||
transform_point(j + (1 - vert.y),vert.z,counts_y,bases, norms)
|
transform_point(j + (1 - vert.y),vert.z,counts_y,bases, norms)
|
||||||
]
|
]
|
||||||
: let( // Heightfield texture
|
:
|
||||||
texcnt = [len(texture[0]), len(texture)]
|
[ // Heightfield texture
|
||||||
) [
|
|
||||||
for (i = [0:1:counts_y-(closed?1:0)], ti = [0:1:texcnt.y-1])
|
for (i = [0:1:counts_y-(closed?1:0)], ti = [0:1:texcnt.y-1])
|
||||||
if (i != counts_y || ti == 0)
|
if (i != counts_y || ti == 0)
|
||||||
transform_point(i + (ti/texcnt.y),texture[ti][0],counts_y,bases, norms)
|
transform_point(i + (ti/texcnt.y),texture[ti][0],counts_y,bases, norms)
|
||||||
],
|
],
|
||||||
path = closed? ppath : [
|
path = closed? ppath : [
|
||||||
[0, ppath[0].y],
|
[0, ppath[0].y],
|
||||||
@@ -4534,10 +4508,8 @@ function _textured_revolution(
|
|||||||
plen = path_length(path, closed=closed),
|
plen = path_length(path, closed=closed),
|
||||||
counts_y = is_vector(counts,2)? counts.y :
|
counts_y = is_vector(counts,2)? counts.y :
|
||||||
is_vector(tex_size,2)? max(1,round(plen/tex_size.y)) : 6,
|
is_vector(tex_size,2)? max(1,round(plen/tex_size.y)) : 6,
|
||||||
obases = resample_path(path, n=counts_y * samples + (closed?0:1), closed=closed),
|
bases = resample_path(path, n=counts_y * samples + (closed?0:1), closed=closed),
|
||||||
onorms = path_normals(obases, closed=closed),
|
norms = path_normals(bases, closed=closed),
|
||||||
bases = closed? list_wrap(obases) : obases,
|
|
||||||
norms = closed? list_wrap(onorms) : onorms,
|
|
||||||
modpaths = [for (j = [0:1:counts_y-1], cpath=side_closed_paths)
|
modpaths = [for (j = [0:1:counts_y-1], cpath=side_closed_paths)
|
||||||
[for(vert=cpath)
|
[for(vert=cpath)
|
||||||
transform_point(j + (1 - vert.y),vert.z,counts_y,bases, norms)]
|
transform_point(j + (1 - vert.y),vert.z,counts_y,bases, norms)]
|
||||||
@@ -4557,10 +4529,8 @@ function _textured_revolution(
|
|||||||
is_vector(tex_size,2)? max(1,round(plen/tex_size.y)) : 6,
|
is_vector(tex_size,2)? max(1,round(plen/tex_size.y)) : 6,
|
||||||
obases = resample_path(rgn[0], n=counts_y * samples + (closed?0:1), closed=closed),
|
obases = resample_path(rgn[0], n=counts_y * samples + (closed?0:1), closed=closed),
|
||||||
onorms = path_normals(obases, closed=closed),
|
onorms = path_normals(obases, closed=closed),
|
||||||
rbases = closed? list_wrap(obases) : obases,
|
bases = xrot(90, p=path3d(obases)),
|
||||||
rnorms = closed? list_wrap(onorms) : onorms,
|
norms = xrot(90, p=path3d(onorms)),
|
||||||
bases = xrot(90, p=path3d(rbases)),
|
|
||||||
norms = xrot(90, p=path3d(rnorms)),
|
|
||||||
caps_vnf = vnf_join([
|
caps_vnf = vnf_join([
|
||||||
for (epath=edge_closed_paths, j = [-1,0])
|
for (epath=edge_closed_paths, j = [-1,0])
|
||||||
let(
|
let(
|
||||||
|
47
vnf.scad
47
vnf.scad
@@ -27,13 +27,14 @@
|
|||||||
EMPTY_VNF = [[],[]]; // The standard empty VNF with no vertices or faces.
|
EMPTY_VNF = [[],[]]; // The standard empty VNF with no vertices or faces.
|
||||||
|
|
||||||
|
|
||||||
// Function: vnf_vertex_array()
|
// Function&Module: vnf_vertex_array()
|
||||||
// Synopsis: Returns a VNF structure from a rectangular vertex list.
|
// Synopsis: Returns a VNF structure from a rectangular vertex list.
|
||||||
// SynTags: VNF
|
// SynTags: VNF, Geom
|
||||||
// Topics: VNF Generators, Lists
|
// Topics: VNF Generators, Lists
|
||||||
// See Also: vnf_tri_array(), vnf_join(), vnf_from_polygons(), vnf_from_region()
|
// See Also: vnf_tri_array(), vnf_join(), vnf_from_polygons(), vnf_from_region()
|
||||||
// Usage:
|
// Usage:
|
||||||
// vnf = vnf_vertex_array(points, [caps=], [cap1=], [cap2=], [style=], [reverse=], [col_wrap=], [row_wrap=], [triangulate=]);
|
// vnf = vnf_vertex_array(points, [caps=], [cap1=], [cap2=], [style=], [reverse=], [col_wrap=], [row_wrap=], [triangulate=]);
|
||||||
|
// vnf_vertex_array(points, [caps=], [cap1=], [cap2=], [style=], [reverse=], [col_wrap=], [row_wrap=], [triangulate=],...) [ATTACHMENTS];
|
||||||
// Description:
|
// Description:
|
||||||
// Creates a VNF structure from a rectangular vertex list, creating edges that connect the adjacent vertices in the vertex list
|
// Creates a VNF structure from a rectangular vertex list, creating edges that connect the adjacent vertices in the vertex list
|
||||||
// and creating the faces defined by those edges. You can optionally create the edges and faces to wrap the last column
|
// and creating the faces defined by those edges. You can optionally create the edges and faces to wrap the last column
|
||||||
@@ -58,6 +59,17 @@ EMPTY_VNF = [[],[]]; // The standard empty VNF with no vertices or faces.
|
|||||||
// reverse = If true, reverse all face normals.
|
// reverse = If true, reverse all face normals.
|
||||||
// style = The style of subdividing the quads into faces. Valid options are "default", "alt", "flip1", "flip2", "min_edge", "min_area", "quincunx", "convex" and "concave".
|
// style = The style of subdividing the quads into faces. Valid options are "default", "alt", "flip1", "flip2", "min_edge", "min_area", "quincunx", "convex" and "concave".
|
||||||
// triangulate = If true, triangulates endcaps to resolve possible CGAL issues. This can be an expensive operation if the endcaps are complex. Default: false
|
// triangulate = If true, triangulates endcaps to resolve possible CGAL issues. This can be an expensive operation if the endcaps are complex. Default: false
|
||||||
|
// convexity = (module) Max number of times a line could intersect a wall of the shape.
|
||||||
|
// cp = (module) Centerpoint for determining intersection anchors or centering the shape. Determines the base of the anchor vector. Can be "centroid", "mean", "box" or a 3D point. Default: "centroid"
|
||||||
|
// anchor = (module) Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `"origin"`
|
||||||
|
// spin = (module) Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
|
||||||
|
// orient = (module) Vector to rotate top toward, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
|
||||||
|
// atype = (module) Select "hull" or "intersect" anchor type. Default: "hull"
|
||||||
|
// Anchor Types:
|
||||||
|
// "hull" = Anchors to the virtual convex hull of the shape.
|
||||||
|
// "intersect" = Anchors to the surface of the shape.
|
||||||
|
// Named Anchors:
|
||||||
|
// "origin" = Anchor at the origin, oriented UP.
|
||||||
// Example(3D):
|
// Example(3D):
|
||||||
// vnf = vnf_vertex_array(
|
// vnf = vnf_vertex_array(
|
||||||
// points=[
|
// points=[
|
||||||
@@ -160,6 +172,23 @@ EMPTY_VNF = [[],[]]; // The standard empty VNF with no vertices or faces.
|
|||||||
// apply(m, [ [rgroove[0].x,0,-z], each rgroove, [last(rgroove).x,0,-z] ])
|
// apply(m, [ [rgroove[0].x,0,-z], each rgroove, [last(rgroove).x,0,-z] ])
|
||||||
// ], caps=true, col_wrap=true, reverse=true);
|
// ], caps=true, col_wrap=true, reverse=true);
|
||||||
// vnf_polyhedron(vnf, convexity=8);
|
// vnf_polyhedron(vnf, convexity=8);
|
||||||
|
|
||||||
|
module vnf_vertex_array(
|
||||||
|
points,
|
||||||
|
caps, cap1, cap2,
|
||||||
|
col_wrap=false,
|
||||||
|
row_wrap=false,
|
||||||
|
reverse=false,
|
||||||
|
style="default",
|
||||||
|
triangulate = false,
|
||||||
|
convexity=2, cp="centroid", anchor="origin", spin=0, orient=UP, atype="hull")
|
||||||
|
{
|
||||||
|
vnf = vnf_vertex_array(points=points, caps=caps, cap1=cap2, cap2=cap2,
|
||||||
|
col_wrap=col_wrap, row_wrap=row_wrap, reverse=reverse, style=style,triangulate=triangulate);
|
||||||
|
vnf_polyhedron(vnf, convexity=2, cp="centroid", anchor="origin", spin=0, orient=UP, atype="hull") children();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function vnf_vertex_array(
|
function vnf_vertex_array(
|
||||||
points,
|
points,
|
||||||
caps, cap1, cap2,
|
caps, cap1, cap2,
|
||||||
@@ -1013,20 +1042,6 @@ function _detri_combine_faces(edgelist,faces,normals,facelist,curface) =
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
function _vnf_sort_vertices(vnf, idx=[2,1,0]) =
|
|
||||||
let(
|
|
||||||
verts = vnf[0],
|
|
||||||
faces = vnf[1],
|
|
||||||
vidx = sortidx(verts, idx=idx),
|
|
||||||
rvidx = sortidx(vidx),
|
|
||||||
sorted_vnf = [
|
|
||||||
[ for (i = vidx) verts[i] ],
|
|
||||||
[ for (face = faces) [ for (i = face) rvidx[i] ] ],
|
|
||||||
]
|
|
||||||
) sorted_vnf;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Function: vnf_slice()
|
// Function: vnf_slice()
|
||||||
// Synopsis: Slice the faces of a VNF along an axis.
|
// Synopsis: Slice the faces of a VNF along an axis.
|
||||||
|
Reference in New Issue
Block a user