Index: release/scripts/startup/bl_ui/properties_texture.py =================================================================== --- release/scripts/startup/bl_ui/properties_texture.py (revision 39316) +++ release/scripts/startup/bl_ui/properties_texture.py (working copy) @@ -531,6 +531,169 @@ texture_filter_common(tex, layout) + +# tilestexture +class TEXTURE_PT_tiles(TextureTypePanel, bpy.types.Panel): + bl_label = "Tiles" + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'} + + @classmethod + def poll(cls, context): + tex = context.texture + engine = context.scene.render.engine + return tex and (tex.type == 'TILES' and (engine in cls.COMPAT_ENGINES)) + + def draw(self, context): + layout = self.layout + + tex = context.texture + + row = layout.row() + row.column().prop(tex, "pattern", text="") + + row = layout.row() + col = row.column() + col.label(text="Number of tiles:") + sub = col.column(align=True) + sub.prop(tex, "hcount") + sub.prop(tex, "vcount") + + col = row.column() + col.label(text="Corner style:") + col.prop(tex, "corner_type", text="") + sub = col.column(align=True) + sub.prop(tex, "hcorner") + sub.prop(tex, "vcorner") + + row = layout.row() + col = row.column() + col.label(text="Tile size variation:") + sub = col.column(align=True) + sub.prop(tex, "widthvar", text="Width") + sub.prop(tex, "heightvar", text="Height") + col.prop(tex, "seed") + col = row.column() + col.label(text="Bump mapping:") + sub = col.column(align=True) + sub.prop(tex, "bump") + sub.prop(tex, "bumpvar", text="Variation") + + row = layout.row() + col = row.column() + col.label(text="Gap:") + sub = col.column(align=True) + sub.prop(tex, "hgap") + sub.prop(tex, "vgap") + col = row.column() + col.label(text="Shifting:") + sub = col.column(align=True) + sub.prop(tex, "shift") + sub.prop(tex, "alternate") + + +class TEXTURE_PT_tiles_color(TextureTypePanel, bpy.types.Panel): + bl_label = "Tiles Color" + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'} + + @classmethod + def poll(cls, context): + tex = context.texture + engine = context.scene.render.engine + return tex and (tex.type == 'TILES' and (engine in cls.COMPAT_ENGINES)) + + def draw(self, context): + layout = self.layout + + tex = context.texture + + row = layout.row() + col = row.column() + sub = col.column(align=True) + sub.prop(tex, "tile_color") + sub.prop(tex, "gap_color") + col = row.column() + col.label(text="Color variation:") + sub = col.column(align=True) + sub.prop(tex, "fhue") + sub.prop(tex, "fsat") + sub.prop(tex, "fval") + + +class TEXTURE_PT_tiles_bevel(TextureTypePanel, bpy.types.Panel): + bl_label = "Tiles Bevel" + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'} + + @classmethod + def poll(cls, context): + tex = context.texture + engine = context.scene.render.engine + return tex and (tex.type == 'TILES' and (engine in cls.COMPAT_ENGINES)) + + def draw(self, context): + layout = self.layout + + tex = context.texture + + row = layout.row() + col = row.column() + col.prop(tex, "bevoption") + col.prop(tex, "bevelshading") + col = row.column() + col.prop(tex, "bevel") + col.prop(tex, "smooth") + + layout.label(text="Bevel shape:") + row = layout.row() + row.column().template_curve_mapping(tex, "curbevel") + + +class TEXTURE_PT_tiles_sampling(TextureTypePanel, bpy.types.Panel): + bl_label = "Tiles Sampling" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'} + + @classmethod + def poll(cls, context): + tex = context.texture + engine = context.scene.render.engine + return tex and (tex.type == 'TILES' and (engine in cls.COMPAT_ENGINES)) + + def draw(self, context): + layout = self.layout + + idblock = context_tex_datablock(context) + tex = context.texture + slot = getattr(context, "texture_slot", None) + + split = layout.split() + + col = split.column() + col.label(text="Alpha:") + col.prop(tex, "use_alpha", text="Use") + col.prop(tex, "use_calculate_alpha", text="Calculate") + col.prop(tex, "invert_alpha", text="Invert") + col.separator() + col.prop(tex, "use_flip_axis", text="Flip X/Y Axis") + + col = split.column() + + #Only for Material based textures, not for Lamp/World... + if slot and isinstance(idblock, bpy.types.Material): + col.prop(tex, "use_normal_map") + row = col.row() + row.active = tex.use_normal_map + row.prop(slot, "normal_map_space", text="") + + col.prop(tex, "use_mipmap") + row = col.row() + row.active = tex.use_mipmap + row.prop(tex, "use_mipmap_gauss") + col.prop(tex, "use_interpolation") + + texture_filter_common(tex, layout) + layout.prop(tex, "resolution") + + class TEXTURE_PT_musgrave(TextureTypePanel, bpy.types.Panel): bl_label = "Musgrave" tex_type = 'MUSGRAVE' Index: source/blender/render/intern/source/render_texture.c =================================================================== --- source/blender/render/intern/source/render_texture.c (revision 39316) +++ source/blender/render/intern/source/render_texture.c (working copy) @@ -39,6 +39,7 @@ #include "BLI_math.h" #include "BLI_rand.h" #include "BLI_utildefines.h" +#include "BLI_threads.h" #include "DNA_texture_types.h" #include "DNA_object_types.h" @@ -67,6 +68,7 @@ #include "BKE_texture.h" #include "BKE_key.h" #include "BKE_ipo.h" +#include "BKE_colortools.h" #include "envmap.h" #include "pointdensity.h" @@ -76,6 +78,7 @@ #include "rendercore.h" #include "shading.h" #include "texture.h" +#include "tiles.h" #include "renderdatabase.h" /* needed for UV */ @@ -87,7 +90,6 @@ - static void init_render_texture(Render *re, Tex *tex) { int cfra= re->scene->r.cfra; @@ -741,8 +743,6 @@ return TEX_INT; } -/* ------------------------------------------------------------------------- */ - static int plugintex(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, TexResult *texres) { PluginTex *pit; @@ -1261,7 +1261,9 @@ case TEX_VOXELDATA: retval= voxeldatatex(tex, texvec, texres); break; - + case TEX_TILES: + retval= tiles_osa(tex, texvec, dxt, dyt, texres); + break; } if (tex->flag & TEX_COLORBAND) { @@ -1289,7 +1291,7 @@ if(mtex) which_output= mtex->which_output; - if(tex->type==TEX_IMAGE) { + if(tex->type==TEX_IMAGE || tex->type==TEX_TILES) { int rgbnor; if(mtex) { @@ -1747,7 +1749,7 @@ { TexResult ttexr = {0, 0, 0, 0, 0, texres->talpha, NULL}; // temp TexResult float tco[3], texv[3], cd, ud, vd, du, dv, idu, idv; - const int fromrgb = ((tex->type == TEX_IMAGE) || ((tex->flag & TEX_COLORBAND)!=0)); + const int fromrgb = ((tex->type == TEX_IMAGE) || (tex->type == TEX_TILES) || ((tex->flag & TEX_COLORBAND)!=0)); const float bf = 0.04f*Tnor*mtex->norfac; int rgbnor; // disable internal bump eval @@ -1768,7 +1770,7 @@ // (which also works without osa, though of course not always good (or even very bad) results), // or based on tex derivative max values (osa only). Not sure which is best... - if (!shi->osatex && (tex->type == TEX_IMAGE) && tex->ima) { + if (!shi->osatex && (tex->type == TEX_IMAGE || tex->type == TEX_TILES) && tex->ima) { // in case we have no proper derivatives, fall back to // computing du/dv it based on image size ImBuf* ibuf = BKE_image_get_ibuf(tex->ima, &tex->iuser); @@ -1779,7 +1781,7 @@ } else if (shi->osatex) { // we have derivatives, can compute proper du/dv - if (tex->type == TEX_IMAGE) { // 2d image, use u & v max. of dx/dy 2d vecs + if (tex->type == TEX_IMAGE || tex->type == TEX_TILES) { // 2d image, use u & v max. of dx/dy 2d vecs const float adx[2] = {fabsf(dx[0]), fabsf(dx[1])}; const float ady[2] = {fabsf(dy[0]), fabsf(dy[1])}; du = MAX2(adx[0], ady[0]); @@ -1903,7 +1905,7 @@ { TexResult ttexr = {0, 0, 0, 0, 0, texres->talpha, NULL}; // temp TexResult - const int fromrgb = ((tex->type == TEX_IMAGE) || ((tex->flag & TEX_COLORBAND)!=0)); + const int fromrgb = ((tex->type == TEX_IMAGE) || (tex->type == TEX_TILES) || ((tex->flag & TEX_COLORBAND)!=0)); float Hscale = Tnor*mtex->norfac; // 2 channels for 2D texture and 3 for 3D textures. @@ -2690,7 +2692,7 @@ texres.nor= NULL; - if(tex->type==TEX_IMAGE) { + if(tex->type==TEX_IMAGE || tex->type==TEX_TILES) { continue; /* not supported yet */ //do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt); } @@ -2869,7 +2871,7 @@ } - if(mtex->tex->type==TEX_IMAGE) do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt); + if(mtex->tex->type==TEX_IMAGE || mtex->tex->type==TEX_TILES) do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt); rgb= multitex(mtex->tex, texvec, dxt, dyt, osatex, &texres, 0, mtex->which_output); @@ -3062,7 +3064,7 @@ else texvec[2]= mtex->size[2]*(mtex->ofs[2]); /* texture */ - if(tex->type==TEX_IMAGE) do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt); + if(tex->type==TEX_IMAGE || tex->type==TEX_TILES) do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt); rgb= multitex(mtex->tex, texvec, dxt, dyt, R.osa, &texres, thread, mtex->which_output); @@ -3266,7 +3268,7 @@ } /* texture */ - if(tex->type==TEX_IMAGE) { + if(tex->type==TEX_IMAGE || tex->type==TEX_TILES) { do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt); } @@ -3361,7 +3363,7 @@ else texvec[2]= mtex->size[2]*(mtex->ofs[2]); /* texture */ - if(tex->type==TEX_IMAGE) { + if(tex->type==TEX_IMAGE || tex->type==TEX_TILES) { do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt); } Index: source/blender/render/intern/source/tiles.c =================================================================== --- source/blender/render/intern/source/tiles.c (revision 0) +++ source/blender/render/intern/source/tiles.c (revision 0) @@ -0,0 +1,2270 @@ +// +// tiles.c +// Blender +// +// Created by Ahmad Kabani on 11-07-21. + +#include +#include +#include +#include + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" +#include "BLI_math.h" +#include "BLI_rand.h" +#include "BLI_utildefines.h" +#include "BLI_threads.h" + +#include "DNA_texture_types.h" + +#include "IMB_imbuf_types.h" +#include "IMB_imbuf.h" + +#include "BKE_colortools.h" +#include "BKE_image.h" +#include "BKE_node.h" + +#include "BKE_global.h" +#include "BKE_main.h" +#include "BKE_material.h" + +#include "BKE_library.h" +#include "BKE_image.h" +#include "BKE_texture.h" +#include "BKE_key.h" +#include "BKE_ipo.h" +#include "BKE_colortools.h" + +#include "IMB_imbuf_types.h" +#include "IMB_imbuf.h" + +#include "render_types.h" +#include "rendercore.h" +#include "texture.h" +#include "tiles.h" + +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); +} + +static int point_in_concave_polygon(float x, float y, float *vx, float *vy, short n) +{ + int i, j, c = 0; + for (i = 0, j = n-1; i < n; j = i++) { + if ((((vy[i]<=y) && (ybevoption) + { + case TEX_BEVEL_UNIFORMMIN: + s = MIN2(tex->tilesdata->minw, tex->tilesdata->minh); + break; + case TEX_BEVEL_UNIFORMMAX: + s = MIN2(tex->tilesdata->maxw, tex->tilesdata->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, short bs) +{ + /* 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; + float v = 0; + + /* Find minimum distance to point from the 4 sides */ + float dmin; + + if ((x < 0) || (x > w) || (y < 0) || (y > h)) return 0; + + switch (bs) + { + case TEX_BEVEL_HGRADIENT: + dmin = MIN2(dx1, dx2); + break; + case TEX_BEVEL_VGRADIENT: + dmin = MIN2(dy1, dy2); + break; + default: + dmin = MIN4(dx1, dx2, dy1, dy2); + break; + } + + 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, short bs) +{ + /* 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, bs); + 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; + + switch (bs) { + case TEX_BEVEL_HGRADIENT: + case TEX_BEVEL_VGRADIENT: + if ((d1 < 0) || (d2 < 0) || (d3 < 0) || (d4 < 0)) d = 0; + else d = v; + break; + default: + LINE_BEVEL(d1, b); + LINE_BEVEL(d2, b); + LINE_BEVEL(d3, b); + LINE_BEVEL(d4, b); + + d = MIN4(d1, d2, d3, d4); + break; + } + + return MIN2(v, d); +} + +static float tiles_poly_func(float x, float y, float *vx, float *vy, short n, float b, short bs) +{ + /* 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; + float xmin, xmax, ymin, ymax, w, h; + + /* Determine if p lies in the polygon */ + p[0] = x; + p[1] = y; + + switch (bs) { + case TEX_BEVEL_HGRADIENT: + case TEX_BEVEL_VGRADIENT: + xmin = vx[0]; + ymin = vy[0]; + xmax = xmin; + ymax = ymin; + 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; + } + + xmin = MIN2(xmin, vx[i]); + ymin = MIN2(ymin, vy[i]); + xmax = MAX2(xmax, vx[i]); + ymax = MAX2(ymax, vy[i]); + } + + w = xmax - xmin; + h = ymax - ymin; + d = tiles_rect_func(x - xmin, y - ymin, w, h, b, bs); + break; + + default: + 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); + break; + } + return d; +} + +static float tiles_concave_poly_helper(float x, float y, float *vx, float *vy, int i, int n, float b) +{ + int j = i - 1; + int k = i + 1; + float l; + float v1[2], v2[2], v1p[2], v2p[2], vh[2]; + float p1[2], p2[2], p3[2], p4[2], p[2]; + float d1, dx, m; + + /* Determine points on either side of point i */ + if (j < 0) j = n - 1; + if (k >= n) k = 0; + + /* Contruct vectors from i to neighbouring points j and k */ + v1[0] = vx[j] - vx[i]; v1[1] = vy[j] - vy[i]; + v2[0] = vx[k] - vx[i]; v2[1] = vy[k] - vy[i]; + + /* Scale to length b */ + l = b / sqrt(v1[0] * v1[0] + v1[1] * v1[1]); + v1[0] *= l; + v1[1] *= l; + + l = b / sqrt(v2[0] * v2[0] + v2[1] * v2[1]); + v2[0] *= l; + v2[1] *= l; + + /* Calculate perpendicular vectors (whose length will be b). + * Note the order of signs, we're trying to get vectors that lie inside + * the convex polygon. + */ + v1p[0] = v1[1]; v1p[1] = -v1[0]; + v2p[0] = -v2[1]; v2p[1] = v2[0]; + + /* Add the 2 vectors to get a vector that is halfway between v1p and v2p. + * It is the opposite vector of v1 and v2's angle bisector. + */ + vh[0] = v1p[0] + v2p[0]; + vh[1] = v1p[1] + v2p[1]; + + /* p1, p2, p3, p4 define the quad in which points require beveling. */ + p[0] = x; p[1] = y; + p1[0] = vx[i]; p1[1] = vy[i]; + p2[0] = p1[0] + v2p[0]; p2[1] = p1[1] + v2p[1]; + p3[0] = p1[0] + vh[0]; p3[1] = p1[1] + vh[1]; + p4[0] = p1[0] + v1p[0]; p4[1] = p1[1] + v1p[1]; + + /* Depending on which side of the vector vh the point falls, apply a bevel with + * corresponding side of the polygon. + */ + d1 = 1; + if (POINT_IN_TRI(p, p1, p2, p3)) { + dx = vx[i] - vx[k]; + if (fabs(dx) > 0) { + m = (vy[i] - vy[k]) / dx; + d1 = fabs(DIST_POINT_TO_LINE(m, -1, vy[i] - vx[i] * m, x, y)); + } + else { + d1 = fabs(x - vx[i]); + } + } + else if (POINT_IN_TRI(p, p1, p3, p4)) { + dx = vx[j] - vx[i]; + if (fabs(dx) > 0) { + m = (vy[j] - vy[i]) / dx; + d1 = fabs(DIST_POINT_TO_LINE(m, -1, vy[j] - vx[j] * m, x, y)); + } + else { + d1 = fabs(x - vx[j]); + } + } + + return d1; +} + +static float tiles_concave_poly_func(float x, float y, float *vx, float *vy, short n, float b, short bs) +{ + /* Handles both convex, concave and overlapping polygons */ + int i, j, c = 0, set = 0; + float d = 0, d1, dx, m; + float doti, dotj; + float xmin, xmax, ymin, ymax, w, h; + + switch (bs) { + case TEX_BEVEL_HGRADIENT: + case TEX_BEVEL_VGRADIENT: + xmin = vx[0]; + ymin = vy[0]; + xmax = xmin; + ymax = ymin; + for (i = 0, j = n-1; i < n; j = i++) { + if ((((vy[i] <= y) && (y < vy[j])) || + ((vy[j] <= y) && (y < vy[i]))) && + (x < (vx[j] - vx[i]) * (y - vy[i]) / (vy[j] - vy[i]) + vx[i])) + { + c = !c; + } + + xmin = MIN2(xmin, vx[i]); + ymin = MIN2(ymin, vy[i]); + xmax = MAX2(xmax, vx[i]); + ymax = MAX2(ymax, vy[i]); + } + if (c) { + w = xmax - xmin; + h = ymax - ymin; + d = tiles_rect_func(x - xmin, y - ymin, w, h, b, bs); + } + else { + d = 0; + } + break; + + default: + for (i = 0, j = n-1; i < n; j = i++) { + if ((((vy[i] <= y) && (y < vy[j])) || + ((vy[j] <= y) && (y < vy[i]))) && + (x < (vx[j] - vx[i]) * (y - vy[i]) / (vy[j] - vy[i]) + vx[i])) + { + c = !c; + } + + /* Check if angles formed at points on the segment are obtuse to determine if + * the point falls between perpendicular lines at segment endpoints. + */ + doti = (vx[j] - vx[i]) * (x - vx[i]) + (vy[j] - vy[i]) * (y - vy[i]); + dotj = (vx[i] - vx[j]) * (x - vx[j]) + (vy[i] - vy[j]) * (y - vy[j]); + + if ((doti >= 0) && (dotj >= 0)) { + /* Compute distance to the line containing current side */ + dx = vx[j] - vx[i]; + if (fabs(dx) > 0) { + m = (vy[j] - vy[i]) / dx; + d1 = fabs(DIST_POINT_TO_LINE(m, -1, vy[j] - vx[j] * m, x, y)); + } + else { + d1 = fabs(x - vx[j]); + } + + /* Take minimum distance so far */ + d = set ? MIN2(d, d1) : d1; + set = 1; + } + else if (doti < 0) { + d1 = tiles_concave_poly_helper(x, y, vx, vy, i, n, b); + d = set ? MIN2(d, d1) : d1; + set = 1; + } + else { + d1 = tiles_concave_poly_helper(x, y, vx, vy, j, n, b); + d = set ? MIN2(d, d1) : d1; + set = 1; + } + } + if (c) { + LINE_BEVEL(d, b); + } + else { + d = 0; + } + break; + } + 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, short bs) +{ + /* First compute the intensity inside the rectangle bounded by (0, 0) and (w, h). */ + float v = tiles_rect_func(x, y, w, h, b, bs); + float t = v; + float hw = w * 0.5; + float hh = h * 0.5; + + if (flip) { + switch (bs) { + case TEX_BEVEL_HGRADIENT: + case TEX_BEVEL_VGRADIENT: + /* For points that lie inside the four corners determine if they fall inside the circle + * centered at the corners use black. + */ + if ((x >= 0) && (x <= hw)) { + if ((y >= 0) && (y <= hh)) { + if (POINT_IN_CIRCLE(x, y, 0, 0, r)) t = 0; + } + else if ((y > hh) && (y <= h)) { + if (POINT_IN_CIRCLE(x, y, 0, h, r)) t = 0; + } + } + else if ((x > hw) && (x <= w)) { + if ((y >= 0) && (y <= hh)) { + if (POINT_IN_CIRCLE(x, y, w, 0, r)) t = 0; + } + else if ((y > hh) && (y <= h)) { + if (POINT_IN_CIRCLE(x, y, w, h, r)) t = 0; + } + } + break; + default: + /* 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); + } + } + break; + } + } + else { + switch (bs) { + case TEX_BEVEL_HGRADIENT: + case TEX_BEVEL_VGRADIENT: + /* For points that lie inside the four corners determine if they fall outside the circle + * centered at the offset by the radius use black. + */ + if ((x >= 0) && (x <= r)) { + if ((y >= 0) && (y <= r)) { + if (POINT_NOT_IN_CIRCLE(x, y, r, r, r)) t = 0; + } + else if ((y >= h - r) && (y <= h)) { + if (POINT_NOT_IN_CIRCLE(x, y, r, h - r, r)) t = 0; + } + } + else if ((x >= w - r) && (x <= w)) { + if ((y >= 0) && (y <= r)) { + if (POINT_NOT_IN_CIRCLE(x, y, w - r, r, r)) t = 0; + } + else if ((y >= h - r) && (y <= h)) { + if (POINT_NOT_IN_CIRCLE(x, y, w - r, h - r, r)) t = 0; + } + } + break; + default: + /* 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)) { + t = tiles_circle_func1(x, y, r, r, b, r); + } + else if ((y >= h - r) && (y <= h)) { + t = tiles_circle_func1(x, y, r, h - r, b, r); + } + } + else if ((x >= w - r) && (x <= w)) { + if ((y >= 0) && (y <= r)) { + t = tiles_circle_func1(x, y, w - r, r, b, r); + } + else if ((y >= h - r) && (y <= h)) { + t = tiles_circle_func1(x, y, w - r, h - r, b, r); + } + } + break; + } + } + return MIN2(t, 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, short bs) +{ + /* First compute the intensity inside the rectangle bounded by (0, 0) and (w, h). */ + float v = tiles_rect_func(x, y, w, h, b, bs); + float t = v; + float hw = w * 0.5; + float hh = h * 0.5; + + if (flip) { + switch (bs) { + case TEX_BEVEL_HGRADIENT: + case TEX_BEVEL_VGRADIENT: + /* For points that lie inside the four corners determine if they fall inside the ellipse + * centered at the corners use black. + */ + if ((x >= 0) && (x <= hw)) { + if ((y >= 0) && (y <= hh)) { + if (POINT_IN_ELLIPSE(x, y, 0, 0, rx, ry)) t = 0; + } + else if ((y > hh) && (y <= h)) { + if (POINT_IN_ELLIPSE(x, y, 0, h, rx, ry)) t = 0; + } + } + else if ((x > hw) && (x <= w)) { + if ((y >= 0) && (y <= hh)) { + if (POINT_IN_ELLIPSE(x, y, w, 0, rx, ry)) t = 0; + } + else if ((y > hh) && (y <= h)) { + if (POINT_IN_ELLIPSE(x, y, w, h, rx, ry)) t = 0; + } + } + break; + + default: + /* 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); + } + } + break; + } + } + else { + switch (bs) { + case TEX_BEVEL_HGRADIENT: + case TEX_BEVEL_VGRADIENT: + /* For points that lie inside the four corners determine if they fall outside the ellipse + * centered at the offset by the radius use black. + */ + if ((x >= 0) && (x <= rx)) { + if ((y >= 0) && (y <= ry)) { + if (POINT_NOT_IN_ELLIPSE(x, y, rx, ry, rx, ry)) t = 0; + } + else if ((y >= h - ry) && (y <= h)) { + if (POINT_NOT_IN_ELLIPSE(x, y, rx, h - ry, rx, ry)) t = 0; + } + } + else if ((x >= w - rx) && (x <= w)) { + if ((y >= 0) && (y <= ry)) { + if (POINT_NOT_IN_ELLIPSE(x, y, w - rx, ry, rx, ry)) t = 0; + } + else if ((y >= h - ry) && (y <= h)) { + if (POINT_NOT_IN_ELLIPSE(x, y, w - rx, h - ry, rx, ry)) t = 0; + } + } + break; + default: + /* 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); + } + else if ((y >= h - ry) && (y <= h)) { + t = tiles_ellipse_func1(x, y, rx, h - ry, b, rx, ry); + } + } + else if ((x >= w - rx) && (x <= w)) { + if ((y >= 0) && (y <= ry)) { + t = tiles_ellipse_func1(x, y, w - rx, ry, b, rx, ry); + } + else if ((y >= h - ry) && (y <= h)) { + t = tiles_ellipse_func1(x, y, w - rx, h - ry, b, rx, ry); + } + } + break; + } + } + return MIN2(t, v); +} + +/* Note: bs will override tex->bevelshading. To avoid that pass in tex->bevelshading for this param */ +static float tiles_recthelper_int(Tex *tex, float x, float y, float w, float h, float dim, float b, short bs) +{ + float rx, ry, intens; + + switch (tex->corner) { + case TEX_CORNER_ROUND: + if (tex->hcorner == tex->vcorner) { + rx = tex->hcorner * dim; + intens = tiles_roundrect_func(x, y, w, h, b, rx, 0, bs); + } + else { + rx = tex->hcorner * dim; + ry = tex->vcorner * dim; + intens = tiles_ellipserect_func(x, y, w, h, b, rx, ry, 0, bs); + } + break; + case TEX_CORNER_ROUND_INV: + if (tex->hcorner == tex->vcorner) { + rx = tex->hcorner * dim; + intens = tiles_roundrect_func(x, y, w, h, b, rx, 1, bs); + } + else { + rx = tex->hcorner * dim; + ry = tex->vcorner * dim; + intens = tiles_ellipserect_func(x, y, w, h, b, rx, ry, 1, bs); + } + break; + case TEX_CORNER_ELLIPSE: + rx = tex->hcorner * w; + ry = tex->vcorner * h; + intens = tiles_ellipserect_func(x, y, w, h, b, rx, ry, 0, bs); + break; + case TEX_CORNER_ELLIPSE_INV: + rx = tex->hcorner * w; + ry = tex->vcorner * h; + intens = tiles_ellipserect_func(x, y, w, h, b, rx, ry, 1, bs); + break; + case TEX_CORNER_STRAIGHT: + rx = tex->hcorner * w; + ry = tex->vcorner * h; + intens = tiles_rect_func2(x, y, w, h, b, rx, ry, bs); + break; + default: + intens = tiles_rect_func(x, y, w, h, b, bs); + break; + } + + return intens; +} + +static void tiles_default_col(Tex *tex, float intens, short htileid, short vtileid, float *col) +{ + float intens1 = 1.0 - intens; + col[0] = tex->tilesdata->r[htileid][vtileid] * intens + tex->colr2 * intens1; + col[1] = tex->tilesdata->g[htileid][vtileid] * intens + tex->colg2 * intens1; + col[2] = tex->tilesdata->b[htileid][vtileid] * intens + tex->colb2 * intens1; +} + +static void tiles_neighbour_col(Tex *tex, float *intens, short htileid, short vtileid, short id, short i, float *col) +{ + float intens1 = 1.0 - (*intens); + float s; + short htileidl, htileidr, vtileida, vtileidb; + + /* Compute indices of neighbouring tiles */ + htileidr = (htileid + 1) % tex->hcount; /* Right */ + htileidl = (htileid - 1 + tex->hcount) % tex->hcount; /* Left */ + vtileida = (vtileid + 1) % tex->vcount; /* Above */ + vtileidb = (vtileid - 1 + tex->vcount) % tex->vcount; /* Below */ + + /* Default colour of current tile */ + col[0] = tex->tilesdata->r[htileid][vtileid]; + col[1] = tex->tilesdata->g[htileid][vtileid]; + col[2] = tex->tilesdata->b[htileid][vtileid]; + s = tex->tilesdata->bpat[htileid][vtileid]; + + /* Add colours of neighbouring tiles and do uniform average */ + switch (id) { + case TILE_BELOW: + col[0] += tex->tilesdata->r[htileid][vtileidb]; + col[1] += tex->tilesdata->g[htileid][vtileidb]; + col[2] += tex->tilesdata->b[htileid][vtileidb]; + col[0] *= 0.5; + col[1] *= 0.5; + col[2] *= 0.5; + + s += tex->tilesdata->bpat[htileid][vtileidb]; + s *= 0.5; + + break; + case TILE_ABOVE: + col[0] += tex->tilesdata->r[htileid][vtileida]; + col[1] += tex->tilesdata->g[htileid][vtileida]; + col[2] += tex->tilesdata->b[htileid][vtileida]; + col[0] *= 0.5; + col[1] *= 0.5; + col[2] *= 0.5; + + s += tex->tilesdata->bpat[htileid][vtileida]; + s *= 0.5; + + break; + case TILE_LEFT: + col[0] += tex->tilesdata->r[htileidl][vtileid]; + col[1] += tex->tilesdata->g[htileidl][vtileid]; + col[2] += tex->tilesdata->b[htileidl][vtileid]; + col[0] *= 0.5; + col[1] *= 0.5; + col[2] *= 0.5; + + s += tex->tilesdata->bpat[htileidl][vtileid]; + s *= 0.5; + + break; + case TILE_RIGHT: + col[0] += tex->tilesdata->r[htileidr][vtileid]; + col[1] += tex->tilesdata->g[htileidr][vtileid]; + col[2] += tex->tilesdata->b[htileidr][vtileid]; + col[0] *= 0.5; + col[1] *= 0.5; + col[2] *= 0.5; + + s += tex->tilesdata->bpat[htileidr][vtileid]; + s *= 0.5; + + break; + case TILE_LEFT_BELOW: + col[0] += tex->tilesdata->r[htileidl][vtileid] + tex->tilesdata->r[htileidl][vtileidb] + tex->tilesdata->r[htileid][vtileidb]; + col[1] += tex->tilesdata->g[htileidl][vtileid] + tex->tilesdata->g[htileid][vtileidb] + tex->tilesdata->g[htileidl][vtileidb]; + col[2] += tex->tilesdata->b[htileidl][vtileid] + tex->tilesdata->b[htileidl][vtileidb] + tex->tilesdata->b[htileid][vtileidb]; + col[0] *= 0.25; + col[1] *= 0.25; + col[2] *= 0.25; + + s += tex->tilesdata->bpat[htileidl][vtileid] + tex->tilesdata->bpat[htileidl][vtileidb] + tex->tilesdata->bpat[htileid][vtileidb]; + s *= 0.25; + + break; + case TILE_LEFT_ABOVE: + col[0] += tex->tilesdata->r[htileidl][vtileid] + tex->tilesdata->r[htileidl][vtileida] + tex->tilesdata->r[htileid][vtileida]; + col[1] += tex->tilesdata->g[htileidl][vtileid] + tex->tilesdata->g[htileid][vtileida] + tex->tilesdata->g[htileidl][vtileida]; + col[2] += tex->tilesdata->b[htileidl][vtileid] + tex->tilesdata->b[htileidl][vtileida] + tex->tilesdata->b[htileid][vtileida]; + col[0] *= 0.25; + col[1] *= 0.25; + col[2] *= 0.25; + + s += tex->tilesdata->bpat[htileidl][vtileid] + tex->tilesdata->bpat[htileidl][vtileida] + tex->tilesdata->bpat[htileid][vtileida]; + s *= 0.25; + + break; + case TILE_RIGHT_BELOW: + col[0] += tex->tilesdata->r[htileidr][vtileid] + tex->tilesdata->r[htileidr][vtileidb] + tex->tilesdata->r[htileid][vtileidb]; + col[1] += tex->tilesdata->g[htileidr][vtileid] + tex->tilesdata->g[htileid][vtileidb] + tex->tilesdata->g[htileidr][vtileidb]; + col[2] += tex->tilesdata->b[htileidr][vtileid] + tex->tilesdata->b[htileidr][vtileidb] + tex->tilesdata->b[htileid][vtileidb]; + col[0] *= 0.25; + col[1] *= 0.25; + col[2] *= 0.25; + + s += tex->tilesdata->bpat[htileidr][vtileid] + tex->tilesdata->bpat[htileidr][vtileidb] + tex->tilesdata->bpat[htileid][vtileidb]; + s *= 0.25; + + break; + case TILE_RIGHT_ABOVE: + col[0] += tex->tilesdata->r[htileidr][vtileid] + tex->tilesdata->r[htileidr][vtileida] + tex->tilesdata->r[htileid][vtileida]; + col[1] += tex->tilesdata->g[htileidr][vtileid] + tex->tilesdata->g[htileid][vtileida] + tex->tilesdata->g[htileidr][vtileida]; + col[2] += tex->tilesdata->b[htileidr][vtileid] + tex->tilesdata->b[htileidr][vtileida] + tex->tilesdata->b[htileid][vtileida]; + col[0] *= 0.25; + col[1] *= 0.25; + col[2] *= 0.25; + + s += tex->tilesdata->bpat[htileidr][vtileid] + tex->tilesdata->bpat[htileidr][vtileida] + tex->tilesdata->bpat[htileid][vtileida]; + s *= 0.25; + + break; + } + *intens *= s; + + /* Additional random scaling */ + if (i >= 0) *intens *= tex->tilesdata->rpat[i]; + + /* Linearly interpolate the 2 colours */ + col[0] = col[0] * (*intens) + tex->colr2 * intens1; + col[1] = col[1] * (*intens) + tex->colg2 * intens1; + col[2] = col[2] * (*intens) + tex->colb2 * intens1; +} + +static float tiles_bevel_func(Tex *tex, float intens) +{ + intens = curvemapping_evaluateF(tex->curbevel, 0, intens); + + /* Smooth out the result using a cubic step function */ + if (tex->smooth) { + intens = smoothstep(intens, 0, 1); + } + + return intens; +} + +static float tiles_default_int(Tex *tex, float x, float y, short htileid, short vtileid, float *col) +{ + /* This handles the default tiling with different corner styles */ + float intens; + float w, h, dim; + + /* Compute tile dimensions */ + w = tex->tilesdata->hpat[htileid + 1] - tex->tilesdata->hpat[htileid] - tex->tilesdata->hgap; + h = tex->tilesdata->vpat[vtileid + 1] - tex->tilesdata->vpat[vtileid] - tex->tilesdata->vgap; + + /* Offset by half-gap */ + x -= tex->tilesdata->hgap * 0.5; + y -= tex->tilesdata->vgap * 0.5; + + /* Bevel */ + dim = tiles_bevel_dim(tex, w, h); + + /* Compute intensity. */ + intens = tiles_recthelper_int(tex, x, y, w, h, dim, dim * tex->bevel, tex->bevelshading); + intens *= tex->tilesdata->bpat[htileid][vtileid]; + + /* Bevel function */ + intens = tiles_bevel_func(tex, intens); + + /* Compute colour */ + tiles_default_col(tex, intens, htileid, vtileid, col); + + return intens; +} + +static float tiles_cross1_int(Tex *tex, float x, float y, short htileid, short vtileid, float *col) +{ + float w = tex->tilesdata->hpat[htileid + 1] - tex->tilesdata->hpat[htileid] - tex->tilesdata->hgap; + float h = tex->tilesdata->vpat[vtileid + 1] - tex->tilesdata->vpat[vtileid] - tex->tilesdata->vgap; + float dim = tiles_bevel_dim(tex, w, h); + float b = dim * tex->bevel; + float intens = 0; + short id = TILE_CURRENT; + short bs = tex->bevelshading; + float vx[12], vy[12]; + + /* Offset by half-gap */ + x -= tex->tilesdata->hgap * 0.5; + y -= tex->tilesdata->vgap * 0.5; + + vx[0] = w * 0.25; vy[0] = 0; + vx[1] = w * 0.75; vy[1] = 0; + vx[2] = w * 0.75; vy[2] = h * 0.25; + vx[3] = w; vy[3] = h * 0.25; + vx[4] = w; vy[4] = h * 0.75; + vx[5] = w * 0.75; vy[5] = h * 0.75; + vx[6] = w * 0.75; vy[6] = h; + vx[7] = w * 0.25; vy[7] = h; + vx[8] = w * 0.25; vy[8] = h * 0.75; + vx[9] = 0; vy[9] = h * 0.75; + vx[10]= 0; vy[10]= h * 0.25; + vx[11]= w * 0.25; vy[11]= h * 0.25; + + intens = tiles_concave_poly_func(x, y, vx, vy, 12, b, bs); + + /* Bevel function */ + intens = tiles_bevel_func(tex, intens); + + /* Compute colour */ + tiles_neighbour_col(tex, &intens, htileid, vtileid, id, -1, col); + + return intens; +} + +static float tiles_cross2_int(Tex *tex, float x, float y, short htileid, short vtileid, float *col) +{ + float w = tex->tilesdata->hpat[htileid + 1] - tex->tilesdata->hpat[htileid] - tex->tilesdata->hgap; + float h = tex->tilesdata->vpat[vtileid + 1] - tex->tilesdata->vpat[vtileid] - tex->tilesdata->vgap; + float dim = tiles_bevel_dim(tex, w, h); + float b = dim * tex->bevel; + float intens = 0; + short id = TILE_CURRENT; + short bs = tex->bevelshading; + float vx[12], vy[12]; + + /* Offset by half-gap */ + x -= tex->tilesdata->hgap * 0.5; + y -= tex->tilesdata->vgap * 0.5; + + vx[0] = w * 0.15; vy[0] = 0; + vx[1] = w * 0.85; vy[1] = 0; + vx[2] = w * 0.75; vy[2] = h * 0.25; + vx[3] = w; vy[3] = h * 0.15; + vx[4] = w; vy[4] = h * 0.85; + vx[5] = w * 0.75; vy[5] = h * 0.75; + vx[6] = w * 0.85; vy[6] = h; + vx[7] = w * 0.15; vy[7] = h; + vx[8] = w * 0.25; vy[8] = h * 0.75; + vx[9] = 0; vy[9] = h * 0.85; + vx[10]= 0; vy[10]= h * 0.15; + vx[11]= w * 0.25; vy[11]= h * 0.25; + + intens = tiles_concave_poly_func(x, y, vx, vy, 12, b, bs); + + /* Bevel function */ + intens = tiles_bevel_func(tex, intens); + + /* Compute colour */ + tiles_neighbour_col(tex, &intens, htileid, vtileid, id, -1, col); + + return intens; +} + +static float tiles_hex_int(Tex *tex, float x, float y, short htileid, short vtileid, float *col) +{ + /* 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->tilesdata->hpat[htileid + 1] - tex->tilesdata->hpat[htileid] - tex->tilesdata->hgap; + float h = tex->tilesdata->vpat[vtileid + 1] - tex->tilesdata->vpat[vtileid] - tex->tilesdata->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 htidl, htidr, vtida, vtidb; + float intens = 0; + float intens2; + short id = TILE_CURRENT; /* Determines how to use color and bump info from neighbouring tiles */ + float vx[6], vy[6]; + short bs = tex->bevelshading; + + /* Offset by half-gap */ + x -= tex->tilesdata->hgap * 0.5; + y -= tex->tilesdata->vgap * 0.5; + + /* Width of tile to right */ + htidr = (htileid + 1) % tex->hcount; + wr = tex->tilesdata->hpat[htidr + 1] - tex->tilesdata->hpat[htidr] - tex->tilesdata->hgap; + dr = wr * c; + /* Width of tile to left */ + htidl = (htileid - 1 + tex->hcount) % tex->hcount; + wl = tex->tilesdata->hpat[htidl + 1] - tex->tilesdata->hpat[htidl] - tex->tilesdata->hgap; + dl = wl * c; + /* Height of tile above */ + vtida = (vtileid + 1) % tex->vcount; + ha = tex->tilesdata->vpat[vtida + 1] - tex->tilesdata->vpat[vtida] - tex->tilesdata->vgap; + ra = ha * 0.5; + /* Height of tile below */ + vtidb = (vtileid - 1 + tex->vcount) % tex->vcount; + hb = tex->tilesdata->vpat[vtidb + 1] - tex->tilesdata->vpat[vtidb] - tex->tilesdata->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, bs); + + /* 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; + intens2 = tiles_poly_func(x, y, vx, vy, 6, b, bs); + if (intens2 > intens) { + intens = intens2; + id = TILE_RIGHT_BELOW; + } + } + 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; + intens2 = tiles_poly_func(x, y, vx, vy, 6, b, bs); + if (intens2 > intens) { + intens = intens2; + id = TILE_RIGHT_ABOVE; + } + } + } + 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; + intens2 = tiles_poly_func(x, y, vx, vy, 6, b, bs); + if (intens2 > intens) { + intens = intens2; + id = TILE_LEFT_BELOW; + } + } + 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; + intens2 = tiles_poly_func(x, y, vx, vy, 6, b, bs); + if (intens2 > intens) { + intens = intens2; + id = TILE_LEFT_ABOVE; + } + } + } + + /* Bevel function */ + intens = tiles_bevel_func(tex, intens); + + /* Compute colour */ + tiles_neighbour_col(tex, &intens, htileid, vtileid, id, -1, col); + + return intens; +} + +static float tiles_herringbone_int(Tex *tex, float x, float y, short htileid, short vtileid, short n, float *col) +{ + /* Creates a nx1 seamless pattern for herringbone tiling where n >= 2. */ + + float w = tex->tilesdata->hpat[htileid + 1] - tex->tilesdata->hpat[htileid] - tex->tilesdata->hgap; + float h = tex->tilesdata->vpat[vtileid + 1] - tex->tilesdata->vpat[vtileid] - tex->tilesdata->vgap; + float w1 = 0.5 * w; + float h1 = 0.5 * h; + float half_over_n = 0.5 / (float)n; + float xstep = w * half_over_n; + float ystep = h * half_over_n; + float dim, b; + short loop = 1; + float xi, yi; + float intens = 0; + short i = -1; /* Used to determine sections that cross seams */ + short id = TILE_CURRENT; + short bs; + + /* Offset by half-gap */ + x -= tex->tilesdata->hgap * 0.5; + y -= tex->tilesdata->vgap * 0.5; + + while (loop) { + if ((x < 0) || (x > w) || (y < 0) || (y > h)) break; + + /* Handle horizontal bars */ + dim = tiles_bevel_dim(tex, w1, ystep); + if (tex->bevelshading == TEX_BEVEL_PATTERN) { + bs = (tex->corner == TEX_CORNER_STRAIGHT) ? TEX_BEVEL_VGRADIENT : TEX_BEVEL_HGRADIENT; + b = w1 * tex->bevel; + } + else { + bs = tex->bevelshading; + b = dim * tex->bevel; + } + + yi = 0; + i = 0; + if (tex->bevoption != TEX_BEVEL_DEFAULTMIN) dim *= half_over_n; + for (xi = 0; xi < w + xstep; xi += xstep) + { + intens = tiles_recthelper_int(tex, x - xi, y - yi, w1, ystep, dim, b, bs); + if (intens > 0) { + if (i > n) id = TILE_RIGHT; + i = i % 16; + break; + } + yi += ystep; + i++; + } + if (intens > 0) break; + + /* Handle the seamless sections of horizontal bars */ + yi = h - (n - 1) * ystep; + i = n + 1; + for (xi = (1 - n) * xstep; xi < 0; xi += xstep) + { + intens = tiles_recthelper_int(tex, x - xi, y - yi, w1, ystep, dim, b, bs); + if (intens > 0) { + id = TILE_LEFT; + i = i % 16; + break; + } + yi += ystep; + i++; + } + if (intens > 0) break; + + /* Handle vertical bars */ + dim = tiles_bevel_dim(tex, xstep, h1); + if (tex->bevelshading == TEX_BEVEL_PATTERN) { + bs = (tex->corner == TEX_CORNER_STRAIGHT) ? TEX_BEVEL_HGRADIENT : TEX_BEVEL_VGRADIENT; + b = h1 * tex->bevel; + } + else { + bs = tex->bevelshading; + b = dim * tex->bevel; + } + + xi = 0; + i = 0; + if (tex->bevoption != TEX_BEVEL_DEFAULTMIN) dim *= half_over_n; + for (yi = ystep; yi < h + ystep; yi += ystep) + { + intens = tiles_recthelper_int(tex, x - xi, y - yi, xstep, h1, dim, b, bs); + if (intens > 0) { + if (i >= n) id = TILE_ABOVE; + i = 15 - i % 16; + break; + } + xi += xstep; + i++; + } + if (intens > 0) break; + + /* Handle the seamless sections of vertical bars */ + xi = w1; + i = n; + for (yi = (1 - n) * ystep; yi < ystep; yi += ystep) + { + intens = tiles_recthelper_int(tex, x - xi, y - yi, xstep, h1, dim, b, bs); + if (intens > 0) { + if (i < 2*n-1) id = TILE_BELOW; + i = 15 - i % 16; + break; + } + xi += xstep; + i++; + } + if (intens > 0) break; + + /* Important: End loop */ + loop = 0; + i = -1; + } + + /* Bevel function */ + intens = tiles_bevel_func(tex, intens); + + /* Compute colour */ + tiles_neighbour_col(tex, &intens, htileid, vtileid, id, i, col); + + return intens; +} + +static float tiles_interlock1_int(Tex *tex, float x, float y, short htileid, short vtileid, float *col) +{ + /* 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->tilesdata->hpat[htileid + 1] - tex->tilesdata->hpat[htileid] - tex->tilesdata->hgap; + float h = tex->tilesdata->vpat[vtileid + 1] - tex->tilesdata->vpat[vtileid] - tex->tilesdata->vgap; + float w2 = 0.5 * w; + float h2 = 0.5 * h; + float dim = tiles_bevel_dim(tex, w2, h2); + float b = dim * tex->bevel; + float intens = 0; + short i = htileid % 4; + short id; + short bs = tex->bevelshading; + + /* Offset by half-gap */ + x -= tex->tilesdata->hgap * 0.5; + y -= tex->tilesdata->vgap * 0.5; + + if (i == 0) { + if (y >= h2) { + intens = tiles_recthelper_int(tex, x, y - h2, w, h2, dim, b, bs); + id = TILE_ABOVE; + } + else if (x <= w2) { + intens = tiles_recthelper_int(tex, x, y, w2, h2, dim, b, bs); + id = TILE_LEFT; + } + else { + intens = tiles_recthelper_int(tex, x - w2, y, w2, h2, dim, b, bs); + id = TILE_RIGHT; + } + } + else if (i == 1) { + if (x >= w2) { + intens = tiles_recthelper_int(tex, x - w2, y, w2, h, dim, b, bs); + id = TILE_LEFT; + } + else if (y <= h2) { + intens = tiles_recthelper_int(tex, x, y, w2, h2, dim, b, bs); + id = TILE_RIGHT; + } + else { + intens = tiles_recthelper_int(tex, x, y - h2, w2, h2, dim, b, bs); + id = TILE_ABOVE; + } + } + else if (i == 2) { + if (y <= h2) { + intens = tiles_recthelper_int(tex, x, y, w, h2, dim, b, bs); + id = TILE_BELOW; + } + else if (x <= w2) { + intens = tiles_recthelper_int(tex, x, y - h2, w2, h2, dim, b, bs); + id = TILE_LEFT; + } + else { + intens = tiles_recthelper_int(tex, x - w2, y - h2, w2, h2, dim, b, bs); + id = TILE_RIGHT; + } + } + else { + if (x <= w2) { + intens = tiles_recthelper_int(tex, x, y, w2, h, dim, b, bs); + id = TILE_RIGHT; + } + else if (y <= h2) { + intens = tiles_recthelper_int(tex, x - w2, y, w2, h2, dim, b, bs); + id = TILE_BELOW; + } + else { + intens = tiles_recthelper_int(tex, x - w2, y - h2, w2, h2, dim, b, bs); + id = TILE_ABOVE; + } + } + + /* Bevel function */ + intens = tiles_bevel_func(tex, intens); + + /* Compute colour */ + tiles_neighbour_col(tex, &intens, htileid, vtileid, id, -1, col); + + return intens; +} + +static float tiles_interlock2_int(Tex *tex, float x, float y, short htileid, short vtileid, short n, float *col) +{ + /* Generate a pattern of n blocks as follows: + * ___ ___ ___ ___ + * | | | | | + * | | | | | .... + * | | | | | + * |___|___|___|___| + * The pattern rotates 90 degrees and after 2 tile repitions it repeats. + * If tex->hcount is not a multiple of 2, the repitions will stop before + * multiple of 180 degrees is reached. + */ + float w = tex->tilesdata->hpat[htileid + 1] - tex->tilesdata->hpat[htileid] - tex->tilesdata->hgap; + float h = tex->tilesdata->vpat[vtileid + 1] - tex->tilesdata->vpat[vtileid] - tex->tilesdata->vgap; + float factor = 1.0 / (float)n; + float w2 = factor * w; + float h2 = factor * h; + float dim, b; + float intens = 0; + short i = htileid % 2; + short id = TILE_CURRENT; + short k; + short r = 0; + short bs = tex->bevelshading; + + /* Offset by half-gap */ + x -= tex->tilesdata->hgap * 0.5; + y -= tex->tilesdata->vgap * 0.5; + + if (i == 0) { + /* I don't understand why the following doesn't work: + * intens = tiles_recthelper_int(tex, x, y - floor(y / h2) * h2, w, h2, dim, tex->bevelshading); + * Hence the looped version. + */ + if (bs == TEX_BEVEL_PATTERN) bs = TEX_BEVEL_VGRADIENT; + dim = tiles_bevel_dim(tex, w, h2); + b = dim * tex->bevel; + for (k = 0; k < n; k++) { + if (y <= (k + 1) * h2) { + intens = tiles_recthelper_int(tex, x, y - k * h2, w, h2, dim, b, bs); + r = k; + break; + } + } + } + else { + if (bs == TEX_BEVEL_PATTERN) bs = TEX_BEVEL_HGRADIENT; + dim = tiles_bevel_dim(tex, w2, h); + b = dim * tex->bevel; + for (k = 0; k < n; k++) { + if (x <= (k + 1) * w2) { + intens = tiles_recthelper_int(tex, x - k * w2, y, w2, h, dim, b, bs); + r = k; + break; + } + } + } + + /* Bevel function */ + intens = tiles_bevel_func(tex, intens); + + /* Compute colour */ + tiles_neighbour_col(tex, &intens, htileid, vtileid, id, r % 16, col); + + return intens; +} + +static float tiles_interlock3_int(Tex *tex, float x, float y, short htileid, short vtileid, float *col) +{ + /* Assuming, the rows are not being shifted, we can do the following pattern + * which will stretch from one rectangular cell to another but will + * remain seamless as long as tex->hgap = tex->vgap = 0. + * |__| + * __/ \__ + * __| |__ + * \____/ + * | | + * + * The figure above is ugly but it generates regular octagons interlocked with squares and + * the edge length of squares and octagons will be equal. + */ + float w = tex->tilesdata->hpat[htileid + 1] - tex->tilesdata->hpat[htileid] - tex->tilesdata->hgap; + float h = tex->tilesdata->vpat[vtileid + 1] - tex->tilesdata->vpat[vtileid] - tex->tilesdata->vgap; + float intens = 0; + short id = TILE_CURRENT; + short bs = tex->bevelshading; + //float s1 = 0; /* Don't ask how I came up with these numbers :) */ + float s2 = 0.14645; + float s3 = 0.35356; + float s4 = 0.64644; + float s5 = 0.85355; + //float s6 = 1; + float s = s4 - s3; /* Edge length of octagons and squares */ + float sh = s * 0.5; + float sr = s * M_SQRT1_2; + float wl, wr; + float ha, hb; + short htidl, htidr, vtida, vtidb; + float vx[8], vy[8]; + float b; + + /* Offset by half-gap */ + x -= tex->tilesdata->hgap * 0.5; + y -= tex->tilesdata->vgap * 0.5; + + if ((x >= 0) && (x <= w) && (y >= 0) && (y <= h)) + { + /* Width of tile to right */ + htidr = (htileid + 1) % tex->hcount; + wr = tex->tilesdata->hpat[htidr + 1] - tex->tilesdata->hpat[htidr] - tex->tilesdata->hgap; + /* Width of tile to left */ + htidl = (htileid - 1 + tex->hcount) % tex->hcount; + wl = tex->tilesdata->hpat[htidl + 1] - tex->tilesdata->hpat[htidl] - tex->tilesdata->hgap; + /* Height of tile above */ + vtida = (vtileid + 1) % tex->vcount; + ha = tex->tilesdata->vpat[vtida + 1] - tex->tilesdata->vpat[vtida] - tex->tilesdata->vgap; + /* Height of tile below */ + vtidb = (vtileid - 1 + tex->vcount) % tex->vcount; + hb = tex->tilesdata->vpat[vtidb + 1] - tex->tilesdata->vpat[vtidb] - tex->tilesdata->vgap; + + /* NOTE: All polygons are defined counter-clockwise */ + + /* Central octagon */ + vx[0] = s3 * w; vy[0] = s2 * h; + vx[1] = s4 * w; vy[1] = s2 * h; + vx[2] = s5 * w; vy[2] = s3 * h; + vx[3] = s5 * w; vy[3] = s4 * h; + vx[4] = s4 * w; vy[4] = s5 * h; + vx[5] = s3 * w; vy[5] = s5 * h; + vx[6] = s2 * w; vy[6] = s4 * h; + vx[7] = s2 * w; vy[7] = s3 * h; + b = tiles_bevel_dim(tex, vx[2] - vx[6], vy[4] - vy[0]) * tex->bevel; + intens = tiles_poly_func(x, y, vx, vy, 8, b, bs); + + /* Squares (rectangles if random widths/heights) */ + if (intens <= 0) { + /* Bottom */ + vx[0] = s4 * w; vy[0] = s2 * h; + vx[1] = s3 * w; vy[1] = vy[0]; + vx[2] = vx[1]; vy[2] = vy[1] - sh * (h + hb); + vx[3] = vx[0]; vy[3] = vy[2]; + b = tiles_bevel_dim(tex, s, sh * (h + hb)) * tex->bevel; + intens = tiles_poly_func(x, y, vx, vy, 4, b, bs); + id = TILE_BELOW; + } + if (intens <= 0) { + /* Top */ + vx[0] = s3 * w; vy[0] = s5 * h; + vx[1] = s4 * w; vy[1] = vy[0]; + vx[2] = vx[1]; vy[2] = vy[1] + sh * (h + ha); + vx[3] = vx[0]; vy[3] = vy[2]; + b = tiles_bevel_dim(tex, s, sh * (h + ha)) * tex->bevel; + intens = tiles_poly_func(x, y, vx, vy, 4, b, bs); + id = TILE_ABOVE; + } + if (intens <= 0) { + /* Left */ + vx[0] = s2 * w; vy[0] = s3 * h; + vx[1] = vx[0]; vy[1] = s4 * h; + vx[2] = vx[1] - sh * (w + wl); vy[2] = vy[1]; + vx[3] = vx[2]; vy[3] = vy[0]; + b = tiles_bevel_dim(tex, s, sh * (w + wl)) * tex->bevel; + intens = tiles_poly_func(x, y, vx, vy, 4, b, bs); + id = TILE_LEFT; + } + if (intens <= 0) { + /* Right */ + vx[0] = s5 * w; vy[0] = s3 * h; + vx[1] = vx[0] + sh * (w + wr); vy[1] = vy[0]; + vx[2] = vx[1]; vy[2] = s4 * h; + vx[3] = vx[0]; vy[3] = vy[2]; + b = tiles_bevel_dim(tex, s, sh * (w + wr)) * tex->bevel; + intens = tiles_poly_func(x, y, vx, vy, 4, b, bs); + id = TILE_RIGHT; + } + + /* More octagons */ + if (intens <= 0) { + /* Bottom Left */ + vx[0] = s3 * w; vy[0] = s2 * h; + vx[1] = s2 * w; vy[1] = s3 * h; + vx[2] = vx[1] - sh * (w + wl); vy[2] = vy[1]; + vx[3] = vx[2] - sr * wl; vy[3] = vy[0]; + vx[4] = vx[3]; vy[4] = vy[3] - sh * (h + hb); + vx[5] = vx[2]; vy[5] = vy[4] - sr * hb; + vx[6] = vx[1]; vy[6] = vy[5]; + vx[7] = vx[0]; vy[7] = vy[4]; + + b = tiles_bevel_dim(tex, vx[0] - vx[4], vy[1] - vy[5]) * tex->bevel; + intens = tiles_poly_func(x, y, vx, vy, 8, b, bs); + id = TILE_LEFT_BELOW; + } + if (intens <= 0) { + /* Bottom Right */ + vx[0] = s5 * w; vy[0] = s3 * h; + vx[1] = s4 * w; vy[1] = s2 * h; + vx[2] = vx[1]; vy[2] = vy[1] - sh * (h + hb); + vx[3] = vx[0]; vy[3] = vy[4] - sr * hb; + vx[4] = vx[3] + sh * (w + wr); vy[4] = vy[3]; + vx[5] = vx[4] + sr * wr; vy[5] = vy[2]; + vx[6] = vx[5]; vy[6] = vy[1]; + vx[7] = vx[4]; vy[7] = vy[0]; + + b = tiles_bevel_dim(tex, vx[5] - vx[1], vy[0] - vy[4]) * tex->bevel; + intens = tiles_poly_func(x, y, vx, vy, 8, b, bs); + id = TILE_RIGHT_BELOW; + } + if (intens <= 0) { + /* Top Left */ + vx[0] = s2 * w; vy[0] = s4 * h; + vx[1] = s3 * w; vy[1] = s5 * h; + vx[2] = vx[1]; vy[2] = vy[1] + sh * (h + ha); + vx[3] = vx[0]; vy[3] = vy[2] + sr * ha; + vx[4] = vx[3] - sh * (w + wl); vy[4] = vy[3]; + vx[5] = vx[4] - sr * wl; vy[5] = vy[2]; + vx[6] = vx[5]; vy[6] = vy[1]; + vx[7] = vx[4]; vy[7] = vy[0]; + + b = tiles_bevel_dim(tex, vx[1] - vx[5], vy[4] - vy[0]) * tex->bevel; + intens = tiles_poly_func(x, y, vx, vy, 8, b, bs); + id = TILE_LEFT_ABOVE; + } + if (intens <= 0) { + /* Top Right */ + vx[0] = s4 * w; vy[0] = s5 * h; + vx[1] = s5 * w; vy[1] = s4 * h; + vx[2] = vx[1] + sh * (w + wr); vy[2] = vy[1]; + vx[3] = vx[2] + sr * wr; vy[3] = vy[0]; + vx[4] = vx[3]; vy[4] = vy[3] + sh * (h + ha); + vx[5] = vx[2]; vy[5] = vy[4] + sr * ha; + vx[6] = vx[1]; vy[6] = vy[5]; + vx[7] = vx[0]; vy[7] = vy[4]; + + b = tiles_bevel_dim(tex, vx[4] - vx[0], vy[5] - vy[1]) * tex->bevel; + intens = tiles_poly_func(x, y, vx, vy, 8, b, bs); + id = TILE_RIGHT_ABOVE; + } + } + + /* Bevel function */ + intens = tiles_bevel_func(tex, intens); + + /* Compute colour */ + tiles_neighbour_col(tex, &intens, htileid, vtileid, id, -1, col); + + return intens; +} + +static float tiles_star1_int(Tex *tex, float x, float y, short htileid, short vtileid, float *col) +{ + float w = tex->tilesdata->hpat[htileid + 1] - tex->tilesdata->hpat[htileid] - tex->tilesdata->hgap; + float h = tex->tilesdata->vpat[vtileid + 1] - tex->tilesdata->vpat[vtileid] - tex->tilesdata->vgap; + float w2 = 0.5 * w; + float h2 = 0.5 * h; + float dim = tiles_bevel_dim(tex, w, h); + float b = dim * tex->bevel; + float intens = 0; + short id = TILE_CURRENT; + short bs = tex->bevelshading; + float vx[10], vy[10]; + int j; + float step = 0.2 * M_PI; + float theta = 0; + float r1, r2; + + /* Offset by half-gap */ + x -= tex->tilesdata->hgap * 0.5; + y -= tex->tilesdata->vgap * 0.5; + + if (htileid % 2) theta += step; + for (j = 0; j < 10; j++, theta += step) { + r1 = w2; + r2 = h2; + if (j % 2) { + r1 *= 0.5; + r2 *= 0.5; + } + + vx[j] = w2 + r1 * cos(theta); + vy[j] = h2 + r2 * sin(theta); + } + intens = tiles_concave_poly_func(x, y, vx, vy, 10, b, bs); + + /* Bevel function */ + intens = tiles_bevel_func(tex, intens); + + /* Compute colour */ + tiles_neighbour_col(tex, &intens, htileid, vtileid, id, -1, col); + + return intens; +} + +static float tiles_weave_int(Tex *tex, float x, float y, short htileid, short vtileid, float *col) +{ + float w = tex->tilesdata->hpat[htileid + 1] - tex->tilesdata->hpat[htileid] - tex->tilesdata->hgap; + float h = tex->tilesdata->vpat[vtileid + 1] - tex->tilesdata->vpat[vtileid] - tex->tilesdata->vgap; + float dim, b; + float intens = 0; + short htidl, htidr, vtida, vtidb; + float wr, wl, ha, hb; + float xi, yi, wi, hi; + short loop = 1; + short id = TILE_CURRENT; + short bs; + + /* Width of tile to right */ + htidr = (htileid + 1) % tex->hcount; + wr = tex->tilesdata->hpat[htidr + 1] - tex->tilesdata->hpat[htidr] - tex->tilesdata->hgap; + /* Width of tile to left */ + htidl = (htileid - 1 + tex->hcount) % tex->hcount; + wl = tex->tilesdata->hpat[htidl + 1] - tex->tilesdata->hpat[htidl] - tex->tilesdata->hgap; + /* Height of tile above */ + vtida = (vtileid + 1) % tex->vcount; + ha = tex->tilesdata->vpat[vtida + 1] - tex->tilesdata->vpat[vtida] - tex->tilesdata->vgap; + /* Height of tile below */ + vtidb = (vtileid - 1 + tex->vcount) % tex->vcount; + hb = tex->tilesdata->vpat[vtidb + 1] - tex->tilesdata->vpat[vtidb] - tex->tilesdata->vgap; + + /* Offset by half-gap */ + x -= tex->tilesdata->hgap * 0.5; + y -= tex->tilesdata->vgap * 0.5; + + while (loop) { + if ((x < 0) || (x > w) || (y < 0) || (y > h)) break; + + /* Horizontal Tiles */ + + /* Compute dimension for bevel and shading */ + if (tex->bevelshading == TEX_BEVEL_PATTERN) { + bs = (tex->corner == TEX_CORNER_STRAIGHT) ? TEX_BEVEL_VGRADIENT : TEX_BEVEL_HGRADIENT; + dim = tiles_bevel_dim(tex, w, MIN2(wl, wr)); + } + else { + bs = tex->bevelshading; + dim = tiles_bevel_dim(tex, MIN3(w, wl, wr), MIN3(h, ha, hb)); + } + b = dim * tex->bevel; + dim *= 0.25; + + /* 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, b, bs); + if (intens > 0) { + id = TILE_BELOW; + break; + } + + /* 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, b, bs); + if (intens > 0) { + id = TILE_ABOVE; + break; + } + + /* 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, b, bs); + if (intens > 0) { + id = TILE_LEFT; + break; + } + + /* 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, b, bs); + if (intens > 0) { + id = TILE_RIGHT; + break; + } + + + /* Vertical Tiles */ + + /* Compute dimension for bevel and shading */ + if (tex->bevelshading == TEX_BEVEL_PATTERN) { + bs = (tex->corner == TEX_CORNER_STRAIGHT) ? TEX_BEVEL_HGRADIENT : TEX_BEVEL_VGRADIENT; + dim = tiles_bevel_dim(tex, h, MIN2(ha, hb)); + } + else { + bs = tex->bevelshading; + dim = tiles_bevel_dim(tex, MIN3(w, wl, wr), MIN3(h, ha, hb)); + } + b = dim * tex->bevel; + dim *= 0.25; + + /* 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, b, bs); + if (intens > 0) { + id = TILE_CURRENT; + break; + } + + /* 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, b, bs); + if (intens > 0) { + id = TILE_LEFT_BELOW; + break; + } + + /* 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, b, bs); + if (intens > 0) { + id = TILE_RIGHT_BELOW; + break; + } + + /* 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, b, bs); + if (intens > 0) { + id = TILE_LEFT_ABOVE; + break; + } + + /* 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, b, bs); + if (intens > 0) { + id = TILE_RIGHT_ABOVE; + break; + } + + loop = 0; + } + + /* Bevel function */ + intens = tiles_bevel_func(tex, intens); + + /* Compute colour */ + tiles_neighbour_col(tex, &intens, htileid, vtileid, id, -1, col); + + return intens; +} + +static void tiles_calc(Tex *tex, float *x, float *y, short *htileid, short *vtileid) +{ + /* Given points (x, y) determines where in the tile pattern, tex->tilesdata->hpat[], + * the point belongs. It returns the index of the tile in htileid, vtileid and x, y + * will contain the relative offset for the tile. + */ + float wtot = tex->tilesdata->hpat[tex->hcount] - tex->tilesdata->hpat[0]; /* Width of tile pattern */ + float htot = tex->tilesdata->vpat[tex->vcount] - tex->tilesdata->vpat[0]; /* Height of tile pattern */ + float y1; + short i; + int row; + + /* Center the pattern */ + //*x += (wtot * 0.5); + //*y += (htot * 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->tilesdata->vpat[i + 1]) { + break; + } + } + *y -= tex->tilesdata->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->tilesdata->hpat[i + 1]) { + break; + } + } + *x -= tex->tilesdata->hpat[i]; + *htileid = i; +} + +static float tiles_int(Tex *tex, float x, float y, float *col) +{ + short htileid, vtileid; + float intens; + + /* Compute coordinates in "tile-space"; i.e. relative to the tile containing + * the texture coordinates. + */ + tiles_calc(tex, &x, &y, &htileid, &vtileid); + + /* Handle predefined patterns and default tiling function */ + switch (tex->pattern) { + case TEX_TILES_CROSS1: + intens = tiles_cross1_int(tex, x, y, htileid, vtileid, col); + break; + case TEX_TILES_CROSS2: + intens = tiles_cross2_int(tex, x, y, htileid, vtileid, col); + break; + case TEX_TILES_HERRINGBONE1: + intens = tiles_herringbone_int(tex, x, y, htileid, vtileid, 2, col); + break; + case TEX_TILES_HERRINGBONE2: + intens = tiles_herringbone_int(tex, x, y, htileid, vtileid, 4, col); + break; + case TEX_TILES_HERRINGBONE3: + intens = tiles_herringbone_int(tex, x, y, htileid, vtileid, 5, col); + break; + case TEX_TILES_HEX: + intens = tiles_hex_int(tex, x, y, htileid, vtileid, col); + break; + case TEX_TILES_INTERLOCK1: + intens = tiles_interlock1_int(tex, x, y, htileid, vtileid, col); + break; + case TEX_TILES_INTERLOCK2: + intens = tiles_interlock2_int(tex, x, y, htileid, vtileid, 2, col); + break; + case TEX_TILES_INTERLOCK3: + intens = tiles_interlock2_int(tex, x, y, htileid, vtileid, 4, col); + break; + case TEX_TILES_INTERLOCK4: + intens = tiles_interlock3_int(tex, x, y, htileid, vtileid, col); + break; + case TEX_TILES_STAR1: + intens = tiles_star1_int(tex, x, y, htileid, vtileid, col); + break; + case TEX_TILES_WEAVE: + intens = tiles_weave_int(tex, x, y, htileid, vtileid, col); + break; + default: + intens = tiles_default_int(tex, x, y, htileid, vtileid, col); + 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); + CLAMP(col[0], 0, 1); + CLAMP(col[1], 0, 1); + CLAMP(col[2], 0, 1); + + return intens; +} + + +static void tiles_precalc_ibuf(Tex *tex) +{ + float *cp; + int x, y; + float sx, sy; + int res = 1 << tex->resolution; + ImBuf *ibuf; + + if (tex->tilesdata->ibuf == NULL) { + tex->tilesdata->ibuf = IMB_allocImBuf(res, res, 24, IB_rectfloat); + } + ibuf = tex->tilesdata->ibuf; + + sx = 1.0f / (float)(ibuf->x - 1); + sy = 1.0f / (float)(ibuf->y - 1); + + cp = ibuf->rect_float; + for(y = 0; y < ibuf->x; y++) { + for(x = 0; x < ibuf->y; x++, cp+=4) { + cp[3] = tiles_int(tex, (float)x * sx, (float)y * sy, cp); + } + } +} + +static void tiles_precalc_no_lock(Tex *tex) { + float width = (float)(1 << tex->resolution); + float height = (float)(1 << tex->resolution); + float hgap = tex->hgap * width; + float vgap = tex->vgap * height; + float maxwidth, minwidth; + float maxheight, minheight; + float maxbump, minbump; + float w, h, b, r, sum; + float h1, s1, v1, h2, s2, v2; + float mh, ms, mv; + short i, j; + RNG *rng; + + rng = rng_new(tex->seed); + + BKE_free_tilesdata(tex->tilesdata); + + /* Compute a set of random widths for the tiles. The array tex->tilesdata->pat[] will + * accumulate the gap and tile widths in each cell starting at 0. + */ + maxwidth = width + tex->widthvar * width; + minwidth = width - tex->widthvar * width; + maxheight = height + tex->heightvar * height; + minheight = height - tex->heightvar * height; + maxbump = tex->bump + tex->bumpvar * tex->bump; + minbump = tex->bump - tex->bumpvar * tex->bump; + + /* Handle negative dimensions */ + if (minwidth < 0) minwidth = 0; + if (minheight < 0) minheight = 0; + + /* Handle bump limits */ + if (minbump < 0) minbump = 0; + if (maxbump > 1) maxbump = 1; + + /* Calculate ranges for width, height and bump */ + w = maxwidth - minwidth; + h = maxheight - minheight; + b = maxbump - minbump; + + /* Initialize min/max values */ + tex->tilesdata->minw = MAX2(minwidth, maxwidth); + tex->tilesdata->maxw = 0; + tex->tilesdata->minh = MAX2(minheight, maxheight); + tex->tilesdata->maxh = 0; + + /* Compute random numbers between minwidth and maxwidth. Keep a running total + * of the width of the pattern. All the width's will then be scaled by this + * to bring into the [0, 1] range; otherwise, the pattern won't be seamless + * for the 2D->3D texture mapping functions. + */ + tex->tilesdata->hpat[0] = 0; + for (i = 1; i <= tex->hcount; i++) { + r = rng_getFloat(rng); + r = minwidth + w * r; + tex->tilesdata->hpat[i] = hgap + tex->tilesdata->hpat[i - 1] + r; + + tex->tilesdata->minw = MIN2(tex->tilesdata->minw, r); + tex->tilesdata->maxw = MAX2(tex->tilesdata->maxw, r); + } + sum = 1.0/tex->tilesdata->hpat[tex->hcount]; + for (i = 1; i <= tex->hcount; i++) { + tex->tilesdata->hpat[i] *= sum; + } + tex->tilesdata->minw *= sum; + tex->tilesdata->maxw *= sum; + tex->tilesdata->hgap = hgap * sum; + + /* Compute random numbers between minheight and maxheight. Keep a running total + * of the height of the pattern. All the height's will then be scaled by this + * to bring into the [0, 1] range; otherwise, the pattern won't be seamless + * for the 2D->3D texture mapping functions. + */ + tex->tilesdata->vpat[0] = 0; + for (i = 1; i <= tex->vcount; i++) { + r = rng_getFloat(rng); + r = minheight + h * r; + tex->tilesdata->vpat[i] = vgap + tex->tilesdata->vpat[i - 1] + r; + + tex->tilesdata->minh = MIN2(tex->tilesdata->minh, r); + tex->tilesdata->maxh = MAX2(tex->tilesdata->maxh, r); + } + sum = 1.0/tex->tilesdata->vpat[tex->vcount]; + for (i = 1; i <= tex->vcount; i++) { + tex->tilesdata->vpat[i] *= sum; + } + tex->tilesdata->minh *= sum; + tex->tilesdata->maxh *= sum; + tex->tilesdata->vgap = vgap * sum; + + /* Compute random numbers between minbump and maxbump */ + for (i = 0; i < tex->hcount; i++) { + for (j = 0; j < tex->vcount; j++) { + r = rng_getFloat(rng); + tex->tilesdata->bpat[i][j] = minbump + b * r; + } + } + for (i = 0; i < 16; i++) { + r = rng_getFloat(rng); + tex->tilesdata->rpat[i] = minbump + b * r; + } + + /* Compute random colours using the base colour [colr1, colg1, colb1] and the + * percentage variation in hue, saturation and value. + */ + rgb_to_hsv(tex->colr1, tex->colg1, tex->colb1, &h1, &s1, &v1); + mh = 0.5 * tex->fhue; + ms = 0.5 * tex->fsat; + mv = 0.5 * tex->fval; + for (i = 0; i < tex->hcount; i++) { + for (j = 0; j < tex->vcount; j++) { + r = rng_getFloat(rng); + h2 = h1 + r * tex->fhue - mh; + s2 = s1 + r * tex->fsat - ms; + v2 = v1 + r * tex->fval - mv; + if (h2 > 1.0) h2 -= 1.0; else if (h2 < 0.0) h2 += 1.0; + if (s2 > 1.0) s2 -= 1.0; else if (s2 < 0.0) s2 += 1.0; + if (v2 > 1.0) v2 -= 1.0; else if (v2 < 0.0) v2 += 1.0; + hsv_to_rgb(h2, s2, v2, &tex->tilesdata->r[i][j], &tex->tilesdata->g[i][j], &tex->tilesdata->b[i][j]); + } + } + + rng_free(rng); + + if (!tex->curbevel) { + tex->curbevel = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); + curvemapping_initialize(tex->curbevel); + } +} + +int tiles_osa(Tex *tex, float *texvec, float *dxt, float *dyt, TexResult *texres) +{ + int do_precalc = 0; + BLI_lock_thread(LOCK_CUSTOM1); + if (tex->tilesdata == NULL) { + tex->tilesdata = BKE_add_tiles(); + do_precalc = 1; + } + if (tex->tilesdata->ibuf == NULL) { + do_precalc = 1; + } + if (do_precalc) { + tiles_precalc_no_lock(tex); + tiles_precalc_ibuf(tex); + } + BLI_unlock_thread(LOCK_CUSTOM1); + + return imagewraposa(tex, tex->ima, tex->tilesdata->ibuf, texvec, dxt, dyt, texres); +} + +/* ------------------------------------------------------------------------- */ + +void tiles_precalc(Tex * tex) { + BLI_lock_thread(LOCK_CUSTOM1); + tiles_precalc_no_lock(tex); + BLI_unlock_thread(LOCK_CUSTOM1); +} + +void default_tiles_tex(Tex *tex) { + tex->resolution = 8; + tex->hcount = 3; + tex->widthvar = 0; + tex->vcount = 3; + tex->heightvar = 0; + tex->hgap = 0.01; + tex->vgap = 0.01; + tex->shift = 0.1; + tex->bevel = 0.2; + tex->corner = TEX_CORNER_STRAIGHT; + tex->hcorner = 0; + tex->vcorner = 0; + tex->seed = 0; + tex->alternate = 1; + //tex->curve = 0; + tex->smooth = 0; + //tex->strength = 1; + tex->pattern = 0; + tex->bevoption = 0; + tex->colr1 = 1; + tex->colg1 = 1; + tex->colb1 = 1; + tex->colr2 = 0; + tex->colg2 = 0; + tex->colb2 = 0; + tex->fhue = 0; + tex->fsat = 0; + tex->fval = 0; + tex->bump = 1; + tex->bumpvar = 0; + tex->bevelshading = TEX_BEVEL_DEFAULT; + if (tex->curbevel) { + curvemapping_free(tex->curbevel); + } + tex->curbevel = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); + curvemapping_initialize(tex->curbevel); +} \ No newline at end of file Index: source/blender/render/intern/include/tiles.h =================================================================== --- source/blender/render/intern/include/tiles.h (revision 0) +++ source/blender/render/intern/include/tiles.h (revision 0) @@ -0,0 +1,54 @@ +// +// tiles.h +// Blender +// +// Created by Ahmad Kabani on 11-07-21. + +#ifndef TILES_H + +#define TILES_H + +#define M_PI_OVER_180 0.0174532925199 + +/* 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 + +/* Determines if a point (x, y) is inside, outside or on a circle with center (cx, cy) and radius r. */ +#define POINT_IN_CIRCLE(x, y, cx, cy, r) (((x) - (cx)) * ((x) - (cx)) + ((y) - (cy)) * ((y) - (cy)) < (r) * (r)) +#define POINT_ON_CIRCLE(x, y, cx, cy, r) (((x) - (cx)) * ((x) - (cx)) + ((y) - (cy)) * ((y) - (cy)) == (r) * (r)) +#define POINT_NOT_IN_CIRCLE(x, y, cx, cy, r) (((x) - (cx)) * ((x) - (cx)) + ((y) - (cy)) * ((y) - (cy)) > (r) * (r)) +/* Determines if a point (x, y) is inside, outside or on an ellipse with center (cx, cy) and radii rx, ry. */ +#define POINT_IN_ELLIPSE(x, y, cx, cy, rx, ry) (((x) - (cx)) * ((x) - (cx)) / ((rx) * (rx)) + ((y) - (cy)) * ((y) - (cy)) / ((ry) * (ry)) < 1) +#define POINT_ON_ELLIPSE(x, y, cx, cy, rx, ry) (((x) - (cx)) * ((x) - (cx)) / ((rx) * (rx)) + ((y) - (cy)) * ((y) - (cy)) / ((ry) * (ry)) == 1) +#define POINT_NOT_IN_ELLIPSE(x, y, cx, cy, rx, ry) (((x) - (cx)) * ((x) - (cx)) / ((rx) * (rx)) + ((y) - (cy)) * ((y) - (cy)) / ((ry) * (ry)) > 1) + +/* Used to identify how neighbouring tiles are used to compute bump and colour */ +#define TILE_CURRENT 0 +#define TILE_ABOVE 1 +#define TILE_BELOW 2 +#define TILE_LEFT 3 +#define TILE_RIGHT 4 +#define TILE_RIGHT_ABOVE 5 +#define TILE_RIGHT_BELOW 6 +#define TILE_LEFT_ABOVE 7 +#define TILE_LEFT_BELOW 8 + +struct TexResult; + +int tiles_osa(Tex *tex, float *texvec, float *dxt, float *dyt, struct TexResult *texres); +void tiles_precalc(Tex * tex); +void default_tiles_tex(Tex *tex); + +#endif \ No newline at end of file Index: source/blender/render/CMakeLists.txt =================================================================== --- source/blender/render/CMakeLists.txt (revision 39316) +++ source/blender/render/CMakeLists.txt (working copy) @@ -74,6 +74,7 @@ intern/source/sss.c intern/source/strand.c intern/source/sunsky.c + intern/source/tiles.c intern/source/volume_precache.c intern/source/volumetric.c intern/source/voxeldata.c @@ -103,6 +104,7 @@ intern/include/strand.h intern/include/sunsky.h intern/include/texture.h + intern/include/tiles.h intern/include/volume_precache.h intern/include/volumetric.h intern/include/voxeldata.h Index: source/blender/blenkernel/intern/texture.c =================================================================== --- source/blender/blenkernel/intern/texture.c (revision 39316) +++ source/blender/blenkernel/intern/texture.c (working copy) @@ -74,6 +74,8 @@ #include "BKE_animsys.h" #include "BKE_colortools.h" +#include "../../render/intern/include/tiles.h" + /* ------------------------------------------------------------------------- */ /* All support for plugin textures: */ @@ -497,6 +499,8 @@ ntreeFreeTree(tex->nodetree); MEM_freeN(tex->nodetree); } + + if (tex->tilesdata) BKE_free_tiles(tex->tilesdata); } /* ------------------------------------------------------------------------- */ @@ -550,6 +554,8 @@ tex->vn_mexp = 2.5; tex->vn_distm = 0; tex->vn_coltype = 0; + /* tilestexture */ + default_tiles_tex(tex); if (tex->env) { tex->env->stype=ENV_ANIM; @@ -603,8 +609,14 @@ if (tex->env == NULL) tex->env = BKE_add_envmap(); break; + case TEX_TILES: + if (tex->tilesdata == NULL) { + tex->tilesdata = BKE_add_tiles(); + } + tiles_precalc(tex); + break; } - + tex->type = type; } @@ -769,6 +781,8 @@ ntreeEndExecTree(tex->nodetree); texn->nodetree= ntreeCopyTree(tex->nodetree); } + + if(texn->tilesdata) texn->tilesdata= BKE_copy_tiles(texn->tilesdata); return texn; } @@ -806,6 +820,10 @@ texn->nodetree= ntreeLocalize(tex->nodetree); } + if(texn->tilesdata) { + texn->tilesdata= BKE_copy_tiles(texn->tilesdata); + } + return texn; } @@ -1358,6 +1376,51 @@ /* ------------------------------------------------------------------------- */ +TilesPreCalc *BKE_add_tiles() +{ + TilesPreCalc *tilesdata; + + tilesdata= MEM_callocN(sizeof(TilesPreCalc), "tilesdata"); + + return tilesdata; +} + +/* ------------------------------------------------------------------------- */ + +TilesPreCalc *BKE_copy_tiles(TilesPreCalc *tilesdata) +{ + TilesPreCalc *tilesdatan; + + tilesdatan= MEM_dupallocN(tilesdata); + + tilesdatan->ibuf= NULL; + + return tilesdatan; +} + +/* ------------------------------------------------------------------------- */ + +void BKE_free_tilesdata(TilesPreCalc *tilesdata) +{ + if(tilesdata && tilesdata->ibuf) + { + IMB_freeImBuf(tilesdata->ibuf); + tilesdata->ibuf= NULL; + } +} + +/* ------------------------------------------------------------------------- */ + +void BKE_free_tiles(TilesPreCalc *tilesdata) +{ + if (tilesdata) { + BKE_free_tilesdata(tilesdata); + MEM_freeN(tilesdata); + } +} + +/* ------------------------------------------------------------------------- */ + PointDensity *BKE_add_pointdensity(void) { PointDensity *pd; Index: source/blender/blenkernel/BKE_texture.h =================================================================== --- source/blender/blenkernel/BKE_texture.h (revision 39316) +++ source/blender/blenkernel/BKE_texture.h (working copy) @@ -55,6 +55,7 @@ struct TexMapping; struct VoxelData; struct World; +struct TilesPreCalc; /* in ColorBand struct */ #define MAXCOLORBAND 32 @@ -114,6 +115,11 @@ struct EnvMap *BKE_add_envmap(void); struct EnvMap *BKE_copy_envmap(struct EnvMap *env); +void BKE_free_tilesdata(struct TilesPreCalc *tilesdata); +void BKE_free_tiles(struct TilesPreCalc *tilesdata); +struct TilesPreCalc *BKE_add_tiles(); +struct TilesPreCalc *BKE_copy_tiles(struct TilesPreCalc *tilesdata); + void BKE_free_pointdensitydata(struct PointDensity *pd); void BKE_free_pointdensity(struct PointDensity *pd); struct PointDensity *BKE_add_pointdensity(void); Index: source/blender/makesdna/DNA_texture_types.h =================================================================== --- source/blender/makesdna/DNA_texture_types.h (revision 39316) +++ source/blender/makesdna/DNA_texture_types.h (working copy) @@ -53,6 +53,7 @@ struct PreviewImage; struct ImBuf; struct CurveMapping; +struct TilesPreCalc; typedef struct MTex { @@ -155,6 +156,22 @@ short recalc, lastsize; } EnvMap; +/* Tiles texture precalculation data */ +typedef struct TilesPreCalc { + float hpat[16]; /* Stores horizontal tile pattern */ + float vpat[16]; /* Stores vertical tile pattern */ + float bpat[16][16]; /* Stores the bump pattern */ + float minw, minh; /* Store overall min of width and height value */ + float maxw, maxh; /* Store overall max of width and height value */ + float r[16][16]; /* Store colour pattern */ + float g[16][16]; + float b[16][16]; + float rpat[16]; /* Stores the random numbers for anything else */ + float hgap, vgap; /* Stores gap values scaled by overall size of pattern */ + + struct ImBuf *ibuf; +} TilesPreCalc; + typedef struct PointDensity { short flag; @@ -238,6 +255,17 @@ short imaflag, flag; short type, stype; + /* tiles texture */ + short hcount, vcount, smooth; + short corner, pattern, bevoption; + float widthvar, heightvar, bump, bumpvar; + float hgap, vgap, shift, bevel; + float colr1, colg1, colb1, colr2, colg2, colb2, fhue, fsat, fval; + float hcorner, vcorner; + unsigned int seed, alternate; + short bevelshading, pad3[3]; + int resolution, pad4; + float cropxmin, cropymin, cropxmax, cropymax; int texfilter; int afmax; // anisotropic filter maximum value, ewa -> max eccentricity, feline -> max probes @@ -263,6 +291,8 @@ struct PreviewImage * preview; struct PointDensity *pd; struct VoxelData *vd; + struct TilesPreCalc *tilesdata; /* tiles texture */ + struct CurveMapping *curbevel; char use_nodes; char pad[7]; @@ -304,6 +334,7 @@ #define TEX_DISTNOISE 13 #define TEX_POINTDENSITY 14 #define TEX_VOXELDATA 15 +#define TEX_TILES 16 /* tiles texture */ /* musgrave stype */ #define TEX_MFRACTAL 0 @@ -422,6 +453,36 @@ #define TEX_COL2 2 #define TEX_COL3 3 +/* tex->stype in texture.c - corner types */ +#define TEX_CORNER_ROUND 0 +#define TEX_CORNER_ROUND_INV 1 +#define TEX_CORNER_ELLIPSE 2 +#define TEX_CORNER_ELLIPSE_INV 3 +#define TEX_CORNER_STRAIGHT 4 + +#define TEX_TILES_NONE 0 +#define TEX_TILES_INTERLOCK1 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_TILES_INTERLOCK2 7 +#define TEX_TILES_INTERLOCK3 8 +#define TEX_TILES_INTERLOCK4 9 +#define TEX_TILES_CROSS1 10 +#define TEX_TILES_CROSS2 11 +#define TEX_TILES_STAR1 12 + +#define TEX_BEVEL_DEFAULTMIN 0 +#define TEX_BEVEL_UNIFORMMIN 1 +#define TEX_BEVEL_UNIFORMMAX 2 + +#define TEX_BEVEL_DEFAULT 0 +#define TEX_BEVEL_PATTERN 1 /* Used for predefined pattern so they can do what they want */ +#define TEX_BEVEL_HGRADIENT 2 +#define TEX_BEVEL_VGRADIENT 3 + /* mtex->normapspace */ #define MTEX_NSPACE_CAMERA 0 #define MTEX_NSPACE_WORLD 1 Index: source/blender/gpu/intern/gpu_material.c =================================================================== --- source/blender/gpu/intern/gpu_material.c (revision 39316) +++ source/blender/gpu/intern/gpu_material.c (working copy) @@ -972,7 +972,7 @@ talpha = 0; rgbnor = 0; - if(tex && tex->type == TEX_IMAGE && tex->ima) { + if(tex && (tex->type == TEX_IMAGE || tex->type == TEX_TILES) && tex->ima) { GPU_link(mat, "mtex_image", texco, GPU_image(tex->ima, &tex->iuser), &tin, &trgb); rgbnor= TEX_RGB; Index: source/blender/makesrna/intern/rna_texture.c =================================================================== --- source/blender/makesrna/intern/rna_texture.c (revision 39316) +++ source/blender/makesrna/intern/rna_texture.c (working copy) @@ -47,6 +47,8 @@ #include "BKE_node.h" +#include "BLI_threads.h" + EnumPropertyItem texture_filter_items[] = { {TXF_BOX, "BOX", 0, "Box", ""}, {TXF_EWA, "EWA", 0, "EWA", ""}, @@ -68,6 +70,7 @@ //{TEX_PLUGIN, "PLUGIN", ICON_PLUGIN, "Plugin", ""}, /* Nothing yet */ {TEX_POINTDENSITY, "POINT_DENSITY", ICON_TEXTURE, "Point Density", ""}, {TEX_STUCCI, "STUCCI", ICON_TEXTURE, "Stucci", "Procedural - Creates a fractal noise texture"}, + {TEX_TILES, "TILES", ICON_TEXTURE, "Tiles", "Procedural - Creates tiling patterns with randomized tile sets"}, {TEX_VORONOI, "VORONOI", ICON_TEXTURE, "Voronoi", "Procedural - Creates cell-like patterns based on Worley noise"}, {TEX_VOXELDATA, "VOXEL_DATA", ICON_TEXTURE, "Voxel Data", "Creates a 3d texture based on volumetric data"}, {TEX_WOOD, "WOOD", ICON_TEXTURE, "Wood", "Procedural - Wave generated bands or rings, with optional noise"}, @@ -118,6 +121,8 @@ return &RNA_PointDensityTexture; case TEX_STUCCI: return &RNA_StucciTexture; + case TEX_TILES: + return &RNA_TilesTexture; case TEX_VORONOI: return &RNA_VoronoiTexture; case TEX_VOXELDATA: @@ -132,12 +137,54 @@ static void rna_Texture_update(Main *bmain, Scene *scene, PointerRNA *ptr) { Tex *tex= ptr->id.data; + + if (tex->type == TEX_TILES) + { + tiles_precalc(tex); + } DAG_id_tag_update(&tex->id, 0); WM_main_add_notifier(NC_TEXTURE, tex); WM_main_add_notifier(NC_MATERIAL|ND_SHADING_DRAW, NULL); } +/* tilestexture */ +static void rna_Tiles_texture_tiles_pattern(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + Tex *tex= ptr->id.data; + + /* Setup parameters for preset patterns. */ + switch (tex->pattern) + { + case TEX_TILES_HEX: + case TEX_TILES_HERRINGBONE1: + case TEX_TILES_HERRINGBONE2: + case TEX_TILES_HERRINGBONE3: + case TEX_TILES_INTERLOCK4: + tex->hgap = 0; + tex->vgap = 0; + tex->alternate = 1; + tex->bevelshading = TEX_BEVEL_DEFAULT; + break; + case TEX_TILES_WEAVE: + tex->hgap = 0; + tex->vgap = 0; + tex->alternate = 1; + tex->bevelshading = TEX_BEVEL_PATTERN; + break; + case TEX_TILES_INTERLOCK1: + case TEX_TILES_INTERLOCK2: + case TEX_TILES_INTERLOCK3: + case TEX_TILES_CROSS1: + case TEX_TILES_CROSS2: + case TEX_TILES_STAR1: + tex->bevelshading = TEX_BEVEL_DEFAULT; + break; + } + + rna_Texture_update(bmain, scene, ptr); +} + static void rna_Texture_voxeldata_update(Main *bmain, Scene *scene, PointerRNA *ptr) { Tex *tex= ptr->id.data; @@ -169,6 +216,22 @@ static void rna_Texture_type_set(PointerRNA *ptr, int value) { Tex *tex= (Tex*)ptr->data; + + /* tilestexture */ + if (value == TEX_TILES) { + /* We have to do this because do_2d_mapping() will mess up the texture mapping + * for Tiles texture + */ + tex->imaflag &= ~TEX_USEALPHA; + tex->extend = TEX_REPEAT; + + tex->cropxmin = 0.0; + tex->cropxmax = 1.0; + tex->cropymin = 0.0; + tex->cropymax = 1.0; + tex->xrepeat = 1.0; + tex->yrepeat = 1.0; + } tex_set_type(tex, value); } @@ -989,6 +1052,264 @@ RNA_def_property_update(prop, 0, "rna_Texture_update"); } +/* tilestexture */ +static void rna_def_texture_tiles(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + static EnumPropertyItem prop_pattern_items[] = { + {TEX_TILES_NONE, "NONE", 0, "No pattern", "Doesn't use any pattern"}, + {TEX_TILES_CROSS1, "CROSS1", 0, "Cross 1", "Cross pattern"}, + {TEX_TILES_CROSS2, "CROSS2", 0, "Cross 2", "Cross pattern"}, + {TEX_TILES_INTERLOCK1, "INTERLOCK1", 0, "Interlock 1", "Interlocking pattern"}, + {TEX_TILES_INTERLOCK2, "INTERLOCK2", 0, "Interlock 2", "Interlocking pattern"}, + {TEX_TILES_INTERLOCK3, "INTERLOCK2", 0, "Interlock 3", "Interlocking pattern"}, + {TEX_TILES_INTERLOCK4, "INTERLOCK2", 0, "Interlock 4", "Interlocking pattern"}, + {TEX_TILES_HERRINGBONE1, "HERRINGBONE1", 0, "Herringbone 1", "Herringbone pattern"}, + {TEX_TILES_HERRINGBONE2, "HERRINGBONE2", 0, "Herringbone 2", "Herringbone pattern"}, + {TEX_TILES_HERRINGBONE3, "HERRINGBONE3", 0, "Herringbone 3", "Herringbone pattern"}, + {TEX_TILES_HEX, "HEX", 0, "Hex", "Honey comb pattern"}, + {TEX_TILES_STAR1, "STAR1", 0, "Star 1", "Star pattern"}, + {TEX_TILES_WEAVE, "WEAVE", 0, "Weave", "Basket weave pattern"}, + {0, NULL, 0, NULL, NULL}}; + + static EnumPropertyItem prop_bevelshading_items[] = { + {TEX_BEVEL_DEFAULT, "DEFAULT", 0, "Default Shading", "Default bevel shading"}, + {TEX_BEVEL_HGRADIENT, "HGRADIENT", 0, "H Gradient", "Horizontal gradient shading"}, + {TEX_BEVEL_VGRADIENT, "VGRADIENT", 0, "V Gradient", "Vertical gradient shading"}, + {TEX_BEVEL_PATTERN, "PATTERN", 0, "Pattern", "Bevel shading based on selected pattern"}, + {0, NULL, 0, NULL, NULL}}; + + static EnumPropertyItem prop_corner_type_items[] = { + {TEX_CORNER_ROUND, "ROUND", 0, "Round", "Rounded corners"}, + {TEX_CORNER_ROUND_INV, "ROUND_INV", 0, "Round Inverse", "Inverted rounded corners"}, + {TEX_CORNER_ELLIPSE, "ELLIPSE", 0, "Ellipse", "Elliptical corners"}, + {TEX_CORNER_ELLIPSE_INV, "ELLIPSE_INV", 0, "Ellipse Inverse", "Inverted elliptical corners"}, + {TEX_CORNER_STRAIGHT, "STRAIGHT", 0, "Straight", "Straight edged corners"}, + {0, NULL, 0, NULL, NULL}}; + + static EnumPropertyItem prop_bevoption_items[] = { + {TEX_BEVEL_DEFAULTMIN, "DEFAULT", 0, "Default", "Default bevel size"}, + {TEX_BEVEL_UNIFORMMIN, "UNIFORMMIN", 0, "Uniform Min", "Use minimum size over all tiles"}, + {TEX_BEVEL_UNIFORMMAX, "UNIFORMMAX", 0, "Uniform Max", "Use maximum size over all tiles"}, + {0, NULL, 0, NULL, NULL}}; + + srna= RNA_def_struct(brna, "TilesTexture", "Texture"); + RNA_def_struct_ui_text(srna, "Tiles Texture", "Procedural tiles texture"); + RNA_def_struct_sdna(srna, "Tex"); + + + prop= RNA_def_property(srna, "pattern", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "pattern"); + RNA_def_property_enum_items(prop, prop_pattern_items); + RNA_def_property_ui_text(prop, "Pattern", "Tiling Pattern"); + RNA_def_property_update(prop, 0, "rna_Tiles_texture_tiles_pattern"); + + prop= RNA_def_property(srna, "resolution", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "resolution"); + RNA_def_property_range(prop, 0, 10); + RNA_def_property_ui_text(prop, "Resolution", "Texture resolution (size of texture is power of 2)"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "hcount", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "hcount"); + RNA_def_property_range(prop, 1, 15); + RNA_def_property_ui_text(prop, "Columns", "Number of horizontal random tiles"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "vcount", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "vcount"); + RNA_def_property_range(prop, 1, 15); + RNA_def_property_ui_text(prop, "Rows", "Number of vertical random tiles"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + + prop= RNA_def_property(srna, "corner_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "corner"); + RNA_def_property_enum_items(prop, prop_corner_type_items); + RNA_def_property_ui_text(prop, "Corner", "Type of corner for the tiles"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "hcorner", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "hcorner"); + RNA_def_property_range(prop, 0, 0.5); + RNA_def_property_ui_range(prop, 0, 10, 1, 2); + RNA_def_property_ui_text(prop, "X", "Horizontal corner radius"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "vcorner", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "vcorner"); + RNA_def_property_range(prop, 0, 0.5); + RNA_def_property_ui_range(prop, 0, 10, 1, 2); + RNA_def_property_ui_text(prop, "Y", "Vertical corner radius"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + + prop= RNA_def_property(srna, "bevelshading", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "bevelshading"); + RNA_def_property_enum_items(prop, prop_bevelshading_items); + RNA_def_property_ui_text(prop, "Shading", "Shading style for the bevel"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "bevoption", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "bevoption"); + RNA_def_property_enum_items(prop, prop_bevoption_items); + RNA_def_property_ui_text(prop, "Option", "Bevel Option"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "curbevel", PROP_POINTER, PROP_NEVER_NULL); + RNA_def_property_pointer_sdna(prop, NULL, "curbevel"); + RNA_def_property_struct_type(prop, "CurveMapping"); + RNA_def_property_ui_text(prop, "Bevel Shape", "Custom Bevel Shape"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "bevel", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "bevel"); + RNA_def_property_range(prop, 0, 0.5); + RNA_def_property_ui_range(prop, 0, 100, 1, 2); + RNA_def_property_ui_text(prop, "Size", "Variation in bevel height"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "smooth", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "smooth", 1); + RNA_def_property_ui_text(prop, "Smooth", "Smooth the bevel profile"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + + prop= RNA_def_property(srna, "widthvar", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "widthvar"); + RNA_def_property_range(prop, 0, 1); + RNA_def_property_ui_range(prop, 0, 100, 1, 2); + RNA_def_property_ui_text(prop, "Width Variation", "Variation in tile width"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "heightvar", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "heightvar"); + RNA_def_property_range(prop, 0, 1); + RNA_def_property_ui_range(prop, 0, 100, 1, 2); + RNA_def_property_ui_text(prop, "Height Variation", "Variation in tile height"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + + prop= RNA_def_property(srna, "bump", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "bump"); + RNA_def_property_range(prop, 0, 1); + RNA_def_property_ui_range(prop, 0, 100, 1, 2); + RNA_def_property_ui_text(prop, "Bump", "Average tile height"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "bumpvar", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "bumpvar"); + RNA_def_property_range(prop, 0, 1); + RNA_def_property_ui_range(prop, 0, 100, 1, 2); + RNA_def_property_ui_text(prop, "Bump Variation", "Variation in bump height"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + + prop= RNA_def_property(srna, "hgap", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "hgap"); + RNA_def_property_range(prop, 0, 1); + RNA_def_property_ui_range(prop, 0, 100, 1, 2); + RNA_def_property_ui_text(prop, "X", "Horizontal gap"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "vgap", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "vgap"); + RNA_def_property_range(prop, 0, 1); + RNA_def_property_ui_range(prop, 0, 100, 1, 2); + RNA_def_property_ui_text(prop, "Y", "Vertical gap"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + + prop= RNA_def_property(srna, "tile_color", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "colr1"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Tile Color", "Base color for tile"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "gap_color", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "colr2"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Gap Color", "Gap color"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + + prop= RNA_def_property(srna, "shift", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "shift"); + RNA_def_property_range(prop, -10, 10); + RNA_def_property_ui_range(prop, -100, 100, 1, 2); + RNA_def_property_ui_text(prop, "Shift", "Variation in bump height"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "alternate", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "alternate"); + RNA_def_property_range(prop, 0, INT_MAX); + RNA_def_property_ui_text(prop, "Rows", "Rows"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + + prop= RNA_def_property(srna, "fhue", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "fhue"); + RNA_def_property_range(prop, 0, 1); + RNA_def_property_ui_range(prop, 0, 100, 1, 2); + RNA_def_property_ui_text(prop, "H", "Variation in hue"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "fsat", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "fsat"); + RNA_def_property_range(prop, 0, 1); + RNA_def_property_ui_range(prop, 0, 100, 1, 2); + RNA_def_property_ui_text(prop, "S", "Variation in saturation"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "fval", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "fval"); + RNA_def_property_range(prop, 0, 1); + RNA_def_property_ui_range(prop, 0, 100, 1, 2); + RNA_def_property_ui_text(prop, "V", "Variation in value"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + + prop= RNA_def_property(srna, "seed", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "seed"); + RNA_def_property_range(prop, 0, INT_MAX); + RNA_def_property_ui_text(prop, "Seed", "Seed"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + rna_def_filter_common(srna); + + prop= RNA_def_property(srna, "use_interpolation", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "imaflag", TEX_INTERPOL); + RNA_def_property_ui_text(prop, "Interpolation", "Interpolates pixels using selected filter"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "use_flip_axis", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "imaflag", TEX_IMAROT); + RNA_def_property_ui_text(prop, "Flip Axis", "Flips the texture's X and Y axis"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "use_alpha", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "imaflag", TEX_USEALPHA); + RNA_def_property_ui_text(prop, "Use Alpha", "Uses the alpha channel information in the image"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "use_calculate_alpha", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "imaflag", TEX_CALCALPHA); + RNA_def_property_ui_text(prop, "Calculate Alpha", "Calculates an alpha channel based on RGB values in the image"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "invert_alpha", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", TEX_NEGALPHA); + RNA_def_property_ui_text(prop, "Invert Alpha", "Inverts all the alpha values in the image"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "use_normal_map", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "imaflag", TEX_NORMALMAP); + RNA_def_property_ui_text(prop, "Normal Map", "Uses image RGB values for normal mapping"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); +} + static void rna_def_texture_noise(BlenderRNA *brna) { StructRNA *srna; @@ -1796,6 +2117,7 @@ rna_def_texture_magic(brna); rna_def_texture_blend(brna); rna_def_texture_stucci(brna); + rna_def_texture_tiles(brna); /* tilestexture */ rna_def_texture_noise(brna); rna_def_texture_image(brna); rna_def_texture_plugin(brna); Index: source/blender/makesrna/RNA_access.h =================================================================== --- source/blender/makesrna/RNA_access.h (revision 39316) +++ source/blender/makesrna/RNA_access.h (working copy) @@ -533,6 +533,7 @@ extern StructRNA RNA_ThemeView3D; extern StructRNA RNA_ThemeWidgetColors; extern StructRNA RNA_ThemeWidgetStateColors; +extern StructRNA RNA_TilesTexture; extern StructRNA RNA_TimelineMarker; extern StructRNA RNA_Timer; extern StructRNA RNA_ToolSettings; Index: source/blender/blenloader/intern/writefile.c =================================================================== --- source/blender/blenloader/intern/writefile.c (revision 39316) +++ source/blender/blenloader/intern/writefile.c (working copy) @@ -1734,6 +1734,8 @@ } if(tex->type == TEX_VOXELDATA && tex->vd) writestruct(wd, DATA, "VoxelData", 1, tex->vd); + if(tex->curbevel) write_curvemapping(wd, tex->curbevel); /* tilestexture */ + /* nodetree is integral part of texture, no libdata */ if(tex->nodetree) { writestruct(wd, DATA, "bNodeTree", 1, tex->nodetree); Index: source/blender/blenloader/intern/readfile.c =================================================================== --- source/blender/blenloader/intern/readfile.c (revision 39316) +++ source/blender/blenloader/intern/readfile.c (working copy) @@ -141,6 +141,8 @@ #include "readfile.h" +#include "../../render/intern/include/tiles.h" + #include "PIL_time.h" #include @@ -2937,6 +2939,8 @@ if(tex->nodetree) lib_link_ntree(fd, &tex->id, tex->nodetree); + tex->tilesdata = BKE_add_tiles(); /* tilestexture */ + tex->id.flag -= LIB_NEEDLINK; } tex= tex->id.next; @@ -2948,6 +2952,8 @@ tex->adt= newdataadr(fd, tex->adt); direct_link_animdata(fd, tex->adt); + tex->tilesdata = BKE_add_tiles(); /* tilestexture */ + tex->plugin= newdataadr(fd, tex->plugin); if(tex->plugin) { tex->plugin->handle= NULL; @@ -2987,6 +2993,11 @@ tex->preview = direct_link_preview_image(fd, tex->preview); + /* tilestexture */ + tex->curbevel= newdataadr(fd, tex->curbevel); + if(tex->curbevel) + direct_link_curvemapping(fd, tex->curbevel); + tex->iuser.ok= 1; } @@ -11709,6 +11720,16 @@ } } + if (main->versionfile < 258 || (main->versionfile == 258 && main->subversionfile < 2)){ + /* Initialize Tiles texture */ + Tex *tex; + for(tex= main->tex.first; tex; tex= tex->id.next) { + /* tilestexture */ + tex->tilesdata = BKE_add_tiles(); + default_tiles_tex(tex); + } + } + /* put compatibility code here until next subversion bump */ { Index: source/blender/nodes/intern/SHD_nodes/SHD_texture.c =================================================================== --- source/blender/nodes/intern/SHD_nodes/SHD_texture.c (revision 39316) +++ source/blender/nodes/intern/SHD_nodes/SHD_texture.c (working copy) @@ -125,7 +125,7 @@ { Tex *tex = (Tex*)node->id; - if(tex && tex->type == TEX_IMAGE && tex->ima) { + if(tex && (tex->type == TEX_IMAGE || tex->type == TEX_TILES) && tex->ima) { GPUNodeLink *texlink = GPU_image(tex->ima, NULL); return GPU_stack_link(mat, "texture_image", in, out, texlink); }