mirror of
https://github.com/revarbat/BOSL2.git
synced 2025-08-16 11:54:16 +02:00
texture support for vnf_vertex_array
This commit is contained in:
@@ -819,7 +819,8 @@ function prismoid(
|
||||
// You can specify the size of the ends using diameter or radius measured either inside or outside. Alternatively
|
||||
// you can give the length of the side of the polygon. You can specify chamfers and roundings for the ends, but not
|
||||
// the vertical edges. See {{rounded_prism()}} for prisms with rounded vertical edges. You can also specify texture for the side
|
||||
// faces, but note that texture is not compatible with any roundings or chamfers.
|
||||
// faces, but note that texture is not compatible with any roundings or chamfers.
|
||||
// See [Texturing](skin.scad#section-texturing) for more details on how textures work.
|
||||
// .
|
||||
// Anchors are based on the VNF of the prism. Especially for tapered or shifted prisms, this may give unexpected anchor positions, such as top side anchors
|
||||
// being located at the bottom of the shape, so confirm anchor positions before use.
|
||||
@@ -1158,7 +1159,9 @@ function regular_prism(n,
|
||||
// textured_tile(texture, [size], [w1=], [w2=], [ang=], [shift=], [h=/height=/thickness=], [atype=], [diff=], [tex_extra=], [tex_skip=], ...) [ATTACHMENTS];
|
||||
// vnf = textured_tile(texture, [size], [w1=], [w2=], [ang=], [shift=], [h=/height=/thickness=], [atype=], [tex_extra=], [tex_skip=], ...);
|
||||
// Description:
|
||||
// Creates a cuboid or trapezoidal prism and places a texture on the top face. You can specify the size by giving a `size` scalar or vector as is
|
||||
// Creates a cuboid or trapezoidal prism and places a texture on the top face.
|
||||
// See [Texturing](skin.scad#section-texturing) for more details on how textures work.
|
||||
// You can specify the size of the object by giving a `size` scalar or vector as is
|
||||
// usual for a cube. If you give a scalar, however, it applies only to the X and Y dimensions: the default is to create a thin tile, not a cube.
|
||||
// The Z size specifies the size of the shape **not** including the applied texture (in the same way that other textured objects work).
|
||||
// If you omit the Z value then for regular textures, the default thickness will be 0.1 which provides a thin backing layer. A zero thickness
|
||||
@@ -1373,14 +1376,9 @@ function textured_tile(
|
||||
height = is_def(size) ? default(size.z,default_thick) : one_defined([h,height,thickness],"h,height,thickness",dflt=default_thick),
|
||||
size = is_def(size) ? is_num(size) ? [size,size,1] : point3d(size,1) // We only use the x and y components of size
|
||||
: [w1,ysize],
|
||||
|
||||
tex = is_string(texture)? texture(texture,$fn=_tex_fn_default()) : texture,
|
||||
texture = tex_rot==0? tex
|
||||
: is_vnf(tex)? zrot(tex_rot, cp=[1/2,1/2], p=tex)
|
||||
: tex_rot==180? reverse([for (row=tex) reverse(row)])
|
||||
: tex_rot==270? [for (row=transpose(tex)) reverse(row)]
|
||||
: reverse(transpose(tex)),
|
||||
check_tex = _validate_texture(texture),
|
||||
|
||||
texture = _get_texture(texture, tex_rot),
|
||||
|
||||
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],
|
||||
@@ -1989,8 +1987,10 @@ function cylinder(h, r1, r2, center, r, d, d1, d2, anchor, spin=0, orient=UP) =
|
||||
// the cylinder or cone's sloped side. The more specific parameters like chamfer1 or rounding2 override the more
|
||||
// general ones like chamfer or rounding, so if you specify `rounding=3, chamfer2=3` you will get a chamfer at the top and
|
||||
// rounding at the bottom. You can specify extra height at either end for use with difference(); the extra height is ignored by
|
||||
// anchoring.
|
||||
// anchoring.
|
||||
// .
|
||||
// You can apply a texture to the cylinder using the usual texture parameters.
|
||||
// See [Texturing](skin.scad#section-texturing) for more details on how textures work.
|
||||
// When creating a textured cylinder, the number of facets is determined by the sampling of the texture. Any `$fn`, `$fa` or `$fs` values in
|
||||
// effect are ignored. To create a textured prism with a specified number of flat facets use {{regular_prism()}}. Anchors for cylinders
|
||||
// appear on the ideal cylinder, not on actual discretized shape the module produces. For anchors on the shape surface, use {{regular_prism()}}.
|
||||
|
243
skin.scad
243
skin.scad
@@ -3150,7 +3150,7 @@ function associate_vertices(polygons, split, curpoly=0) =
|
||||
|
||||
|
||||
|
||||
// DefineHeader(Table;Headers=Texture Name|Type|Description): Texture Values
|
||||
|
||||
|
||||
// Section: Texturing
|
||||
// Some operations are able to add texture to the objects they create. A texture can be any regularly repeated variation in the height of the surface.
|
||||
@@ -4036,6 +4036,29 @@ function _validate_texture(texture) =
|
||||
true;
|
||||
|
||||
|
||||
|
||||
function _tex_height(scale, inset, z) = scale<0 ? -(1-z - inset) * scale
|
||||
: (z - inset) * scale;
|
||||
|
||||
function _get_texture(texture, tex_rot, extra_rot=0) =
|
||||
let(
|
||||
tex_rot=!is_bool(tex_rot)? tex_rot
|
||||
: echo("boolean value for tex_rot is deprecated. Use a numerical angle divisible by 90.") tex_rot?90:0
|
||||
)
|
||||
assert(is_num(tex_rot) && posmod(tex_rot,90)==0, "tex_rot must be a multiple of 90 degrees")
|
||||
let(
|
||||
tex = is_string(texture)? texture(texture,$fn=_tex_fn_default()) : texture,
|
||||
check_tex = _validate_texture(tex),
|
||||
tex_rot = posmod(tex_rot+extra_rot,360),
|
||||
)
|
||||
tex_rot==0 ? tex
|
||||
: is_vnf(tex)? zrot(tex_rot, cp=[1/2,1/2], p=tex)
|
||||
: tex_rot==180? reverse([for (row=tex) reverse(row)])
|
||||
: tex_rot==270? [for (row=transpose(tex)) reverse(row)]
|
||||
: reverse(transpose(tex));
|
||||
|
||||
|
||||
|
||||
function _textured_linear_sweep(
|
||||
region, texture, tex_size=[5,5],
|
||||
h, counts, inset=false, rot=0,
|
||||
@@ -4065,14 +4088,8 @@ function _textured_linear_sweep(
|
||||
|
||||
caps = is_bool(caps) ? [caps,caps] : caps,
|
||||
regions = is_path(region,2)? [[region]] : region_parts(region),
|
||||
tex = is_string(texture)? texture(texture,$fn=_tex_fn_default()) : texture,
|
||||
dummy = assert(is_undef(samples) || is_vnf(tex), "You gave the tex_samples argument with a heightfield texture, which is not permitted. Use the n= argument to texture() instead"),
|
||||
dummy2=is_bool(rot)?echo("boolean value for tex_rot is deprecated. Use a numerical angle, one of 0, 90, 180, or 270.")0:0,
|
||||
texture = !rot? tex :
|
||||
is_vnf(tex)? zrot(is_num(rot)?rot:90, cp=[1/2,1/2], p=tex) :
|
||||
rot==180? reverse([for (row=tex) reverse(row)]) :
|
||||
rot==270? [for (row=transpose(tex)) reverse(row)] :
|
||||
reverse(transpose(tex)),
|
||||
texture = _get_texture(texture, tex_rot),
|
||||
dummy = assert(is_undef(samples) || is_vnf(texture), "You gave the tex_samples argument with a heightfield texture, which is not permitted. Use the n= argument to texture() instead"),
|
||||
h = first_defined([h, l, height, length, 1]),
|
||||
inset = is_num(inset)? inset : inset? 1 : 0,
|
||||
twist = default(twist, 0),
|
||||
@@ -4081,7 +4098,6 @@ function _textured_linear_sweep(
|
||||
is_num(scale)? [scale,scale,1] : scale,
|
||||
samples = !is_vnf(texture)? len(texture[0]) :
|
||||
is_num(samples)? samples : 8,
|
||||
check_tex = _validate_texture(texture),
|
||||
vnf_tile =
|
||||
!is_vnf(texture) || samples==1 ? texture
|
||||
:
|
||||
@@ -4352,15 +4368,8 @@ function _textured_revolution(
|
||||
)
|
||||
assert(closed || is_path(shape,2))
|
||||
let(
|
||||
tex = is_string(texture)? texture(texture,$fn=_tex_fn_default()) : texture,
|
||||
texture = _get_texture(texture, tex_rot),
|
||||
dummy = assert(is_undef(samples) || is_vnf(tex), "You gave the tex_samples argument with a heightfield texture, which is not permitted. Use the n= argument to texture() instead"),
|
||||
dummy2=is_bool(rot)?echo("boolean value for tex_rot is deprecated. Use a numerical angle, one of 0, 90, 180, or 270.")0:0,
|
||||
texture = !rot? tex :
|
||||
is_vnf(tex)? zrot(is_num(rot)?rot:90, cp=[1/2,1/2], p=tex) :
|
||||
rot==180? reverse([for (row=tex) reverse(row)]) :
|
||||
rot==270? [for (row=transpose(tex)) reverse(row)] :
|
||||
reverse(transpose(tex)),
|
||||
check_tex = _validate_texture(texture),
|
||||
inset = is_num(inset)? inset : inset? 1 : 0,
|
||||
samples = !is_vnf(texture)? len(texture) :
|
||||
is_num(samples)? samples : 8,
|
||||
@@ -4620,5 +4629,203 @@ 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) =
|
||||
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")
|
||||
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")
|
||||
assert(is_consistent(points), "Non-rectangular or invalid point array")
|
||||
let(
|
||||
cap1 = first_defined([cap1,caps,false]),
|
||||
cap2 = first_defined([cap2,caps,false]),
|
||||
sidecap1 = first_defined([sidecap1,sidecaps,false]),
|
||||
sidecap2 = first_defined([sidecap2,sidecaps,false]),
|
||||
tex_inset = is_num(tex_inset)? tex_inset : tex_inset? 1 : 0,
|
||||
texture = _get_texture(texture, tex_rot),
|
||||
dummy = assert(is_undef(tex_samples) || is_vnf(texture),
|
||||
"You gave the tex_samples argument with a heightfield texture, which is not permitted. Use the n= argument to texture() instead"),
|
||||
ptsize=[len(points[0]), len(points)],
|
||||
tex_reps = is_def(tex_reps) ? tex_reps
|
||||
: let(
|
||||
tex_size = is_undef(tex_sizes) ? [5,5] : force_list(tex_size,2),
|
||||
xsize = norm(points[0][0]-points[0][1])*(ptsize.x+(col_wrap?1:0)),
|
||||
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),
|
||||
getscale = function(x,y) (x+y)/2
|
||||
)
|
||||
!is_vnf(texture) ? // heightmap case
|
||||
let(
|
||||
extra = is_def(tex_extra) ? force_list(tex_extra,2)
|
||||
: [col_wrap?0:1, row_wrap?0:1],
|
||||
skip = is_def(tex_skip) ? force_list(tex_skip,2) : [0,0],
|
||||
texsize = [len(texture[0]), len(texture)],
|
||||
fullsize = [texsize.x*tex_reps.x+extra.x-skip.x, texsize.y*tex_reps.y+extra.y-skip.y],
|
||||
res_points = resample(points,fullsize, col_wrap=col_wrap, row_wrap=row_wrap),
|
||||
res_normals=resample(normals,fullsize, col_wrap=col_wrap, row_wrap=row_wrap),
|
||||
local_scale = [for(y=[0:1:fullsize.y-1])
|
||||
[for(x=[0:1:fullsize.x-1])
|
||||
let(
|
||||
xlen = [
|
||||
if(x>0 || col_wrap) norm(res_points[y][x] - select(res_points[y], x-1)),
|
||||
if(x<fullsize.x-1 || col_wrap) norm(res_points[y][x] - select(res_points[y], x+1))
|
||||
],
|
||||
ylen = [
|
||||
if(y>0 || row_wrap) norm(res_points[y][x] - select(res_points,y-1)[x]),
|
||||
if(y<fullsize.y-1 || row_wrap) norm(res_points[y][x] - select(res_points,y+1)[x])
|
||||
]
|
||||
)
|
||||
getscale(mean(xlen),mean(ylen))
|
||||
]
|
||||
],
|
||||
tex_surf =
|
||||
[for(y=[0:1:fullsize.y-1])
|
||||
[for(x=[0:1:fullsize.x-1])
|
||||
let(yind = (y+skip.y)%texsize.y,
|
||||
xind = (x+skip.x)%texsize.x,
|
||||
)
|
||||
res_points[y][x] + _tex_height(tex_depth,tex_inset,texture[yind][xind]) * res_normals[y][x]*(reverse?-1:1)*local_scale[y][x]/local_scale[0][0]
|
||||
]
|
||||
]
|
||||
)
|
||||
vnf_vertex_array(tex_surf, row_wrap=row_wrap, col_wrap=col_wrap, reverse=reverse,style=style, caps=caps, triangulate=triangulate)
|
||||
: // VNF case
|
||||
let(
|
||||
local_scale = [for(y=[-1:1:ptsize.y-1])
|
||||
[for(x=[-1:1:ptsize.x-1])
|
||||
((!col_wrap && (x<0 || x==ptsize.x-1))
|
||||
|| (!row_wrap && (y<0 || y==ptsize.y-1))) ? undef
|
||||
: let(
|
||||
dx = [norm(select(select(points,y),x) - select(select(points,y),x+1)),
|
||||
norm(select(select(points,y+1),x) - select(select(points,y+1),x+1))],
|
||||
dy = [norm(select(select(points,y),x) - select(select(points,y+1),x)),
|
||||
norm(select(select(points,y),x+1) - select(select(points,y+1),x+1))]
|
||||
)
|
||||
getscale(mean(dx),mean(dy))]],
|
||||
samples = default(tex_samples,8),
|
||||
vnf = samples==1? texture :
|
||||
let(
|
||||
s = 1 / 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]) [
|
||||
approx(p.x,0)? 0 : approx(p.x,1)? 1 : p.x,
|
||||
approx(p.y,0)? 0 : approx(p.y,1)? 1 : p.y,
|
||||
p.z
|
||||
]
|
||||
],
|
||||
vnft[1]
|
||||
]
|
||||
)
|
||||
zvnf,
|
||||
yedge_paths = !row_wrap ? _tile_edge_path_list(vnf,1) : undef,
|
||||
xedge_paths = !col_wrap ? _tile_edge_path_list(vnf,0) : undef,
|
||||
trans_pt = function(x,y,pt)
|
||||
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),
|
||||
yind = floor(refy),
|
||||
xfrac = refx-xind,
|
||||
yfrac = refy-yind,
|
||||
corners = [points[yind%ptsize.y][xind%ptsize.x], points[(yind+1)%ptsize.y][xind%ptsize.x],
|
||||
points[yind%ptsize.y][(xind+1)%ptsize.x], points[(yind+1)%ptsize.y][(xind+1)%ptsize.x]],
|
||||
base = bilerp(corners,xfrac, yfrac),
|
||||
scale_list = xfrac==0 && yfrac==0 ? [local_scale[yind][xind], local_scale[yind][xind+1], local_scale[yind+1][xind], local_scale[yind+1][xind+1]]
|
||||
: xfrac==0 ? [local_scale[yind+1][xind], local_scale[yind+1][xind+1]]
|
||||
: yfrac==0 ? [local_scale[yind][xind+1], local_scale[yind+1][xind+1]]
|
||||
: [ local_scale[yind+1][xind+1]],
|
||||
scale = mean([for(s=scale_list) if (is_def(s)) s])/local_scale[1][1],
|
||||
normal = bilerp([normals[yind%ptsize.y][xind%ptsize.x], normals[(yind+1)%ptsize.y][xind%ptsize.x],
|
||||
normals[yind%ptsize.y][(xind+1)%ptsize.x], normals[(yind+1)%ptsize.y][(xind+1)%ptsize.x]],
|
||||
xfrac, yfrac)
|
||||
)
|
||||
base + _tex_height(tex_depth,tex_inset,pt.z) * normal*(reverse?-1:1) * scale,
|
||||
fullvnf = vnf_join([
|
||||
for(y=[0:1:tex_reps.y-1], x=[0:1:tex_reps.x-1])
|
||||
[
|
||||
[for(pt=vnf[0]) trans_pt(x,y,pt)],
|
||||
vnf[1]
|
||||
],
|
||||
for(y=[if (cap1) 0, if (cap2) tex_reps.y-1])
|
||||
let(
|
||||
cap_paths = [
|
||||
if (col_wrap && len(yedge_paths[0])>0)
|
||||
[for(x=[0:1:tex_reps.x-1], pt=yedge_paths[0][0])
|
||||
trans_pt(x,y,[pt.x,y?0:1,pt.z])],
|
||||
if (!row_wrap)
|
||||
for(closed_path=yedge_paths[1], x=[0:1:tex_reps.x-1])
|
||||
[for(pt = closed_path) trans_pt(x,y,[pt.x,y?0:1,pt.z])]
|
||||
]
|
||||
)
|
||||
for(path=cap_paths) [path, [count(path,reverse=y==0)]],
|
||||
if (!col_wrap)
|
||||
for(x=[if (sidecap1) 0, if (sidecap2) tex_reps.x-1])
|
||||
let(
|
||||
cap_paths = [for(closed_path=xedge_paths[1], y=[0:1:tex_reps.y-1])
|
||||
[for(pt = closed_path) trans_pt(x,y,[x?1:0,pt.y,pt.z])]]
|
||||
)
|
||||
for(path=cap_paths) [path, [count(path,reverse=x!=0)]]
|
||||
])
|
||||
)
|
||||
reverse ? vnf_reverse_faces(fullvnf) : fullvnf;
|
||||
|
||||
///// These need to be either hidden or documented and placed somewhere.
|
||||
|
||||
|
||||
function bilerp(pts,x,y) =
|
||||
[1,x,y,x*y]*[[1, 0, 0, 0],[-1, 0, 1, 0],[-1,1,0,0],[1,-1,-1,1]]*pts;
|
||||
|
||||
|
||||
function resample(data, size, col_wrap=false, row_wrap=false) =
|
||||
let(
|
||||
xL=len(data[0]),
|
||||
yL=len(data),
|
||||
lastx=xL-(col_wrap?0:1),
|
||||
lasty=yL-(row_wrap?0:1),
|
||||
lastoutx = size.x - (col_wrap?0:1),
|
||||
lastouty = size.y - (row_wrap?0:1),
|
||||
xscale = lastx/lastoutx,
|
||||
yscale = lasty/lastouty
|
||||
)
|
||||
[
|
||||
for(y=[0:1:lastouty])
|
||||
[
|
||||
for(x=[0:1:lastoutx])
|
||||
let(
|
||||
sx = xscale*x,
|
||||
sy = yscale*y,
|
||||
xind=floor(sx),
|
||||
yind=floor(sy)
|
||||
)
|
||||
bilerp([data[yind%yL][xind%xL], data[(yind+1)%yL][xind%xL],
|
||||
data[yind%yL][(xind+1)%xL], data[(yind+1)%yL][(xind+1)%xL]],
|
||||
sx-xind, sy-yind)
|
||||
]
|
||||
];
|
||||
|
||||
|
||||
|
||||
|
||||
function surfnormals(data, col_wrap=false, row_wrap=false) =
|
||||
let(
|
||||
rowderivs = [for(y=[0:1:len(data)-1]) path_tangents(data[y],closed=col_wrap)],
|
||||
colderivs = [for(x=[0:1:len(data[0])-1]) path_tangents(column(data,x), closed=row_wrap)]
|
||||
)
|
||||
[for(y=[0:1:len(data)-1])
|
||||
[for(x=[0:1:len(data[0])-1])
|
||||
cross(colderivs[x][y],rowderivs[y][x])]];
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
50
vnf.scad
50
vnf.scad
@@ -48,6 +48,23 @@ EMPTY_VNF = [[],[]]; // The standard empty VNF with no vertices or faces.
|
||||
// adds a vertex in the center of each quadrilateral and creates four triangles, and the "convex" and "concave" styles
|
||||
// choose the locally convex/concave subdivision. The "min_area" option creates the triangulation with the minimal area. Degenerate faces
|
||||
// are not included in the output, but if this results in unused vertices they still appear in the output.
|
||||
// .
|
||||
// You can apply a texture to the vertex array VNF using the usual texture parameters.
|
||||
// See [Texturing](skin.scad#section-texturing) for more details on how textures work.
|
||||
// The top left corner of the texture tile will be aligned with `points[0][0]`, and the the X and Y directions correspond to `points[y][x]`.
|
||||
// In practice, it is probably easiest to observe the result and apply a suitable texture tile rotation by setting `tex_rot` if the result
|
||||
// is not what you wanted. The reference scale of your point data is also taken from the square at the [0][0] corner. This determines
|
||||
// the meaning of `tex_size` and it also affects the vertical texture scale. The size of the texture tiles will be proportional to the point
|
||||
// spacing of the location where they are placed, so if the points are closer together, you will get small texture elements. The `tex_depth` you
|
||||
// specify will be correct at the `points[0][0]` but will be different at places in the point array where the scale is different. Note that this
|
||||
// differs from {{rotate_sweep()}} which uses a uniform resampling of the curve you specify.
|
||||
// .
|
||||
// The point data for `vnf_vertex_array()` is resampled using bilinear interpolation to match the required point density of the tile count, but the
|
||||
// sampling is based on the grid, not on the distance between points. If you want to
|
||||
// avoid resampling, match the point data to the required point number for your tile count. For height field textures this means
|
||||
// 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.
|
||||
// Arguments:
|
||||
// points = A list of vertices to divide into columns and rows.
|
||||
// ---
|
||||
@@ -60,6 +77,18 @@ EMPTY_VNF = [[],[]]; // The standard empty VNF with no vertices or faces.
|
||||
// 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
|
||||
// convexity = (module) Max number of times a line could intersect a wall of the shape.
|
||||
// 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
|
||||
// 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
|
||||
// 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`
|
||||
@@ -181,10 +210,15 @@ module vnf_vertex_array(
|
||||
reverse=false,
|
||||
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,
|
||||
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);
|
||||
col_wrap=col_wrap, row_wrap=row_wrap, reverse=reverse, style=style,triangulate=triangulate,
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -196,14 +230,22 @@ function vnf_vertex_array(
|
||||
row_wrap=false,
|
||||
reverse=false,
|
||||
style="default",
|
||||
triangulate = false
|
||||
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
|
||||
) =
|
||||
assert(!(any([caps,cap1,cap2]) && !col_wrap), "col_wrap must be true if caps are requested")
|
||||
assert(!(any([caps,cap1,cap2]) && row_wrap), "Cannot combine caps with row_wrap")
|
||||
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")
|
||||
assert(is_consistent(points), "Non-rectangular or invalid point array")
|
||||
assert(is_bool(triangulate))
|
||||
is_def(texture) ?
|
||||
_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)
|
||||
:
|
||||
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)")
|
||||
let(
|
||||
pts = flatten(points),
|
||||
pcnt = len(pts),
|
||||
|
Reference in New Issue
Block a user