
/* 
 * This is a texture plugin for blender 1.60 or above.
 *
 * Dot-drawing plugin, based on a sample plugin from NaN
 * Copyright (c) 1999, Bernd Breitenbach
 * 
 * $Id: rtilings.c,v 1.7 1999/06/28 18:41:39 bernd Exp bernd $
 * 
 */

/* ************************************************************
	NOTE: This software comes with absolute no warranty.
	You may distribute, modify and use it free of charge.
	
	If you have any enhancements or bug fixes, please let me now:

	              breitenb@iml.fhg.de
   ************************************************************ */


#include <stdio.h>
#include <math.h>
#include "plugin.h"

/* ******************** GLOBAL VARIABLES ***************** */

char name[]= "Tilings";
char *release="$Revision: 1.7 $";

/* Subtype names must be less than 15 characters */

#if defined(IRIX_WORKAROUND)

#define NR_TYPES	1
#if defined(SQUARES)
char stnames[NR_TYPES][16]= {"Squares"};
#elif defined(TRIANGLES)
char stnames[NR_TYPES][16]= {"Triangles"};
#elif defined(HEXAGONS)
char stnames[NR_TYPES][16]= {"Hexagons"};
#endif 

#else /*IRIX_WORKAROUND*/

#define NR_TYPES	3
char stnames[NR_TYPES][16]= {"Squares","Triangles","Hexagons"};

#endif /*IRIX_WORKAROUND*/



VarStruct varstr[]= {
  {LABEL|FLO,   "V1.7  bb",             0.,    0.,   0.,   ""},
  {NUM|FLO,	"Outer Size",		0.75,	 0.0, 1.0,  "Outer size "}, 
  {NUM|FLO,	"Inner Size",		0.0,	 0.0, 1.0,  "Inner size "},
  {NUM|FLO,     "Noise",                0.0,     0.0, 10.0, "Noise"},
  {TOG|INT,	"Multi Col",	        0.0,	 0.0, 1.0,  "Using colorband for coloring"},
  {TOG|INT,	"No AAlias",	        0.0,	 0.0, 1.0,  "Turn antialias off (independent from render settings)"}
};

/* The cast struct is for input in the main doit function
   Varstr and Cast must have the same variables in the same order */ 

typedef struct Cast {
        float dummy;
	float osize;
	float isize;
        float noise;
        int  multicol;
        int  noaalias;
} Cast;

/* result: 
   Intensity, R, G, B, Alpha, nor.x, nor.y, nor.z
 */

float result[8];

/* cfra: the current frame */

float cfra;

int plugin_tex_doit(int, Cast *, float *, float *, float *);




/* ******************** Fixed functions ***************** */

int plugin_tex_getversion(void) 
{	
	return B_PLUGIN_VERSION;
}

void plugin_but_changed(int but) 
{
}

void plugin_init(void)
{
}

/* this function should not be changed: */

void plugin_getinfo(PluginInfo *info)
{
  info->name= name;
  info->stypes= NR_TYPES;
  info->nvars= sizeof(varstr)/sizeof(VarStruct);
	
  info->snames= stnames[0];
  info->result= result;
  info->cfra= &cfra;
  info->varstr= varstr;

  info->init= plugin_init;
  info->tex_doit=  (TexDoit) plugin_tex_doit;
  info->callback= plugin_but_changed;
}

/* ************************************************************
	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,Cast *cast)
{ 
  float retval=0.;
  float osize1=1.-cast->osize;
  float isize1=1.-cast->isize;
  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-ffloor(x);
  y=y-ffloor(y);

  if ((x<=cast->osize && x>=osize1) &&
      (y<=cast->osize && y>=osize1)) {

    if ((x<=cast->isize && x>=isize1) &&
	(y<=cast->isize && y>=isize1)) {
      if (cast->multicol)
	retval= parity>0 ? 0.25 : 0.75;
    } else
      retval=1.;
  }
  return retval;
}




float calc_tri_value(float x,float y,Cast *cast)
{
  float retval=0.;
  float osize1=1.-cast->osize;
  float isize1=1.-cast->isize;
  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-ffloor(x);
  y=y-ffloor(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 (cast->multicol) 
	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 (cast->multicol)
	retval=(parity<0) ? 0.75 : 0.25;
    } else
      retval=1.;
  } 
  return retval;
}




#define SHIFT(type,a,b,c) {type _shift=(a);a=(b);b=(c);c=_shift;}

float calc_hex_value(float x,float y,Cast *cast)
{
  float retval=0.;
  float osize1=1.-cast->osize;
  float isize1=1.-cast->isize;
  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-ffloor(x/3)*3;
  if (x>1.5) x=3.-x;
  
  tf=ffloor(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=(cast->osize-x)*SQRT3;
  yi=(cast->isize-x)*SQRT3;
  if (y<=yo && y<=cast->osize*SQRT3_2) {
    if (y<=yi && y<=cast->isize*SQRT3_2) {
      if (cast->multicol) 
	retval=cols[coli[0]];
    } else
      retval=1.;
  } 

  yo=((2.-cast->osize)-x)*SQRT3;
  yi=((2.-cast->isize)-x)*SQRT3;
  if (y>yo && y>osize1_s3_2) {
    if (y>yi && y>isize1_s3_2) {
      if (cast->multicol) 
	retval=cols[coli[1]];
    } else
      retval=1.;
  } 

  return retval;
}

typedef float (*calc_func_t)(float x,float y,Cast *cast);


#if defined(IRIX_WORKAROUND)

int plugin_tex_doit(int stype, Cast *cast, float *texvec, float *dxt, float *dyt)
{
  float x,y;
  static calc_func_t funcs[3]={calc_square_value,calc_tri_value,calc_hex_value};


  if (stype<0 || stype>2) stype=0;

  x=texvec[0];
  y=texvec[1];
  if(cast->noise>0.001) {
    x+= hnoise(cast->noise, texvec[0], texvec[1], texvec[2]);
    y+= hnoise(cast->noise, texvec[1], texvec[2], texvec[0]);
  }
#if defined(SQUARES)
  result[0]=calc_square_value(x,y,cast);
  if (!cast->noaalias && dxt && dyt) {
    float offx=fabs(dxt[0])+fabs(dxt[1]);
    float offy=fabs(dyt[0])+fabs(dyt[1]);
    result[0]+=calc_square_value(x+offx,y,cast);
    result[0]+=calc_square_value(x,y+offy,cast);
    result[0]+=calc_square_value(x+offx,y+offy,cast);
    result[0]/=4.0;
  }
#elif defined(TRIANGLES)
  result[0]=calc_triangles_value(x,y,cast);
  if (!cast->noaalias && dxt && dyt) {
    float offx=fabs(dxt[0])+fabs(dxt[1]);
    float offy=fabs(dyt[0])+fabs(dyt[1]);
    result[0]+=calc_triangles_value(x+offx,y,cast);
    result[0]+=calc_triangles_value(x,y+offy,cast);
    result[0]+=calc_triangles_value(x+offx,y+offy,cast);
    result[0]/=4.0;
  }
#elif defined(HEXAGONS)
  result[0]=calc_hexagons_value(x,y,cast);
  if (!cast->noaalias && dxt && dyt) {
    float offx=fabs(dxt[0])+fabs(dxt[1]);
    float offy=fabs(dyt[0])+fabs(dyt[1]);
    result[0]+=calc_hexagons_value(x+offx,y,cast);
    result[0]+=calc_hexagons_value(x,y+offy,cast);
    result[0]+=calc_hexagons_value(x+offx,y+offy,cast);
    result[0]/=4.0;
  }
#endif
  return 0;
}

#else /*IRIX_WORKAROUND*/

int plugin_tex_doit(int stype, Cast *cast, float *texvec, float *dxt, float *dyt)
{
  float x,y;
  static calc_func_t funcs[3]={calc_square_value,calc_tri_value,calc_hex_value};

  if (stype<0 || stype>2) stype=0;

  x=texvec[0];
  y=texvec[1];
  if(cast->noise>0.001) {
    x+= hnoise(cast->noise, texvec[0], texvec[1], texvec[2]);
    y+= hnoise(cast->noise, texvec[1], texvec[2], texvec[0]);
  }
  result[0]=funcs[stype](x,y,cast);
  if (!cast->noaalias && dxt && dyt) {
    float offx=fabs(dxt[0])+fabs(dxt[1]);
    float offy=fabs(dyt[0])+fabs(dyt[1]);
    result[0]+=funcs[stype](x+offx,y,cast);
    result[0]+=funcs[stype](x,y+offy,cast);
    result[0]+=funcs[stype](x+offx,y+offy,cast);
    result[0]/=4.0;
  }

  return 0;
}

#endif



