Added texture support to linear_sweep()

This commit is contained in:
Revar Desmera 2022-08-15 16:23:49 -07:00
parent 3fe1ae77ee
commit 709c7a152f
2 changed files with 318 additions and 274 deletions

View file

@ -521,6 +521,13 @@ function skin(profiles, slices, refine=1, method="direct", sampling, caps, close
// shift = The amount to shift the top of the shape, in the X and Y directions, relative to the position of the bottom. Default: [0,0]
// slices = The number of slices to divide the shape into along the Z axis, to allow refinement of detail, especially when working with a twist. Default: `twist/5`
// maxseg = If given, then any long segments of the region will be subdivided to be shorter than this length. This can refine twisting flat faces a lot. Default: `undef` (no subsampling)
// texture = A texture name string, or a rectangular array of scalar height values (0.0 to 1.0), or a VNF tile that defines the texture to apply to vertical surfaces. See {{texture()}} for what named textures are supported.
// tex_size = An optional 2D target size for the textures. Actual texture sizes will be scaled somewhat to evenly fit the available surface. Default: `[5,5]`
// tex_counts = If given instead of tex_size, gives the tile repetition counts for textures over the surface length and height.
// tex_inset = If numeric, lowers the texture into the surface by that amount, before the tscale multiplier is applied. If `true`, insets by exactly `1`. Default: `false`
// tex_rot = If true, rotates the texture 90º.
// tex_scale = Scaling multiplier for the texture depth.
// tex_samples = Minimum number of "bend points" to have in VNF texture tiles. Default: 8
// style = The style to use when triangulating the surface of the object. Valid values are `"default"`, `"alt"`, or `"quincunx"`.
// convexity = Max number of surfaces any single ray could pass through. Module use only.
// cp = 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"`
@ -569,10 +576,14 @@ function skin(profiles, slices, refine=1, method="direct", sampling, caps, close
// orgn = difference(mrgn,rgn3);
// linear_sweep(orgn,height=20,convexity=16)
// show_anchors();
module linear_sweep(
region, height, center,
twist=0, scale=1, shift=[0,0],
slices, maxseg, style="default", convexity,
texture, tex_size=[5,5], tex_counts,
tex_inset=false, tex_rot=false,
tex_scale=1, tex_samples,
cp, atype="hull", h,
anchor, spin=0, orient=UP
) {
@ -585,7 +596,15 @@ module linear_sweep(
vnf = linear_sweep(
region, height=h, style=style,
twist=twist, scale=scale, shift=shift,
slices=slices, maxseg=maxseg,
texture=texture,
tex_size=tex_size,
tex_counts=tex_counts,
tex_inset=tex_inset,
tex_rot=tex_rot,
tex_scale=tex_scale,
tex_samples=tex_samples,
slices=slices,
maxseg=maxseg,
anchor="origin"
);
anchors = [
@ -607,6 +626,9 @@ function linear_sweep(
twist=0, scale=1, shift=[0,0],
slices, maxseg, style="default",
cp, atype="hull", h,
texture, tex_size=[5,5], tex_counts,
tex_inset=false, tex_rot=false,
tex_scale=1, tex_samples,
anchor, spin=0, orient=UP
) =
let( region = force_region(region) )
@ -614,7 +636,18 @@ function linear_sweep(
assert(is_num(scale) || is_vector(scale))
assert(is_vector(shift, 2), str(shift))
let(
h = first_defined([h, height, 1]),
h = first_defined([h, height, 1])
)
!is_undef(texture)? textured_linear_sweep(
region, h=h,
texture=texture, tex_size=tex_size,
counts=tex_counts, inset=tex_inset,
rot=tex_rot, tscale=tex_scale,
twist=twist, scale=scale, shift=shift,
style=style, samples=tex_samples,
anchor=anchor, spin=spin, orient=orient
) :
let(
anchor = center==true? "origin" :
center == false? "original_base" :
default(anchor, "original_base"),
@ -2760,14 +2793,14 @@ function texture(tex, n, inset, gap, roughness) =
// vnf_polyhedron(vnf, convexity=10);
function textured_linear_sweep(
region, texture,
tex_size=[5,5], h, counts,
inset=false, rot=false, tscale=1,
twist, scale, shift,
style="min_edge", l, samples,
region, texture, tex_size=[5,5],
h, counts, inset=false, rot=false,
tscale=1, twist, scale, shift,
style="min_edge", l,
height, length, samples,
anchor=CENTER, spin=0, orient=UP
) =
assert(is_path(region,[2])||is_region(region))
assert(is_path(region,[2]) || is_region(region))
assert(is_undef(samples) || is_int(samples))
assert(counts==undef || is_vector(counts,2))
assert(tex_size==undef || is_vector(tex_size,2))
@ -2780,7 +2813,7 @@ function textured_linear_sweep(
rot==180? reverse([for (row=tex) reverse(row)]) :
rot==270? [for (row=transpose(tex)) reverse(row)] :
reverse(transpose(tex)),
h = first_defined([h, l, 1]),
h = first_defined([h, l, height, length, 1]),
inset = is_num(inset)? inset : inset? 1 : 0,
twist = default(twist, 0),
shift = default(shift, [0,0]),
@ -2824,7 +2857,8 @@ function textured_linear_sweep(
) [for (i = [0:1:rlen]) [i/rlen, row[i%rlen]]],
tmat = scale(scale) * zrot(twist) * up(h/2),
pre_skew_vnf = vnf_join([
for (rgn = regions) let(
/*for (rgn = regions)*/ let(
rgn = last(regions),
walls_vnf = vnf_join([
for (path = rgn) let(
path = reverse(path),
@ -2922,8 +2956,8 @@ function textured_linear_sweep(
obases = resample_path(path, n=counts.x * samples, closed=true),
onorms = path_normals(obases, closed=true),
bases = close_path(obases),
norms = close_path(onorms)
) [
norms = close_path(onorms),
nupath = [
for (j = [0:1:counts.x-1], vert = tpath) let(
part = (j + vert.x) * samples,
u = floor(part),
@ -2934,6 +2968,7 @@ function textured_linear_sweep(
xy = base + norm * texh
) xy
]
) nupath
],
bot_vnf = vnf_from_region(brgn, down(h/2), reverse=true),
top_vnf = vnf_from_region(brgn, tmat, reverse=false)
@ -2954,11 +2989,12 @@ module textured_linear_sweep(
path, texture, tex_size=[5,5], h,
inset=false, rot=false, tscale=1,
twist, scale, shift, samples,
style="min_edge", l, counts,
style="min_edge", l,
height, length, counts,
anchor=CENTER, spin=0, orient=UP,
convexity=10
) {
h = first_defined([h, l]);
h = first_defined([h, l, height, length, 1]);
vnf = textured_linear_sweep(
path, texture, h=h,
tex_size=tex_size, counts=counts,

View file

@ -178,23 +178,28 @@ function vnf_vertex_array(
let(
d42=norm(pts[i4]-pts[i2]),
d13=norm(pts[i1]-pts[i3]),
shortedge = d42<d13+EPSILON ? [[i1,i4,i2],[i2,i4,i3]]
shortedge = d42<d13+EPSILON
? [[i1,i4,i2],[i2,i4,i3]]
: [[i1,i3,i2],[i1,i4,i3]]
)
shortedge
: style=="convex"?
let( // Find normal for 3 of the points. Is the other point above or below?
n = (reverse?-1:1)*cross(pts[i2]-pts[i1],pts[i3]-pts[i1]),
convexfaces = n==0 ? [[i1,i4,i3]]
: n*pts[i4] > n*pts[i1] ? [[i1,i4,i2],[i2,i4,i3]]
convexfaces = n==0
? [[i1,i4,i3]]
: n*pts[i4] > n*pts[i1]
? [[i1,i4,i2],[i2,i4,i3]]
: [[i1,i3,i2],[i1,i4,i3]]
)
convexfaces
: style=="concave"?
let( // Find normal for 3 of the points. Is the other point above or below?
n = (reverse?-1:1)*cross(pts[i2]-pts[i1],pts[i3]-pts[i1]),
concavefaces = n==0 ? [[i1,i4,i3]]
: n*pts[i4] <= n*pts[i1] ? [[i1,i4,i2],[i2,i4,i3]]
concavefaces = n==0
? [[i1,i4,i3]]
: n*pts[i4] <= n*pts[i1]
? [[i1,i4,i2],[i2,i4,i3]]
: [[i1,i3,i2],[i1,i4,i3]]
)
concavefaces
@ -573,10 +578,14 @@ function _bridge(pt, outer,eps) =
// vnf_wireframe(vnf,width=.25);
function vnf_from_region(region, transform, reverse=false) =
let (
region = [for (path = region) deduplicate(path, closed=true)],
regions = region_parts(force_region(region)),
vnfs =
[ for (rgn = regions)
let( cleaved = path3d(_cleave_connected_region(rgn)) )
[
for (rgn = regions)
let(
cleaved = path3d(_cleave_connected_region(rgn))
)
assert( cleaved, "The region is invalid")
let(
face = is_undef(transform)? cleaved : apply(transform,cleaved),
@ -1226,7 +1235,6 @@ function vnf_bend(vnf,r,d,axis="Z") =
axis=="X"? [p.x, p.z*sin(a), p.z*cos(a)] :
axis=="Y"? [p.z*sin(a), p.y, p.z*cos(a)] :
[p.y*sin(a), p.y*cos(a), p.z]]
) [new_vert,sliced[1]];