Index: release/scripts/ui/properties_texture.py =================================================================== --- release/scripts/ui/properties_texture.py (revision 34984) +++ release/scripts/ui/properties_texture.py (working copy) @@ -148,6 +148,7 @@ else: split.label(text="Type:") split.prop(tex, "type", text="") + split.prop(tex, "proctoim") class TEXTURE_PT_preview(TextureButtonsPanel, bpy.types.Panel): @@ -324,6 +325,55 @@ col.prop(tex, "turbulence") +class TEXTURE_PT_pattern(TextureTypePanel, bpy.types.Panel): + bl_label = "Pattern" + tex_type = 'PATTERN' + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'} + + def draw(self, context): + layout = self.layout + + tex = context.texture + sub = layout.row() + sub.prop(tex, "stype") + sub = layout.row() + sub.prop(tex, "flip_axis", expand=True) + + if tex.stype in ('CLOTH', 'TILE', 'PIPELINE'): + sub = layout.row() + sub.prop(tex, "formula") + + if tex.stype in ('PIPELINE'): + sub = layout.row() + sub.prop(tex, "pipeline") + + sub = layout.row() + sub.active = (tex.stype in ('CHECK', 'DOTS', 'PIPELINE', 'GRID', 'CLOTH', 'TILE')) + sub.prop(tex, "frequency", text="Frequency") + sub.prop(tex, "dvar", text="Dvar Alias Factor") + if tex.stype != 'x': + sub = layout.row() + sub.prop(tex, "awidth", text="Width", slider=True) + sub.prop(tex, "iwidth", text="IWidth", slider=True) + sub = layout.row() + sub.prop(tex, "avar", text="Slider A", slider=True) + sub.prop(tex, "bvar", text="Slider B", slider=True) + sub = layout.row() + sub.prop(tex, "multi", text="Multicolor") + sub.prop(tex, "alias", text="Alias") + sub = layout.row() + sub.prop(tex, "xflag", text="X") + sub.prop(tex, "yflag", text="Y") + sub.prop(tex, "zflag", text="Z") + sub = layout.row() + sub.prop(tex, "xratio", text="X Ratio") + sub.prop(tex, "yratio", text="Y Ratio") + sub.prop(tex, "zratio", text="Z Ratio") + + texture_noise_common(tex, layout) + + + class TEXTURE_PT_blend(TextureTypePanel, bpy.types.Panel): bl_label = "Blend" tex_type = 'BLEND' @@ -340,7 +390,13 @@ sub.active = (tex.progression in ('LINEAR', 'QUADRATIC', 'EASING', 'RADIAL')) sub.prop(tex, "use_flip_axis", expand=True) + layout.prop(tex, "blend_invert", expand=True) + + #noise + #layout.label(text="Noise:") + layout.prop(tex, "use_noise", expand=True) + texture_noise_common(tex, layout) class TEXTURE_PT_stucci(TextureTypePanel, bpy.types.Panel): bl_label = "Stucci" @@ -366,6 +422,81 @@ col.prop(tex, "turbulence") +class TEXTURE_PT_tiles(TextureTypePanel, bpy.types.Panel): + bl_label = "Tiles" + tex_type = 'TILES' + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'} + + def draw(self, context): + layout = self.layout + + + tex = context.texture + + layout.prop(tex, "pattern") + + layout.prop(tex, "corner_type") + layout.prop(tex, "hcorner") + layout.prop(tex, "vcorner") + + + layout.prop(tex, "hcount") + layout.prop(tex, "seamless") + layout.prop(tex, "width") + layout.prop(tex, "scale") + layout.prop(tex, "widthvar") + layout.prop(tex, "height") + layout.prop(tex, "heightvar") + + layout.prop(tex, "hgap") + layout.prop(tex, "vgap") + layout.prop(tex, "shift") + layout.prop(tex, "alternate") + + layout.prop(tex, "fhue") + layout.prop(tex, "fsat") + layout.prop(tex, "fval") + + + texture_noise_common(tex, layout) + + + + +class TEXTURE_PT_tiles_advanced(TextureTypePanel, bpy.types.Panel): + bl_label = "Tiles Advanced" + tex_type = 'TILES' + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'} + + def draw(self, context): + layout = self.layout + + tex = context.texture + + layout.label(text="Bump") + layout.prop(tex, "bump") + layout.prop(tex, "bumpvar") + + layout.label(text="Colors") + layout.prop(tex, "colr1", text="") + layout.prop(tex, "colr2", text="") + + layout.label(text="Bevel") + layout.prop(tex, "bevel") + layout.prop(tex, "smooth") + layout.prop(tex, "bevoption") + layout.prop(tex, "bevelshading") + + layout.label(text="Bevel Shape") + layout.template_curve_mapping(tex, "curbevel") + + layout.prop(tex, "seed") + layout.prop(tex, "nabla") + + + + + class TEXTURE_PT_image(TextureTypePanel, bpy.types.Panel): bl_label = "Image" tex_type = 'IMAGE' @@ -391,7 +522,30 @@ layout.prop(tex, "filter_size") layout.prop(tex, "use_filter_size_min") +def texture_noise_common(tex, layout): + layout.label(text="Noise:") + layout.prop(tex, "use_noise", expand=True) + layout.prop(tex, "postflag", expand=True) + + if tex.use_noise or tex.postflag: + layout.prop(tex, "blend_noise", text="Mode") + + layout.prop(tex, "noise_type", text="Type", expand=True) + layout.prop(tex, "noise_basis", text="Basis") + + split = layout.split() + + col = split.column() + col.prop(tex, "noise_scale", text="Size") + col.prop(tex, "noise_depth", text="Depth") + + col = split.column() + col.prop(tex, "nabla", text="Nabla") + col.prop(tex, "turbulence", text="Turb") + + + class TEXTURE_PT_image_sampling(TextureTypePanel, bpy.types.Panel): bl_label = "Image Sampling" bl_options = {'DEFAULT_CLOSED'} Index: source/blender/blenkernel/BKE_texture.h =================================================================== --- source/blender/blenkernel/BKE_texture.h (revision 34984) +++ source/blender/blenkernel/BKE_texture.h (working copy) @@ -59,7 +59,21 @@ /* in ColorBand struct */ #define MAXCOLORBAND 32 +/* Tiles 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 */ +} TilesPreCalc; + void free_texture(struct Tex *t); int test_dlerr(const char *name, const char *symbol); void open_plugin_tex(struct PluginTex *pit); @@ -74,6 +88,7 @@ struct CBData *colorband_element_add(struct ColorBand *coba, float position); int colorband_element_remove(struct ColorBand *coba, int index); +void tiles_precalc(struct Tex *tex); /* tilestexture */ void default_tex(struct Tex *tex); struct Tex *add_texture(const char *name); void tex_set_type(struct Tex *tex, int type); Index: source/blender/blenkernel/intern/texture.c =================================================================== --- source/blender/blenkernel/intern/texture.c (revision 34984) +++ source/blender/blenkernel/intern/texture.c (working copy) @@ -42,7 +42,11 @@ #include "BLI_math.h" #include "BLI_kdopbvh.h" #include "BLI_utildefines.h" +#include "BLI_threads.h" /* tilestexture */ +#include "BLI_rand.h" /* tilestexture */ + + #include "DNA_key_types.h" #include "DNA_object_types.h" #include "DNA_lamp_types.h" @@ -59,6 +63,7 @@ #include "BKE_utildefines.h" #include "BKE_global.h" #include "BKE_main.h" +#include "BKE_colortools.h" /* tilestexture */ #include "BKE_library.h" #include "BKE_image.h" @@ -477,6 +482,16 @@ free_plugin_tex(tex->plugin); if(tex->coba) MEM_freeN(tex->coba); if(tex->env) BKE_free_envmap(tex->env); + + /* tilestexture */ + if(tex->tilesdata) { + BLI_lock_thread(LOCK_CUSTOM1); + MEM_freeN(tex->tilesdata); + tex->tilesdata = NULL; + BLI_unlock_thread(LOCK_CUSTOM1); + } + curvemapping_free(tex->curbevel); + if(tex->pd) BKE_free_pointdensity(tex->pd); if(tex->vd) BKE_free_voxeldata(tex->vd); BKE_free_animdata((struct ID *)tex); @@ -492,6 +507,151 @@ /* ------------------------------------------------------------------------- */ +/* tilestexture */ +void tiles_precalc(Tex *tex) +{ + 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_new(tex->seed); + + if (!tex->tilesdata) { + tex->tilesdata = MEM_callocN(sizeof(TilesPreCalc), "tiles precalc data"); + } + + /* 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 = tex->width + tex->widthvar * tex->width; + minwidth = tex->width - tex->widthvar * tex->width; + maxheight = tex->height + tex->heightvar * tex->height; + minheight = tex->height - tex->heightvar * tex->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; + sum = 0; + for (i = 1; i <= tex->hcount; i++) { + r = rng_getFloat(rng); + r = minwidth + w * r; + tex->tilesdata->hpat[i] = tex->hgap + tex->tilesdata->hpat[i - 1] + r; + sum += tex->hgap + r; + + tex->tilesdata->minw = MIN2(tex->tilesdata->minw, r); + tex->tilesdata->maxw = MAX2(tex->tilesdata->maxw, r); + } + if (tex->seamless) { + sum = 1.0/sum; + for (i = 1; i <= tex->hcount; i++) { + tex->tilesdata->hpat[i] *= sum; + } + tex->tilesdata->minw *= sum; + tex->tilesdata->maxw *= sum; + tex->tilesdata->hgap = tex->hgap * sum; + } + else { + tex->tilesdata->hgap = tex->hgap; + } + + /* 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; + sum = 0; + for (i = 1; i <= tex->vcount; i++) { + r = rng_getFloat(rng); + r = minheight + h * r; + tex->tilesdata->vpat[i] = tex->vgap + tex->tilesdata->vpat[i - 1] + r; + sum += tex->vgap + r; + + tex->tilesdata->minh = MIN2(tex->tilesdata->minh, r); + tex->tilesdata->maxh = MAX2(tex->tilesdata->maxh, r); + } + if (tex->seamless) { + sum = 1.0/sum; + for (i = 1; i <= tex->vcount; i++) { + tex->tilesdata->vpat[i] *= sum; + } + tex->tilesdata->minh *= sum; + tex->tilesdata->maxh *= sum; + tex->tilesdata->vgap = tex->vgap * sum; + } + else { + tex->tilesdata->vgap = tex->vgap; + } + + /* 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 == NULL) { + tex->curbevel = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); + curvemapping_initialize(tex->curbevel); + } +} + + void default_tex(Tex *tex) { PluginTex *pit; @@ -542,6 +702,52 @@ tex->vn_distm = 0; tex->vn_coltype = 0; + /* pattern */ + tex->frequency = 4.0f; + tex->awidth = 0.1f; + tex->iwidth = 0.1f; + tex->dvar = 1.0f; + tex->xratio = tex->yratio = tex->zratio = 1; + tex->multi = tex->alias = 0; + + /* tilestexture */ + tex->scale = 1; + tex->hcount = 3; + tex->width = 0.2; + tex->widthvar = 0; + tex->vcount = 3; + tex->height = 0.1; + 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->bump = 1; + tex->bumpvar = 0; + tex->seamless = 1; + tex->bevelshading = TEX_BEVEL_DEFAULT; + if (tex->curbevel != NULL) { + curvemapping_free(tex->curbevel); + } + tex->curbevel = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); + curvemapping_initialize(tex->curbevel); + if (tex->env) { tex->env->stype=ENV_ANIM; tex->env->clipsta=0.1; @@ -608,6 +814,17 @@ tex= alloc_libblock(&bmain->tex, ID_TE, name); + /* tilestexture */ + tex->tilesdata = NULL; + + if (tex->curbevel != NULL) + { + curvemapping_free(tex->curbevel); + } + tex->curbevel = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); + curvemapping_initialize(tex->curbevel); + + default_tex(tex); return tex; @@ -766,6 +983,15 @@ texn->nodetree= ntreeCopyTree(tex->nodetree); /* 0 == full new tree */ } + /* tilestexture */ + if(tex->tilesdata) { + BLI_lock_thread(LOCK_CUSTOM1); + texn->tilesdata = MEM_dupallocN(tex->tilesdata); + BLI_unlock_thread(LOCK_CUSTOM1); + } + texn->curbevel = curvemapping_copy(tex->curbevel); + + return texn; } Index: source/blender/blenloader/intern/readfile.c =================================================================== --- source/blender/blenloader/intern/readfile.c (revision 34984) +++ source/blender/blenloader/intern/readfile.c (working copy) @@ -2815,7 +2815,7 @@ if(tex->nodetree) lib_link_ntree(fd, &tex->id, tex->nodetree); - + tex->tilesdata = NULL; /* tilestexture */ tex->id.flag -= LIB_NEEDLINK; } tex= tex->id.next; @@ -2826,7 +2826,7 @@ { tex->adt= newdataadr(fd, tex->adt); direct_link_animdata(fd, tex->adt); - + tex->tilesdata = NULL; /* tilestexture */ tex->plugin= newdataadr(fd, tex->plugin); if(tex->plugin) { tex->plugin->handle= NULL; @@ -2862,6 +2862,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; } @@ -9203,6 +9208,7 @@ Scene *sce; Object *ob; PartEff *paf=0; + Tex *tex; for(ob = main->object.first; ob; ob= ob->id.next) { if(ob->soft && ob->soft->keys) { @@ -11377,7 +11383,63 @@ } } } + + { + Tex *tex; + /* Initialize Tiles texture */ + for(tex= main->tex.first; tex; tex= tex->id.next) { + /* pattern */ + tex->frequency = 4.0f; + tex->awidth = 0.1f; + tex->iwidth = 0.1f; + tex->dvar = 1.0f; + tex->xratio = tex->yratio = tex->zratio = 1; + tex->multi = tex->alias = 0; + + /* tilestexture */ + tex->scale = 1; + tex->hcount = 3; + tex->width = 0.2; + tex->widthvar = 0; + tex->vcount = 3; + tex->height = 0.1; + 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->seamless = 1; + tex->bevelshading = TEX_BEVEL_DEFAULT; + if (tex->curbevel != NULL) { + curvemapping_free(tex->curbevel); + } + tex->curbevel = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); + curvemapping_initialize(tex->curbevel); + } + } + /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ /* WATCH IT 2!: Userdef struct init has to be in editors/interface/resources.c! */ Index: source/blender/blenloader/intern/writefile.c =================================================================== --- source/blender/blenloader/intern/writefile.c (revision 34984) +++ source/blender/blenloader/intern/writefile.c (working copy) @@ -1684,6 +1684,7 @@ if(tex->type == TEX_PLUGIN && tex->plugin) writestruct(wd, DATA, "PluginTex", 1, tex->plugin); if(tex->coba) writestruct(wd, DATA, "ColorBand", 1, tex->coba); if(tex->type == TEX_ENVMAP && tex->env) writestruct(wd, DATA, "EnvMap", 1, tex->env); + if(tex->type == TEX_TILES && tex->curbevel) write_curvemapping(wd, tex->curbevel); /* tilestexture */ if(tex->type == TEX_POINTDENSITY && tex->pd) { writestruct(wd, DATA, "PointDensity", 1, tex->pd); if(tex->pd->coba) writestruct(wd, DATA, "ColorBand", 1, tex->pd->coba); Index: source/blender/makesdna/DNA_texture_types.h =================================================================== --- source/blender/makesdna/DNA_texture_types.h (revision 34984) +++ source/blender/makesdna/DNA_texture_types.h (working copy) @@ -37,6 +37,7 @@ #include "DNA_ID.h" #include "DNA_image_types.h" /* ImageUser */ +#include "DNA_color_types.h" #ifdef __cplusplus extern "C" { @@ -236,6 +237,17 @@ short imaflag, flag; short type, stype; + /* tilestexture */ + short hcount, vcount, smooth; + short corner, pattern, bevoption; + float scale; + float width, widthvar, height, 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 seamless, bevelshading; + float cropxmin, cropymin, cropxmax, cropymax; int texfilter; int afmax; // anisotropic filter maximum value, ewa -> max eccentricity, feline -> max probes @@ -261,9 +273,21 @@ struct PreviewImage * preview; struct PointDensity *pd; struct VoxelData *vd; + struct TilesPreCalc *tilesdata; /* tilestexture */ + struct CurveMapping *curbevel; /* tilestexture */ char use_nodes; - char pad[7]; + char use_noise; + char blend_noise; + char blend_invert; + char pad[4]; + + char pad3[3], postflag; + short proctoim, alias; // for patterns etc + float frequency, awidth, iwidth, dvar; // additional variables for testing + short xratio, yratio, zratio, multi; + short xflag, yflag, zflag, formula; //additional flags for testing + float avar, bvar; //additional vars for testing } Tex; @@ -302,6 +326,8 @@ #define TEX_DISTNOISE 13 #define TEX_POINTDENSITY 14 #define TEX_VOXELDATA 15 +#define TEX_TILES 16 +#define TEX_PATTERN 17 /* musgrave stype */ #define TEX_MFRACTAL 0 @@ -408,7 +434,40 @@ #define TEX_SPHERE 4 #define TEX_HALO 5 #define TEX_RAD 6 +#define TEX_SQUARE 7 +#define TEX_CROSS 8 +/* tilestexture */ +/* 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 + /* tex->stype in texture.c - stucci types */ #define TEX_PLASTIC 0 #define TEX_WALLIN 1 @@ -420,6 +479,14 @@ #define TEX_COL2 2 #define TEX_COL3 3 +/* tex->stype in texture.c - pattern types */ +#define TEX_GRID 0 +#define TEX_DOTS 1 +#define TEX_CHECK 2 +#define TEX_CLOTH 3 +#define TEX_TILE 4 +#define TEX_QUARTER 5 + /* mtex->normapspace */ #define MTEX_NSPACE_CAMERA 0 #define MTEX_NSPACE_WORLD 1 Index: source/blender/makesrna/intern/rna_texture.c =================================================================== --- source/blender/makesrna/intern/rna_texture.c (revision 34984) +++ source/blender/makesrna/intern/rna_texture.c (working copy) @@ -41,7 +41,10 @@ #include "DNA_scene_types.h" /* MAXFRAME only */ #include "BKE_node.h" +#include "BKE_texture.h" /* tilestexture */ +#include "BLI_threads.h" /* tilestexture */ + EnumPropertyItem texture_filter_items[] = { {TXF_BOX, "BOX", 0, "Box", ""}, {TXF_EWA, "EWA", 0, "EWA", ""}, @@ -52,6 +55,7 @@ EnumPropertyItem texture_type_items[] = { {0, "NONE", 0, "None", ""}, {TEX_BLEND, "BLEND", ICON_TEXTURE, "Blend", ""}, + {TEX_PATTERN, "PATTERN", ICON_TEXTURE, "Pattern", ""}, {TEX_CLOUDS, "CLOUDS", ICON_TEXTURE, "Clouds", ""}, {TEX_DISTNOISE, "DISTORTED_NOISE", ICON_TEXTURE, "Distorted Noise", ""}, {TEX_ENVMAP, "ENVIRONMENT_MAP", ICON_IMAGE_DATA, "Environment Map", ""}, @@ -66,6 +70,7 @@ {TEX_VORONOI, "VORONOI", ICON_TEXTURE, "Voronoi", ""}, {TEX_VOXELDATA, "VOXEL_DATA", ICON_TEXTURE, "Voxel Data", ""}, {TEX_WOOD, "WOOD", ICON_TEXTURE, "Wood", ""}, + {TEX_TILES, "TILES", ICON_TEXTURE, "Tiles", ""}, {0, NULL, 0, NULL, NULL}}; #ifdef RNA_RUNTIME @@ -91,7 +96,9 @@ switch(tex->type) { case TEX_BLEND: return &RNA_BlendTexture; - case TEX_CLOUDS: + case TEX_PATTERN: + return &RNA_PatternTexture; + case TEX_CLOUDS: return &RNA_CloudsTexture; case TEX_DISTNOISE: return &RNA_DistortedNoiseTexture; @@ -113,6 +120,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: @@ -124,9 +133,22 @@ } } +static void rna_Tiles_texture_precalc(Tex *tex) +{ + + BLI_lock_thread(LOCK_CUSTOM1); + tiles_precalc(tex); + BLI_unlock_thread(LOCK_CUSTOM1); + +} + static void rna_Texture_update(Main *bmain, Scene *scene, PointerRNA *ptr) { Tex *tex= ptr->id.data; + + if (tex->type == TEX_TILES) { + rna_Tiles_texture_precalc(tex); + } DAG_id_tag_update(&tex->id, 0); WM_main_add_notifier(NC_TEXTURE, tex); @@ -353,6 +375,78 @@ rna_Texture_update(bmain, scene, ptr); } + + +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_Tiles_texture_precalc(tex); + rna_Texture_update(bmain, scene, ptr); +} + +static PointerRNA rna_Tiles_texture_curve_get(PointerRNA *ptr) +{ + return rna_pointer_inherit_refine(ptr, &RNA_CurveMapping, NULL); +} + +static void rna_Tiles_texture_type_select(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + Tex *tex= ptr->id.data; + + if (tex->proctoim & 1) { + /* We have to do this because do_2d_mapping() will mess up the texture mapping + * for Tiles texture + */ + 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; + } + rna_Tiles_texture_precalc(tex); + rna_Texture_update(bmain, scene, ptr); +} + +static void rna_Tiles_texture_update(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + Tex *tex= ptr->id.data; + + rna_Tiles_texture_precalc(tex); + rna_Texture_update(bmain, scene, ptr); +} + static PointerRNA rna_PointDensity_psys_get(PointerRNA *ptr) { PointDensity *pd= ptr->data; @@ -580,6 +674,7 @@ RNA_def_property_update(prop, 0, "rna_Texture_update"); } + static void rna_def_environment_map(BlenderRNA *brna) { StructRNA *srna; @@ -675,7 +770,276 @@ {TEX_NOISEPERL, "HARD_NOISE", 0, "Hard", ""}, {0, NULL, 0, NULL, NULL}}; +static void rna_def_noise_common(StructRNA *srna) +{ + PropertyRNA *prop; + prop= RNA_def_property(srna, "turbulence", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "turbul"); + RNA_def_property_range(prop, 0.0001, FLT_MAX); + RNA_def_property_ui_range(prop, 0.0001, 200, 10, 2); + RNA_def_property_ui_text(prop, "Turbulence", "Sets the turbulence of the bandnoise and ringnoise types"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "noise_scale", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "noisesize"); + RNA_def_property_range(prop, 0.0001, FLT_MAX); + RNA_def_property_ui_range(prop, 0.0001, 2, 1, 3); + RNA_def_property_ui_text(prop, "Noise Size", "Sets scaling for noise input"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "noise_depth", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "noisedepth"); + RNA_def_property_range(prop, 0, 30); + RNA_def_property_ui_range(prop, 0, 24, 0, 2); + RNA_def_property_ui_text(prop, "Noise Depth", "Sets the depth of the cloud calculation"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "noise_basis", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "noisebasis"); + RNA_def_property_enum_items(prop, prop_noise_basis_items); + RNA_def_property_ui_text(prop, "Noise Basis", "Sets the noise basis used for turbulence"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "noise_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "noisetype"); + RNA_def_property_enum_items(prop, prop_noise_type); + RNA_def_property_ui_text(prop, "Noise Type", ""); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "nabla", PROP_FLOAT, PROP_NONE); + RNA_def_property_range(prop, 0.001, 0.1); + RNA_def_property_ui_range(prop, 0.001, 0.1, 1, 2); + RNA_def_property_ui_text(prop, "Nabla", "Size of derivative offset used for calculating normal"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + +} + + +static void rna_def_texture_pattern(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + static const EnumPropertyItem prop_use_noise_items[]= { + {0, "OFF", 0, "Off", "Turn off blend noise"}, + {1, "ON", 0, "On", "Use blend noise"}, + {0, NULL, 0, NULL, NULL}}; + + static const EnumPropertyItem prop_blend_invert_items[]= { + {0, "NORMAL", 0, "Normal", "Intensity"}, + {1, "INVERTED", 0, "Inverted", "Invert intensity"}, + {0, NULL, 0, NULL, NULL}}; + + static const EnumPropertyItem prop_flip_axis_items[]= { + {0, "HORIZONTAL", 0, "Horizontal", "Flips the texture's X and Y axis"}, + {TEX_FLIPBLEND, "VERTICAL", 0, "Vertical", "Flips the texture's X and Y axis"}, + {0, NULL, 0, NULL, NULL}}; + + + + static EnumPropertyItem prop_pipeline[] = { + {0, "DXT DYT", 0, "dxt dyt", ""}, + {1, "DXT", 0, "dxt", ""}, + {2, "DYT", 0, "dyt", ""}, + {3, "DXYT INT", 0, "int dxt dyt", ""}, + {4, "TEXVEC", 0, "Texvec", ""}, + {5, "Test2", 0, "Rhombus", ""}, + {6, "Test3", 0, "Circles", ""}, + {7, "Test4", 0, "Tear Drops", ""}, + {8, "Test5", 0, "Hearts", ""}, + {9, "Test5", 0, "Octogon", ""}, + {10, "Test5", 0, "Axe", ""}, + {11, "Test5", 0, "+ Shape", ""}, + {12, "Test5", 0, "T Shape", ""}, + {13, "Test5", 0, "13", ""}, + {14, "Test5", 0, "14", ""}, + {15, "Test5", 0, "15", ""}, + {0, NULL, 0, NULL, NULL}}; + + static EnumPropertyItem prop_pattern_stype[] = { + {TEX_CLOTH, "CLOTH", 0, "Cloth", "Creates a cloth pattern"}, + {TEX_TILE, "TILE", 0, "Tile", "Creates a tiled pattern"}, + {TEX_QUARTER, "PIPELINE", 0, "Pipeline", "Various pipeline properties"}, + {TEX_GRID, "GRID", 0, "Grid", "Creates a grid"}, + {TEX_DOTS, "DOTS", 0, "Dots", "Creates a pattern of dots"}, + {TEX_CHECK, "CHECK", 0, "Check", "Creates a checkered pattern"}, + {0, NULL, 0, NULL, NULL}}; + + + static EnumPropertyItem prop_formula[] = { + {0, "SINE", 0, "00", ""}, + {1, "1", 0, "01", ""}, + {2, "ROUND_DOTS", 0, "02", ""}, + {3, "SQUARE_DOTS", 0, "03", ""}, + {4, "Test", 0, "Square", ""}, + {5, "Test2", 0, "Rhombus", ""}, + {6, "Test3", 0, "Circles", ""}, + {7, "Test4", 0, "Tear Drops", ""}, + {8, "Test5", 0, "Hearts", ""}, + {9, "Test5", 0, "Octogon", ""}, + {10, "Test5", 0, "Axe", ""}, + {11, "Test5", 0, "+ Shape", ""}, + {12, "Test5", 0, "T Shape", ""}, + {13, "Test5", 0, "13", ""}, + {14, "Test5", 0, "14", ""}, + {15, "Test5", 0, "15", ""}, + {0, NULL, 0, NULL, NULL}}; + + static const EnumPropertyItem prop_blend_noise_items[]= { + {0, "TURB", 0, "Turbulence factor", "No noise"}, + {1, "INTENSITY", 0, "Intensity", "Adds noise according to intensity"}, + {2, "INPUT", 0, "Input", "Adds noise to x, y input"}, + {3, "BOTH", 0, "Both", "Adds noise to x, y input and modulates intensity"}, + {4, "SELF", 0, "Self factor", "Adds noise to x, y input and multiplie distance"}, + {5, "5", 0, "5", "Adds noise to x, y input and modulates intensity"}, + {0, NULL, 0, NULL, NULL}}; + + srna= RNA_def_struct(brna, "PatternTexture", "Texture"); + RNA_def_struct_ui_text(srna, "Pattern Texture", "Procedural pattern."); + RNA_def_struct_sdna(srna, "Tex"); + + prop= RNA_def_property(srna, "use_flip_axis", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag"); + RNA_def_property_enum_items(prop, prop_flip_axis_items); + RNA_def_property_ui_text(prop, "Flip Axis", "Flips the texture's X and Y axis"); + RNA_def_property_update(prop, 0, "rna_Texture_nodes_update"); + + prop= RNA_def_property(srna, "blend_invert", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "blend_invert"); + RNA_def_property_enum_items(prop, prop_blend_invert_items); + RNA_def_property_ui_text(prop, "Invert", "Invert blend"); + RNA_def_property_update(prop, 0, "rna_Texture_nodes_update"); + + + + prop= RNA_def_property(srna, "stype", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "stype"); + RNA_def_property_enum_items(prop, prop_pattern_stype); + RNA_def_property_ui_text(prop, "Pattern", "Sets the style of the pattern"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + + prop= RNA_def_property(srna, "pipeline", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "formula"); + RNA_def_property_enum_items(prop, prop_pipeline); + RNA_def_property_ui_text(prop, "pipeline", "Choose the formula"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "formula", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "formula"); + RNA_def_property_enum_items(prop, prop_formula); + RNA_def_property_ui_text(prop, "Formula", "Choose the formula"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "flip_axis", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag"); + RNA_def_property_enum_items(prop, prop_flip_axis_items); + 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, "frequency", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "frequency"); + RNA_def_property_range(prop, 0.0f, 100.0f); + RNA_def_property_ui_text(prop, "Frequency", "Sets the repetition frequency for the pattern"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "avar", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "avar"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Slider A", "Width of gap or border"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "bvar", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "bvar"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Slider B", "Width of gap or border"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "awidth", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "awidth"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Width", "Width of gap or border"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "iwidth", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "iwidth"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "IWidth", "Inner width"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "dvar", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "dvar"); + RNA_def_property_range(prop, 0.0f, 100.0f); + RNA_def_property_ui_text(prop, "Variable D", "Variable D"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "xflag", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "xflag", 1); + RNA_def_property_ui_text(prop, "X", "Toggle X"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "yflag", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "yflag", 1); + RNA_def_property_ui_text(prop, "Y", "Toggle Y"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "zflag", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "zflag", 1); + RNA_def_property_ui_text(prop, "Z", "Toggle Z"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "xratio", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "xratio"); + RNA_def_property_range(prop, 1, 8); + RNA_def_property_ui_text(prop, "X Ratio", "Sets input ratio X direction"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "yratio", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "yratio"); + RNA_def_property_range(prop, 1, 8); + RNA_def_property_ui_text(prop, "Y Ratio", "Sets input ratio Y direction"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "zratio", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "zratio"); + RNA_def_property_range(prop, 1, 8); + RNA_def_property_ui_text(prop, "Z Ratio", "Sets input ratio Z direction"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "multi", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "multi", 1); + RNA_def_property_ui_text(prop, "Multi", "Toggle Multi"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "alias", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "alias", 1); + RNA_def_property_ui_text(prop, "Alias", "Toggle Alias"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "blend_noise", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "blend_noise"); + RNA_def_property_enum_items(prop, prop_blend_noise_items); + RNA_def_property_ui_text(prop, "Noise", "Adds noise to blend"); + RNA_def_property_update(prop, 0, "rna_Texture_nodes_update"); + + prop= RNA_def_property(srna, "postflag", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "postflag", 1); + RNA_def_property_ui_text(prop, "Noise x Intensity", "Add noise based on intensity"); + RNA_def_property_update(prop, 0, "rna_Texture_nodes_update"); + + prop= RNA_def_property(srna, "use_noise", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "use_noise", 1); + RNA_def_property_ui_text(prop, "Use Noise", "Adds noise to blend"); + RNA_def_property_update(prop, 0, "rna_Texture_nodes_update"); + + rna_def_noise_common(srna); + //rna_def_filter_size_common(srna); + //rna_def_mapping_common(srna); + + + } + static void rna_def_texture_clouds(BlenderRNA *brna) { StructRNA *srna; @@ -908,17 +1272,41 @@ {TEX_SPHERE, "SPHERICAL", 0, "Spherical", "Creates a spherical progression"}, {TEX_HALO, "QUADRATIC_SPHERE", 0, "Quadratic sphere", "Creates a quadratic progression in the shape of a sphere"}, {TEX_RAD, "RADIAL", 0, "Radial", "Creates a radial progression"}, + {TEX_SQUARE, "SQUARE", 0, "Square", "Creates a square pattern"}, + {TEX_CROSS, "CROSS", 0, "Cross", "Creates a cross pattern"}, {0, NULL, 0, NULL, NULL}}; + + static const EnumPropertyItem prop_use_noise_items[]= { + {0, "OFF", 0, "Off", "Turn off blend noise"}, + {1, "ON", 0, "On", "Use blend noise"}, + {0, NULL, 0, NULL, NULL}}; + + static const EnumPropertyItem prop_blend_invert_items[]= { + {0, "NORMAL", 0, "Normal", "Intensity"}, + {1, "INVERTED", 0, "Inverted", "Invert intensity"}, + {0, NULL, 0, NULL, NULL}}; + static const EnumPropertyItem prop_flip_axis_items[]= { {0, "HORIZONTAL", 0, "Horizontal", "Flips the texture's X and Y axis"}, {TEX_FLIPBLEND, "VERTICAL", 0, "Vertical", "Flips the texture's X and Y axis"}, {0, NULL, 0, NULL, NULL}}; + + + static const EnumPropertyItem prop_blend_noise_items[]= { + {0, "TURB", 0, "Turbulence factor", "No noise"}, + {1, "INTENSITY", 0, "Intensity", "Adds noise according to intensity"}, + {2, "INPUT", 0, "Input", "Adds noise to x, y input"}, + {3, "BOTH", 0, "Both", "Adds noise to x, y input and modulates intensity"}, + {4, "SELF", 0, "Self factor", "Adds noise to x, y input and multiplie distance"}, + {5, "5", 0, "5", "Adds noise to x, y input and modulates intensity"}, + {0, NULL, 0, NULL, NULL}}; srna= RNA_def_struct(brna, "BlendTexture", "Texture"); RNA_def_struct_ui_text(srna, "Blend Texture", "Procedural color blending texture"); RNA_def_struct_sdna(srna, "Tex"); + prop= RNA_def_property(srna, "progression", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "stype"); RNA_def_property_enum_items(prop, prop_blend_progression); @@ -931,6 +1319,32 @@ RNA_def_property_ui_text(prop, "Flip Axis", "Flips the texture's X and Y axis"); RNA_def_property_update(prop, 0, "rna_Texture_nodes_update"); + prop= RNA_def_property(srna, "blend_invert", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "blend_invert"); + RNA_def_property_enum_items(prop, prop_blend_invert_items); + RNA_def_property_ui_text(prop, "Invert", "Invert blend"); + RNA_def_property_update(prop, 0, "rna_Texture_nodes_update"); + + prop= RNA_def_property(srna, "use_noise", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "use_noise", 1); + RNA_def_property_ui_text(prop, "Use Noise", "Adds noise to blend"); + RNA_def_property_update(prop, 0, "rna_Texture_nodes_update"); + + + prop= RNA_def_property(srna, "blend_noise", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "blend_noise"); + RNA_def_property_enum_items(prop, prop_blend_noise_items); + RNA_def_property_ui_text(prop, "Noise", "Adds noise to blend"); + RNA_def_property_update(prop, 0, "rna_Texture_nodes_update"); + + prop= RNA_def_property(srna, "postflag", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "postflag", 1); + RNA_def_property_ui_text(prop, "Noise x Intensity", "Add noise based on intensity"); + RNA_def_property_update(prop, 0, "rna_Tiles_texture_update"); + + + rna_def_noise_common(srna); + } static void rna_def_texture_stucci(BlenderRNA *brna) @@ -981,6 +1395,295 @@ RNA_def_property_update(prop, 0, "rna_Texture_update"); } + +static void rna_def_texture_tiles(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + static EnumPropertyItem prop_stucci_stype[] = { + {TEX_PLASTIC, "PLASTIC", 0, "Plastic", "Uses standard stucci"}, + {TEX_WALLIN, "WALL_IN", 0, "Wall in", "Creates Dimples"}, + {TEX_WALLOUT, "WALL_OUT", 0, "Wall out", "Creates Ridges"}, + {0, NULL, 0, NULL, NULL}}; + + static EnumPropertyItem prop_pattern_items[] = { + {TEX_TILES_NONE, "NONE", 0, "No pattern", "---"}, + {TEX_TILES_INTERLOCK1, "INTERLOCK1", 0, "Interlock 1", "---"}, + {TEX_TILES_HEX, "HEX", 0, "Hex", "---"}, + {TEX_TILES_HERRINGBONE1, "HERRINGBONE1", 0, "Herringbone 1", "---"}, + {TEX_TILES_HERRINGBONE2, "HERRINGBONE2", 0, "Herringbone 2", "---"}, + {TEX_TILES_HERRINGBONE3, "HERRINGBONE3", 0, "Herringbone 3", "---"}, + {TEX_TILES_WEAVE, "WEAVE", 0, "Weave", "---"}, + {TEX_TILES_INTERLOCK2, "INTERLOCK2", 0, "Interlock 2", "---"}, + {TEX_TILES_INTERLOCK3, "INTERLOCK2", 0, "Interlock 3", "---"}, + {TEX_TILES_INTERLOCK4, "INTERLOCK2", 0, "Interlock 4", "---"}, + {TEX_TILES_CROSS1, "CROSS1", 0, "Cross 1", "---"}, + {TEX_TILES_CROSS2, "CROSS2", 0, "Cross 2", "---"}, + {TEX_TILES_STAR1, "STAR1", 0, "Star 1", "---"}, + {0, NULL, 0, NULL, NULL}}; + + static EnumPropertyItem prop_bevelshading_items[] = { + {TEX_BEVEL_DEFAULT, "DEFAULT", 0, "Default Shading", "---"}, + {TEX_BEVEL_HGRADIENT, "HGRADIENT", 0, "H Gradient", "---"}, + {TEX_BEVEL_VGRADIENT, "VGRADIENT", 0, "V Gradient", "---"}, + {TEX_BEVEL_PATTERN, "PATTERN", 0, "Pattern", "---"}, + {0, NULL, 0, NULL, NULL}}; + + static EnumPropertyItem prop_corner_type_items[] = { + {TEX_CORNER_ROUND, "ROUND", 0, "Round", "---"}, + {TEX_CORNER_ROUND_INV, "ROUND_INV", 0, "Round Inverse", "---"}, + {TEX_CORNER_ELLIPSE, "ELLIPSE", 0, "Ellipse", "---"}, + {TEX_CORNER_ELLIPSE_INV, "ELLIPSE_INV", 0, "Ellipse Inverse", "---"}, + {TEX_CORNER_STRAIGHT, "STRAIGHT", 0, "Straight", "---"}, + {0, NULL, 0, NULL, NULL}}; + + static const EnumPropertyItem prop_blend_noise_items[]= { + {0, "TURB", 0, "Turbulence factor", "No noise"}, + {1, "INTENSITY", 0, "Intensity", "Adds noise according to intensity"}, + {2, "INPUT", 0, "Input", "Adds noise to x, y input"}, + {3, "BOTH", 0, "Both", "Adds noise to x, y input and modulates intensity"}, + {4, "SELF", 0, "Self factor", "Adds noise to x, y input and multiplie distance"}, + {5, "5", 0, "5", "Adds noise to x, y input and modulates intensity"}, + {0, NULL, 0, NULL, NULL}}; + + static EnumPropertyItem prop_bevoption_items[] = { + {TEX_BEVEL_DEFAULTMIN, "DEFAULT", 0, "Default", "---"}, + {TEX_BEVEL_UNIFORMMIN, "UNIFORMMIN", 0, "Uniform Min", "---"}, + {TEX_BEVEL_UNIFORMMAX, "UNIFORMMAX", 0, "Uniform Max", "---"}, + {0, NULL, 0, NULL, NULL}}; + + static const EnumPropertyItem prop_use_noise_items[]= { + {0, "OFF", 0, "Off", "Turn off blend noise"}, + {1, "ON", 0, "On", "Use blend noise"}, + {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, "corner_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "stype"); + RNA_def_property_enum_items(prop, prop_corner_type_items); + RNA_def_property_ui_text(prop, "Corner", "Corner type"); + RNA_def_property_update(prop, 0, "rna_Tiles_texture_update"); + + prop= RNA_def_property(srna, "bevelshading", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "extend"); + RNA_def_property_enum_items(prop, prop_bevelshading_items); + RNA_def_property_ui_text(prop, "Bevel", "bevelshading"); + RNA_def_property_update(prop, 0, "rna_Tiles_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, "Bevel Option", ""); + RNA_def_property_update(prop, 0, "rna_Tiles_texture_update"); + + 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", ""); + RNA_def_property_update(prop, 0, "rna_Tiles_texture_tiles_pattern"); //rna_Tiles_texture_type_select + + // prop= RNA_def_property(srna, "curbevel", PROP_POINTER, PROP_NONE); + // RNA_def_property_struct_type(prop, "curbevel"); + // RNA_def_property_pointer_funcs(prop, "rna_Tiles_texture_curve_get", NULL, NULL, NULL); + // RNA_def_property_ui_text(prop, "Curve Bevel", ""); + // RNA_def_property_update(prop, 0, "rna_Tiles_texture_update"); + prop= RNA_def_property(srna, "curbevel", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "curbevel"); + RNA_def_property_ui_text(prop, "Curve Bevel", "Custom Bevel"); + RNA_def_property_update(prop, 0, "rna_Tiles_texture_update"); + + //prop= RNA_def_property(srna, "falloff_curve", PROP_POINTER, PROP_NONE); + //RNA_def_property_pointer_sdna(prop, NULL, "curfalloff"); + //RNA_def_property_ui_text(prop, "Falloff Curve", "Custom Lamp Falloff Curve"); + //RNA_def_property_update(prop, 0, "rna_Lamp_update"); + + prop= RNA_def_property(srna, "scale", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "scale"); + RNA_def_property_range(prop, 0.0001, FLT_MAX); + RNA_def_property_ui_range(prop, 0.0001, 200, 10, 2); + RNA_def_property_ui_text(prop, "Scale", "Scale texture"); + RNA_def_property_update(prop, 0, "rna_Tiles_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, 512); + RNA_def_property_ui_text(prop, "Columns", "Number of horizontal random tiles"); + RNA_def_property_update(prop, 0, "rna_Tiles_texture_update"); + + prop= RNA_def_property(srna, "width", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "width"); + RNA_def_property_range(prop, 0.0001, FLT_MAX); + RNA_def_property_ui_range(prop, 0.0001, 200, 10, 2); + RNA_def_property_ui_text(prop, "Width", "Average tile width"); + RNA_def_property_update(prop, 0, "rna_Tiles_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, FLT_MAX); + RNA_def_property_ui_range(prop, 0, 1, 10, 2); + RNA_def_property_ui_text(prop, "Variation", "Variation in tile width"); + RNA_def_property_update(prop, 0, "rna_Tiles_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, 512); + RNA_def_property_ui_text(prop, "Rows", "Number of vertical random tiles"); + RNA_def_property_update(prop, 0, "rna_Tiles_texture_update"); + + prop= RNA_def_property(srna, "height", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "height"); + RNA_def_property_range(prop, 0, FLT_MAX); + RNA_def_property_ui_range(prop, 0, 1, 10, 2); + RNA_def_property_ui_text(prop, "Height", "Average tile height"); + RNA_def_property_update(prop, 0, "rna_Tiles_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, FLT_MAX); + RNA_def_property_ui_range(prop, 0, 1, 10, 2); + RNA_def_property_ui_text(prop, "Height Variation", "Variation in tile height"); + RNA_def_property_update(prop, 0, "rna_Tiles_texture_update"); + + prop= RNA_def_property(srna, "seamless", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "seamless", 1); + RNA_def_property_ui_text(prop, "Seamless", "Seamless texture"); + RNA_def_property_update(prop, 0, "rna_Tiles_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, FLT_MAX); + RNA_def_property_ui_range(prop, 0, 1, 10, 2); + RNA_def_property_ui_text(prop, "Bump", "Average tile height"); + RNA_def_property_update(prop, 0, "rna_Tiles_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, FLT_MAX); + RNA_def_property_ui_range(prop, 0, 1, 10, 2); + RNA_def_property_ui_text(prop, "Bump Variation", "Variation in bump height"); + RNA_def_property_update(prop, 0, "rna_Tiles_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, FLT_MAX); + RNA_def_property_ui_range(prop, 0, 1, 10, 2); + RNA_def_property_ui_text(prop, "Bevel Size", "Variation in bump height"); + RNA_def_property_update(prop, 0, "rna_Tiles_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_Tiles_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, FLT_MAX); + RNA_def_property_ui_range(prop, 0, 1, 10, 2); + RNA_def_property_ui_text(prop, "Size X", "Horizontal gap"); + RNA_def_property_update(prop, 0, "rna_Tiles_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, FLT_MAX); + RNA_def_property_ui_range(prop, 0, 1, 10, 2); + RNA_def_property_ui_text(prop, "Size Y", "Vertical gap"); + RNA_def_property_update(prop, 0, "rna_Tiles_texture_update"); + + + prop= RNA_def_property(srna, "colr1", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "colr1"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Brick Color", "Base color for brick"); + RNA_def_property_update(prop, 0, "rna_Tiles_texture_update"); + + prop= RNA_def_property(srna, "colr2", 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_Tiles_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, 0, FLT_MAX); + RNA_def_property_ui_range(prop, 0, 1, 10, 2); + RNA_def_property_ui_text(prop, "Shift", "Variation in bump height"); + RNA_def_property_update(prop, 0, "rna_Tiles_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, 1, 512); + RNA_def_property_ui_text(prop, "Rows", "Rows"); + RNA_def_property_update(prop, 0, "rna_Tiles_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, FLT_MAX); + RNA_def_property_ui_range(prop, 0, 1, 10, 2); + RNA_def_property_ui_text(prop, "Hue", "Variation in hue"); + RNA_def_property_update(prop, 0, "rna_Tiles_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, FLT_MAX); + RNA_def_property_ui_range(prop, 0, 1, 10, 2); + RNA_def_property_ui_text(prop, "H Corner", "Horizontal corner"); + RNA_def_property_update(prop, 0, "rna_Tiles_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, FLT_MAX); + RNA_def_property_ui_range(prop, 0, 1, 10, 2); + RNA_def_property_ui_text(prop, "V Corner", "Vertical corner"); + RNA_def_property_update(prop, 0, "rna_Tiles_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, FLT_MAX); + RNA_def_property_ui_range(prop, 0, 1, 10, 2); + RNA_def_property_ui_text(prop, "Sat", "Variation in saturation"); + RNA_def_property_update(prop, 0, "rna_Tiles_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, FLT_MAX); + RNA_def_property_ui_range(prop, 0, 1, 10, 2); + RNA_def_property_ui_text(prop, "Val", "Variation in value"); + RNA_def_property_update(prop, 0, "rna_Tiles_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, 1, 512); + RNA_def_property_ui_text(prop, "Seed", "Seed"); + RNA_def_property_update(prop, 0, "rna_Tiles_texture_update"); + + prop= RNA_def_property(srna, "blend_noise", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "blend_noise"); + RNA_def_property_enum_items(prop, prop_blend_noise_items); + RNA_def_property_ui_text(prop, "Noise", "Adds noise to blend"); + RNA_def_property_update(prop, 0, "rna_Tiles_texture_update"); + + prop= RNA_def_property(srna, "postflag", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "postflag", 1); + RNA_def_property_ui_text(prop, "Noise x Intensity", "Add noise based on intensity"); + RNA_def_property_update(prop, 0, "rna_Tiles_texture_update"); + + prop= RNA_def_property(srna, "use_noise", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "use_noise", 1); + RNA_def_property_ui_text(prop, "Use Noise", "Adds noise to blend"); + RNA_def_property_update(prop, 0, "rna_Tiles_texture_update"); + + rna_def_noise_common(srna); +} + static void rna_def_texture_noise(BlenderRNA *brna) { StructRNA *srna; @@ -990,6 +1693,7 @@ RNA_def_struct_sdna(srna, "Tex"); } + static void rna_def_texture_image(BlenderRNA *brna) { StructRNA *srna; @@ -1741,6 +2445,12 @@ RNA_def_property_ui_text(prop, "Factor Blue", ""); RNA_def_property_update(prop, 0, "rna_Texture_update"); + /* map proc as image */ + prop= RNA_def_property(srna, "proctoim", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "proctoim", 1); + RNA_def_property_ui_text(prop, "2D Mapping", "Map procedural as 2D texture"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + /* Alpha for preview render */ prop= RNA_def_property(srna, "use_preview_alpha", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", TEX_PRV_ALPHA); @@ -1762,11 +2472,13 @@ rna_def_animdata_common(srna); /* specific types */ - rna_def_texture_clouds(brna); + rna_def_texture_tiles(brna); + rna_def_texture_clouds(brna); rna_def_texture_wood(brna); rna_def_texture_marble(brna); rna_def_texture_magic(brna); rna_def_texture_blend(brna); + rna_def_texture_pattern(brna); rna_def_texture_stucci(brna); rna_def_texture_noise(brna); rna_def_texture_image(brna); Index: source/blender/makesrna/RNA_access.h =================================================================== --- source/blender/makesrna/RNA_access.h (revision 34984) +++ source/blender/makesrna/RNA_access.h (working copy) @@ -356,6 +356,7 @@ extern StructRNA RNA_ParticleKey; extern StructRNA RNA_ParticleSettings; extern StructRNA RNA_ParticleSettingsTextureSlot; +extern StructRNA RNA_PatternTexture; extern StructRNA RNA_ParticleSystem; extern StructRNA RNA_ParticleSystemModifier; extern StructRNA RNA_ParticleTarget; @@ -532,6 +533,7 @@ extern StructRNA RNA_ThemeWidgetColors; extern StructRNA RNA_ThemeWidgetStateColors; extern StructRNA RNA_TimelineMarker; +extern StructRNA RNA_TilesTexture; extern StructRNA RNA_ToolSettings; extern StructRNA RNA_TouchSensor; extern StructRNA RNA_TrackToConstraint; Index: source/blender/render/intern/include/texture.h =================================================================== --- source/blender/render/intern/include/texture.h (revision 34984) +++ source/blender/render/intern/include/texture.h (working copy) @@ -53,6 +53,7 @@ struct HaloRen; struct ShadeInput; struct TexResult; +struct TexPreCalc; /* tilestexture */ struct Tex; struct Image; struct ImBuf; Index: source/blender/render/intern/source/render_texture.c =================================================================== --- source/blender/render/intern/source/render_texture.c (revision 34984) +++ source/blender/render/intern/source/render_texture.c (working copy) @@ -34,6 +34,7 @@ #include "BLI_math.h" #include "BLI_rand.h" #include "BLI_utildefines.h" +#include "BLI_threads.h" /* tilestexture */ #include "DNA_texture_types.h" #include "DNA_object_types.h" @@ -51,6 +52,7 @@ #include "BKE_image.h" #include "BKE_node.h" #include "BKE_plugin_types.h" +#include "BKE_colortools.h" /* tilestexture */ #include "BKE_global.h" @@ -81,8 +83,8 @@ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ +#define M_PI_OVER_180 0.0174532925199 /* tilestexture */ - static void init_render_texture(Render *re, Tex *tex) { int cfra= re->scene->r.cfra; @@ -126,6 +128,2071 @@ /* ------------------------------------------------------------------------- */ +/* tilestexture */ + +/* 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 + +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, float z, 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, float z, 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, float z, 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, float z, 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, float z, 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, float z, 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, float z, 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, float z, 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, dl, dr; + float ha, hb, ra, rb; + 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, float z, 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, float z, 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_transform(Tex *tex, float *x, float *y, float *z) +{ + float angle, sinval, cosval, scale; + float x1, y1; + + /* Move origin to (0.5, 0.5) */ + *x -= 0.5; + *y -= 0.5; + *z -= 0.5; + + /* Apply texture coordinate scale */ + scale = 1.0 / tex->scale; + *x *= scale; + *y *= scale; + *z *= scale; + + /* Move origin back to (0, 0) */ + *x += 0.5; + *y += 0.5; + *z += 0.5; +} + +static void tiles_calc(Tex *tex, float *x, float *y, float *z, short *htileid, short *vtileid) +{ + /* Given points (x, y, z) determines where in the tile pattern, tex->tilesdata->hpat[], + * the point belongs. It returns the index of the tile in htileid, vtileid and x, y, z + * will contain the relative offset for the tile. + * NOTE: currently z is ignored as this is a 2D texture. + */ + float wtot = tex->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 z, float *col) +{ + short htileid, vtileid; + float intens; + + /* Compute coordinates in "tile-space"; i.e. relative to the tile containing + * the texture coordinates. + */ + tiles_transform(tex, &x, &y, &z); + tiles_calc(tex, &x, &y, &z, &htileid, &vtileid); + + /* Handle predefined patterns and default tiling function */ + switch (tex->pattern) { + case TEX_TILES_CROSS1: + intens = tiles_cross1_int(tex, x, y, z, htileid, vtileid, col); + break; + case TEX_TILES_CROSS2: + intens = tiles_cross2_int(tex, x, y, z, htileid, vtileid, col); + break; + case TEX_TILES_HERRINGBONE1: + intens = tiles_herringbone_int(tex, x, y, z, htileid, vtileid, 2, col); + break; + case TEX_TILES_HERRINGBONE2: + intens = tiles_herringbone_int(tex, x, y, z, htileid, vtileid, 4, col); + break; + case TEX_TILES_HERRINGBONE3: + intens = tiles_herringbone_int(tex, x, y, z, htileid, vtileid, 5, col); + break; + case TEX_TILES_HEX: + intens = tiles_hex_int(tex, x, y, z, htileid, vtileid, col); + break; + case TEX_TILES_INTERLOCK1: + intens = tiles_interlock1_int(tex, x, y, z, htileid, vtileid, col); + break; + case TEX_TILES_INTERLOCK2: + intens = tiles_interlock2_int(tex, x, y, z, htileid, vtileid, 2, col); + break; + case TEX_TILES_INTERLOCK3: + intens = tiles_interlock2_int(tex, x, y, z, htileid, vtileid, 4, col); + break; + case TEX_TILES_INTERLOCK4: + intens = tiles_interlock3_int(tex, x, y, z, htileid, vtileid, col); + break; + case TEX_TILES_STAR1: + intens = tiles_star1_int(tex, x, y, z, htileid, vtileid, col); + break; + case TEX_TILES_WEAVE: + intens = tiles_weave_int(tex, x, y, z, htileid, vtileid, col); + break; + default: + intens = tiles_default_int(tex, x, y, z, 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; +} + + +/* ------------------------------------------------------------------------- */ + + void init_render_textures(Render *re) { Tex *tex; @@ -183,7 +2250,1205 @@ } +static float repeat(float in, float r) +{ + int i, v; + + in= fabs(in); + + if(r > 0) { + + in= in * r; + i= ceil(in); + + if (in > 1) { + in= in - floorf(in); + if (i % 2 == 0 ) { + in = 1-in; + } + } + + } + + + + return in; + + + + +} +static float warp(float x, float y, float z, float f) +{ + float t; + + y = y + f/2 * cos(x) * cos(z); + + if (fabs(y) > f/2) { + return 0.0; + } + + t= cos(y); + + t= t * cos(z); + + t= t * t; + + return t; +} + +/* functions ported from rtilings.c */ + + +/* ************************************************************ + Regular Tilings + + These functions generate regular tilings + for the x-y-plane with squares, triangles or hexagons. + + Anti-aliasing is performed (if not turned off) by calculating + the mean value from four texture values at the vertices of an pixel. + ************************************************************ */ + +#define SQRT3 (1.73205080756888) +#define SQRT3_2 (SQRT3/2.) + + + +float calc_square_value(float x,float y,Tex *tex) +{ + + float width = 1.-tex->awidth; + float iwidth = 1.-tex->iwidth; + + float retval=0.; + float osize1=1.-width; + float isize1=1.-iwidth; + int parity=1; + + + if (x<0.) { + x=fabs(x); + parity=-parity; + } + if (y<0.) { + y=fabs(y); + parity=-parity; + } + if ((int)x & 1) parity=-parity; + if ((int)y & 1) parity=-parity; + + x=x-floorf(x); + y=y-floorf(y); + + if ((x<=width && x>=osize1) && + (y<=width && y>=osize1)) { + + if ((x<=iwidth && x>=isize1) && + (y<=iwidth && y>=isize1)) { + if (tex->multi) + retval= parity>0 ? 0.25 : 0.75; + } else + retval=1.; + } + return retval; +} + + + + +float calc_tri_value(float x,float y,Tex *tex) +{ + float width = 1.-tex->awidth; + float iwidth = 1.-tex->iwidth; + float retval=0.; + float osize1=1.-width; + float isize1=1.-iwidth; + float osize1_s3_2=osize1*SQRT3_2; + float isize1_s3_2=isize1*SQRT3_2; + float yo,yi; + int parity=1; + + + if (x<0.) { + x=fabs(x); + } + if (y<0.) { + y=fabs(y); + parity=-parity; + } + + x=x-floorf(x); + y=y-floorf(y/SQRT3)*SQRT3; + + if (x>0.5) x=1.-x; + if (y>SQRT3_2) { + y=SQRT3-y; + parity=-parity; + } + yo=(x-osize1)*SQRT3; + if (y<=yo && y>=osize1_s3_2) { + yi=(x-isize1)*SQRT3; + if (y<=yi && y>=isize1_s3_2) { + if (tex->multi) + retval=(parity<0) ? 0.25 : 0.75; + } else + retval=1.; + } + yo=(x+osize1)*SQRT3; + if (y>yo && y<(SQRT3_2-osize1_s3_2)) { + yi=(x+isize1)*SQRT3; + if (y>yi && y<(SQRT3_2-isize1_s3_2)) { + if (tex->multi) + retval=(parity<0) ? 0.75 : 0.25; + } else + retval=1.; + } + return retval; +} + + +#define NORM(v,min,max) (((v)-(min))/((max)-(min))) + +#define SIN45 0.7071067 +#define OCTEDGE 0.2928932 /* 0.5 - tan(22.5) */ + +#define SHIFT(type,a,b,c) {type _shift=(a);a=(b);b=(c);c=_shift;} + +float calc_hex_value(float x,float y,Tex *tex) +{ + float width = 1.-tex->awidth; + float iwidth = 1.-tex->iwidth; + float retval=0.; + float osize1=1.-width; + float isize1=1.-iwidth; + float osize1_s3_2=osize1*0.75; /* SQRT3_2*SQRT3_2 */ + float isize1_s3_2=isize1*0.75; /* SQRT3_2*SQRT3_2 */ + static float cols[3]={0.25,0.50,0.75}; + float yo,yi,tf; + int coli[3],t; + + coli[0]=0; + coli[1]=1; + coli[2]=2; + + if (x<0.) x=fabs(x); + if (y<0.) { + y=fabs(y); + SWAP(int,coli[1],coli[2]); + } + + x=x-floorf(x/3)*3; + if (x>1.5) x=3.-x; + + tf=floorf(y/SQRT3); + t=((int)tf)%3; + if (t==1) { + SHIFT(int,coli[0],coli[2],coli[1]); + } else if (t==2) { + SHIFT(int,coli[0],coli[1],coli[2]); + } + y=y-tf*SQRT3; + if (y>SQRT3_2) { + y=SQRT3-y; + SWAP(int,coli[0],coli[2]); + } + + yo=(width-x)*SQRT3; + yi=(iwidth-x)*SQRT3; + if (y<=yo && y<=width*SQRT3_2) { + if (y<=yi && y<=iwidth*SQRT3_2) { + if (tex->multi) + retval=cols[coli[0]]; + } else + retval=1.; + } + + yo=((2.-width)-x)*SQRT3; + yi=((2.-iwidth)-x)*SQRT3; + if (y>yo && y>osize1_s3_2) { + if (y>yi && y>isize1_s3_2) { + if (tex->multi) + retval=cols[coli[1]]; + } else + retval=1.; + } + + return retval; +} + +typedef float (*calc_func_t)(float x,float y,Tex *tex); + + +/* end of */ + + +float calc_trellis(int type, float x, float y, Tex *tex) { + float lineval; /* value to return if point is on a "line" of trellis */ + float areaval; /* value to return if point is not on "line" */ + float midval; /* value to return if point is not on "line" */ + float d; /* width of circle */ + float cx, cy; /* centre of circle to test for */ + float tx; /* temp x */ + float ts; /* temp for swap */ + float t; + float t2; + float t3; + float tmpa; + float tmpb; + float tmpc; + + t= tex->awidth; + t2= t/2; + t3= ((1-t)*tex->iwidth)/2; + + if (tex->multi) { /* multi-colour */ + areaval = 0.75; + midval = 0.50; + lineval = 0.25; + } else { + areaval = 1.0; + midval = 0.50; + lineval = 0.0; + } + + switch (type) { + case 1: /* Square */ + if ((x < t2) || (x > (1.0 - t2)) || (y < t2) || (y > (1.0 - t2))) + return lineval; + else if ((x < t3) || (x > (1.0 - t3)) || (y < t3) || (y > (1.0 - t3))) + { + midval= (1-MAX2(fabs(x-0.5),fabs(y-0.5))*2)*t3; + return midval; + } + else return areaval; //areaval; + break; + case 2: /* Rhombus */ + tmpa = t2 / SIN45; + tmpb = ABS(x - y); + tmpc = ABS(1.0 - y - x); + lineval = (lineval+tmpa+tmpb+tmpc)/2; + if ((tmpb < tmpa) || (tmpc < tmpa)) /*if ((ABS(x - y) < (t2 / SIN45)) || (ABS(1.0 - y - x) < (t2 / SIN45)))*/ + return lineval; + else return areaval; + break; + case 3: /* Circles in a square arrangement */ + d = (float) sqrt(((x - 0.5) * (x - 0.5)) + ((y - 0.5) * (y - 0.5))); + if ((d < (0.5 + t2)) && (d > (0.5 - t2))) return lineval; + else return areaval; + break; + case 4: /* Double Tear Drops */ + case 5: /* Heart shapes */ + if (type == 5) { /* extra arc to make heart */ + tx = x; + + if (y > 0.5) { + if (x > 0.5) x -= 0.5; + + d = (float) sqrt(((x - 0.25) * (x - 0.25)) + + ((y - 0.5) * (y - 0.5))); + if ((d < (0.25 + t2)) && (d > (0.25 - t2))) { + return lineval; + break; + } + } else { + if (x > 0.5) x -= 0.5; + d = sqrt(((x - 0.25) * (x - 0.25)) + ((y) * (y))); + if ((d < (0.25 + t2)) && (d > (0.25 - t2))) { + return lineval; + break; + } + } + x = tx; + } + if (x < 0.25) { + if (y > 0.5) y = 1.0 - y; + cx = 0.25; + cy = 0.0; + } else if (x < 0.75) { + if (x > 0.5) x -= 0.25; + else x += 0.25; + cx = 0.5; + cy = 0.5; + } else { /* x > 0.75 */ + if (y > 0.5) y = 1.0 - y; + cx = 0.75; + cy = 0.0; + } + + /* test for point on circle */ + d = sqrt(((x - cx) * (x - cx)) + ((y - cy) * (y - cy))); + if ((d < (0.25 + t2)) && (d > (0.25 - t2))) return lineval; + else return areaval; + break; + case 6: /* Octogon */ + /* Fold coordinates into bottom left corner */ + if (x > 0.5) x = 1.0 - x; + if (y > 0.5) y = 1.0 - y; + + /* draw vertical edge */ + if ((x < t2) && (y > OCTEDGE)) return lineval; + + /* draw horizontal edge */ + else if ((x > OCTEDGE) && (y < t2)) return lineval; + + /* draw diagonal line */ + else if (ABS(OCTEDGE - y - x) < (t2 / SIN45)) return lineval; + + /* otherwise, blank */ + else return areaval; + break; + case 7: /* Double Headed Axe */ + /* move top right quarter into lower left */ + if (x > 0.5 && y > 0.5) { + x -= 0.5; + y -= 0.5; + } else if (y > 0.5) { + /* Rotate top left quarter & move into lower left */ + ts = x; + x = y - 0.5; + y = ts; + } else if (x > 0.5) { + /* Rotate lower right quarter and move into lower left */ + ts = y; + y = x - 0.5; + x = ts; + } + + /* now swap left and right halves of lower left quarter */ + /* and expand x to double width */ + if (x > 0.25) { + x -= 0.25; + x = 0.25 - ((0.25 - x) * 2); + } else { + x += 0.25; + x = 0.25 + ((x - 0.25) * 2); + } + + /* Finally, check for a circle */ + d = sqrt(((x - 0.25) * (x - 0.25)) + ((y - 0.25) * (y - 0.25))); + if ((d < (0.25 + t2)) && (d > (0.25 - t2))) return lineval; + else return areaval; + break; + case 8: /* '+' Shapes */ + /* The '+' pattern has two-way rotational symmetry, so rotate + other three quarters into bottom left */ + if (x < 0.5 && y > 0.5) { /* top left */ + ts = x; + x = 1.0 - y; + y = ts; + } else if (x > 0.5 && y < 0.5) { /* bottom right */ + ts = x; + x = y; + y = 1.0 - ts; + } else if (x > 0.5 && y > 0.5) { /* top right */ + x = 1.0 - x; + y = 1.0 - y; + } + + /* Now check for presence on cross shape */ + /* Vertical lines first */ + if (((x < t2) || (x >= 0.2 - t2 && x < 0.2 + t2)) && + (y <= 0.2 + t2 || y > 0.4 - t2)) { + return lineval; + break; + } else if ((x >= 0.4 - t2 && x < 0.4 + t2) && (y <= 0.4 + t2)) { + return lineval; + break; + } + + /* Then horizontal lines */ + if ((y <= t2) && (x < 0.2 + t2 || x >= 0.4 - t2)) { + return lineval; + break; + } else if ((y > 0.2 - t2 && y <= 0.2 + t2) + && (x >= 0.2 - t2)) { + return lineval; + break; + } else if ((y > 0.4 - t2 && y <= 0.4 + t2) + &&(x >= 0.2 - t2 && x < 0.4 + t2)) { + return lineval; + break; + } + return areaval; + break; + case 9: /* 'T' Shapes */ + + /* Horizontal lines first */ + if (((y > (1.0 - t)) || (y <= 0.5 && y > (0.5 - t))) && + (x < 0.25 || x >= 0.5)) { + return lineval; + break; + } else if (((y <= 0.75 && y > (0.75 - t)) || + (y <= 0.25 && y > (0.25 - t))) &&(x < 0.75)) { + return lineval; + break; + } + + /* If none found, check for vertical lines */ + if (((x < t) || (x >= 0.75 && x < (0.75 + t))) + && ((y <= 0.25) || (y > 0.5 && y <= 0.75))) { + return lineval; + break; + } + if (((x >= 0.25 && x < (0.25 + t)) || (x >= 0.5 & x < (0.5 + t))) && + ((y > 0.25 && y <= 0.5) || y > 0.75)) { + return lineval; + break; + } + return areaval; + break; + default: + return areaval; + } + return areaval; +} + +float calc_cube(float aval, float x, float y, float z, Tex *tex) { + float lineval; /* value to return if point is on a "line" of trellis */ + float areaval; /* value to return if point is not on "line" */ + float t; + float t2; + + t= tex->awidth; + t2= t*tex->iwidth; + + if (tex->multi) { /* multi-colour */ + areaval = aval; + lineval = 0.0; + } else { + areaval = 1.0; + lineval = 0.0; + } + + /* It is easier to search for point NOT in a line */ + if (((x > t2 && x < (1.0 - t2)) && (y > t2 && y < (1.0 - t2))) + || ((z > t2 && z < (1.0 - t2)) && (y > t2 && y < (1.0 - t2))) + || ((x > t2 && x < (1.0 - t2)) && (z > t2 && z < (1.0 - t2)))) + return areaval; + else return lineval; +} + +static float noise(int n) /* fast integer noise */ +{ + int nn; + n = (n >> 13) ^ n; + nn = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff; + return 0.5f * ((float)nn / 1073741824.0f); +} + +float calc_bricks(float x, float y, float z, Tex *tex) { + int bricknum, rownum; + float offset = 0; + float ins_x, ins_y; + float tint; + //float color[4]; + float retval; + + + float bias = tex->iwidth; + float brick_width = tex->xratio; + float row_height = tex->yratio; + float mortar_thickness = tex->frequency/row_height*tex->awidth/2; + float contrast = tex->avar; + + rownum = (int)floor(y / row_height); + + offset = ((int)(rownum) % 2 ) ? 0 : (brick_width*tex->iwidth); + + bricknum = (int)floor((x+offset) / brick_width); + + ins_x = (x+offset) - brick_width*bricknum; + ins_y = y - row_height*rownum; + + tint = noise((rownum << 16) + (bricknum & 0xFFFF)) + bias; + CLAMP(tint,0.0f,1.0f); + + if( ins_x < mortar_thickness || ins_y < mortar_thickness || + ins_x > (brick_width - mortar_thickness) || + ins_y > (row_height - mortar_thickness) ) { + + if (!tex->multi) { + retval= contrast-mortar_thickness; + } else { + retval= BLI_gTurbulence(tex->dvar, x, y, z, tex->noisedepth, (tex->noisetype!=TEX_NOISESOFT), tex->noisebasis); + CLAMP(retval,0.0f,contrast-mortar_thickness); + } + + + } else { + + if (!tex->multi) { + retval= 1-contrast+mortar_thickness; + } else { + retval= tint; + CLAMP(retval,0.0f,(1-contrast+mortar_thickness)); + } + } + + return retval; +} + + +static int pattern(Tex *tex, float *texvec, TexResult *texres, float *dxt, float *dyt) +{ + float x, y, z, t; + int rt, i, j; + int xi, yi, zi; + float sx, sy, sz; + int rv=TEX_INT; + + if(tex->flag & TEX_FLIPBLEND) { + x= texvec[1]; + y= texvec[0]; + z= texvec[2]; + } + else { + x= texvec[0]; + y= texvec[1]; + z= texvec[2]; + } + + x= x * tex->frequency * tex->xratio; + y= y * tex->frequency * tex->yratio; + z= z * tex->frequency * tex->zratio; + + + if(tex->xflag & 1) y= x; + if(tex->yflag & 1) {t= x * y; y= t; x= t;} + if(tex->zflag & 1) y= (x+y)/2; + + + + if(tex->use_noise & 1) { + x+= BLI_gTurbulence(tex->noisesize, x, y, z, tex->noisedepth, (tex->noisetype!=TEX_NOISESOFT), tex->noisebasis); //BLI_gTurbulence BLI_hnoise + y+= BLI_gTurbulence(tex->noisesize, y, z, x, tex->noisedepth, (tex->noisetype!=TEX_NOISESOFT), tex->noisebasis); + } + + if(tex->stype==TEX_QUARTER) { /* quarter */ + /*texres->tin= (sin(x*4*M_PI)+sin(y*4*M_PI))/4+0.5; //dots */ + /*texres->tin= (atanf(x*y) / (2*M_PI) + 0.5); //nope */ + /*texres->tin= powf((sin(x*5)+sin(y*5)),3)*cos(x*y*M_PI)*0.065+0.5; //curious */ + + + //texres->tin= (((sin(x)+sin(y)+sin(z))/4+0.5))*0.333333; + //texres->tin= (atan2(y,x) / (2*M_PI) + 0.5); //temp + if(tex->formula == 0) { + + float offx=(fabs(dxt[0])+fabs(dxt[1])+fabs(dxt[2]))*tex->dvar; + float offy=(fabs(dyt[0])+fabs(dyt[1])+fabs(dyt[2]))*tex->dvar; + float offz=fabs(offx-offy); + texres->tr= offx; + texres->tg= offy; + texres->tb= offz; + texres->tin= (offx+offy+offz)/3; + texres->ta= 1.0; + if (texres->nor!=NULL) { + texres->nor[0]=offx; + texres->nor[1]=offy; + texres->nor[2]=offz; + } + } + else if(tex->formula == 1) { + + float offx=fabs(dxt[0])*tex->dvar; + float offy=fabs(dxt[1])*tex->dvar; + float offz=fabs(dxt[2])*tex->dvar; + + texres->tr= offx; + texres->tg= offy; + texres->tb= offz; + texres->tin= (offx+offy+offz)/3; + texres->ta= 1.0; + if (texres->nor!=NULL) { + texres->nor[0]=offx; + texres->nor[1]=offy; + texres->nor[2]=offz; + } + + + } + else if(tex->formula == 2) { + + float offx=fabs(dyt[0])*tex->dvar; + float offy=fabs(dyt[1])*tex->dvar; + float offz=fabs(dyt[2])*tex->dvar; + + texres->tr= offx; + texres->tg= offy; + texres->tb= offz; + texres->tin= (offx+offy+offz)/3; + texres->ta= 1.0; + if (texres->nor!=NULL) { + texres->nor[0]=offx; + texres->nor[1]=offy; + texres->nor[2]=offz; + } + + + } + else if(tex->formula == 3) { + + float offx=texvec[0]*tex->dvar; + float offy=texvec[1]*tex->dvar; + float offz=texvec[2]*tex->dvar; + + texres->tr= offx; + texres->tg= offy; + texres->tb= offz; + texres->tin= (offx+offy+offz)/3; + texres->ta= 1.0; + if (texres->nor!=NULL) { + texres->nor[0]=offx; + texres->nor[1]=offy; + texres->nor[2]=offz; + } + + + } + else if(tex->formula == 4) { + + float offx=(fabs(dxt[0])+fabs(dxt[1])+fabs(dxt[2]))*tex->dvar; + float offy=(fabs(dyt[0])+fabs(dyt[1])+fabs(dyt[2]))*tex->dvar; + + + texres->tin= (offx+offy); + texres->ta= 1.0; + if (texres->nor!=NULL) { + texres->nor[0]=offx; + texres->nor[1]=offy; + texres->nor[2]=1.0; + } + + BRICONT; //BRICONTRGB; + //texres->ta= 1.0; + + return TEX_INT; //TEX_RGB + } + BRICONTRGB; //BRICONTRGB; + //texres->ta= 1.0; + + return TEX_RGB; //TEX_RGB + + + } + else if(tex->stype==TEX_TILE) { /* tile */ + +/* Intensity, R, G, B, Alpha, nor.x, nor.y, nor.z */ + +float t; /* thickness */ +float t2; /* 1/2 thickness */ +int multi; /* Use multi-colours? */ + if(tex->formula == 15 ) { /* bricks adapted from TEX_bricks.c */ + + + texres->tin= calc_bricks(x,y,z,tex); + if (tex->alias) { + float offx=(fabs(dxt[0])+fabs(dxt[1])+fabs(dxt[2]))*tex->dvar; + float offy=(fabs(dyt[0])+fabs(dyt[1])+fabs(dyt[2]))*tex->dvar; + texres->tin+=calc_bricks(x+offx,y,z,tex); + texres->tin+=calc_bricks(x,y+offy,z,tex); + texres->tin+=calc_bricks(x-offx,y,z,tex); + texres->tin+=calc_bricks(x,y-offy,z,tex); + texres->tin+=calc_bricks(x+offx,y+offy,z,tex); + texres->tin+=calc_bricks(x-offx,y-offy,z,tex); + texres->tin+=calc_bricks(x-offx,y+offy,z,tex); + texres->tin+=calc_bricks(x+offx,y-offy,z,tex); + texres->tin/=9.0; + } + + + BRICONT; //BRICONTRGB; + //texres->ta= 1.0; + + return TEX_INT; //TEX_RGB + + } + if(tex->formula == 13 ) { /* bricks adapted from TEX_bricks.c */ + + + + float offx=(fabs(dxt[0])+fabs(dxt[1])+fabs(dxt[2]))*tex->dvar; + float offy=(fabs(dyt[0])+fabs(dyt[1])+fabs(dyt[2]))*tex->dvar; + float offz=fabs(offx-offy); + texres->tr= offx; + texres->tg= offy; + texres->tb= offz; + texres->tin= (offx+offy+offz)/3; + texres->ta= 1.0; + if (texres->nor!=NULL) { + texres->nor[0]=offx; + texres->nor[1]=offy; + texres->nor[2]=offz; + } + + + BRICONTRGB; //BRICONTRGB; + //texres->ta= 1.0; + + return TEX_RGB; //TEX_RGB + + } + else if(tex->formula == 14 ) { /* scales adapted from scales.c (Robert Wenzlaff) */ + /* scales */ + float cr=0,cg=0,cb=0,er=0,nx=0,ny=0; + float sr, sg, sb, fr, fb, fg; + + sr= 0.5; + sg= 0.2; + sb= 0.2; + fr= 0.3; + fg= 0.4; + fb= 0.5; + + /* Normalize to 0-1 */ + y=fabs(y); /* Normalize to 0-1 */ + y=y-(int)y; + + x=fabs(x); + x=x-(int)x; + + /* printf("Args: texvec[0]= %f X=%f Y=%f\n",texvec[1],x,y); */ + + + if (tex->noisesize !=0) { + er=BLI_hnoise(tex->noisesize,texvec[0], texvec[1], texvec[2])-0.5; + er*=tex->noisesize; + } + + if (tex->noisesize!=0) { // cast->ColNoiseDep + cr=BLI_hnoise(tex->noisesize, texvec[0], texvec[1], texvec[2])-0.5; + cr*=tex->noisesize; + cg=BLI_hnoise(tex->noisesize, texvec[2], texvec[0], texvec[1])-0.5; + cg*=tex->noisesize; + cb=BLI_hnoise(tex->noisesize, texvec[0], texvec[2], texvec[1])-0.5; + cb*=tex->noisesize; + } + + if (tex->noisesize!=0){ // cast->NorNoiseDep!=0 + nx=BLI_hnoise(tex->noisesize, texvec[0], texvec[1], texvec[2])-0.5; + nx*=tex->noisesize; + nx=BLI_hnoise(tex->noisesize, texvec[1], texvec[0], texvec[2])-0.5; + nx*=tex->noisesize; + } + + if (1) { + + if ( ((x-0.5)*(x-0.5)+(y+er)*(y+er) )< 0.25 ) { /* -.5>y>.5, 0>x>1 */ + + texres->tr=(0.5-y) * sr+(0.5+y) * fr +cr; + texres->tg=(0.5-y) * sg+(0.5+y) * fg +cg; + texres->tb=(0.5-y) * sb+(0.5+y) * fb +cb; + texres->tin=(texres->tr+texres->tg+texres->tb)/3.0; + /*printf("case 1: Results %f %f %f %f\n", result[0],texres->tr,texres->tg,texres->tb); */ + + if (texres->nor!=NULL) { + texres->nor[0]=(4 * (x-0.5) * (x-0.5)+nx); + texres->nor[1]=y+ny; + } + + } + + else if ( ( ( x * x + (y-0.5+er) * (y-0.5+er) ) < 0.25) || + ( ( (x-1) * (x-1) + (y-0.5+er)*(y-0.5+er) ) < 0.25) ) { /*0tr=(1-y) * sr+(y+cr) * fr +cr; + texres->tg=(1-y) * sg+(y+cg) * fg +cg; + texres->tb=(1-y) * sb+(y+cb) * fb +cb; + texres->tin=(texres->tr+texres->tg+texres->tb)/3.0; + /*printf("case 2: Results %f %f %f %f\n", result[0],texres->tr,texres->tg,texres->tb); */ + + if (texres->nor!=NULL) { + if (x>0.5) x=1-x; + texres->nor[0]=(4*x*x)+nx; + texres->nor[1]=(y-0.5)+ny; + } + } + + else { + texres->tr=(1.5-y) * sr+(y-0.5) * fr + cr; + texres->tg=(1.5-y) * sg+(y-0.5) * fg + cg; + texres->tb=(1.5-y) * sb+(y-0.5) * fb + cb; + texres->tin=(texres->tr+texres->tg+texres->tb)/3.0; + /*printf("Default: Results %f %f %f %f\n", result[0],texres->tr,texres->tg,texres->tb); */ + + if (texres->nor!=NULL) { + texres->nor[0]=(4*(x-0.5)*(x-0.5)+nx); + texres->nor[1]=(y-1)+ny; + } + } + } + + texres->ta=1.0; + if (texres->nor!=NULL) { + texres->nor[2]=0.0; + } + + BRICONTRGB; + texres->ta= 1.0; + + return TEX_RGB; + /* end of scales */ + + + } + else if(tex->formula > 2) { + + i = tex->formula-3; /*hack*/ + + t = tex->awidth; + t2 = t / 2.0; + multi = tex->multi; + + /* We only calculate the shape inside the unit square */ + x = x - floor(x); + y = y - floor(y); + z = z - floor(z); + if (i > 0) { + texres->tin= calc_trellis(i,x,y,tex); + + if (tex->alias) { + float offx=(fabs(dxt[0])+fabs(dxt[1])+fabs(dxt[2]))/2*tex->dvar; + float offy=(fabs(dyt[0])+fabs(dyt[1])+fabs(dyt[2]))/2*tex->dvar; + texres->tin+=calc_trellis(i,x+offx,y,tex); + texres->tin+=calc_trellis(i,x,y+offy,tex); + texres->tin+=calc_trellis(i,x-offx,y,tex); + texres->tin+=calc_trellis(i,x,y-offy,tex); + texres->tin+=calc_trellis(i,x+offx,y+offy,tex); + texres->tin+=calc_trellis(i,x-offx,y-offy,tex); + texres->tin+=calc_trellis(i,x-offx,y+offy,tex); + texres->tin+=calc_trellis(i,x+offx,y-offy,tex); + texres->tin/=9.0; + } + + } else { /* stype == THREE_D */ + int xn, yn, zn; /* integer parts of coordinate */ + float rnd; + + xn = ((int) floor(x) * 4 - 23) & 0x3FF; + yn = ((int) floor(y) * 7 - 9) & 0x3FF; + zn = ((int) floor(z) * 3 + 1) & 0x3FF; + srand((unsigned int) (yn * xn * zn)); + rnd= BLI_rand(); + texres->tin= calc_cube(rnd,x,y, z,tex); + + if (tex->alias) { + float offx=(fabs(dxt[0])+fabs(dxt[1])+fabs(dxt[2]))/2*tex->dvar; + float offy=(fabs(dyt[0])+fabs(dyt[1])+fabs(dyt[2]))/2*tex->dvar; + texres->tin+=calc_cube(rnd,x+offx,y,z,tex); + texres->tin+=calc_cube(rnd,x,y+offy,z,tex); + texres->tin+=calc_cube(rnd,x-offx,y,z,tex); + texres->tin+=calc_cube(rnd,x,y-offy,z,tex); + texres->tin+=calc_cube(rnd,x+offx,y+offy,z,tex); + texres->tin+=calc_cube(rnd,x-offx,y-offy,z,tex); + texres->tin+=calc_cube(rnd,x-offx,y+offy,z,tex); + texres->tin+=calc_cube(rnd,x+offx,y-offy,z,tex); + texres->tin/=9.0; + } + } + + } + else + { + + static calc_func_t funcs[3]={calc_square_value,calc_tri_value,calc_hex_value}; + + if (tex->formula<0 || tex->formula>2) tex->formula=0; + + /* invert widths to normalise ui values for this formula*/ + + texres->tin=funcs[tex->formula](x,y,tex); + /* offset effect */ + /*if (tex->dvar>0) { + float offx=(fabs(dxt[0])+fabs(dxt[1])+tex->dvar); + float offy=(fabs(dyt[0])+fabs(dyt[1])+tex->dvar); + texres->tin+=funcs[tex->formula](x+offx,y,tex); + texres->tin+=funcs[tex->formula](x,y+offy,tex); + texres->tin/=3.0; + }*/ + /* anti-aliasing basic*/ + if (tex->alias) { + float offx=(fabs(dxt[0])+fabs(dxt[1])+fabs(dxt[2]))/2*tex->dvar; + float offy=(fabs(dyt[0])+fabs(dyt[1])+fabs(dyt[2]))/2*tex->dvar; + texres->tin+=funcs[tex->formula](x+offx,y,tex); + texres->tin+=funcs[tex->formula](x,y+offy,tex); + texres->tin+=funcs[tex->formula](x-offx,y,tex); + texres->tin+=funcs[tex->formula](x,y-offy,tex); + texres->tin+=funcs[tex->formula](x+offx,y+offy,tex); + texres->tin+=funcs[tex->formula](x-offx,y-offy,tex); + texres->tin+=funcs[tex->formula](x-offx,y+offy,tex); + texres->tin+=funcs[tex->formula](x+offx,y-offy,tex); + texres->tin/=9.0; + } + }; + + + + } + else if(tex->stype==TEX_CHECK) { /* grid */ + + + + + + /* taken from TEX_checker.c */ + xi = (int)fabs(floor(x)); + yi = (int)fabs(floor(y)); + zi = (int)fabs(floor(z)); + + if( (xi % 2 == yi % 2) == (zi % 2) ) { + texres->tin= 1.0f; + if (texres->nor!=NULL) { + // calculate bumpnormal + texres->nor[0] = BLI_gTurbulence(tex->noisesize, (xi%2) + tex->nabla, (yi%2), (zi%2), tex->noisedepth, (tex->noisetype!=TEX_NOISESOFT), tex->noisebasis); + texres->nor[1] = BLI_gTurbulence(tex->noisesize, (xi%2), (yi%2) + tex->nabla, (zi%2), tex->noisedepth, (tex->noisetype!=TEX_NOISESOFT), tex->noisebasis); + texres->nor[2] = BLI_gTurbulence(tex->noisesize, (xi%2), (yi%2), (zi%2) + tex->nabla, tex->noisedepth, (tex->noisetype!=TEX_NOISESOFT), tex->noisebasis); + + tex_normal_derivate(tex, texres); + rv |= TEX_NOR; + } + + } else { + texres->tin= 0.0f; + if (texres->nor!=NULL) { + // calculate bumpnormal + texres->nor[0] = BLI_gTurbulence(tex->noisesize, (xi%2) + tex->nabla, (yi%2), (zi%2), tex->noisedepth, (tex->noisetype!=TEX_NOISESOFT), tex->noisebasis); + texres->nor[1] = BLI_gTurbulence(tex->noisesize, (xi%2), (yi%2) + tex->nabla, (zi%2), tex->noisedepth, (tex->noisetype!=TEX_NOISESOFT), tex->noisebasis); + texres->nor[2] = BLI_gTurbulence(tex->noisesize, (xi%2), (yi%2), (zi%2) + tex->nabla, tex->noisedepth, (tex->noisetype!=TEX_NOISESOFT), tex->noisebasis); + + tex_normal_derivate(tex, texres); + rv |= TEX_NOR; + } + } + + BRICONT; + + return rv; + + + } + else if(tex->stype==TEX_GRID) { /* grid */ + z= texvec[2]; + x = (1+sin(x*tex->frequency))/2; + y = (1+sin(y*tex->frequency))/2; + z = (1+sin(z*tex->frequency))/2; + sy = tex->awidth*0.90; + if ( x > tex->awidth || y > tex->awidth || z > tex->awidth ) { + if ( x > y && x > z) texres->tin= x; + else if ( y > x && y > z) texres->tin= y; + else if ( z > x && z > y) texres->tin= z; + else texres->tin= tex->awidth*tex->awidth; + + } + else if ( x > sy || y > sy || z > sy ) { + if ( x > y && x > z) texres->tin= x; + else if ( y > x && y > z) texres->tin= y; + else if ( z > x && z > y) texres->tin= z; + else texres->tin= tex->awidth*tex->awidth; + + } + else { + texres->tin= tex->awidth*tex->awidth*tex->awidth; + } + } + else if(tex->stype==TEX_DOTS) { /* dots */ + texres->tin= (sin(x*tex->frequency)+sin(y*tex->frequency))/4+0.5; + } + else if(tex->stype==TEX_CLOTH) { /* cloth */ + sz = tex->frequency; + z= texvec[2]; + + + + switch(tex->formula) { + + case 0: /* bands */ + texres->tin= (cos(x * tex->frequency - (tex->iwidth*sz)) /2+0.5) * fabs(cos(y*tex->iwidth)) * fabs(cos(y*tex->iwidth)) ; + break; + + case 1: + if(tex->awidth > 0.0 ) { + /* floor(x*3)/(3-1)*/ + if(tex->awidth > 1) { + sz = floorf(y*tex->awidth) / (tex->awidth-1); + } else { + sz= tex->awidth; + } + } + + texres->tin= (cos(x * tex->frequency - (tex->iwidth*sz)) /2+0.5) * fabs(cos(y*tex->iwidth)) * fabs(cos(y*tex->iwidth)) ; + break; + + case 2: /* dots */ + texres->tin= (sin(x*tex->frequency*tex->awidth)+sin(y*tex->frequency*tex->iwidth))/4+0.5; + break; + + case 3: /* dots2 */ + texres->tin= (sin(x*tex->frequency*tex->awidth) * sin(y*tex->frequency*tex->iwidth))/2+0.5; + break; + + case 4: /* test */ + texres->tin= (((sin(x*tex->frequency*tex->awidth)+sin(y*tex->frequency*tex->iwidth))/4+0.5) + ((sin(x*tex->frequency*tex->awidth) * sin(y*tex->frequency*tex->iwidth))/2+0.5) )/2; + break; + + case 5: /* test2 */ + texres->tin= (((sin(x*tex->frequency*tex->awidth)+sin(y*tex->frequency*tex->iwidth))/4+0.5) * ((sin(x*tex->frequency*tex->awidth) * sin(y*tex->frequency*tex->iwidth))/2+0.5) ); + break; + + case 6: /* 3plus */ + texres->tin= (((sin(x*tex->frequency*tex->awidth)+sin(y*tex->frequency*tex->iwidth)+sin(z*tex->frequency*tex->iwidth))/4+0.5))*0.333333; + break; + + case 7: /* 3mult */ + texres->tin= (((sin(x*tex->frequency*tex->awidth)*sin(y*tex->frequency*tex->iwidth)*sin(z*tex->frequency*tex->iwidth))/2+0.5))*0.333333; + break; + + case 8: /* checks */ + + sz = tex->frequency; + + /* taken from TEX_checker.c */ + xi = (int)fabs(floor(x * sz)); + yi = (int)fabs(floor(y * sz)); + zi = (int)fabs(floor(z * sz)); + + if( (xi % 2 == yi % 2) == (zi % 2) ) { + texres->tin= 1.0f; + } else { + texres->tin= 0.0f; + } + break; + + case 9: /* checks2 */ + + sz = tex->frequency; + + /* taken from TEX_checker.c */ + xi = (int)fabs(floor(x * sz)); + yi = (int)fabs(floor(y * sz)); + zi = (int)fabs(floor(z * sz)); + + if( (xi % 2 == yi % 2) == (zi % 2) ) { + texres->tin= 1.0f; + } else { + texres->tin= 0.0f; + } + + texres->tin= texres->tin + sin(x*sz*2) + sin(y*sz*2); + break; + + case 10: /* checks2 */ + + x = (1+sin(x*tex->frequency))/2; + y = (1+sin(y*tex->frequency))/2; + z = (1+sin(z*tex->frequency))/2; + sy = tex->awidth*0.90; + if ( x > tex->awidth || y > tex->awidth || z > tex->awidth ) { + if ( x > y && x > z) texres->tin= x; + else if ( y > x && y > z) texres->tin= y; + else if ( z > x && z > y) texres->tin= z; + else texres->tin= tex->awidth*tex->awidth; + + } + else if ( x > sy || y > sy || z > sy ) { + if ( x > y && x > z) texres->tin= x; + else if ( y > x && y > z) texres->tin= y; + else if ( z > x && z > y) texres->tin= z; + else texres->tin= tex->awidth*tex->awidth; + + } + else { + texres->tin= tex->awidth*tex->awidth*tex->awidth; + } + + texres->tin= texres->tin * (atan(fabs(x))+atan(fabs(y))); + break; + + case 11: /* checks2 */ + + + break; + + } + + + } + + // texres->tr= 0.5-x; + // texres->tg= 0.5-y; + // texres->tb= 0.5-z; + + /*if (texres->nor!=NULL) { + // calculate bumpnormal + tex_normal_derivate(tex, texres); + rv |= TEX_NOR; + }*/ + + // BRICONTRGB; //BRICONTRGB; + // //texres->ta= 1.0; + + // return TEX_RGB; //TEX_RGB + + if (tex->postflag) { + //texres->tin= BLI_gTurbulence((texres->tin*tex->noisesize), x, y, texvec[2], tex->noisedepth, (tex->noisetype!=TEX_NOISESOFT), tex->noisebasis); //BLI_gTurbulence BLI_hnoise + texres->tin= BLI_hnoise((texres->tin*tex->noisesize), x, y, texvec[2]); + } + + BRICONT; + + return TEX_INT; +} + + + +static int tiles(Tex *tex, float *texvec, TexResult *texres) +{ + int rv = TEX_INT; + float col[3]; + + if (!tex->tilesdata) { //was ! + BLI_lock_thread(LOCK_CUSTOM1); + tiles_precalc(tex); + BLI_unlock_thread(LOCK_CUSTOM1); + } + + if(tex->use_noise & 1) { + texvec[0]+= BLI_gTurbulence(tex->noisesize, texvec[0], texvec[1], texvec[2], tex->noisedepth, (tex->noisetype!=TEX_NOISESOFT), tex->noisebasis); //BLI_gTurbulence BLI_hnoise + texvec[1]+= BLI_gTurbulence(tex->noisesize, texvec[0], texvec[1], texvec[2], tex->noisedepth, (tex->noisetype!=TEX_NOISESOFT), tex->noisebasis); + } + + texres->tin = tiles_int(tex, texvec[0], texvec[1], texvec[2], col); + + if (tex->postflag) { + texres->tin= BLI_gTurbulence((texres->tin*tex->noisesize), texvec[0], texvec[1], texvec[2], tex->noisedepth, (tex->noisetype!=TEX_NOISESOFT), tex->noisebasis); //BLI_gTurbulence BLI_hnoise + //texres->tin= BLI_hnoise((texres->tin*tex->noisesize), texvec[0], texvec[1], texvec[2]); + } + + texres->tr = col[0]; + texres->tg = col[1]; + texres->tb = col[2]; + texres->ta = 1.0; + rv |= TEX_RGB; + + if (texres->nor!=NULL) { + /* calculate bumpnormal */ + texres->nor[0] = tiles_int(tex, texvec[0] + tex->nabla, texvec[1], texvec[2], col); + texres->nor[1] = tiles_int(tex, texvec[0], texvec[1] + tex->nabla, texvec[2], col); + texres->nor[2] = tiles_int(tex, texvec[0], texvec[1], texvec[2] + tex->nabla, col); + + tex_normal_derivate(tex, texres); + rv |= TEX_NOR; + } + + + + BRICONTRGB; + + BRICONT; + + return rv; +} + static int blend(Tex *tex, float *texvec, TexResult *texres) { float x, y, t; @@ -196,7 +3461,25 @@ x= texvec[0]; y= texvec[1]; } - + + if (tex->use_noise & 1) { + if( tex->blend_noise == 2 || tex->blend_noise == 3 ) { + // distorts x,y + x+= BLI_gTurbulence(tex->noisesize, fabs(x), fabs(y), texvec[2], tex->noisedepth, (tex->noisetype!=TEX_NOISESOFT), tex->noisebasis); //BLI_gTurbulence BLI_hnoise + y+= BLI_gTurbulence(tex->noisesize, fabs(y), fabs(x), texvec[2], tex->noisedepth, (tex->noisetype!=TEX_NOISESOFT), tex->noisebasis); + } + else if( tex->blend_noise == 4 ) { + // different distortion + x*= BLI_gTurbulence(tex->noisesize, x, y, texvec[2], tex->noisedepth, (tex->noisetype!=TEX_NOISESOFT), tex->noisebasis); //BLI_gTurbulence BLI_hnoise + y*= BLI_gTurbulence(tex->noisesize, y, x, texvec[2], tex->noisedepth, (tex->noisetype!=TEX_NOISESOFT), tex->noisebasis); + } + else if( tex->blend_noise == 0 ) { + // different distortion + x*= tex->turbul*BLI_gTurbulence(tex->noisesize, x, y, texvec[2], tex->noisedepth, (tex->noisetype!=TEX_NOISESOFT), tex->noisebasis); //BLI_gTurbulence BLI_hnoise + y*= tex->turbul*BLI_gTurbulence(tex->noisesize, y, x, texvec[2], tex->noisedepth, (tex->noisetype!=TEX_NOISESOFT), tex->noisebasis); + } + } + if(tex->stype==TEX_LIN) { /* lin */ texres->tin= (1.0+x)/2.0; } @@ -220,12 +3503,40 @@ else if(tex->stype==TEX_RAD) { /* radial */ texres->tin= (atan2(y,x) / (2*M_PI) + 0.5); } + else if(tex->stype==TEX_SQUARE) { /* square */ + texres->tin= MAX2(fabs(x),fabs(y)); + } + else if(tex->stype==TEX_CROSS) { /* cross */ + texres->tin= atan(fabs(x))+atan(fabs(y)); + } else { /* sphere TEX_SPHERE */ texres->tin= 1.0-sqrt(x*x+ y*y+texvec[2]*texvec[2]); if(texres->tin<0.0) texres->tin= 0.0; if(tex->stype==TEX_HALO) texres->tin*= texres->tin; /* halo */ } - + + if (tex->blend_invert) { + texres->tin= 1.0-texres->tin; + } + + /* intensity modulates noisesize */ + if (tex->use_noise & 1) { + if( tex->blend_noise == 1 || tex->blend_noise == 3 ) { + if(texres->tin<0.0) texres->tin= 0.0; + texres->tin= BLI_gTurbulence((texres->tin+tex->noisesize), x, y, texvec[2], tex->noisedepth, (tex->noisetype!=TEX_NOISESOFT), tex->noisebasis); //BLI_gTurbulence BLI_hnoise + + } + else if(tex->blend_noise == 5) { + if(texres->tin<0.0) texres->tin= 0.0; + + texres->tin= BLI_gTurbulence((texres->tin+tex->noisesize), y*tex->turbul, x*tex->turbul, texvec[2]*tex->turbul, tex->noisedepth, (tex->noisetype!=TEX_NOISESOFT), tex->noisebasis); //BLI_gTurbulence BLI_hnoise + //y+= BLI_gTurbulence(tex->noisesize, y, x, texvec[2], tex->noisedepth, (tex->noisetype!=TEX_NOISESOFT), tex->noisebasis)-0.5; + + } + + + } + BRICONT; return TEX_INT; @@ -1191,6 +4502,9 @@ case TEX_BLEND: retval= blend(tex, texvec, texres); break; + case TEX_PATTERN: + retval= pattern(tex, texvec, texres, dxt, dyt); + break; case TEX_STUCCI: retval= stucci(tex, texvec, texres); break; @@ -1256,6 +4570,9 @@ case TEX_VOXELDATA: retval= voxeldatatex(tex, texvec, texres); break; + case TEX_TILES: + retval = tiles(tex, texvec, texres); + break; } @@ -1284,7 +4601,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) { @@ -1581,7 +4898,7 @@ static void texco_mapping(ShadeInput* shi, Tex* tex, MTex* mtex, float* co, float* dx, float* dy, float* texvec, float* dxt, float* dyt) { // new: first swap coords, then map, then trans/scale - if (tex->type == TEX_IMAGE) { + if (tex->type == TEX_IMAGE || tex->proctoim & 1) { // placement texvec[0] = mtex->projx ? co[mtex->projx - 1] : 0.f; texvec[1] = mtex->projy ? co[mtex->projy - 1] : 0.f; @@ -2850,7 +6167,7 @@ } - if(mtex->tex->type==TEX_IMAGE) do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt); + if(mtex->tex->type == TEX_IMAGE || mtex->tex->proctoim & 1) do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt); rgb= multitex(mtex->tex, texvec, dxt, dyt, osatex, &texres, 0, mtex->which_output); @@ -3043,7 +6360,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->proctoim & 1) do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt); rgb= multitex(mtex->tex, texvec, dxt, dyt, R.osa, &texres, thread, mtex->which_output); @@ -3247,7 +6564,7 @@ } /* texture */ - if(tex->type==TEX_IMAGE) { + if(tex->type == TEX_IMAGE || tex->proctoim & 1) { do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt); } @@ -3342,7 +6659,7 @@ else texvec[2]= mtex->size[2]*(mtex->ofs[2]); /* texture */ - if(tex->type==TEX_IMAGE) { + if(tex->type == TEX_IMAGE || tex->proctoim & 1) { do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt); }