mirror of
https://github.com/revarbat/BOSL2.git
synced 2025-04-21 16:22:28 +02:00
texture code cleanup
This commit is contained in:
parent
25f4d82ba0
commit
236a66c46d
37
math.scad
37
math.scad
@ -139,6 +139,43 @@ function lerpn(a,b,n,endpoint=true) =
|
||||
let( d = n - (endpoint? 1 : 0) )
|
||||
[for (i=[0:1:n-1]) let(u=i/d) (1-u)*a + u*b];
|
||||
|
||||
// Function: bilerp()
|
||||
// Synopsis: Bi-linear interpolation between four values
|
||||
// Topics: Interpolation, Math
|
||||
// See Also: lerpn()
|
||||
// Usage:
|
||||
// x = lerp(pts, x, y);
|
||||
// Description:
|
||||
// Compute bilinear interpolation between four values using two
|
||||
// coordinates that are meant to lie in [0,1]. (If they are outside
|
||||
// this range, the function will extrapolate values.) The `pts`
|
||||
// argument is a list of the four values at the for corners, `[A,B,C,D]`.
|
||||
// These values are arranged on the corners as shown below. The `x` and
|
||||
// `y` parameters give the fraction of the distance from the left and bottom
|
||||
// respectively.
|
||||
// Figure(Med,2D,NoScales): The layout of the points for the bilinear interpolation.
|
||||
// stroke(square(10),closed=true,width=.5);
|
||||
// move([-1,-1])
|
||||
// hide("thing")
|
||||
// tag_this("thing") square(10)
|
||||
// color("black")grid_copies(n=[2,2],spacing=14) text("ABCD"[$idx],size=3);
|
||||
// pt=[.6,.7]*10;
|
||||
// color("red")move(pt) circle(r=1/2,$fn=12);
|
||||
// color("blue"){
|
||||
// stroke([[-1.5,.3],[-1.5,pt.y]], width=1/2, color="blue",endcap2="arrow2");
|
||||
// stroke([[0,-1.5],[pt.x,-1.5]], width=1/2, color="blue",endcap2="arrow2");
|
||||
// fwd(4.5)right(3)text("x",size=2);
|
||||
// back(2)left(4)text("y",size=2);
|
||||
// }
|
||||
// Arguments:
|
||||
// points = Four point values at the corners
|
||||
// x = First proportional distance
|
||||
// y = Second proportional distance
|
||||
|
||||
|
||||
function bilerp(points,x,y) =
|
||||
[1,y,x,x*y]*[[1, 0, 0, 0],[-1, 0, 1, 0],[-1,1,0,0],[1,-1,-1,1]]*points;
|
||||
|
||||
|
||||
|
||||
// Section: Miscellaneous Functions
|
||||
|
26
paths.scad
26
paths.scad
@ -765,6 +765,32 @@ function path_torsion(path, closed=false) =
|
||||
];
|
||||
|
||||
|
||||
// Function: surface_normals()
|
||||
// Synopsis: Estimates the normals to a surface defined by a point array
|
||||
// Topics: Math, Geometry
|
||||
// See Also: path_tangents(), path_normals()
|
||||
// Usage:
|
||||
// normals = surface_normals(surf, [col_wrap=], [row_wrap=]);
|
||||
// Description:
|
||||
// Numerically estimate the normals to a surface defined by a 2d array of 3d points, which can
|
||||
// also be regarded as an array of paths (all of the same length).
|
||||
// Arguments:
|
||||
// surf = surface in 3d defined by a 2d array of points
|
||||
// ---
|
||||
// row_wrap = if true then wrap path in the row direction (first index)
|
||||
// col_wrap = if true then wrap path in the column direction (second index)
|
||||
|
||||
function surface_normals(surf, col_wrap=false, row_wrap=false) =
|
||||
let(
|
||||
rowderivs = [for(y=[0:1:len(surf)-1]) path_tangents(surf[y],closed=col_wrap)],
|
||||
colderivs = [for(x=[0:1:len(surf[0])-1]) path_tangents(column(surf,x), closed=row_wrap)]
|
||||
)
|
||||
[for(y=[0:1:len(surf)-1])
|
||||
[for(x=[0:1:len(surf[0])-1])
|
||||
cross(colderivs[x][y],rowderivs[y][x])]];
|
||||
|
||||
|
||||
|
||||
// Section: Breaking paths up into subpaths
|
||||
|
||||
|
||||
|
@ -877,8 +877,8 @@ function prismoid(
|
||||
// realign = If true, rotate the prism by half the angle of one face so that a face points in the X+ direction. Default: false
|
||||
// teardrop = If given as a number, rounding around the bottom edge of the prism won't exceed this many degrees from vertical. If true, the limit angle is 45 degrees. Default: `false`
|
||||
// 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_reps = If given instead of tex_size, a 2-vector giving the number of texture tile repetitions in the horizontal and vertical directions.
|
||||
// tex_size = An optional 2D target size (2-vector or scalar) for the textures. 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 scalar or 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.
|
||||
@ -1188,8 +1188,9 @@ function regular_prism(n,
|
||||
// .
|
||||
// Most of the heightfield textures are designed to repeat in a way that requires one extra line of the texture to complete the pattern.
|
||||
// The `tex_extra` parameter specifies the number of extra lines to repeat at the end of the texture and it defaults to 1 because most textures
|
||||
// do requires this extra line. If you need to disable this feature you can set the `tex_extra` parameter to 0, or you can set it to a list of two
|
||||
// booleans to control the extra line of texture in the X and Y directions independently. The `tex_extra` parameter
|
||||
// do requires this extra line. There is one exception: if you specify only a single tile, then you are probably using an image for your texture and do not want a repeated line, so in
|
||||
// this case, `tex_extra` defaults to zero. If you need to adjust the number of extra lines you can set the `tex_extra` parameter to 0, or you can set it to a list of two
|
||||
// integers to control the extra line of texture in the X and Y directions independently. The `tex_extra` parameter
|
||||
// is ignored for VNF textures. A heightfield texture may also have extra margin along a starting side that makes the texture unbalanced. You can
|
||||
// removed this using the `tex_skip` parameter, which defaults to zero and similarly specifies the number of lines to skip in the X and Y directions at
|
||||
// the starting edges of the tile. You must have enough tile repetitions to accomodate the specified skip.
|
||||
@ -1206,13 +1207,13 @@ function regular_prism(n,
|
||||
// ang = Specify the front angle(s) of the trapezoidal prism. Can give a scalar for an isosceles trapezoidal prism or a list of two angles, the left angle and right angle. You must omit one of `h`, `w1`, or `w2` to allow the freedom to control the angles.
|
||||
// shift = Scalar value to shift the back of the trapezoidal prism along the X axis by. Cannot be combined with ang. Default: 0
|
||||
// h / height / thickness = The thickness in the Z direction of the base that the texture sits on. Default: 0.1 or for inset textures 0.1 more than the inset depth
|
||||
// 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_reps = If given instead of tex_size, a 2-vector giving the number of texture tile repetitions in the horizontal and vertical directions.
|
||||
// tex_size = An optional 2D target size (2-vector or scalar) for the textures. 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 scalar or 2-vector giving the integer 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.
|
||||
// diff = if set to true then "remove" and "keep" tags are set to cut out a space for the texture so that inset textures can be attached. Default: false
|
||||
// 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_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: 0 if there is only one tile, 1 otherwise
|
||||
// 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
|
||||
// style = {{vnf_vertex_array()}} style used to triangulate heightfield textures. Default: "min_edge"
|
||||
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
|
||||
@ -1303,7 +1304,7 @@ function textured_tile(
|
||||
texture,
|
||||
size,
|
||||
ysize, height, w1, w2, ang, h, shift, thickness,
|
||||
tex_size=[5,5],
|
||||
tex_size,
|
||||
tex_reps,
|
||||
tex_inset=false,
|
||||
tex_rot=0,
|
||||
@ -1315,15 +1316,13 @@ function textured_tile(
|
||||
anchor=CENTER, spin=0, orient=UP,
|
||||
_return_anchor=false
|
||||
) =
|
||||
assert(tex_reps==undef || is_vector(tex_reps,2))
|
||||
assert(tex_size==undef || is_vector(tex_size,2))
|
||||
assert(in_list(tex_rot,[0,90,180,270]))
|
||||
assert(tex_reps==undef || is_int(tex_reps) || (all_integer(tex_reps) && len(tex_reps)==2), "tex_reps must be an integer or list of two integers")
|
||||
assert(tex_size==undef || is_vector(tex_size,2) || is_finite(tex_size))
|
||||
assert(num_defined([tex_size, tex_reps])<2, "Cannot give both tex_size and tex_reps")
|
||||
assert(is_undef(size) || is_num(size) || is_vector(size,2) || is_vector(size,3), "size must be a 2-vector or 3-vector")
|
||||
assert(is_undef(size) || num_defined([ysize,h, height, thickness, w1,w2,ang])==0, "Cannot combine size with any other dimensional specifications")
|
||||
|
||||
let(
|
||||
extra = is_list(tex_extra) ? tex_extra : [tex_extra,tex_extra],
|
||||
skip = is_list(tex_skip) ? tex_skip : [tex_skip,tex_skip],
|
||||
inset = is_num(tex_inset)? tex_inset : tex_inset? 1 : 0,
|
||||
default_thick = inset>0 ? 0.1+abs(tex_depth)*inset : 0.1,
|
||||
extra_ht = max(0,abs(tex_depth)*(1-inset)),
|
||||
@ -1346,8 +1345,12 @@ function textured_tile(
|
||||
|
||||
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)],
|
||||
tex_reps = is_def(tex_reps) ? force_list(tex_reps,2)
|
||||
: let(tex_size=is_undef(tex_size)? [5,5] : force_list(tex_size,2))
|
||||
[round(size.x/tex_size.x), round(size.y/tex_size.y)],
|
||||
extra = is_undef(extra)? tex_reps == [1,1] ? [0,0] : [1,1]
|
||||
: force_list(tex_extra,2),
|
||||
skip = force_list(tex_skip,2),
|
||||
scale = [size.x/tex_reps.x, size.y/tex_reps.y],
|
||||
setz=function (v,z) [v.x,v.y,z],
|
||||
vnf = !is_vnf(texture) ?
|
||||
@ -2060,8 +2063,8 @@ function cylinder(h, r1, r2, center, r, d, d1, d2, anchor, spin=0, orient=UP) =
|
||||
// realign = If true, rotate the cylinder by half the angle of one face.
|
||||
// teardrop = If given as a number, rounding around the bottom edge of the cylinder won't exceed this many degrees from vertical. If true, the limit angle is 45 degrees. Default: `false`
|
||||
// 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_reps = If given instead of tex_size, a 2-vector giving the number of texture tile repetitions in the horizontal and vertical directions.
|
||||
// tex_size = An optional 2D target size (2-vector or scalar) for the textures. 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 scalar or 2-vector giving the integer 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.
|
||||
|
84
skin.scad
84
skin.scad
@ -552,8 +552,8 @@ function skin(profiles, slices, refine=1, method="direct", sampling, caps, close
|
||||
// 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 are 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 are 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 on the extrusion.
|
||||
// tex_size = An optional 2D target size (2-vector or scalar) for the textures. 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 scalar or 2-vector giving the integer 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.
|
||||
@ -897,8 +897,8 @@ function linear_sweep(
|
||||
// ---
|
||||
// start = Start extrusion at this angle counterclockwise from the X+ axis. Default:0
|
||||
// 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 are 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 direction perpendicular to extrusion and in the direction parallel to extrusion.
|
||||
// tex_size = An optional 2D target size (2-vector or scalar) for the textures. 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 scalar or 2-vector giving the integer 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.
|
||||
@ -1602,8 +1602,8 @@ module spiral_sweep(poly, h, r, turns=1, taper, r1, r2, d, d1, d2, internal=fals
|
||||
// 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 are 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_size = An optional 2D target size (2-vector or scalar) for the texture at the first point of your shape and first path point. 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 scalar or 2-vector giving the integer 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.
|
||||
@ -2340,8 +2340,8 @@ function _ofs_face_edge(face,firstlen,second=false) =
|
||||
// ---
|
||||
// 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 are 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_size = An optional 2D target size (2-vector or scalar) for the texture at the first point of your shape and first transformation. 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 scalar or 2-vector giving the integer 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.
|
||||
@ -2432,7 +2432,7 @@ function sweep(shape, transforms, closed=false, caps, style="min_edge",
|
||||
normals = is_def(normals) ? normals
|
||||
: (!(is_def(texture) && (closed || _closed_for_normals))) ? undef
|
||||
: let(
|
||||
n = surfnormals(select(points,0,-2), col_wrap=true, row_wrap=true)
|
||||
n = surface_normals(select(points,0,-2), col_wrap=true, row_wrap=true)
|
||||
)
|
||||
[each n, n[0]]
|
||||
)
|
||||
@ -4163,11 +4163,13 @@ function _textured_linear_sweep(
|
||||
) =
|
||||
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))
|
||||
assert(counts==undef || is_int(counts) || (all_integer(counts) && len(counts)==2), "tex_reps must be an integer or list of two integers")
|
||||
assert(tex_size==undef || is_vector(tex_size,2) || is_finite(tex_size))
|
||||
assert(is_bool(rot) || in_list(rot,[0,90,180,270]))
|
||||
assert(is_bool(caps) || is_bool_list(caps,2))
|
||||
let(
|
||||
counts = is_undef(counts) ? undef : force_list(counts,2),
|
||||
tex_size = force_list(tex_size,2),
|
||||
transform_pt = function(tileind,tilex,tilez,samples,inset,scale,bases,norms)
|
||||
let(
|
||||
pos = (tileind + tilex) * samples, // tileind is which tile, tilex is position in a tile
|
||||
@ -4218,10 +4220,7 @@ function _textured_linear_sweep(
|
||||
for (path = rgn) let(
|
||||
path = reverse(path),
|
||||
plen = path_length(path, closed=true),
|
||||
counts = is_vector(counts,2)? counts :
|
||||
is_vector(tex_size,2)
|
||||
? [round(plen/tex_size.x), max(1,round(h/tex_size.y)), ]
|
||||
: [ceil(6*plen/h), 6],
|
||||
counts = is_def(counts) ? counts : [round(plen/tex_size.x), max(1,round(h/tex_size.y)) ],
|
||||
bases = resample_path(path, n=counts.x * samples, closed=true),
|
||||
norms = path_normals(bases, closed=true),
|
||||
vnf = is_vnf(texture)
|
||||
@ -4292,10 +4291,7 @@ function _textured_linear_sweep(
|
||||
for (path = rgn) let(
|
||||
path = reverse(path),
|
||||
plen = path_length(path, closed=true),
|
||||
counts = is_vector(counts,2)? counts :
|
||||
is_vector(tex_size,2)
|
||||
? [round(plen/tex_size.x), max(1,round(h/tex_size.y)), ]
|
||||
: [ceil(6*plen/h), 6],
|
||||
counts = is_def(counts) ? counts : [round(plen/tex_size.x), max(1,round(h/tex_size.y)) ],
|
||||
bases = resample_path(path, n=counts.x * samples, closed=true),
|
||||
norms = path_normals(bases, closed=true),
|
||||
nupath = [
|
||||
@ -4310,10 +4306,7 @@ function _textured_linear_sweep(
|
||||
let(
|
||||
path = reverse(path),
|
||||
plen = path_length(path, closed=true),
|
||||
counts = is_vector(counts,2)? counts :
|
||||
is_vector(tex_size,2)
|
||||
? [round(plen/tex_size.x), max(1,round(h/tex_size.y)), ]
|
||||
: [ceil(6*plen/h), 6],
|
||||
counts = is_def(counts) ? counts : [round(plen/tex_size.x), max(1,round(h/tex_size.y))],
|
||||
bases = resample_path(path, n=counts.x * samples, closed=true),
|
||||
norms = path_normals(bases, closed=true),
|
||||
modpaths = [for (j = [0:1:counts.x-1], cpath = edge_closed_paths)
|
||||
@ -4430,8 +4423,8 @@ function _textured_revolution(
|
||||
assert(is_path(shape,[2]) || is_region(shape))
|
||||
assert(is_undef(samples) || is_int(samples))
|
||||
assert(is_bool(closed))
|
||||
assert(counts==undef || is_vector(counts,2))
|
||||
assert(tex_size==undef || is_vector(tex_size,2))
|
||||
assert(counts==undef || is_int(counts) || (all_integer(counts) && len(counts)==2), "tex_reps must be an integer or list of two integers")
|
||||
assert(tex_size==undef || is_vector(tex_size,2) || is_finite(tex_size))
|
||||
assert(is_bool(rot) || in_list(rot,[0,90,180,270]))
|
||||
let( taper_is_ok = is_undef(taper) || (is_finite(taper) && taper>=0 && taper<50) || is_path(taper,2) )
|
||||
assert(taper_is_ok, "Bad taper= value.")
|
||||
@ -4452,6 +4445,8 @@ function _textured_revolution(
|
||||
)
|
||||
assert(closed || is_path(shape,2))
|
||||
let(
|
||||
counts = is_undef(counts) ? undef : force_list(counts,2),
|
||||
tex_size = force_list(tex_size,2),
|
||||
texture = _get_texture(texture, 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"),
|
||||
inset = is_num(inset)? inset : inset? 1 : 0,
|
||||
@ -4699,7 +4694,7 @@ module _textured_revolution(
|
||||
|
||||
function _textured_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,normals) =
|
||||
assert(tex_reps==undef || is_vector(tex_reps,2))
|
||||
assert(tex_reps==undef || is_int(tex_reps) || (all_integer(tex_reps) && len(tex_reps)==2), "tex_reps must be an integer or list of two integers")
|
||||
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"]))
|
||||
@ -4715,14 +4710,14 @@ function _textured_point_array(points, texture, tex_reps, tex_size, tex_samples,
|
||||
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
|
||||
tex_reps = is_def(tex_reps) ? force_list(tex_reps,2)
|
||||
: let(
|
||||
tex_size = is_undef(tex_size) ? [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))
|
||||
)
|
||||
[max(1,round(xsize/tex_size.x)), max(1,round(ysize/tex_size.y))],
|
||||
normals = default(normals,surfnormals(points, col_wrap=col_wrap, row_wrap=row_wrap)),
|
||||
normals = default(normals,surface_normals(points, col_wrap=col_wrap, row_wrap=row_wrap)),
|
||||
getscale = function(x,y) (x+y)/2
|
||||
)
|
||||
!is_vnf(texture) ? // heightmap case
|
||||
@ -4732,8 +4727,8 @@ function _textured_point_array(points, texture, tex_reps, tex_size, tex_samples,
|
||||
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),
|
||||
res_points = _resample_point_array(points,fullsize, col_wrap=col_wrap, row_wrap=row_wrap),
|
||||
res_normals= _resample_point_array(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(
|
||||
@ -4799,7 +4794,7 @@ function _textured_point_array(points, texture, tex_reps, tex_size, tex_samples,
|
||||
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),
|
||||
base = bilerp(corners,yfrac, xfrac),
|
||||
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]]
|
||||
@ -4807,7 +4802,7 @@ function _textured_point_array(points, texture, tex_reps, tex_size, tex_samples,
|
||||
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)
|
||||
yfrac, xfrac)
|
||||
)
|
||||
base + _tex_height(tex_depth,tex_inset,pt.z) * normal*(reverse?-1:1) * scale,
|
||||
fullvnf = vnf_join([
|
||||
@ -4839,14 +4834,13 @@ function _textured_point_array(points, texture, tex_reps, tex_size, tex_samples,
|
||||
)
|
||||
reverse ? vnf_reverse_faces(fullvnf) : fullvnf;
|
||||
|
||||
///// These need to be either hidden or documented and placed somewhere.
|
||||
|
||||
// Resamples a point array to the specified size.
|
||||
// In use above, data is a list of points in R^3 on a grid
|
||||
// and size is the desired dimensions of the output array covering the
|
||||
// same data.
|
||||
|
||||
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) =
|
||||
function _resample_point_array(data, size, col_wrap=false, row_wrap=false) =
|
||||
let(
|
||||
xL=len(data[0]),
|
||||
yL=len(data),
|
||||
@ -4869,24 +4863,12 @@ function resample(data, size, col_wrap=false, row_wrap=false) =
|
||||
)
|
||||
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)
|
||||
sy-yind, sx-xind)
|
||||
]
|
||||
];
|
||||
|
||||
|
||||
|
||||
|
||||
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user