Index: source/blender/render/intern/source/texture.c =================================================================== --- source/blender/render/intern/source/texture.c (revision 11208) +++ source/blender/render/intern/source/texture.c (working copy) @@ -28,6 +28,9 @@ #include #include #include +#ifdef WIN32 +#define _USE_MATH_DEFINES +#endif #include #include "MTC_matrixops.h" @@ -73,8 +76,7 @@ extern struct Render R; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - - +#define M_PI_OVER_180 0.0174532925199 /* note; this is called WITH RENDER IS NULL in src/drawview.c for animated background image, option should move to kernel */ @@ -690,6 +692,1062 @@ } +/* ------------------------------------------------------------------------- */ + +/* ------------------------------------------------------------------------- */ + +/* Determines which side of the line a point is. Assume +ve for left of vector pointing from pa to pb. */ +#define SIDE_OF_LINE(pa,pb,pp) ((pa[0]-pp[0])*(pb[1]-pp[1]))-((pb[0]-pp[0])*(pa[1]-pp[1])) + +/* Determines if a point p0 is inside a triangle (p1, p2, p3). */ +#define POINT_IN_TRI(p0,p1,p2,p3) ((SIDE_OF_LINE(p1,p2,p0)>=0) && (SIDE_OF_LINE(p2,p3,p0)>=0) && (SIDE_OF_LINE(p3,p1,p0)>=0)) + +/* Signed distance of point (x, y) from line Ax + By + C = 0. */ +#define DIST_POINT_TO_LINE(A, B, C, x, y) (((A) * (x) + (B) * (y) + (C)) / sqrt((A) * (A) + (B) * (B))) + +/* Given signed distance d from a line and bevel width b, compute a linear gradient for the positive + * side of the line. Points on the negative side will have intensity 0 and points beyond distance + * b will have intensity 1. + */ +#define LINE_BEVEL(d, b) d = (d < 0) ? 0 : ((d <= b) && (b > 0)) ? (d) / (b) : 1 + +static float mod(float a, float b) +{ + /* Calculate a mod b for floating point numbers. + * NOTE: a can be negative however I'm not sure what behaviour this function + * has if b is negative + * + * NOTE: Copied from plugin brick.c by Unicorn. The original code was in Public + * Domain and is supplied with the Blender Texture Plugins repository. + */ + int n = (int)(a / b); + a -= n * b; + if ( a < 0 ) a += b; + return a; +} + +static float smoothstep(float x, float a, float b) +{ + /* Calculate a step function as follows: + * y = 0 for x < 0 + * y = -2x^2 + 3x^3 for 0 <= x <= 1 + * y = 1 for x > 1 + * + * Since we're using an interval of [a, b] instead of [0, 1] + * we have to transform x with (x - a) / (b - a). + */ + float e; + + if (a == b) + { + return (x < a) ? 0 : 1; + } + + if (x < a) return 0; + if (x > b) return 1; + + e = (x - a) / (b - a); + return e * e * (3 - 2 * e); +} + +void tiles_precalc(Tex *tex) +{ + /* Compute a set of random widths for the tiles. The array tex->precalc->pat[] will + * accumulate the gap and tile widths in each cell starting at 0. + */ + Tex *t = (Tex *)tex; + float w = fabs(t->maxwidth - t->minwidth); + float h = fabs(t->maxheight - t->minheight); + float rw, rh; + short i; + RNG *rng = rng_new(tex->seed); + + t->precalc.minw = MAX2(t->minwidth, t->maxwidth); + t->precalc.maxw = 0; + t->precalc.minh = MAX2(t->minheight, t->maxheight); + t->precalc.maxh = 0; + + t->precalc.hpat[0] = 0; + for (i = 1; i <= t->hcount; i++) { + rw = rng_getFloat(rng); + rw = t->minwidth + w * rw; + t->precalc.hpat[i] = t->hgap + t->precalc.hpat[i - 1] + rw; + + t->precalc.minw = MIN2(t->precalc.minw, rw); + t->precalc.maxw = MAX2(t->precalc.maxw, rw); + } + + t->precalc.vpat[0] = 0; + for (i = 1; i <= t->vcount; i++) { + rh = rng_getFloat(rng); + rh = t->minheight + h * rh; + t->precalc.vpat[i] = t->vgap + t->precalc.vpat[i - 1] + rh; + + t->precalc.minh = MIN2(t->precalc.minh, rh); + t->precalc.maxh = MAX2(t->precalc.maxh, rh); + } + + rng_free(rng); +} + +static void tiles_calc(Tex *tex, float *x, float *y, float *z, short *htileid, short *vtileid) +{ + /* Given points (x, y, z) determines where in the tile pattern, tex->precalc.hpat[], + * the point belongs. It returns the index of the tile in htileid, vtileid and x, y, z + * will contain the relative offset for the tile. + * NOTE: currently z is ignored as this is a 2D texture. + */ + float wtot = tex->precalc.hpat[tex->hcount] - tex->precalc.hpat[0]; /* Width of tile pattern */ + float htot = tex->precalc.vpat[tex->vcount] - tex->precalc.vpat[0]; /* Height of tile pattern */ + float y1; + short i; + int row; + + /* Center the pattern */ + *x += ((wtot - tex->hgap) * 0.5); + *y += ((htot - tex->vgap) * 0.5); + + y1 = *y; + + /* Compute relative y offset for current tile */ + *y = mod(*y, htot); + + /* Determine vertical start of the tile */ + for (i = 0; i < tex->vcount; i++) { + if (*y <= tex->precalc.vpat[i + 1]) { + break; + } + } + *y -= tex->precalc.vpat[i]; + *vtileid = i; + + /* Calculate row number */ + row = (int)floor(y1 / htot) * tex->vcount + i; + + /* Shift rows */ + if ( tex->alternate > 0 ) { + *x += (mod(row, tex->alternate) * tex->shift); + } + else { + /* Shift every row */ + *x += (row * tex->shift); + } + + /* Compute relative x offset for current tile */ + *x = mod(*x, wtot); + + /* Determine horizontal start of the tile */ + for (i = 0; i < tex->hcount; i++) { + if (*x <= tex->precalc.hpat[i + 1]) { + break; + } + } + *x -= tex->precalc.hpat[i]; + *htileid = i; +} + +static float tiles_bevel_dim(Tex *tex, float w, float h) +{ + /* Determine the dimension of the tiles used to compute the bevel */ + float s; + switch (tex->bevoption) + { + case TEX_BEVEL_UNIFORMMIN: + s = MIN2(tex->precalc.minw, tex->precalc.minh); + break; + case TEX_BEVEL_UNIFORMMAX: + s = MIN2(tex->precalc.maxw, tex->precalc.maxh); + break; + default: + s = MIN2(w, h); + break; + } + return s; +} + +static float tiles_rect_func(float x, float y, float w, float h, float b) +{ + /* Calculate signed distance from the 4 sides of the rectangle bounded by: + * x = 0, y = 0, x = w, y = h. + * The sign indicates whether point is inside, on or outside the rectangle + * aiding us in applying gradients based on sidedness. + * + * NOTE: This is optimized version of tiles_poly_func() + */ + float dx1 = x; + float dy1 = y; + float dx2 = w - x; + float dy2 = h - y; + + /* Find minimum distance to point from the 4 sides */ + float dmin = MIN4(dx1, dx2, dy1, dy2); + + float v = 0; + if (dmin > b) { + v = 1; + } + else if ((dmin >= 0) && (b > 0)) { + v = dmin / b; + } + + return v; +} + +static float tiles_rect_func2(float x, float y, float w, float h, float b, float sx, float sy) +{ + /* Calculate signed distance from the 8 lines: + * x = 0, y = 0, x = w, y = h, + * sy * x + sx * y - sx * sy = 0, + * sy * x - sx * y + sx * (h - sy) = 0, + * -sy * x + sx * y + sy * (w - sx) = 0, + * -sy * x - sx * y + sy * (w - sx) + sx * h = 0 + * + * The sign indicates whether point is inside, on or outside the rectangle + * aiding us in applying gradients based on sidedness. + * + * NOTE: This is optimized version of tiles_poly_func() + */ + float v = tiles_rect_func(x, y, w, h, b); + float d1 = DIST_POINT_TO_LINE(sy, sx, -sx * sy, x, y); + float d2 = DIST_POINT_TO_LINE(sy, -sx, sx * (h - sy), x, y); + float d3 = DIST_POINT_TO_LINE(-sy, sx, sy * (w - sx), x, y); + float d4 = DIST_POINT_TO_LINE(-sy, -sx, sy * (w - sx) + sx * h, x, y); + float d; + + LINE_BEVEL(d1, b); + LINE_BEVEL(d2, b); + LINE_BEVEL(d3, b); + LINE_BEVEL(d4, b); + + d = MIN4(d1, d2, d3, d4); + + return MIN2(v, d); +} + + +static float tiles_poly_func(float x, float y, float *vx, float *vy, short n, float b) +{ + /* Do a linear gradient for an n-sided polygon from 0 for outer edge to 1 + * for a distance b from outer edge inside the polygon. Any point beyond + * distance b inside the polygon gets intensity 1. + * + * NOTE: Specify polygon vertices counter-clockwise and n >= 3. + */ + int i, i1; + float p[2], p1[2], p2[2]; + float m, d, d1, dx; + + /* Determine if p lies in the polygon */ + p[0] = x; + p[1] = y; + for (i = 0; i < n; i++) + { + /* If point lies outside boundary just return 0. */ + i1 = (i + 1) % n; + p1[0] = vx[i]; + p1[1] = vy[i]; + p2[0] = vx[i1]; + p2[1] = vy[i1]; + if (SIDE_OF_LINE(p1, p2, p) < 0) { + return 0; + } + + /* Compute distance to the line containing current side */ + dx = p1[0] - p2[0]; + if (fabs(dx) > 0) { + m = (p1[1] - p2[1]) / dx; + d1 = fabs(DIST_POINT_TO_LINE(m, -1, p1[1] - p1[0] * m, x, y)); + } + else + { + d1 = fabs(x - p1[0]); + } + + /* Take minimum distance so far */ + d = (i == 0) ? d1 : MIN2(d, d1); + } + + LINE_BEVEL(d, b); + + return d; +} + +static float tiles_circle_func1(float x, float y, float cx, float cy, float b, float r) +{ + /* Calculate signed distance from the circle bounded by: + * (x - cx)^2 + (y - cy)^2 = r^2 + * The sign indicates whether point is inside, on or outside the circle + * aiding us in applying gradients based on sidedness. + * + * For points that lie within a distance of r - b from the center the intensity is 1. + * For points at distance of r - b to r, the intensity is linear from 1 to 0. + * For all other points the intensity is 0. + */ + float dx = (x - cx); + float dy = (y - cy); + float d = r - sqrt(dx * dx + dy * dy); + + float v = 0; + if (d > b) { + v = 1; + } + else if ((d >= 0) && (b > 0)) { + v = d / b; + } + + return v; +} + +static float tiles_circle_func2(float x, float y, float cx, float cy, float b, float r) +{ + /* Calculate signed distance from the circle bounded by: + * (x - cx)^2 + (y - cy)^2 = r^2 + * The sign indicates whether point is inside, on or outside the circle + * aiding us in applying gradients based on sidedness. + * + * For points that lie within a distance of r - b from the center the intensity is 0. + * For points at distance of r - b to r, the intensity is linear from 0 to 1. + * For all other points the intensity is 1. + */ + float dx = (x - cx); + float dy = (y - cy); + float d = sqrt(dx * dx + dy * dy) - r; + + float v = 0; + if (d > b) { + v = 1; + } + else if ((d >= 0) && (b > 0)) { + v = d / b; + } + + return v; +} + +static float tiles_roundrect_func(float x, float y, float w, float h, float b, float r, short flip) +{ + /* First compute the intensity inside the rectangle bounded by (0, 0) and (w, h). */ + float v = tiles_rect_func(x, y, w, h, b); + float t = v; + float hw = w * 0.5; + float hh = h * 0.5; + + if (flip) { + /* For points that lie inside the four corners determine if they fall inside the circle + * centered at the corners and apply a linear gradient. This does the inverted circular + * shape. + */ + if ((x >= 0) && (x <= hw)) { + if ((y >= 0) && (y <= hh)) { + t = tiles_circle_func2(x, y, 0, 0, b, r); + } + else if ((y > hh) && (y <= h)) { + t = tiles_circle_func2(x, y, 0, h, b, r); + } + } + else if ((x > hw) && (x <= w)) { + if ((y >= 0) && (y <= hh)) { + t = tiles_circle_func2(x, y, w, 0, b, r); + } + else if ((y > hh) && (y <= h)) { + t = tiles_circle_func2(x, y, w, h, b, r); + } + } + v = MIN2(t, v); + } + else { + /* For points that lie inside the four corners determine if they fall inside the circle + * centered at the offset by the radius and apply a linear gradient. + */ + if ((x >= 0) && (x <= r)) { + if ((y >= 0) && (y <= r)) { + v = tiles_circle_func1(x, y, r, r, b, r); + } + else if ((y >= h - r) && (y <= h)) { + v = tiles_circle_func1(x, y, r, h - r, b, r); + } + } + else if ((x >= w - r) && (x <= w)) { + if ((y >= 0) && (y <= r)) { + v = tiles_circle_func1(x, y, w - r, r, b, r); + } + else if ((y >= h - r) && (y <= h)) { + v = tiles_circle_func1(x, y, w - r, h - r, b, r); + } + } + } + + return v; +} + +static float tiles_ellipse_func1(float x, float y, float cx, float cy, float b, float rx, float ry) +{ + /* Calculate signed distance from the ellipse bounded by: + * [(x - cx) / rx]^2 + [(y - cy) / ry]^2 = 1 + * The sign indicates whether point is inside, on or outside the ellipse + * aiding us in applying gradients based on sidedness. + * + * For points inside the ellipse from the center to distance b from the curve, intensity is 1. + * For points starting at distance b from the curve to the curve, the intensity is linear from 1 to 0. + * For all other points the intensity is 0. + */ + float v, c, x1, y1, d, f, r2; + + /* Shift origin to (0, 0) */ + x -= cx; + y -= cy; + + /* Compute the point (x1, y1) on the ellipse that forms a line through + * (0, 0) and (x, y). + */ + f = sqrt(x * x * ry * ry + y * y * rx * rx); + r2 = rx * ry; + c = r2 / f; + x1 = x * c; + y1 = y * c; + + /* Compute distance between the given point and computed point */ + d = sqrt((x - x1)*(x - x1) + (y - y1)*(y - y1)); + + v = 0; + + /* Test signed distance to see if point is inside or outside the ellipse */ + if (f <= r2) { + /* Apply linear gradient */ + if (d > b) { + v = 1; + } + else if (b > 0) { + v = d / b; + } + } + + return v; +} + +static float tiles_ellipse_func2(float x, float y, float cx, float cy, float b, float rx, float ry) +{ + /* Calculate signed distance from the ellipse bounded by: + * [(x - cx) / rx]^2 + [(y - cy) / ry]^2 = 1 + * The sign indicates whether point is inside, on or outside the ellipse + * aiding us in applying gradients based on sidedness. + * + * For points inside the ellipse from the center to distance b from the curve, intensity is 0. + * For points starting at distance b from the curve to the curve, the intensity is linear from 0 to 1. + * For all other points the intensity is 1. + */ + float v, c, x1, y1, d, f, r2; + + /* Shift origin to (0, 0) */ + x -= cx; + y -= cy; + + /* Compute the point (x1, y1) on the ellipse that forms a line through + * (0, 0) and (x, y). + */ + f = sqrt(x * x * ry * ry + y * y * rx * rx); + r2 = rx * ry; + c = r2 / f; + x1 = x * c; + y1 = y * c; + + /* Compute distance between the given point and computed point */ + d = sqrt((x - x1)*(x - x1) + (y - y1)*(y - y1)); + + v = 0; + + /* Test signed distance to see if point is inside or outside the ellipse */ + if (f >= r2) { + /* Apply linear gradient */ + if (d > b) { + v = 1; + } + else if (b > 0) { + v = d / b; + } + } + + return v; +} + +static float tiles_ellipserect_func(float x, float y, float w, float h, float b, float rx, float ry, short flip) +{ + /* First compute the intensity inside the rectangle bounded by (0, 0) and (w, h). */ + float v = tiles_rect_func(x, y, w, h, b); + float t = v; + float hw = w * 0.5; + float hh = h * 0.5; + + if (flip) { + /* For points that lie inside the four corners determine if they fall inside the ellipse + * centered at the corners and apply a linear gradient. This does the inverted circular + * shape. + */ + if ((x >= 0) && (x <= hw)) { + if ((y >= 0) && (y <= hh)) { + t = tiles_ellipse_func2(x, y, 0, 0, b, rx, ry); + } + else if ((y > hh) && (y <= h)) { + t = tiles_ellipse_func2(x, y, 0, h, b, rx, ry); + } + } + else if ((x > hw) && (x <= w)) { + if ((y >= 0) && (y <= hh)) { + t = tiles_ellipse_func2(x, y, w, 0, b, rx, ry); + } + else if ((y > hh) && (y <= h)) { + t = tiles_ellipse_func2(x, y, w, h, b, rx, ry); + } + } + v = MIN2(t, v); + } + else { + /* For points that lie inside the four corners determine if they fall inside the ellipse + * centered at the offset (rx, ry) and apply a linear gradient. + */ + if ((x >= 0) && (x <= rx)) { + if ((y >= 0) && (y <= ry)) { + t = tiles_ellipse_func1(x, y, rx, ry, b, rx, ry); + v = MIN2(v, t); + } + else if ((y >= h - ry) && (y <= h)) { + t = tiles_ellipse_func1(x, y, rx, h - ry, b, rx, ry); + v = MIN2(v, t); + } + } + else if ((x >= w - rx) && (x <= w)) { + if ((y >= 0) && (y <= ry)) { + t = tiles_ellipse_func1(x, y, w - rx, ry, b, rx, ry); + v = MIN2(v, t); + } + else if ((y >= h - ry) && (y <= h)) { + t = tiles_ellipse_func1(x, y, w - rx, h - ry, b, rx, ry); + v = MIN2(v, t); + } + } + } + + return v; +} + +static float tiles_recthelper_int(Tex *tex, float x, float y, float w, float h, float dim) +{ + float b = dim * tex->bevel; + float rx, ry, intens; + + switch (tex->corner) { + case TEX_CORNER_ROUND1: + if (tex->hcorner == tex->vcorner) { + rx = tex->hcorner * dim; + intens = tiles_roundrect_func(x, y, w, h, b, rx, 0); + } + else { + rx = tex->hcorner * dim; + ry = tex->vcorner * dim; + intens = tiles_ellipserect_func(x, y, w, h, b, rx, ry, 0); + } + break; + case TEX_CORNER_ROUND2: + if (tex->hcorner == tex->vcorner) { + rx = tex->hcorner * dim; + intens = tiles_roundrect_func(x, y, w, h, b, rx, 1); + } + else { + rx = tex->hcorner * dim; + ry = tex->vcorner * dim; + intens = tiles_ellipserect_func(x, y, w, h, b, rx, ry, 1); + } + break; + case TEX_CORNER_ELLIPSE1: + rx = tex->hcorner * w; + ry = tex->vcorner * h; + intens = tiles_ellipserect_func(x, y, w, h, b, rx, ry, 0); + break; + case TEX_CORNER_ELLIPSE2: + rx = tex->hcorner * w; + ry = tex->vcorner * h; + intens = tiles_ellipserect_func(x, y, w, h, b, rx, ry, 1); + break; + case TEX_CORNER_STRAIGHT: + rx = tex->hcorner * w; + ry = tex->vcorner * h; + intens = tiles_rect_func2(x, y, w, h, b, rx, ry); + break; + default: + intens = tiles_rect_func(x, y, w, h, b); + break; + } + + return intens; +} + +static float tiles_default_int(Tex *tex, float x, float y, float z, short htileid, short vtileid) +{ + /* This handles the default tiling with different corner styles */ + float intens; + float w, h, dim; + + /* Compute tile dimensions */ + w = tex->precalc.hpat[htileid + 1] - tex->precalc.hpat[htileid] - tex->hgap; + h = tex->precalc.vpat[vtileid + 1] - tex->precalc.vpat[vtileid] - tex->vgap; + + /* Bevel */ + dim = tiles_bevel_dim(tex, w, h); + + /* Compute intensity. */ + return tiles_recthelper_int(tex, x, y, w, h, dim); +} + +static float tiles_1_int(Tex *tex, float x, float y, float z, short htileid, short vtileid) +{ + /* Generate a pattern as follows: + * _______ + * | | + * |_______| + * | | | + * |___|___| + * The pattern rotates 90 degrees and after 4 tile repitions it repeats. + * If tex->hcount is not a multiple of 4, the repitions will stop before + * multiple of 360 degrees is reached. + */ + + float w = tex->precalc.hpat[htileid + 1] - tex->precalc.hpat[htileid] - tex->hgap; + float h = tex->precalc.vpat[vtileid + 1] - tex->precalc.vpat[vtileid] - tex->vgap; + float w2 = 0.5 * w; + float h2 = 0.5 * h; + float dim = tiles_bevel_dim(tex, w2, h2); + float intens = 0; + short id = htileid % 4; + + if (id == 0) { + if (y >= h2) { + intens = tiles_recthelper_int(tex, x, y - h2, w, h2, dim); + } + else if (x <= w2) { + intens = tiles_recthelper_int(tex, x, y, w2, h2, dim); + } + else { + intens = tiles_recthelper_int(tex, x - w2, y, w2, h2, dim); + } + } + else if (id == 1) { + if (x >= w2) { + intens = tiles_recthelper_int(tex, x - w2, y, w2, h, dim); + } + else if (y <= h2) { + intens = tiles_recthelper_int(tex, x, y, w2, h2, dim); + } + else { + intens = tiles_recthelper_int(tex, x, y - h2, w2, h2, dim); + } + } + else if (id == 2) { + if (y <= h2) { + intens = tiles_recthelper_int(tex, x, y, w, h2, dim); + } + else if (x <= w2) { + intens = tiles_recthelper_int(tex, x, y - h2, w2, h2, dim); + } + else { + intens = tiles_recthelper_int(tex, x - w2, y - h2, w2, h2, dim); + } + } + else { + if (x <= w2) { + intens = tiles_recthelper_int(tex, x, y, w2, h, dim); + } + else if (y <= h2) { + intens = tiles_recthelper_int(tex, x - w2, y, w2, h2, dim); + } + else { + intens = tiles_recthelper_int(tex, x - w2, y - h2, w2, h2, dim); + } + } + + return intens; +} + +static float tiles_hex_int(Tex *tex, float x, float y, float z, short htileid, short vtileid) +{ + /* The tight honeycomb pattern is generated using tiles that are not shifted every + * row. So assuming, the rows are not being shifted, we can do a "lollipop" shape + * with a hexagon which will stretch from one rectangular cell to another but will + * remain seamless as long as tex->hgap = tex->vgap = 0. + * _______ + * / \ + * / \_______ + * \ / + * \_______/ + * + * Now note that points that fall above and below the "stick" AND points that fall + * to the left of the hexagon have to be tested inside a hexagon that is in the neighbouring + * tile. A total of 5 hexagon's need to tested for inclusion of given point. + */ + float c = 1.0 / 6.0; + float w = tex->precalc.hpat[htileid + 1] - tex->precalc.hpat[htileid] - tex->hgap; + float h = tex->precalc.vpat[vtileid + 1] - tex->precalc.vpat[vtileid] - tex->vgap; + float d = w * c; + float r = h * 0.5; + float b = tiles_bevel_dim(tex, 4 * d, h) * tex->bevel; /* hex part is 4*d wide */ + float wl, wr, dl, dr; + float ha, hb, ra, rb; + short htid, vtid; + float intens = 0; + float vx[6], vy[6]; + + /* Width of tile to right */ + htid = (htileid + 1) % tex->hcount; + wr = tex->precalc.hpat[htid + 1] - tex->precalc.hpat[htid] - tex->hgap; + dr = wr * c; + /* Width of tile to left */ + htid = (htileid - 1 + tex->hcount) % tex->hcount; + wl = tex->precalc.hpat[htid + 1] - tex->precalc.hpat[htid] - tex->hgap; + dl = wl * c; + /* Height of tile above */ + vtid = (vtileid + 1) % tex->vcount; + ha = tex->precalc.vpat[vtid + 1] - tex->precalc.vpat[vtid] - tex->vgap; + ra = ha * 0.5; + /* Height of tile below */ + vtid = (vtileid - 1 + tex->vcount) % tex->vcount; + hb = tex->precalc.vpat[vtid + 1] - tex->precalc.vpat[vtid] - tex->vgap; + rb = hb * 0.5; + + /* Handle hexagon in current tile */ + vx[0] = d; vy[0] = 0; + vx[1] = 3 * d; vy[1] = 0; + vx[2] = 4 * d; vy[2] = r; + vx[3] = 3 * d; vy[3] = h; + vx[4] = d; vy[4] = h; + vx[5] = 0; vy[5] = r; + intens = tiles_poly_func(x, y, vx, vy, 6, b); + + /* Handle sections that overlap with other tiles. Note that we do a MAX of current + * intens value with the next tile in question. This cleans up the code and seems + * to fix up any artifacts in the bevels. + */ + if ((x >= 3 * d) && (x <= w)) { + /* Take the width of the next tile to the right into consideration */ + if ((y >= 0) && (y <= r)) { + /* Take the height of the next tile below into consideration */ + b = tiles_bevel_dim(tex, 3 * d + dr, r + rb) * tex->bevel; + vx[0] = 4 * d; vy[0] = -rb; + vx[1] = w; vy[1] = -rb; + vx[2] = w + dr; vy[2] = 0; + vx[3] = w; vy[3] = r; + vx[4] = 4 * d; vy[4] = r; + vx[5] = 3 * d; vy[5] = 0; + intens = MAX2(intens, tiles_poly_func(x, y, vx, vy, 6, b)); + } + else if ((y > r) && (y <= h)) { + /* Take the height of the next tile above into consideration */ + b = tiles_bevel_dim(tex, 3 * d + dr, r + ra) * tex->bevel; + vx[0] = 4 * d; vy[0] = r; + vx[1] = w; vy[1] = r; + vx[2] = w + dr; vy[2] = h; + vx[3] = w; vy[3] = h + ra; + vx[4] = 4 * d; vy[4] = h + ra; + vx[5] = 3 * d; vy[5] = h; + intens = MAX2(intens, tiles_poly_func(x, y, vx, vy, 6, b)); + } + } + else if ((x >= 0) && (x <= d)) { + /* Take the width of the next tile to the left into consideration */ + if ((y >= 0) && (y <= r)) { + /* Take the height of the next tile below into consideration */ + b = tiles_bevel_dim(tex, 3 * dl + d, r + rb) * tex->bevel; + vx[0] = d; vy[0] = 0; + vx[1] = 0; vy[1] = r; + vx[2] = -2 * dl; vy[2] = r; + vx[3] = -3 * dl; vy[3] = 0; + vx[4] = -2 * dl; vy[4] = -rb; + vx[5] = 0; vy[5] = -rb; + intens = MAX2(intens, tiles_poly_func(x, y, vx, vy, 6, b)); + } + else if ((y > r) && (y <= h)) { + /* Take the height of the next tile above into consideration */ + b = tiles_bevel_dim(tex, 3 * dl + d, r + ra) * tex->bevel; + vx[0] = d; vy[0] = h; + vx[1] = 0; vy[1] = h + ra; + vx[2] = -2 * dl; vy[2] = h + ra; + vx[3] = -3 * dl; vy[3] = h; + vx[4] = -2 * dl; vy[4] = r; + vx[5] = 0; vy[5] = r; + intens = MAX2(intens, tiles_poly_func(x, y, vx, vy, 6, b)); + } + } + + return intens; +} + +static float tiles_herringbone_int(Tex *tex, float x, float y, float z, short htileid, short vtileid, short n) +{ + /* Creates a nx1 seamless pattern for herringbone tiling where n >= 2. */ + + float w = tex->precalc.hpat[htileid + 1] - tex->precalc.hpat[htileid] - tex->hgap; + float h = tex->precalc.vpat[vtileid + 1] - tex->precalc.vpat[vtileid] - tex->vgap; + float w1 = 0.5 * w; + float h1 = 0.5 * h; + float one_over_n = 1.0 / (float)n; + float xstep = w1 * one_over_n; + float ystep = h1 * one_over_n; + float dim = tiles_bevel_dim(tex, w1, h1) * one_over_n; + + float xi, yi, intens; + + if ((x < 0) || (x > w) || (y < 0) || (y > h)) return 0; + + /* Handle horizontal bars */ + yi = 0; + for (xi = 0; xi <= w; xi += xstep) + { + intens = tiles_recthelper_int(tex, x - xi, y - yi, w1, ystep, dim); + if (intens > 0) return intens; + yi += ystep; + } + /* Handle the seamless sections of horizontal bars */ + yi = h - (n - 1) * ystep; + for (xi = (1 - n) * xstep; xi <= -xstep; xi += xstep) + { + intens = tiles_recthelper_int(tex, x - xi, y - yi, w1, ystep, dim); + if (intens > 0) return intens; + yi += ystep; + } + + /* Handle vertical bars */ + xi = 0; + for (yi = ystep; yi <= h; yi += ystep) + { + intens = tiles_recthelper_int(tex, x - xi, y - yi, xstep, h1, dim); + if (intens > 0) return intens; + xi += xstep; + } + /* Handle the seamless sections of vertical bars */ + xi = w1; + for (yi = (1 - n) * ystep; yi <= 0; yi += ystep) + { + intens = tiles_recthelper_int(tex, x - xi, y - yi, xstep, h1, dim); + if (intens > 0) return intens; + xi += xstep; + } + + return 0; +} + +static float tiles_weave_int(Tex *tex, float x, float y, float z, short htileid, short vtileid) +{ + float w = tex->precalc.hpat[htileid + 1] - tex->precalc.hpat[htileid] - tex->hgap; + float h = tex->precalc.vpat[vtileid + 1] - tex->precalc.vpat[vtileid] - tex->vgap; + float dim, intens; + short htid, vtid; + float wr, wl, ha, hb; + float xi, yi, wi, hi; + + /* Width of tile to right */ + htid = (htileid + 1) % tex->hcount; + wr = tex->precalc.hpat[htid + 1] - tex->precalc.hpat[htid] - tex->hgap; + /* Width of tile to left */ + htid = (htileid - 1 + tex->hcount) % tex->hcount; + wl = tex->precalc.hpat[htid + 1] - tex->precalc.hpat[htid] - tex->hgap; + /* Height of tile above */ + vtid = (vtileid + 1) % tex->vcount; + ha = tex->precalc.vpat[vtid + 1] - tex->precalc.vpat[vtid] - tex->vgap; + /* Height of tile below */ + vtid = (vtileid - 1 + tex->vcount) % tex->vcount; + hb = tex->precalc.vpat[vtid + 1] - tex->precalc.vpat[vtid] - tex->vgap; + + if ((x < 0) || (x > w) || (y < 0) || (y > h)) return 0; + + /* Compute dimension for bevel */ + dim = tiles_bevel_dim(tex, MIN3(w, wl, wr), MIN3(h, ha, hb)) * 0.25; + + /* Horizontal Tiles */ + /* Bottom Center */ + xi = 0.125 * w; + yi = -0.125 * hb; + wi = 0.75 * w; + hi = 0.125 * (h + hb); + intens = tiles_recthelper_int(tex, x - xi, y - yi, wi, hi, dim); + if (intens > 0) return intens; + + /* Top Center */ + xi = 0.125 * w; + yi = 0.875 * h; + hi = 0.125 * (h + ha); + intens = tiles_recthelper_int(tex, x - xi, y - yi, wi, hi, dim); + if (intens > 0) return intens; + + /* Middle Left */ + xi = -0.375 * wl; + yi = 0.375 * h; + wi = 0.375 * (w + wl); + hi = 0.25 * h; + intens = tiles_recthelper_int(tex, x - xi, y - yi, wi, hi, dim); + if (intens > 0) return intens; + + /* Middle Right */ + xi = 0.625 * w; + yi = 0.375 * h; + wi = 0.375 * (w + wr); + intens = tiles_recthelper_int(tex, x - xi, y - yi, wi, hi, dim); + if (intens > 0) return intens; + + + /* Vertical Tiles */ + /* Center */ + xi = 0.375 * w; + yi = 0.125 * h; + wi = 0.25 * w; + hi = 0.75 * h; + intens = tiles_recthelper_int(tex, x - xi, y - yi, wi, hi, dim); + if (intens > 0) return intens; + + /* Bottom Left */ + xi = -0.125 * wl; + yi = -0.375 * hb; + wi = 0.125 * (w + wl); + hi = 0.375 * (h + hb); + intens = tiles_recthelper_int(tex, x - xi, y - yi, wi, hi, dim); + if (intens > 0) return intens; + + /* Bottom Right */ + xi = 0.875 * w; + yi = -0.375 * hb; + wi = 0.125 * (w + wr); + intens = tiles_recthelper_int(tex, x - xi, y - yi, wi, hi, dim); + if (intens > 0) return intens; + + /* Top Left */ + xi = -0.125 * wl; + yi = 0.625 * h; + wi = 0.125 * (w + wl); + hi = 0.375 * (h + ha); + intens = tiles_recthelper_int(tex, x - xi, y - yi, wi, hi, dim); + if (intens > 0) return intens; + + /* Top Right */ + xi = 0.875 * w; + yi = 0.625 * h; + wi = 0.125 * (w + wr); + intens = tiles_recthelper_int(tex, x - xi, y - yi, wi, hi, dim); + if (intens > 0) return intens; + + return 0; +} + +static float tiles_int(Tex *tex, float x, float y, float z) +{ + short htileid, vtileid; + float intens, icubic1, icubic2, i; + float angle, sinval, cosval, x1, y1, scale; + + /* Apply texture coordinates rotation. */ + angle = tex->rotate * M_PI_OVER_180; + sinval = sin(angle); + cosval = cos(angle); + x1 = x * cosval - y * sinval; + y1 = y * cosval + x * sinval; + + /* Apply texture coordinates offset */ + x1 += tex->hoffset; + y1 += tex->voffset; + + /* Apply texture coordinates skew */ + x = x1 + y1 * tex->hskew; + y = y1 + x1 * tex->vskew; + + /* Apply texture coordinate scale */ + scale = 1.0 / tex->scale; + x *= scale; + y *= scale; + z *= scale; + + /* Compute coordinates in "tile-space"; i.e. relative to the tile containing + * the texture coordinates. + */ + tiles_calc(tex, &x, &y, &z, &htileid, &vtileid); + + /* Handle preset patterns and default tiling function */ + switch (tex->preset) { + case TEX_TILES_1: + intens = tiles_1_int(tex, x, y, z, htileid, vtileid); + break; + case TEX_TILES_HEX: + intens = tiles_hex_int(tex, x, y, z, htileid, vtileid); + break; + case TEX_TILES_HERRINGBONE1: + intens = tiles_herringbone_int(tex, x, y, z, htileid, vtileid, 2); + break; + case TEX_TILES_HERRINGBONE2: + intens = tiles_herringbone_int(tex, x, y, z, htileid, vtileid, 4); + break; + case TEX_TILES_HERRINGBONE3: + intens = tiles_herringbone_int(tex, x, y, z, htileid, vtileid, 7); + break; + case TEX_TILES_WEAVE: + intens = tiles_weave_int(tex, x, y, z, htileid, vtileid); + break; + default: + intens = tiles_default_int(tex, x, y, z, htileid, vtileid); + break; + } + + /* Clamp to [0, 1] range. The clamping prevents artifacts around the border + * in case negative numbers are generated by the tile functions. + */ + CLAMP(intens, 0, 1); + + /* Apply bevel strength and center the result in [0, 1] */ + intens *= tex->strength; + intens += (1.0 - tex->strength) * 0.5; + + /* Map the intensity x to the 2 functions: x^3, 1+(x-1)^3. */ + icubic1 = intens * intens * intens; + icubic2 = intens - 1.0; + icubic2 *= icubic2 * icubic2; + icubic2 += 1.0; + + if (tex->curve <= 0) { + /* Do a linear blend between 1 + (x - 1)^3 and x functions */ + i = tex->curve + 1; + intens = (1 - i) * icubic2 + i * intens; + } + else { + /* Do a linear blend between x and xi^3 functions */ + i = tex->curve; + intens = (1 - i) * intens + i * icubic1; + } + + /* Apply wave function */ + intens += tex->amp * sin(M_2_PI * intens * tex->freq); + + /* Smooth out the result using a cubic step function */ + if (tex->smooth) { + intens = smoothstep(intens, 0, 1); + } + + return intens; +} + +static int tiles(Tex *tex, float *texvec, TexResult *texres) +{ + int rv = TEX_INT; + + texres->tin = tiles_int(tex, texvec[0], texvec[1], texvec[2]); + + if (texres->nor!=NULL) { + /* calculate bumpnormal */ + texres->nor[0] = tiles_int(tex, texvec[0] + tex->nabla, texvec[1], texvec[2]); + texres->nor[1] = tiles_int(tex, texvec[0], texvec[1] + tex->nabla, texvec[2]); + texres->nor[2] = tiles_int(tex, texvec[0], texvec[1], texvec[2] + tex->nabla); + + tex_normal_derivate(tex, texres); + rv |= TEX_NOR; + } + + BRICONT; + + return rv; +} /* ------------------------------------------------------------------------- */ @@ -1185,6 +2243,9 @@ VecMulf(tmpvec, 1.0/tex->noisesize); retval= mg_distNoiseTex(tex, tmpvec, texres); + break; + case TEX_TILES: + retval = tiles(tex, texvec, texres); break; } Index: source/blender/render/intern/include/texture.h =================================================================== --- source/blender/render/intern/include/texture.h (revision 11208) +++ source/blender/render/intern/include/texture.h (working copy) @@ -49,6 +49,7 @@ struct HaloRen; struct ShadeInput; struct TexResult; +struct TexPreCalc; struct Tex; struct Image; struct ImBuf; Index: source/blender/blenkernel/BKE_blender.h =================================================================== --- source/blender/blenkernel/BKE_blender.h (revision 11208) +++ source/blender/blenkernel/BKE_blender.h (working copy) @@ -44,7 +44,7 @@ struct MemFile; #define BLENDER_VERSION 244 -#define BLENDER_SUBVERSION 2 +#define BLENDER_SUBVERSION 3 #define BLENDER_MINVERSION 240 #define BLENDER_MINSUBVERSION 0 Index: source/blender/blenkernel/intern/texture.c =================================================================== --- source/blender/blenkernel/intern/texture.c (revision 11208) +++ source/blender/blenkernel/intern/texture.c (working copy) @@ -440,6 +440,36 @@ tex->vn_mexp = 2.5; tex->vn_distm = 0; tex->vn_coltype = 0; + /* tiles */ + tex->scale = 1; + tex->hcount = 3; + tex->minwidth = 0.2; + tex->maxwidth = 0.3; + tex->vcount = 3; + tex->minheight = 0.1; + tex->maxheight = 0.2; + tex->hgap = 0.05; + tex->vgap = 0.05; + tex->shift = 0.1; + tex->bevel = 0.2; + tex->corner = 0; + tex->hcorner = 0.25; + tex->vcorner = 0.25; + tex->rotate = 0; + tex->seed = 0; + tex->alternate = 2; + tex->hskew = 0; + tex->vskew = 0; + tex->curve = 0; + tex->smooth = 0; + tex->freq = 0; + tex->amp = 0; + tex->hoffset = 0; + tex->voffset = 0; + tex->strength = 1; + tex->preset = 0; + tex->bevoption = 0; + tiles_precalc(tex); if (tex->env) { tex->env->stype=ENV_STATIC; Index: source/blender/makesdna/DNA_texture_types.h =================================================================== --- source/blender/makesdna/DNA_texture_types.h (revision 11208) +++ source/blender/makesdna/DNA_texture_types.h (working copy) @@ -127,6 +127,15 @@ short recalc, lastsize; } EnvMap; +/* --------------------------------------- Tiles Specific ---------------------------------------------- */ +typedef struct TexPreCalc { + float hpat[16]; /* Stores horizontal tile pattern */ + float vpat[16]; /* Stores vertical tile pattern */ + float minw, minh; /* Store overall min of width and height value */ + float maxw, maxh; /* Store overall max of width and height value */ +} TexPreCalc; +/* --------------------------------------- Tiles Specific ---------------------------------------------- */ + typedef struct Tex { ID id; @@ -151,7 +160,17 @@ short imaflag, flag; short type, stype; - + + short hcount, vcount, smooth; + short corner, preset, bevoption; + float scale, rotate, hskew, vskew, hoffset, voffset; + float minwidth, maxwidth, minheight, maxheight; + float curve, freq, amp; + float hgap, vgap, shift, bevel, strength, pad4; + float hcorner, vcorner; + unsigned int seed, alternate; + struct TexPreCalc precalc; + float cropxmin, cropymin, cropxmax, cropymax; short xrepeat, yrepeat; short extend; @@ -171,10 +190,10 @@ struct PluginTex *plugin; struct ColorBand *coba; struct EnvMap *env; - - } Tex; +void tiles_precalc(Tex *tex); + /* used for mapping node. note: rot is in degrees */ typedef struct TexMapping { @@ -208,6 +227,7 @@ #define TEX_MUSGRAVE 11 #define TEX_VORONOI 12 #define TEX_DISTNOISE 13 +#define TEX_TILES 14 /* musgrave stype */ #define TEX_MFRACTAL 0 @@ -300,6 +320,25 @@ #define TEX_SPHERE 4 #define TEX_HALO 5 #define TEX_RAD 6 + +/* tex->stype in texture.c - corner types */ +#define TEX_CORNER_ROUND1 0 +#define TEX_CORNER_ROUND2 1 +#define TEX_CORNER_ELLIPSE1 2 +#define TEX_CORNER_ELLIPSE2 3 +#define TEX_CORNER_STRAIGHT 4 + +#define TEX_TILES_NONE 0 +#define TEX_TILES_1 1 +#define TEX_TILES_HEX 2 +#define TEX_TILES_HERRINGBONE1 3 +#define TEX_TILES_HERRINGBONE2 4 +#define TEX_TILES_HERRINGBONE3 5 +#define TEX_TILES_WEAVE 6 + +#define TEX_BEVEL_DEFAULTMIN 0 +#define TEX_BEVEL_UNIFORMMIN 1 +#define TEX_BEVEL_UNIFORMMAX 2 /* wrap */ #define MTEX_FLAT 0 Index: source/blender/src/buttons_shading.c =================================================================== --- source/blender/src/buttons_shading.c (revision 11208) +++ source/blender/src/buttons_shading.c (working copy) @@ -717,6 +717,144 @@ uiDefButF(block, NUMSLI, B_TEXPRV, "W4: ", 10, 10, 150, 19, &tex->vn_w4, -2.0, 2.0, 10, 0, "Sets feature weight 4"); } +static void texture_tiles_precalc(void *tex, void *unused) +{ + tiles_precalc((Tex *)tex); +} +static void texture_tiles_preset(void *tex, void *unused) +{ + Tex *t = (Tex *)tex; + + /* Setup parameters for preset patterns. */ + switch (t->preset) + { + case TEX_TILES_HEX: + t->hgap = 0; + t->vgap = 0; + t->alternate = 1; + break; + case TEX_TILES_HERRINGBONE1: + case TEX_TILES_HERRINGBONE2: + case TEX_TILES_HERRINGBONE3: + t->hgap = 0; + t->vgap = 0; + t->alternate = 1; + break; + case TEX_TILES_WEAVE: + t->hgap = 0; + t->vgap = 0; + t->alternate = 1; + break; + case TEX_TILES_1: + break; + } + + texture_tiles_precalc(tex, unused); +} +static char* tiles_corner_menu() +{ + static char nbmenu[256]; + sprintf(nbmenu, "Corner Style %%t|Round 1 %%x%d|Round 2 %%x%d|Ellipse 1 %%x%d|Ellipse 2 %%x%d|Straight %%x%d", TEX_CORNER_ROUND1, TEX_CORNER_ROUND2, TEX_CORNER_ELLIPSE1, TEX_CORNER_ELLIPSE2, TEX_CORNER_STRAIGHT); + return nbmenu; +} +static char* tiles_preset_menu() +{ + static char nbmenu[256]; + sprintf(nbmenu, "Preset %%t|None %%x%d|Tiles 1 %%x%d|Honeycomb %%x%d|Herringbone 1 %%x%d|Herringbone 2 %%x%d|Herringbone 3 %%x%d|Weave %%x%d", TEX_TILES_NONE, TEX_TILES_1, TEX_TILES_HEX, TEX_TILES_HERRINGBONE1, TEX_TILES_HERRINGBONE2, TEX_TILES_HERRINGBONE3, TEX_TILES_WEAVE); + return nbmenu; +} +static char* tiles_bevopt_menu() +{ + static char nbmenu[256]; + sprintf(nbmenu, "Bevel Option %%t|Default %%x%d|Uniform Min %%x%d|Uniform Max %%x%d", TEX_BEVEL_DEFAULTMIN, TEX_BEVEL_UNIFORMMIN, TEX_BEVEL_UNIFORMMAX); + return nbmenu; +} +static void texture_panel_tiles(Tex *tex) +{ + uiBut *bt; + uiBlock *block; + + block= uiNewBlock(&curarea->uiblocks, "texture_panel_tiles", UI_EMBOSS, UI_HELV, curarea->win); + if(uiNewPanel(curarea, block, "Tiles Basic", "Texture", 640, 0, 318, 204)==0) return; + + uiSetButLock(tex->id.lib!=NULL, ERROR_LIBDATA_MESSAGE); + + bt = uiDefBut(block, LABEL, 0, "Preset", 10, 180, 60, 19, 0, 0, 0, 0, 0, ""); + bt = uiDefButS(block, MENU, B_TEXPRV, tiles_preset_menu(), 70, 180, 100, 19, &tex->preset, 0, 0, 0, 0, "Tile preset"); + uiButSetFunc(bt, texture_tiles_preset, tex, NULL); + + bt = uiDefBut(block, LABEL, 0, "Scale", 200, 180, 50, 19, 0, 0.0, 0.0, 0, 0, ""); + bt = uiDefButF(block, NUM, B_TEXPRV, "%:", 250, 180, 80, 19, &tex->scale, 0.0001, 10, 10, 0, "Scaling"); + + bt = uiDefBut(block, LABEL, 0, "Width", 10, 132, 60, 19, 0, 0.0, 0.0, 0, 0, ""); + bt = uiDefButF(block, NUM, B_TEXPRV, "Lo:", 70, 132, 80, 19, &tex->minwidth, 0.01, 10, 10, 0, "Minimum tile width"); + uiButSetFunc(bt, texture_tiles_precalc, tex, NULL); + bt = uiDefButF(block, NUM, B_TEXPRV, "Hi:", 160, 132, 80, 19, &tex->maxwidth, 0.01, 10, 10, 0, "Maximum tile width"); + uiButSetFunc(bt, texture_tiles_precalc, tex, NULL); + bt = uiDefButS(block, NUMSLI, B_TEXPRV, "N:", 250, 132, 80, 19, &tex->hcount, 1, 15, 10, 0, "Number of horizontal random tiles"); + uiButSetFunc(bt, texture_tiles_precalc, tex, NULL); + + bt = uiDefBut(block, LABEL, 0, "Height", 10, 108, 60, 19, 0, 0.0, 0.0, 0, 0, ""); + bt = uiDefButF(block, NUM, B_TEXPRV, "Lo:", 70, 108, 80, 19, &tex->minheight, 0.01, 10, 10, 0, "Minimum tile height"); + uiButSetFunc(bt, texture_tiles_precalc, tex, NULL); + bt = uiDefButF(block, NUM, B_TEXPRV, "Hi:", 160, 108, 80, 19, &tex->maxheight, 0.01, 10, 10, 0, "Maximum tile height"); + uiButSetFunc(bt, texture_tiles_precalc, tex, NULL); + bt = uiDefButS(block, NUMSLI, B_TEXPRV, "N:", 250, 108, 80, 19, &tex->vcount, 1, 15, 10, 0, "Number of vertical random tiles"); + uiButSetFunc(bt, texture_tiles_precalc, tex, NULL); + + bt = uiDefBut(block, LABEL, 0, "Gap", 10, 84, 60, 19, 0, 0.0, 0.0, 0, 0, ""); + bt = uiDefButF(block, NUM, B_TEXPRV, "H:", 70, 84, 80, 19, &tex->hgap, 0, 10, 10, 0, "Horizontal gap"); + uiButSetFunc(bt, texture_tiles_precalc, tex, NULL); + bt = uiDefButF(block, NUM, B_TEXPRV, "V:", 160, 84, 80, 19, &tex->vgap, 0, 10, 10, 0, "Vertical gap"); + uiButSetFunc(bt, texture_tiles_precalc, tex, NULL); + + bt = uiDefBut(block, LABEL, 0, "Shift", 10, 60, 60, 19, 0, 0.0, 0.0, 0, 0, ""); + bt = uiDefButF(block, NUM, B_TEXPRV, "D:", 70, 60, 80, 19, &tex->shift, -10, 10, 10, 0, "Tile shift amount"); + bt = uiDefButI(block, NUM, B_TEXPRV, "N:", 160, 60, 80, 19, &tex->alternate, 0, 0x8000, 0, 0, "Number of tiles after which shifting starts again"); + + bt = uiDefButI(block, NUM, B_TEXPRV, "Seed:", 10, 10, 150, 19, &tex->seed, 0, 0x80000000, 10, 0, "Seed for random number generator"); + uiButSetFunc(bt, texture_tiles_precalc, tex, NULL); + + bt = uiDefButF(block, NUM, B_NOP, "Nabla:", 180, 10, 150, 19, &tex->nabla, 0.001, 0.1, 1, 0, "Defines size of derivative offset used for calculating normal"); +} +static void texture_panel_tiles_advanced(Tex *tex) +{ + uiBut *bt; + uiBlock *block; + + block= uiNewBlock(&curarea->uiblocks, "texture_panel_tiles_advanced", UI_EMBOSS, UI_HELV, curarea->win); + uiNewPanelTabbed("Tiles Basic", "Texture"); + if(uiNewPanel(curarea, block, "Tiles Advanced", "Texture", 1280, 0, 318, 204)==0) return; + + uiSetButLock(tex->id.lib!=NULL, ERROR_LIBDATA_MESSAGE); + + + bt = uiDefBut(block, LABEL, 0, "Bevel", 10, 180, 80, 19, 0, 0.0, 0.0, 0, 0, ""); + bt = uiDefButF(block, NUM, B_TEXPRV, "%:", 90, 180, 80, 19, &tex->bevel, 0, 0.5, 10, 0, "Tile bevel factor"); + bt = uiDefButF(block, NUM, B_TEXPRV, "C:", 180, 180, 80, 19, &tex->curve, -1, 1, 10, 0, "Adjust the bevel profile"); + bt = uiDefButS(block, TOG, B_TEXPRV, "Smooth", 270, 180, 80, 19, &tex->smooth, 0, 1, 0, 0, "Smooth the bevel profile"); + bt = uiDefButF(block, NUM, B_TEXPRV, "Freq:", 90, 156, 80, 19, &tex->freq, 0, 100, 10, 0, "Frequency of wave function for bevel"); + bt = uiDefButF(block, NUM, B_TEXPRV, "Amp:", 180, 156, 80, 19, &tex->amp, 0, 100, 10, 0, "Amplitude of wave function for bevel"); + bt = uiDefButF(block, NUM, B_TEXPRV, "S:", 270, 156, 80, 19, &tex->strength, 0, 1, 10, 0, "Strength of bevel"); + bt = uiDefButS(block, MENU, B_TEXPRV, tiles_bevopt_menu(), 90, 132,170, 19, &tex->bevoption, 0, 0, 0, 0, "Controls uniformity of bevel across tiles"); + uiButSetFunc(bt, texture_tiles_precalc, tex, NULL); + + bt = uiDefBut(block, LABEL, 0, "Corner", 10, 108, 80, 19, 0, 0.0, 0.0, 0, 0, ""); + bt = uiDefButF(block, NUM, B_TEXPRV, "H%:", 90, 108, 80, 19, &tex->hcorner, 0, 0.5, 10, 0, "Tile corner horizontal factor"); + bt = uiDefButF(block, NUM, B_TEXPRV, "V%:", 180, 108, 80, 19, &tex->vcorner, 0, 0.5, 10, 0, "Tile corner vertical factor"); + bt = uiDefButS(block, MENU, B_TEXPRV, tiles_corner_menu(), 270, 108, 80, 19, &tex->corner, 0, 0, 0, 0, "Tile corner type"); + + bt = uiDefBut(block, LABEL, 0, "Rotate", 10, 60, 80, 19, 0, 0.0, 0.0, 0, 0, ""); + bt = uiDefButF(block, NUM, B_TEXPRV, "Deg:", 90, 60, 80, 19, &tex->rotate, 0, 360, 100, 0, "Texture rotation in degrees"); + + bt = uiDefBut(block, LABEL, 0, "Skew", 10, 36, 80, 19, 0, 0.0, 0.0, 0, 0, ""); + bt = uiDefButF(block, NUM, B_TEXPRV, "H:", 90, 36, 80, 19, &tex->hskew, -100, 100, 10, 0, "Horizontal skew"); + bt = uiDefButF(block, NUM, B_TEXPRV, "V:", 180, 36, 80, 19, &tex->vskew, -100, 100, 10, 0, "Vertical skew"); + + bt = uiDefBut(block, LABEL, 0, "Offset", 10, 12, 80, 19, 0, 0.0, 0.0, 0, 0, ""); + bt = uiDefButF(block, NUM, B_TEXPRV, "H:", 90, 12, 80, 19, &tex->hoffset, -100, 100, 10, 0, "Horizontal offset"); + bt = uiDefButF(block, NUM, B_TEXPRV, "V:", 180, 12, 80, 19, &tex->voffset, -100, 100, 10, 0, "Vertical offset"); +} static char *layer_menu(RenderResult *rr, short *curlay) { @@ -1617,7 +1755,7 @@ /* newnoise: all texture types as menu, not enough room for more buttons. * Can widen panel, but looks ugly when other panels overlap it */ - sprintf(textypes, "Texture Type %%t|None %%x%d|Image %%x%d|EnvMap %%x%d|Clouds %%x%d|Marble %%x%d|Stucci %%x%d|Wood %%x%d|Magic %%x%d|Blend %%x%d|Noise %%x%d|Plugin %%x%d|Musgrave %%x%d|Voronoi %%x%d|DistortedNoise %%x%d", 0, TEX_IMAGE, TEX_ENVMAP, TEX_CLOUDS, TEX_MARBLE, TEX_STUCCI, TEX_WOOD, TEX_MAGIC, TEX_BLEND, TEX_NOISE, TEX_PLUGIN, TEX_MUSGRAVE, TEX_VORONOI, TEX_DISTNOISE); + sprintf(textypes, "Texture Type %%t|None %%x%d|Image %%x%d|EnvMap %%x%d|Clouds %%x%d|Marble %%x%d|Stucci %%x%d|Wood %%x%d|Magic %%x%d|Blend %%x%d|Noise %%x%d|Plugin %%x%d|Musgrave %%x%d|Voronoi %%x%d|DistortedNoise %%x%d|Tiles %%x%d", 0, TEX_IMAGE, TEX_ENVMAP, TEX_CLOUDS, TEX_MARBLE, TEX_STUCCI, TEX_WOOD, TEX_MAGIC, TEX_BLEND, TEX_NOISE, TEX_PLUGIN, TEX_MUSGRAVE, TEX_VORONOI, TEX_DISTNOISE, TEX_TILES); uiDefBut(block, LABEL, 0, "Texture Type", 160, 150, 140, 20, 0, 0.0, 0.0, 0, 0, ""); uiDefButS(block, MENU, B_TEXTYPE, textypes, 160, 125, 140, 25, &tex->type, 0,0,0,0, "Select texture type"); @@ -4042,6 +4180,10 @@ /* newnoise: voronoi */ case TEX_VORONOI: texture_panel_voronoi(tex); + break; + case TEX_TILES: + texture_panel_tiles(tex); + texture_panel_tiles_advanced(tex); break; } } Index: source/blender/blenloader/intern/readfile.c =================================================================== --- source/blender/blenloader/intern/readfile.c (revision 11208) +++ source/blender/blenloader/intern/readfile.c (working copy) @@ -6528,6 +6528,42 @@ } } } + + if(main->versionfile != 244 || main->subversionfile < 3) { + /* Initialize Tiles texture */ + Tex *tex; + for(tex= main->tex.first; tex; tex= tex->id.next) { + tex->scale = 1; + tex->hcount = 3; + tex->minwidth = 0.2; + tex->maxwidth = 0.3; + tex->vcount = 3; + tex->minheight = 0.1; + tex->maxheight = 0.2; + tex->hgap = 0.05; + tex->vgap = 0.05; + tex->shift = 0.1; + tex->bevel = 0.2; + tex->corner = 0; + tex->hcorner = 0.25; + tex->vcorner = 0.25; + tex->rotate = 0; + tex->seed = 0; + tex->alternate = 2; + tex->hskew = 0; + tex->vskew = 0; + tex->curve = 0; + tex->smooth = 0; + tex->freq = 0; + tex->amp = 0; + tex->hoffset = 0; + tex->voffset = 0; + tex->strength = 1; + tex->preset = 0; + tex->bevoption = 0; + tiles_precalc(tex); + } + } } /* WATCH IT!!!: pointers from libdata have not been converted yet here! */