mirror of
https://github.com/revarbat/BOSL2.git
synced 2025-08-09 13:36:58 +02:00
textured_tile bugfix & texture support for sweeps
This commit is contained in:
@@ -899,8 +899,6 @@ function _rounded_arc(radius, rounding=0, angle, n) =
|
||||
let(
|
||||
rounding = force_list(rounding,3),
|
||||
dir = sign(angle),
|
||||
|
||||
// inner_corner_radius = abs(angle)==180?0 : abs(angle)>180 ? -dir*rounding[0] : dir*rounding[0],
|
||||
inner_corner_radius = abs(angle)>180 ? -dir*rounding[0] : dir*rounding[0],
|
||||
arc1_opt_radius = radius - rounding[1],
|
||||
arc2_opt_radius = radius - rounding[2],
|
||||
|
@@ -1250,36 +1250,6 @@ function regular_prism(n,
|
||||
// textured_tile("trunc_ribs", 10, tex_reps=[5,2], tex_skip=1);
|
||||
|
||||
|
||||
// This is like _tile_edge_path_list in that it finds the paths
|
||||
// on the x=0 or y=0 face of a VNF tile. But instead of returning
|
||||
// paths it turns them into a VNF. The open path is closed to the specified
|
||||
// z coordinate.
|
||||
|
||||
function _tile_edge_vnf(vnf, axis, z, maxopen=1) =
|
||||
let(
|
||||
verts = vnf[0],
|
||||
faces = vnf[1],
|
||||
segs = [for(face=faces, edge=pair(select(verts,face),wrap=true)) if (approx(edge[0][axis],0) && approx(edge[1][axis],0)) [edge[1],edge[0]]],
|
||||
paths = _assemble_partial_paths(segs),
|
||||
facelist = [
|
||||
for(path=paths)
|
||||
if (!(len(path)<=3 && path[0]==last(path)))
|
||||
path[0]==len(path) ? [list_unwrap(path),[count(len(path)-1)]]
|
||||
: [
|
||||
[
|
||||
point3d(point2d(path[0]),z),
|
||||
each path,
|
||||
point3d(point2d(last(path)),z)
|
||||
],
|
||||
[count(len(path)+2)]
|
||||
]
|
||||
],
|
||||
openlist = [for(entry=facelist) if (!are_ends_equal(entry[0])) 1]
|
||||
)
|
||||
assert(len(openlist)<=maxopen, str("VNF has ",len(openlist)," open paths on an edge and at most ",maxopen," is supported."))
|
||||
vnf_join(facelist);
|
||||
|
||||
|
||||
module textured_tile(
|
||||
texture,
|
||||
size,
|
||||
@@ -1382,6 +1352,7 @@ function textured_tile(
|
||||
tex_reps = is_def(tex_reps) ? tex_reps
|
||||
: [round(size.x/tex_size.x), round(size.y/tex_size.y)],
|
||||
scale = [size.x/tex_reps.x, size.y/tex_reps.y],
|
||||
setz=function (v,z) [v.x,v.y,z],
|
||||
vnf = !is_vnf(texture) ?
|
||||
let(
|
||||
texsteps = [len(texture[0]), len(texture)],
|
||||
@@ -1412,18 +1383,57 @@ function textured_tile(
|
||||
],
|
||||
scaled_vnf = scale(scale, zadj_vnf),
|
||||
tiled_vnf = [for(i=[0:1:tex_reps.x-1], j=[0:1:tex_reps.y-1]) move([scale.x*i,scale.y*j], scaled_vnf)],
|
||||
unscaled_hedge=_tile_edge_vnf(zadj_vnf,1,-height/2),
|
||||
hedge = unscaled_hedge==EMPTY_VNF ? [] : xscale(scale.x, unscaled_hedge),
|
||||
unscaled_vedge=_tile_edge_vnf(zadj_vnf,0,-height/2),
|
||||
vedge = unscaled_vedge==EMPTY_VNF ? [] : yscale(scale.y, unscaled_vedge),
|
||||
hedge_flip = hedge==[] ? hedge : back(size.y,vnf_reverse_faces(hedge)),
|
||||
vedge_flip = vedge==[] ? vedge : right(size.x,vnf_reverse_faces(vedge)),
|
||||
front_edge = hedge==[] ? [] : [for(i=[0:1:tex_reps.x-1]) xmove(scale.x*i, hedge)],
|
||||
left_edge = vedge==[] ? [] : [for(j=[0:1:tex_reps.y-1]) ymove(scale.y*j, vedge)],
|
||||
back_edge = hedge==[] ? [] : [for(i=[0:1:tex_reps.x-1]) xmove(scale.x*i, hedge_flip)],
|
||||
right_edge = vedge==[] ? [] : [for(j=[0:1:tex_reps.y-1]) ymove(scale.y*j, vedge_flip)],
|
||||
|
||||
yedge_list = _tile_edge_path_list(zadj_vnf, 0),
|
||||
xedge_list = _tile_edge_path_list(zadj_vnf, 1),
|
||||
|
||||
front_back_closed = [for(i=[0:1:tex_reps.x-1], cpath=xedge_list[1])
|
||||
each [[xscale(scale.x,xmove(i,cpath)), [count(cpath)]],
|
||||
[xscale(scale.x,move([i,size.y],cpath)),[count(cpath,reverse=true)]]]],
|
||||
sides_closed = [for(j=[0:1:tex_reps.y-1], cpath=yedge_list[1])
|
||||
each [[yscale(scale.y,ymove(j,cpath)), [count(cpath)]],
|
||||
[yscale(scale.y,move([size.x, j], cpath)),[count(cpath,reverse=true)]]]],
|
||||
|
||||
leftpath = yedge_list[0]==[] ? []
|
||||
: deduplicate([for(j=[0:1:tex_reps.y-1]) each reverse(yscale(scale.y,ymove(j,yedge_list[0][0])))]),
|
||||
frontpath = xedge_list[0]==[] ? []
|
||||
: deduplicate([for(i=[0:1:tex_reps.x-1]) each xscale(scale.x,xmove(i,xedge_list[0][0]))]),
|
||||
|
||||
base = frontpath==[] || leftpath==[] ? []
|
||||
: [
|
||||
[
|
||||
[setz(frontpath[0],-height/2),
|
||||
each frontpath,
|
||||
setz(last(frontpath), -height/2)
|
||||
],
|
||||
[count(len(frontpath)+2)]
|
||||
],
|
||||
[
|
||||
[setz(last(leftpath),-height/2),
|
||||
each reverse(leftpath),
|
||||
setz(leftpath[0], -height/2)
|
||||
],
|
||||
[count(len(leftpath)+2)]
|
||||
],
|
||||
[
|
||||
back(size.y,
|
||||
[setz(last(frontpath),-height/2),
|
||||
each reverse(frontpath),
|
||||
setz(frontpath[0],-height/2)
|
||||
]),
|
||||
[count(len(frontpath)+2)]
|
||||
],
|
||||
[right(size.x,
|
||||
[setz(leftpath[0],-height/2),
|
||||
each leftpath,
|
||||
setz(last(leftpath),-height/2)
|
||||
]),
|
||||
[count(len(leftpath)+2)]
|
||||
]
|
||||
],
|
||||
|
||||
bottom = [path3d(rect(point2d(size),anchor=FWD+LEFT),-height/2), [[3,2,1,0]]],
|
||||
result = vnf_join(concat(tiled_vnf, front_edge, left_edge, right_edge, back_edge, [bottom]))
|
||||
result = vnf_join(concat(tiled_vnf,front_back_closed, sides_closed,base,[bottom]))
|
||||
)
|
||||
move([-size.x/2,-size.y/2],result),
|
||||
trans_vnf = is_undef(h_w1_w2_shift) ? vnf
|
||||
|
106
skin.scad
106
skin.scad
@@ -14,6 +14,7 @@
|
||||
// FileFootnotes: STD=Included in std.scad
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
__vnf_no_n_mesg=" texture is a VNF so it does not accept n. Set sample rate for VNF textures using the tex_samples parameter to cyl(), linear_sweep() or rotate_sweep().";
|
||||
|
||||
// Section: Skin and sweep
|
||||
|
||||
@@ -1570,6 +1571,11 @@ module spiral_sweep(poly, h, r, turns=1, taper, r1, r2, d, d1, d2, internal=fals
|
||||
// the object's VNF data. The center of the object is determined based on the `cp` argument and can be "centroid" (the default), "mean" to use the mean of the object,
|
||||
// or "box" to use the center of the bounding box. For complicated objects you may find it difficult to get useful results from the anchoring
|
||||
// system, which is designed for an object whose center is inside the object. When using an anchors, confirm that it is in the location you desire.
|
||||
// .
|
||||
// You can apply a texture to the path sweep object using the usual texture parameters.
|
||||
// See [Texturing](skin.scad#section-texturing) for more details on how textures work.
|
||||
// This works by passing through to {{vnf_vertex_array()}}, which also has more details on
|
||||
// texturing. Note that textures only work when the shape is a path; you cannot apply a texture to a region.
|
||||
// Arguments:
|
||||
// shape = A 2D polygon path or region describing the shape to be swept.
|
||||
// path = 2D or 3D path giving the path to sweep over
|
||||
@@ -1592,6 +1598,15 @@ module spiral_sweep(poly, h, r, turns=1, taper, r1, r2, d, d1, d2, internal=fals
|
||||
// width = the width of lines used for profile display. (module only) Default: 1
|
||||
// transforms = set to true to return transforms instead of a VNF. These transforms can be manipulated and passed to sweep(). (function only) Default: false.
|
||||
// convexity = convexity parameter for polyhedron(). (module only) Default: 10
|
||||
// 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 at `points[0][0]`. Actual texture sizes will be scaled somewhat to evenly fit the available surface. Default: `[5,5]`
|
||||
// tex_reps = If given instead of tex_size, a 2-vector giving the number of texture tile repetitions in the horizontal and vertical directions.
|
||||
// tex_inset = If numeric, lowers the texture into the surface by the specified proportion, e.g. 0.5 would lower it half way into the surface. If `true`, insets by exactly its full depth. Default: `false`
|
||||
// tex_rot = Rotate texture by specified angle, which must be a multiple of 90 degrees. Default: 0
|
||||
// tex_depth = Specify texture depth; if negative, invert the texture. Default: 1.
|
||||
// tex_samples = Minimum number of "bend points" to have in VNF texture tiles. Default: 8
|
||||
// tex_extra = number of extra lines of a hightfield texture to add at the end. Can be a scalar or 2-vector to give x and y values. Default: 1
|
||||
// tex_skip = number of lines of a heightfield texture to skip when starting. Can be a scalar or two vector to give x and y values. Default: 0
|
||||
// anchor = Translate so anchor point is at the origin. Default: "origin"
|
||||
// spin = Rotate this many degrees around Z axis after anchor. Default: 0
|
||||
// orient = Vector to rotate top towards after spin
|
||||
@@ -1908,9 +1923,14 @@ module spiral_sweep(poly, h, r, turns=1, taper, r1, r2, d, d1, d2, internal=fals
|
||||
// attach("end") stroke([path3d(yscale(1.5,shape))],width=.5);
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
module path_sweep(shape, path, method="incremental", normal, closed, twist=0, twist_by_length=true, scale=1, scale_by_length=true,
|
||||
symmetry=1, last_normal, tangent, uniform=true, relaxed=false, caps, style="min_edge", convexity=10,
|
||||
anchor="origin",cp="centroid",spin=0, orient=UP, atype="hull",profiles=false,width=1)
|
||||
anchor="origin",cp="centroid",spin=0, orient=UP, atype="hull",profiles=false,width=1,
|
||||
texture, tex_reps, tex_size, tex_samples, tex_inset=false, tex_rot=0,
|
||||
tex_depth=1, tex_extra, tex_skip)
|
||||
{
|
||||
dummy = assert(is_region(shape) || is_path(shape,2), "shape must be a 2D path or region")
|
||||
assert(in_list(atype, _ANCHOR_TYPES), "Anchor type must be \"hull\" or \"intersect\"");
|
||||
@@ -1923,7 +1943,9 @@ module path_sweep(shape, path, method="incremental", normal, closed, twist=0, tw
|
||||
scales = trans_scale[1];
|
||||
firstscale = is_num(scales[0]) ? 1/scales[0] : [1/scales[0].x, 1/scales[0].y];
|
||||
lastscale = is_num(last(scales)) ? 1/last(scales) : [1/last(scales).x, 1/last(scales).y];
|
||||
vnf = sweep(is_path(shape)?clockwise_polygon(shape):shape, transforms, closed=false, caps=fullcaps,style=style);
|
||||
vnf = sweep(is_path(shape)?clockwise_polygon(shape):shape, transforms, closed=false, _closed_for_normals=closed, caps=fullcaps,style=style,
|
||||
texture=texture, tex_reps=tex_reps, tex_size=tex_size, tex_samples=tex_samples,
|
||||
tex_inset=tex_inset, tex_rot=tex_rot, tex_depth=tex_depth, tex_extra=tex_extra, tex_skip=tex_skip);
|
||||
shapecent = point3d(centroid(shape));
|
||||
$sweep_transforms = transforms;
|
||||
$sweep_scales = scales;
|
||||
@@ -1957,10 +1979,14 @@ module path_sweep(shape, path, method="incremental", normal, closed, twist=0, tw
|
||||
|
||||
function path_sweep(shape, path, method="incremental", normal, closed, twist=0, twist_by_length=true, scale=1, scale_by_length=true,
|
||||
symmetry=1, last_normal, tangent, uniform=true, relaxed=false, caps, style="min_edge", transforms=false,
|
||||
texture, tex_reps, tex_size, tex_samples, tex_inset=false, tex_rot=0,
|
||||
tex_depth=1, tex_extra, tex_skip,
|
||||
anchor="origin",cp="centroid",spin=0, orient=UP, atype="hull",_return_scales=false) =
|
||||
is_1region(path) ? path_sweep(shape=shape,path=path[0], method=method, normal=normal, closed=default(closed,true),
|
||||
twist=twist, scale=scale, scale_by_length=scale_by_length, twist_by_length=twist_by_length, symmetry=symmetry, last_normal=last_normal,
|
||||
tangent=tangent, uniform=uniform, relaxed=relaxed, caps=caps, style=style, transforms=transforms,
|
||||
texture, tex_reps, tex_size, tex_samples, tex_inset=false, tex_rot=0,
|
||||
tex_depth=1, tex_extra, tex_skip,
|
||||
anchor=anchor, cp=cp, spin=spin, orient=orient, atype=atype, _return_scales=_return_scales) :
|
||||
let(closed=default(closed,false))
|
||||
assert(in_list(atype, _ANCHOR_TYPES), "Anchor type must be \"hull\" or \"intersect\"")
|
||||
@@ -2117,7 +2143,11 @@ function path_sweep(shape, path, method="incremental", normal, closed, twist=0,
|
||||
? [transform_list,scale]
|
||||
: transforms ? transform_list
|
||||
: sweep(is_path(shape)?clockwise_polygon(shape):shape, transform_list, closed=false, caps=fullcaps,style=style,
|
||||
anchor=anchor,cp=cp,spin=spin,orient=orient,atype=atype);
|
||||
anchor=anchor,cp=cp,spin=spin,orient=orient,atype=atype,
|
||||
texture=texture, tex_reps=tex_reps, tex_size=tex_size, tex_samples=tex_samples,
|
||||
tex_inset=tex_inset, tex_rot=tex_rot, tex_depth=tex_depth, tex_extra=tex_extra, tex_skip=tex_skip,
|
||||
_closed_for_normals=closed
|
||||
);
|
||||
|
||||
|
||||
// Function&Module: path_sweep2d()
|
||||
@@ -2276,6 +2306,12 @@ function _ofs_face_edge(face,firstlen,second=false) =
|
||||
// overlooked self-intersection. Note also that the errors will not occur when your shape is alone
|
||||
// in your model, but will arise if you add a second object to the model. This may mislead you into
|
||||
// thinking the second object caused a problem. Even adding a simple cube to the model will reveal the problem.
|
||||
// .
|
||||
// You can apply a texture to the sweep object using the usual texture parameters.
|
||||
// See [Texturing](skin.scad#section-texturing) for more details on how textures work.
|
||||
// This works by passing through to {{vnf_vertex_array()}}, which also has more details on
|
||||
// texturing. Note that textures only work when the shape is a path; you cannot apply a texture to a region.
|
||||
// The texture tiles are oriented on the path sweep so that the Y axis of the tile is aligned with the sweep direction.
|
||||
// Arguments:
|
||||
// shape = 2d path or region, describing the shape to be swept.
|
||||
// transforms = list of 4x4 matrices to apply
|
||||
@@ -2284,6 +2320,15 @@ function _ofs_face_edge(face,firstlen,second=false) =
|
||||
// style = vnf_vertex_array style. Default: "min_edge"
|
||||
// ---
|
||||
// convexity = convexity setting for use with polyhedron. (module only) Default: 10
|
||||
// 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 at `points[0][0]`. Actual texture sizes will be scaled somewhat to evenly fit the available surface. Default: `[5,5]`
|
||||
// tex_reps = If given instead of tex_size, a 2-vector giving the number of texture tile repetitions in the horizontal and vertical directions.
|
||||
// tex_inset = If numeric, lowers the texture into the surface by the specified proportion, e.g. 0.5 would lower it half way into the surface. If `true`, insets by exactly its full depth. Default: `false`
|
||||
// tex_rot = Rotate texture by specified angle, which must be a multiple of 90 degrees. Default: 0
|
||||
// tex_depth = Specify texture depth; if negative, invert the texture. Default: 1.
|
||||
// tex_samples = Minimum number of "bend points" to have in VNF texture tiles. Default: 8
|
||||
// tex_extra = number of extra lines of a hightfield texture to add at the end. Can be a scalar or 2-vector to give x and y values. Default: 1
|
||||
// tex_skip = number of lines of a heightfield texture to skip when starting. Can be a scalar or two vector to give x and y values. Default: 0
|
||||
// cp = Centerpoint for determining "intersect" anchors or centering the shape. Determintes the base of the anchor vector. Can be "centroid", "mean", "box" or a 3D point. Default: "centroid"
|
||||
// atype = Select "hull" or "intersect" anchor types. Default: "hull"
|
||||
// anchor = Translate so anchor point is at the origin. Default: "origin"
|
||||
@@ -2306,7 +2351,7 @@ function _ofs_face_edge(face,firstlen,second=false) =
|
||||
// function rotate(t) = 180 * pow((1 - t), 3);
|
||||
// step = 0.01;
|
||||
// path_transforms = [for (t=[0:step:1-step]) translate(path(t)) * zrot(rotate(t)) * scale([drop(t), drop(t), 1])];
|
||||
// sweep(circle(1, $fn=12), path_transforms);
|
||||
// sweep(reverse(circle(1, $fn=12)), path_transforms);
|
||||
// Example: Another example from list-comprehension-demos
|
||||
// function f(x) = 3 - 2.5 * x;
|
||||
// function r(x) = 2 * 180 * x * x * x;
|
||||
@@ -2320,9 +2365,19 @@ function _ofs_face_edge(face,firstlen,second=false) =
|
||||
// outside = [for(i=[0:24]) up(i)*rot(i)*scale(1.25*i/24+1)];
|
||||
// inside = [for(i=[24:-1:2]) up(i)*rot(i)*scale(1.2*i/24+1)];
|
||||
// sweep(shape, concat(outside,inside));
|
||||
// Example: "sweet-drop" with a dots texture
|
||||
// function drop(t) = 100 * 0.5 * (1 - cos(180 * t)) * sin(180 * t) + 1;
|
||||
// function path(t) = [0, 0, 80 + 80 * cos(180 * t)];
|
||||
// function rotate(t) = 180 * pow((1 - t), 3);
|
||||
// step = 0.01;
|
||||
// path_transforms = [for (t=[0:step:1-step]) translate(path(t)) * zrot(rotate(t)) * scale([drop(t), drop(t), 1])];
|
||||
// sweep(reverse(circle(1, $fn=12)), path_transforms, texture="dots", tex_reps=[12,12],tex_depth=.1);
|
||||
|
||||
|
||||
function sweep(shape, transforms, closed=false, caps, style="min_edge",
|
||||
anchor="origin", cp="centroid", spin=0, orient=UP, atype="hull") =
|
||||
anchor="origin", cp="centroid", spin=0, orient=UP, atype="hull",
|
||||
texture, tex_reps, tex_size, tex_samples, tex_inset=false, tex_rot=0,
|
||||
tex_depth=1, tex_extra, tex_skip, _closed_for_normals=false) =
|
||||
assert(is_consistent(transforms, ident(4)), "Input transforms must be a list of numeric 4x4 matrices in sweep")
|
||||
assert(is_path(shape,2) || is_region(shape), "Input shape must be a 2d path or a region.")
|
||||
let(
|
||||
@@ -2334,7 +2389,9 @@ function sweep(shape, transforms, closed=false, caps, style="min_edge",
|
||||
assert(len(transforms)>=2, "transformation must be length 2 or more")
|
||||
assert(capsOK, "caps must be boolean or a list of two booleans")
|
||||
assert(!closed || !caps, "Cannot make closed shape with caps")
|
||||
is_region(shape)? let(
|
||||
is_region(shape)?
|
||||
assert(is_undef(texture), "textures are not supported for regions, only paths")
|
||||
let(
|
||||
regions = region_parts(shape),
|
||||
rtrans = reverse(transforms),
|
||||
vnfs = [
|
||||
@@ -2346,19 +2403,35 @@ function sweep(shape, transforms, closed=false, caps, style="min_edge",
|
||||
],
|
||||
],
|
||||
vnf = vnf_join(vnfs)
|
||||
) vnf :
|
||||
)
|
||||
vnf
|
||||
:
|
||||
assert(len(shape)>=3, "shape must be a path of at least 3 non-colinear points")
|
||||
vnf_vertex_array([for(i=[0:len(transforms)-(closed?0:1)]) apply(transforms[i%len(transforms)],path3d(shape))],
|
||||
cap1=fullcaps[0],cap2=fullcaps[1],col_wrap=true,style=style);
|
||||
let(
|
||||
points = [for(i=[0:len(transforms)-(closed?0:1)]) apply(transforms[i%len(transforms)],path3d(shape))],
|
||||
normals = (!(is_def(texture) && (closed || _closed_for_normals))) ? undef
|
||||
: let(
|
||||
n = surfnormals(select(points,0,-2), col_wrap=true, row_wrap=true)
|
||||
)
|
||||
[each n, n[0]]
|
||||
)
|
||||
vnf_vertex_array(points, normals=normals,
|
||||
cap1=fullcaps[0],cap2=fullcaps[1],col_wrap=true,style=style,
|
||||
texture=texture, tex_reps=tex_reps, tex_size=tex_size, tex_samples=tex_samples,
|
||||
tex_inset=tex_inset, tex_rot=tex_rot, tex_depth=tex_depth, tex_extra=tex_extra, tex_skip=tex_skip);
|
||||
|
||||
|
||||
module sweep(shape, transforms, closed=false, caps, style="min_edge", convexity=10,
|
||||
anchor="origin",cp="centroid",spin=0, orient=UP, atype="hull")
|
||||
anchor="origin",cp="centroid",spin=0, orient=UP, atype="hull",
|
||||
texture, tex_reps, tex_size, tex_samples, tex_inset=false, tex_rot=0,
|
||||
tex_depth=1, tex_extra, tex_skip)
|
||||
{
|
||||
$sweep_transforms=transforms;
|
||||
$sweep_shape=shape;
|
||||
$sweep_closed=closed;
|
||||
vnf = sweep(shape, transforms, closed, caps, style);
|
||||
vnf = sweep(shape, transforms, closed, caps, style,
|
||||
texture=texture, tex_reps=tex_reps, tex_size=tex_size, tex_samples=tex_samples,
|
||||
tex_inset=tex_inset, tex_rot=tex_rot, tex_depth=tex_depth, tex_extra=tex_extra, tex_skip=tex_skip);
|
||||
vnf_polyhedron(vnf, convexity=convexity, anchor=anchor, spin=spin, orient=orient, atype=atype, cp=cp)
|
||||
children();
|
||||
}
|
||||
@@ -3563,7 +3636,7 @@ function associate_vertices(polygons, split, curpoly=0) =
|
||||
|
||||
function _tex_fn_default() = 16;
|
||||
|
||||
__vnf_no_n_mesg=" texture is a VNF so it does not accept n. Set sample rate for VNF textures using the tex_samples parameter to cyl(), linear_sweep() or rotate_sweep().";
|
||||
|
||||
|
||||
function texture(tex, n, border, gap, roughness, inset) =
|
||||
assert(num_defined([border,inset])<2, "In texture() the 'inset' parameter has been replaced by 'border'. You cannot give both parameters.")
|
||||
@@ -4630,7 +4703,7 @@ module _textured_revolution(
|
||||
|
||||
|
||||
function _texture_point_array(points, texture, tex_reps, tex_size, tex_samples, tex_inset=false, tex_rot=0, triangulate=false,
|
||||
col_wrap=false, tex_depth=1, row_wrap=false, caps, cap1, cap2, reverse=false, style="min_edge", tex_extra, tex_skip, sidecaps,sidecap1,sidecap2) =
|
||||
col_wrap=false, tex_depth=1, row_wrap=false, caps, cap1, cap2, reverse=false, style="min_edge", tex_extra, tex_skip, sidecaps,sidecap1,sidecap2,normals) =
|
||||
assert(tex_reps==undef || is_vector(tex_reps,2))
|
||||
assert(tex_size==undef || is_num(tex_size) || is_vector(tex_size,2), "tex_size must be a scalar or 2-vector")
|
||||
assert(num_defined([tex_size, tex_reps])<2, "Cannot give both tex_size and tex_reps")
|
||||
@@ -4654,7 +4727,7 @@ function _texture_point_array(points, texture, tex_reps, tex_size, tex_samples,
|
||||
ysize = norm(points[0][0]-points[1][0])*(ptsize.y+(row_wrap?1:0))
|
||||
)
|
||||
[round(xsize/tex_size.x), round(ysize/tex_size.y)],
|
||||
normals = surfnormals(points, col_wrap=col_wrap, row_wrap=row_wrap),
|
||||
normals = default(normals,surfnormals(points, col_wrap=col_wrap, row_wrap=row_wrap)),
|
||||
getscale = function(x,y) (x+y)/2
|
||||
)
|
||||
!is_vnf(texture) ? // heightmap case
|
||||
@@ -4691,7 +4764,7 @@ function _texture_point_array(points, texture, tex_reps, tex_size, tex_samples,
|
||||
]
|
||||
]
|
||||
)
|
||||
vnf_vertex_array(tex_surf, row_wrap=row_wrap, col_wrap=col_wrap, reverse=reverse,style=style, caps=caps, triangulate=triangulate)
|
||||
vnf_vertex_array(tex_surf, row_wrap=row_wrap, col_wrap=col_wrap, reverse=reverse,style=style, caps=caps, cap1=cap1, cap2=cap2, triangulate=triangulate)
|
||||
: // VNF case
|
||||
let(
|
||||
local_scale = [for(y=[-1:1:ptsize.y-1])
|
||||
@@ -4712,6 +4785,7 @@ function _texture_point_array(points, texture, tex_reps, tex_size, tex_samples,
|
||||
slice_us = list([s:s:1-s/2]),
|
||||
vnft1 = vnf_slice(texture, "X", slice_us),
|
||||
vnft = vnf_slice(vnft1, "Y", slice_us),
|
||||
|
||||
zvnf = [
|
||||
[
|
||||
for (p=vnft[0]) [
|
||||
@@ -4730,6 +4804,8 @@ function _texture_point_array(points, texture, tex_reps, tex_size, tex_samples,
|
||||
let(
|
||||
tileindx = x+pt.x,
|
||||
tileindy = y+(1-pt.y),
|
||||
|
||||
|
||||
refx = tileindx/tex_reps.x*(ptsize.x-(col_wrap?0:1)),
|
||||
refy = tileindy/tex_reps.y*(ptsize.y-(row_wrap?0:1)),
|
||||
xind = floor(refx),
|
||||
|
@@ -134,7 +134,7 @@ module test_make_region(){
|
||||
22.451398829]], [[69.0983005625, 22.451398829], [50, 36.3271264003],
|
||||
[80.9016994375, 58.7785252292]], [[61.803398875, 3.5527136788e-15],
|
||||
[69.0983005625, 22.451398829], [100, 0]], [[38.196601125, 0],
|
||||
[61.803398875, 3.94430452611e-31], [50, -36.3271264003]]]));
|
||||
[61.803398875, 3.94430452611e-31], [50, -36.3271264003]]], either_winding=true));
|
||||
/*assert_approx(region1,
|
||||
[[[0, 0], [38.196601125, 0], [30.9016994375, 22.451398829]], [[50,
|
||||
36.3271264003], [19.0983005625, 58.7785252292], [30.9016994375,
|
||||
|
11
vnf.scad
11
vnf.scad
@@ -65,6 +65,10 @@ EMPTY_VNF = [[],[]]; // The standard empty VNF with no vertices or faces.
|
||||
// the number of data points must equal the tile count times the number of entries in the tile minus `tex_skip` plus `tex_extra`.
|
||||
// Note that `tex_extra` defaults to 1 along dimensions that are not wrapped. For a VNF tile you need to have the the point
|
||||
// count equal to the tile count times tex_samples, plus one if wrapping is disabled.
|
||||
// .
|
||||
// For creating the texture, `vnf_vertex_array()` uses normals to the surface that it estimates from the surface data itself.
|
||||
// If you have more accurate normals or need the normals to take particular values, you can pass an array of normals
|
||||
// using the `normals` parameter.
|
||||
// Arguments:
|
||||
// points = A list of vertices to divide into columns and rows.
|
||||
// ---
|
||||
@@ -89,6 +93,7 @@ EMPTY_VNF = [[],[]]; // The standard empty VNF with no vertices or faces.
|
||||
// sidecaps = if `col_wrap==false` this controls whether to cap any floating ends of a VNF tile on the texture. Does not affect the main texture surface. Ignored it doesn't apply. Default: false
|
||||
// sidecap1 = set sidecap only for the `points[][0]` edge of the output
|
||||
// sidecap2 = set sidecap only for the `points[][max]` edge of the output
|
||||
// normals = array of normal vectors to each point in the point array for more accurate texture height calculation
|
||||
// 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`
|
||||
@@ -219,7 +224,7 @@ module vnf_vertex_array(
|
||||
texture=texture, tex_reps=tex_reps, tex_size=tex_size, tex_samples=tex_samples, tex_inset=tex_inset, tex_rot=tex_rot,
|
||||
tex_depth=tex_depth, tex_extra=tex_extra, tex_skip=tex_skip, sidecaps=sidecaps,sidecap1=sidecap1,sidecap2=sidecap2
|
||||
);
|
||||
vnf_polyhedron(vnf, convexity=2, cp="centroid", anchor="origin", spin=0, orient=UP, atype="hull") children();
|
||||
vnf_polyhedron(vnf, convexity=convexity, cp="centroid", anchor="origin", spin=0, orient=UP, atype="hull") children();
|
||||
}
|
||||
|
||||
|
||||
@@ -232,7 +237,7 @@ function vnf_vertex_array(
|
||||
style="default",
|
||||
triangulate = false,
|
||||
texture, tex_reps, tex_size, tex_samples, tex_inset=false, tex_rot=0,
|
||||
tex_depth=1, tex_extra, tex_skip, sidecaps,sidecap1,sidecap2
|
||||
tex_depth=1, tex_extra, tex_skip, sidecaps,sidecap1,sidecap2, normals
|
||||
) =
|
||||
assert(in_list(style,["default","alt","quincunx", "convex","concave", "min_edge","min_area","flip1","flip2"]))
|
||||
assert(is_matrix(points[0], n=3),"Point array has the wrong shape or points are not 3d")
|
||||
@@ -242,7 +247,7 @@ function vnf_vertex_array(
|
||||
_texture_point_array(points=points, texture=texture, tex_reps=tex_reps, tex_size=tex_size,
|
||||
tex_inset=tex_inset, tex_samples=tex_samples, tex_rot=tex_rot,
|
||||
col_wrap=col_wrap, row_wrap=row_wrap, tex_depth=tex_depth, caps=caps, cap1=cap1, cap2=cap2, reverse=reverse,
|
||||
style=style, tex_extra=tex_extra, tex_skip=tex_skip, sidecaps=sidecaps, sidecap1=sidecap1, sidecap2=sidecap2,triangulate=triangulate)
|
||||
style=style, tex_extra=tex_extra, tex_skip=tex_skip, sidecaps=sidecaps, sidecap1=sidecap1, sidecap2=sidecap2,normals=normals,triangulate=triangulate)
|
||||
:
|
||||
assert(!(any([caps,cap1,cap2]) && !col_wrap), "col_wrap must be true if caps are requested (without texture)")
|
||||
assert(!(any([caps,cap1,cap2]) && row_wrap), "Cannot combine caps with row_wrap (without texture)")
|
||||
|
Reference in New Issue
Block a user