mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2025-04-10 02:05:10 +00:00
fix rotate_sweep texture endcaps
This commit is contained in:
parent
f1673f4cc8
commit
19fa25b6e7
3 changed files with 172 additions and 90 deletions
256
skin.scad
256
skin.scad
|
@ -1008,6 +1008,61 @@ function linear_sweep(
|
|||
// tex_taper=[[0,0], [10,0], [10.1,1], [100,1]],
|
||||
// style="convex",
|
||||
// convexity=10);
|
||||
// Example(3D,NoAxes,Med,VPT=[-2.92656,1.26781,0.102897],VPR=[62.7,0,222.4],VPD=216.381): This VNF tile makes a closed shape and the actual main extrusion is not created.
|
||||
// shape = skin([rect(2/5),
|
||||
// rect(2/3),
|
||||
// rect(2/5)],
|
||||
// z=[0,1/2,1],
|
||||
// slices=0,
|
||||
// caps=false);
|
||||
// tile = move([0,1/2,2/3],yrot(90,shape));
|
||||
// path = [for(y=[-30:30]) [ 20-3*(1-cos((y+30)/60*360)),y]];
|
||||
// rotate_sweep(path, closed=false, texture=tile,
|
||||
// tex_size=[10,10], tex_depth=5);
|
||||
// Example(3D,Med,VPT=[1.04269,4.35278,-0.716624],VPR=[98.4,0,43.9],VPD=175.268): Adding the angle parameter cuts off the extrusion. Note how each extruded component is capped.
|
||||
// shape = skin([rect(2/5),
|
||||
// rect(2/3),
|
||||
// rect(2/5)],
|
||||
// z=[0,1/2,1],
|
||||
// slices=0,
|
||||
// caps=false);
|
||||
// tile = move([0,1/2,2/3],yrot(90,shape));
|
||||
// path = [for(y=[-30:30]) [ 20-3*(1-cos((y+30)/60*360)),y]];
|
||||
// rotate_sweep(path, closed=false, texture=tile,
|
||||
// tex_size=[10,15], tex_depth=5, angle=215);
|
||||
// Example(3D,NoAxes,Med,VPT=[1.00759,3.89216,-1.27032],VPR=[57.1,0,34.8],VPD=240.423): Turning the texture 90 degrees with `tex_rot` produces a texture that ends at the top and bottom.
|
||||
// shape = skin([rect(2/5),
|
||||
// rect(2/3),
|
||||
// rect(2/5)],
|
||||
// z=[0,1/2,1],
|
||||
// slices=0,
|
||||
// caps=false);
|
||||
// tile = move([0,1/2,2/3],yrot(90,shape));
|
||||
// path = [for(y=[-30:30]) [ 20-3*(1-cos((y+30)/60*360)),y]];
|
||||
// rotate_sweep(path, closed=false, texture=tile, tex_rot=90,
|
||||
// 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.
|
||||
// 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.5, 0.3, 0], [0.2, 0, 0.5], [0.8, 0, 0.5], [1, 0.2, 1], [1, 0.8, 1],
|
||||
// [0.7, 0.5, 1], [0.5, 0.3, 0.5], [1, 0.2, 0], [1, 0.8, 0], [0.8, 1, 0.5],
|
||||
// [0.2, 1, 0.5], [0.5, 0.7, 0.5], [0.7, 0.5, 0], [0.8, 1, 1], [0.2, 1, 1],
|
||||
// [0.5, 0.7, 1], [0.8, 1, 0], [0.2, 1, 0], [0, 0.8, 0.5], [0, 0.2, 0.5],
|
||||
// [0.3, 0.5, 0.5], [0.5, 0.7, 0], [0, 0.8, 1], [0, 0.2, 1], [0.3, 0.5, 1],
|
||||
// [0, 0.8, 0], [0, 0.2, 0], [0.3, 0.5, 0], [0.2, 0, 1], [0.8, 0, 1], [0.5, 0.3, 1]],
|
||||
// [[0, 1, 5], [1, 2, 4, 5], [7, 11, 10, 8], [8, 10, 9], [7, 8, 2, 1], [9, 10, 4, 3],
|
||||
// [10, 11, 5, 4], [0, 5, 11, 6], [12, 13, 17], [13, 14, 16, 17], [3, 4, 20, 18],
|
||||
// [18, 20, 19], [3, 18, 14, 13], [19, 20, 16, 15], [20, 4, 17, 16], [12, 17, 4, 2],
|
||||
// [21, 22, 26], [22, 23, 25, 26], [15, 16, 29, 27], [27, 29, 28], [15, 27, 23, 22],
|
||||
// [28, 29, 25, 24], [29, 16, 26, 25], [21, 26, 16, 14], [30, 31, 32], [31, 6, 11, 32],
|
||||
// [24, 25, 35, 33], [33, 35, 34], [24, 33, 6, 31], [34, 35, 11, 7],
|
||||
// [35, 25, 32, 11], [30, 32, 25, 23]]
|
||||
// ];
|
||||
// path = [for(y=[-30:30]) [ 20-3*(1-cos((y+30)/60*360)),y]];
|
||||
// down(31)linear_extrude(height=1)arc(r=23,angle=[0,180], wedge=true);
|
||||
// rotate_sweep(path, closed=false, texture=diag_weave_vnf, angle=180,
|
||||
// tex_size=[10,10], convexity=12, tex_depth=2);
|
||||
|
||||
|
||||
function rotate_sweep(
|
||||
shape, angle=360,
|
||||
|
@ -1144,6 +1199,7 @@ module rotate_sweep(
|
|||
}
|
||||
|
||||
|
||||
|
||||
// Function&Module: spiral_sweep()
|
||||
// Synopsis: Sweep a path along a helix.
|
||||
// SynTags: VNF, Geom
|
||||
|
@ -4195,6 +4251,12 @@ function _textured_linear_sweep(
|
|||
|
||||
|
||||
|
||||
// Given a VNF texture tile finds the paths on either the x=0 (axis=0) or the y=0 (axis=1) cases.
|
||||
// Would also find the z=0 paths if you gave axis=2.
|
||||
//
|
||||
// It returns two lists, a list of open paths and a list of closed paths. By default a max of
|
||||
// one open path is permitted; either list can be empty. The paths go in the direction of the segments
|
||||
// in the VNF.
|
||||
|
||||
function _tile_edge_path_list(vnf, axis, maxopen=1) =
|
||||
let(
|
||||
|
@ -4283,6 +4345,7 @@ function _find_vnf_tile_edge_path(vnf, val) =
|
|||
/// "hull" = Anchors to the virtual convex hull of the shape.
|
||||
/// "intersect" = Anchors to the surface of the shape.
|
||||
|
||||
|
||||
function _textured_revolution(
|
||||
shape, texture, tex_size, tex_scale=1,
|
||||
inset=false, rot=false, shift=[0,0],
|
||||
|
@ -4358,12 +4421,18 @@ function _textured_revolution(
|
|||
) zvnf
|
||||
) _vnf_sort_vertices(utex, idx=[0,1]),
|
||||
vertzs = is_vnf(texture)? group_sort(tile[0], idx=0) : undef,
|
||||
bpath = is_vnf(tile)
|
||||
? _find_vnf_tile_edge_path(tile,1)
|
||||
edge_paths = is_vnf(tile) ? _tile_edge_path_list(tile,1) : undef,
|
||||
bpath = is_def(edge_paths)
|
||||
? len(edge_paths[0])==0 ? [] : hstack([column(edge_paths[0][0],0), column(edge_paths[0][0],2)])
|
||||
: let(
|
||||
row = tile[0],
|
||||
rlen = len(row)
|
||||
) [for (i = [0:1:rlen]) [i/rlen, row[i%rlen]]],
|
||||
edge_closed_paths = is_def(edge_paths) ? edge_paths[1] : [],
|
||||
side_paths = angle==360 || !is_vnf(tile) ? undef
|
||||
: _tile_edge_path_list(tile,0),
|
||||
side_open_path = is_undef(side_paths) ? undef : len(side_paths[0])==0 ? [] : side_paths[0][1],
|
||||
side_closed_paths = is_undef(side_paths) ? [] : side_paths[1],
|
||||
counts_x = is_vector(counts,2)? counts.x :
|
||||
is_vector(tex_size,2)
|
||||
? max(1,round(angle/360*circumf/tex_size.x))
|
||||
|
@ -4379,6 +4448,18 @@ function _textured_revolution(
|
|||
taperout = [[-1,retaper[0][1]], each retaper, [2,last(retaper)[1]]]
|
||||
) taperout :
|
||||
assert(false, "Bad taper= argument value."),
|
||||
transform_point = function(tileind, tilez, counts_y, bases, norms)
|
||||
let(
|
||||
part = tileind * samples,
|
||||
ind = floor(part),
|
||||
frac = part - ind,
|
||||
base = lerp(bases[ind], select(bases,ind+1), frac),
|
||||
norm = unit(lerp(norms[ind], select(norms,ind+1), frac)),
|
||||
scale = tex_scale * lookup(tileind/counts_y, taper_lup) * base.x/maxx,
|
||||
texh = scale<0 ? -(1-tilez - inset) * scale
|
||||
: (tilez - inset) * scale
|
||||
)
|
||||
base - norm * texh,
|
||||
full_vnf = vnf_join([
|
||||
for (rgn = regions) let(
|
||||
rgn_wall_vnf = vnf_join([
|
||||
|
@ -4398,17 +4479,9 @@ function _textured_revolution(
|
|||
[
|
||||
[
|
||||
for (group = vertzs) each [
|
||||
for (vert = group) let(
|
||||
part = (j + (1-vert.y)) * samples,
|
||||
u = floor(part),
|
||||
uu = part - u,
|
||||
base = lerp(select(bases,u), select(bases,u+1), uu),
|
||||
norm = unit(lerp(select(norms,u), select(norms,u+1), uu)),
|
||||
tex_scale = tex_scale * lookup(part/samples/counts_y, taper_lup),
|
||||
texh = tex_scale<0 ? -(1-vert.z - inset) * tex_scale * (base.x / maxx)
|
||||
: (vert.z - inset) * tex_scale * (base.x / maxx),
|
||||
xyz = base - norm * texh
|
||||
) zrot(vert.x*angle/counts_x, p=xyz)
|
||||
for (vert = group)
|
||||
let(xyz = transform_point(j + (1-vert.y),vert.z,counts_y,bases, norms))
|
||||
zrot(vert.x*angle/counts_x, p=xyz)
|
||||
]
|
||||
],
|
||||
tile[1]
|
||||
|
@ -4422,21 +4495,12 @@ function _textured_revolution(
|
|||
let(
|
||||
v = (j + (tj/texcnt.x)) / counts_x,
|
||||
mat = zrot(v*angle)
|
||||
) apply(mat, [
|
||||
for (i = [0:1:counts_y-(closed?1:0)], ti = [0:1:texcnt.y-1])
|
||||
if (i != counts_y || ti == 0)
|
||||
let(
|
||||
part = (i + (ti/texcnt.y)) * samples,
|
||||
u = floor(part),
|
||||
uu = part - u,
|
||||
base = lerp(bases[u], select(bases,u+1), uu),
|
||||
norm = unit(lerp(norms[u], select(norms,u+1), uu)),
|
||||
tex_scale = tex_scale * lookup(part/samples/counts_y, taper_lup),
|
||||
texh = tex_scale<0 ? -(1-texture[ti][tj] - inset) * tex_scale * (base.x / maxx)
|
||||
: (texture[ti][tj] - inset) * tex_scale * (base.x / maxx),
|
||||
xyz = base - norm * texh
|
||||
) xyz
|
||||
])
|
||||
)
|
||||
apply(mat, [
|
||||
for (i = [0:1:counts_y-(closed?1:0)], ti = [0:1:texcnt.y-1])
|
||||
if (i != counts_y || ti == 0)
|
||||
transform_point(i + (ti/texcnt.y),texture[ti][tj],counts_y, bases, norms)
|
||||
])
|
||||
])
|
||||
) vnf_vertex_array(
|
||||
tiles, caps=false, style=style,
|
||||
|
@ -4448,9 +4512,9 @@ function _textured_revolution(
|
|||
for (i = [0:1:counts_x-1])
|
||||
zrot(i*angle/counts_x, rgn_wall_vnf)
|
||||
]),
|
||||
endcap_vnf = angle == 360? EMPTY_VNF :
|
||||
sidecap_vnf = angle == 360? EMPTY_VNF :
|
||||
let(
|
||||
cap_rgn = [
|
||||
cap_rgn = side_open_path == [] ? [] : [
|
||||
for (path = rgn) let(
|
||||
plen = path_length(path, closed=closed),
|
||||
counts_y = is_vector(counts,2)? counts.y :
|
||||
|
@ -4462,35 +4526,16 @@ function _textured_revolution(
|
|||
ppath = is_vnf(texture)
|
||||
? [ // VNF tile texture
|
||||
for (j = [0:1:counts_y-1])
|
||||
for (group = vertzs, vert = reverse(group))
|
||||
if (approx(vert.x, 0)) let(
|
||||
part = (j + (1 - vert.y)) * samples,
|
||||
u = floor(part),
|
||||
uu = part - u,
|
||||
base = lerp(select(bases,u), select(bases,u+1), uu),
|
||||
norm = unit(lerp(select(norms,u), select(norms,u+1), uu)),
|
||||
tex_scale = tex_scale * lookup(part/samples/counts_y, taper_lup),
|
||||
texh = tex_scale<0 ? -(1-vert.z - inset) * tex_scale * (base.x / maxx)
|
||||
: (vert.z - inset) * tex_scale * (base.x / maxx),
|
||||
xyz = base - norm * texh
|
||||
) xyz
|
||||
//for (group = vertzs, vert = reverse(group))
|
||||
for(vert=side_open_path)
|
||||
transform_point(j + (1 - vert.y),vert.z,counts_y,bases, norms)
|
||||
]
|
||||
: let( // Heightfield texture
|
||||
texcnt = [len(texture[0]), len(texture)]
|
||||
) [
|
||||
for (i = [0:1:counts_y-(closed?1:0)], ti = [0:1:texcnt.y-1])
|
||||
if (i != counts_y || ti == 0)
|
||||
let(
|
||||
part = (i + (ti/texcnt.y)) * samples,
|
||||
u = floor(part),
|
||||
uu = part - u,
|
||||
base = lerp(bases[u], select(bases,u+1), uu),
|
||||
norm = unit(lerp(norms[u], select(norms,u+1), uu)),
|
||||
tex_scale = tex_scale * lookup(part/samples/counts_y, taper_lup),
|
||||
texh = tex_scale<0 ? -(1-texture[ti][0] - inset) * tex_scale * (base.x / maxx)
|
||||
: (texture[ti][0] - inset) * tex_scale * (base.x / maxx),
|
||||
xyz = base - norm * texh
|
||||
) xyz
|
||||
transform_point(i + (ti/texcnt.y),texture[ti][0],counts_y,bases, norms)
|
||||
],
|
||||
path = closed? ppath : [
|
||||
[0, ppath[0].y],
|
||||
|
@ -4499,10 +4544,30 @@ function _textured_revolution(
|
|||
]
|
||||
) deduplicate(path, closed=closed)
|
||||
],
|
||||
vnf2 = vnf_from_region(cap_rgn, xrot(90), reverse=false),
|
||||
vnf3 = vnf_from_region(cap_rgn, rot([90,0,angle]), reverse=true)
|
||||
) vnf_join([vnf2, vnf3]),
|
||||
allcaps_vnf = closed? EMPTY_VNF :
|
||||
vnf2 = cap_rgn==[] ? EMPTY_VNF : vnf_from_region(cap_rgn, xrot(90), reverse=false),
|
||||
vnf3 = cap_rgn==[] ? EMPTY_VNF : vnf_from_region(cap_rgn, rot([90,0,angle]), reverse=true),
|
||||
extra_paths = side_closed_paths==[] ? []
|
||||
: [for (path = rgn) let(
|
||||
plen = path_length(path, closed=closed),
|
||||
counts_y = is_vector(counts,2)? counts.y :
|
||||
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),
|
||||
onorms = path_normals(obases, 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)
|
||||
[for(vert=cpath)
|
||||
transform_point(j + (1 - vert.y),vert.z,counts_y,bases, norms)]
|
||||
]
|
||||
)
|
||||
each modpaths
|
||||
],
|
||||
extra_vnfs = [
|
||||
if (len(extra_paths)>0) for(path=extra_paths) [xrot(90,path3d(path)), [count(len(path))]],
|
||||
if (len(extra_paths)>0) for(path=extra_paths) [rot([90,0,angle],p=path3d(path)), [count(len(path),reverse=true)]],
|
||||
]
|
||||
) vnf_join([vnf2, vnf3, each extra_vnfs]),
|
||||
endcaps_vnf = closed? EMPTY_VNF :
|
||||
let(
|
||||
plen = path_length(rgn[0], closed=closed),
|
||||
counts_y = is_vector(counts,2)? counts.y :
|
||||
|
@ -4514,39 +4579,55 @@ function _textured_revolution(
|
|||
bases = xrot(90, p=path3d(rbases)),
|
||||
norms = xrot(90, p=path3d(rnorms)),
|
||||
caps_vnf = vnf_join([
|
||||
for (j = [-1,0]) let(
|
||||
base = select(bases,j),
|
||||
norm = unit(select(norms,j)),
|
||||
ppath = [
|
||||
for (vert = bpath) let(
|
||||
uang = vert.x / counts_x,
|
||||
tex_scale = tex_scale * lookup([0,1][j+1], taper_lup),
|
||||
texh = tex_scale<0 ? -(1-vert.y - inset) * tex_scale * (base.x / maxx)
|
||||
: (vert.y - inset) * tex_scale * (base.x / maxx),
|
||||
xyz = base - norm * texh
|
||||
) zrot(angle*uang, p=xyz)
|
||||
],
|
||||
pplen = len(ppath),
|
||||
zed = j<0? max(column(ppath,2)) :
|
||||
min(column(ppath,2)),
|
||||
slice_vnf = [
|
||||
[
|
||||
each ppath,
|
||||
[0, 0, zed],
|
||||
], [
|
||||
for (i = [0:1:pplen-2])
|
||||
j<0? [pplen, i, (i+1)%pplen] :
|
||||
[pplen, (i+1)%pplen, i]
|
||||
]
|
||||
],
|
||||
cap_vnf = vnf_join([
|
||||
for (epath=edge_closed_paths, j = [-1,0])
|
||||
let(
|
||||
base = select(bases,j),
|
||||
norm = unit(select(norms,j)),
|
||||
ppath = [
|
||||
for (vert = epath) let(
|
||||
uang = vert.x / counts_x,
|
||||
tex_scale = tex_scale * lookup(j+1, taper_lup),
|
||||
texh = tex_scale<0 ? -(1-vert.z - inset) * tex_scale * (base.x / maxx)
|
||||
: (vert.z - inset) * tex_scale * (base.x / maxx),
|
||||
xyz = base - norm * texh
|
||||
) zrot(angle*uang, p=xyz)
|
||||
],
|
||||
faces = [count(ppath,reverse=j==0)]
|
||||
)
|
||||
for(i=[0:1:counts_x-1])
|
||||
[zrot(i*angle/counts_x, ppath), faces],
|
||||
if (len(bpath)>0)
|
||||
for (j = [-1,0])
|
||||
let(
|
||||
base = select(bases,j),
|
||||
norm = unit(select(norms,j)),
|
||||
ppath = [
|
||||
for (vert = bpath) let(
|
||||
uang = vert.x / counts_x,
|
||||
tex_scale = tex_scale * lookup(j+1, taper_lup),
|
||||
texh = tex_scale<0 ? -(1-vert.y - inset) * tex_scale * (base.x / maxx)
|
||||
: (vert.y - inset) * tex_scale * (base.x / maxx),
|
||||
xyz = base - norm * texh
|
||||
) zrot(angle*uang, p=xyz)
|
||||
],
|
||||
pplen = len(ppath),
|
||||
zed = j<0? max(column(ppath,2)): min(column(ppath,2)),
|
||||
slice_vnf = [
|
||||
[
|
||||
each ppath,
|
||||
[0, 0, zed],
|
||||
], [
|
||||
for (i = [0:1:pplen-2])
|
||||
j<0? [pplen, i, (i+1)%pplen]
|
||||
: [pplen, (i+1)%pplen, i]
|
||||
]
|
||||
]
|
||||
)
|
||||
for (i = [0:1:counts_x-1])
|
||||
zrot(i*angle/counts_x, p=slice_vnf)
|
||||
])
|
||||
) cap_vnf
|
||||
zrot(i*angle/counts_x, p=slice_vnf)
|
||||
])
|
||||
) caps_vnf
|
||||
) vnf_join([walls_vnf, endcap_vnf, allcaps_vnf])
|
||||
) vnf_join([walls_vnf, sidecap_vnf, endcaps_vnf])
|
||||
]),
|
||||
skmat = zrot(start) * down(-miny) * skew(sxz=shift.x/h, syz=shift.y/h) * up(-miny),
|
||||
skvnf = apply(skmat, full_vnf),
|
||||
|
@ -4556,6 +4637,7 @@ function _textured_revolution(
|
|||
) reorient(anchor,spin,orient, geom=geom, p=skvnf);
|
||||
|
||||
|
||||
|
||||
module _textured_revolution(
|
||||
shape, texture, tex_size, tex_scale=1,
|
||||
inset=false, rot=false, shift=[0,0],
|
||||
|
|
2
std.scad
2
std.scad
|
@ -34,8 +34,8 @@ include <coords.scad>
|
|||
include <geometry.scad>
|
||||
include <regions.scad>
|
||||
include <strings.scad>
|
||||
include <skin.scad>
|
||||
include <vnf.scad>
|
||||
include <skin.scad>
|
||||
include <utility.scad>
|
||||
include <partitions.scad>
|
||||
include <structs.scad>
|
||||
|
|
4
vnf.scad
4
vnf.scad
|
@ -1092,8 +1092,8 @@ function _split_polygon_at_x(poly, x) =
|
|||
out1 = [for (p = poly2) if(p.x <= x) p],
|
||||
out2 = [for (p = poly2) if(p.x >= x) p],
|
||||
out3 = [
|
||||
if (len(out1)>=3) each split_path_at_self_crossings(out1),
|
||||
if (len(out2)>=3) each split_path_at_self_crossings(out2),
|
||||
if (len(out1)>=3 && polygon_area(out1)>EPSILON) each split_path_at_self_crossings(out1),
|
||||
if (len(out2)>=3 && polygon_area(out2)>EPSILON) each split_path_at_self_crossings(out2),
|
||||
],
|
||||
out = [for (p=out3) if (len(p) > 2) list_unwrap(p)]
|
||||
) out;
|
||||
|
|
Loading…
Reference in a new issue