 /*fold00*/
/* Copyright (c) 2004, Sylvio Sell - maitag
 *
 * lyapunov.c
 *
 * blender plugin for generating lyapunov fat fractals.
 *
 * (source written/compiled by Sylvio Sell , december 2004)
 *
 * Contact:      semmi@maitag.de
 * Information:  http://www.maitag.de
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 */

#include "math.h" /*fold00*/
#include "plugin.h"

#define NR_TYPES 4


float result[8];
float cfra;

/* plugin menu and variables******************************************* */

char name[]= "Lyapunovs fat fractals";
char stnames[NR_TYPES][16]= {"pos","neg","all","rgb"};

VarStruct varstr[]= { /*fold00*/
	/* butcode,	name,		default, min,   max	tooltips comment*/
	{   TOG|INT,	"inverse",        0,  	 0,	1,   "inverse output"},
	{   NUM|INT,	"it",           10,	 10,   500,  "Number of main-iterations (realism of dynamic system simmulation)"},
	{   NUM|INT,	"ip",		3,	 0,    300,  "Number of pre-iterations, (randomize startpoint of dynamic system) "},
	{   NUM|FLO,	"x ",		0.0,	-20,	20, "move fractal in x direction"},
	{   NUM|FLO,	"y ",		0.0,	-20,	20, "move fractal in y direction"},
	{   NUM|FLO,	"z ",		0.0,	-20,	20, "move fractal in z direction"},

	{   NUM|FLO,	"r:",		1,	0, 1, "rgb-mode: red color for a negative index"},
	{   NUM|FLO,	"g:",		0,	0, 1, "rgb-mode: green color for a negative index"},
	{   NUM|FLO,	"b:",		0,	0, 1, "rgb-mode: blue color for a negative index"},
	{   NUM|FLO,	"sx ",		1.0,	-20.0, 20, "scale fractal in x direction (negative values have a mirror-effect)"},
	{   NUM|FLO,	"sy ",		1.0,	-20.0, 20, "scale fractal in y direction (negative values have a mirror-effect)"},
	{   NUM|FLO,	"sz ",		1.0,	-20.0, 20, "scale fractal in z direction (negative values have a mirror-effect)"},

	{   NUM|FLO,	"r:",		0,	0, 1, "rgb-mode: red color for a index near null"},
	{   NUM|FLO,	"g:",		0,	0, 1, "rgb-mode: green color for a index near null"},
	{   NUM|FLO,	"b:",		0,	0, 1, "rgb-mode: blue color for a index near null"},
	{   NUM|FLO,	"x0:",		0,	-20, 20, "start-value for the iterated variable of dynamic function"},
	{   NUM|FLO,	"p1:",		2.5,	-20, 20, "first constant parameter in iteration function"},
	{   NUM|FLO,	"p2:",		0,	-20, 20, "second constant parameter in iteration function"},

	{   NUM|FLO,	"r:",		0,	0, 1, "rgb-mode: red color for a positive index"},
	{   NUM|FLO,	"g:",		0,	0, 1, "rgb-mode: green color for a positive index"},
	{   NUM|FLO,	"b:",		1,	0, 1, "rgb-mode: blue color for a positive index"},
	{   LABEL,	"2002 by",	0,	0, 0,  "codet on 07 december 2004 by Sylvio Sell"},
	{   LABEL,	"Sylvio Sell",	0,	0, 0,  "mail to semmi@maitag.de for questions"},
	{   LABEL,	"maitag.de",	0,      0, 0,  "look at my website for updates: www.maitag.de -> projects"},
};
typedef struct Cast {
    int inv,it,ip;
    float x,y,z,  r0,g0,b0,sx,sy,sz,   r1,g1,b1,x0,p1,p2,   r2,g2,b2,dum5,dum6,dum7;
} Cast;

/* ******************************************************************* */

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

int plugin_tex_getversion(void)  /*fold00*/
{
	return B_PLUGIN_VERSION;
}

void plugin_but_changed(int but)  /*fold00*/
{
}

void plugin_init(void) /*fold00*/
{
}

void plugin_getinfo(PluginInfo *info) /*fold00*/
{
	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;
}

int plugin_tex_doit(int stype, Cast *cast, float *texvec, float *dxt, float *dyt) /*fold00*/
{

    float a,b,c;
    float index;
    float x,ableitung;
    int i,it1,modus;

    a= (texvec[0] + -cast->x) * cast->sx;
    b= (texvec[1] + -cast->y) * cast->sy;
    c= (texvec[2] + cast->z) * cast->sz;

    x=cast->x0;
    /* pre-iteration */
    for(i=0;i < cast->ip;i++)
    {
	x=cast->p1*sin(x+a)*sin(x+a)+cast->p2;
        x=cast->p1*sin(x+b)*sin(x+b)+cast->p2;
	x=cast->p1*sin(x+c)*sin(x+c)+cast->p2;
    }
    /* main-iteration */
    index=0;it1=0;
    for(i = 0; i < cast->it; i++)
    {
	x=cast->p1*sin(x+a)*sin(x+a)+cast->p2;  ableitung=2*cast->p1*sin(x+a)*cos(x+a);
	if (ableitung!=0) {index=index+log(fabs(ableitung));it1++;}

	x=cast->p1*sin(x+b)*sin(x+b)+cast->p2;  ableitung=2*cast->p1*sin(x+b)*cos(x+b);
	if (ableitung!=0) {index=index+log(fabs(ableitung));it1++;}

        x=cast->p1*sin(x+c)*sin(x+c)+cast->p2;  ableitung=2*cast->p1*sin(x+c)*cos(x+c);
	if (ableitung!=0) {index=index+log(fabs(ableitung));it1++;}

    }
    index=index/(float)(it1);

    if(stype<=1)
    {
	if (stype==1) {index=0-index;}
        if (index<0) index=0.0;
	if (index>1) index=1.0;
	if(cast->inv) {index=1-index;}
        modus=0;
	result[0] = index;
    }
    if(stype==2)
    {
        index=fabs(index);
        if(index>1) index=1;
	if(cast->inv) {index=1-index;}
	modus=0;
        result[0]=index;
    }
    if(stype==3)
    {   if(cast->inv) {index=0-index;}
	if(index<0)
	{
	    if(index<-1) {index=-1;}
	    // index=0-index;
	    result[1]=(cast->r1 - cast->r0)*index+cast->r1;
	    result[2]=(cast->g1 - cast->g0)*index+cast->g1;;
            result[3]=(cast->b1 - cast->b0)*index+cast->b1;;
	}
	else
	{
	    if(index>1) {index=1;}
	    result[1]=(cast->r2 - cast->r1)*index+cast->r1;
	    result[2]=(cast->g2 - cast->g1)*index+cast->g1;;
            result[3]=(cast->b2 - cast->b1)*index+cast->b1;;
	}

        modus=1;
    }

    result[4] = 1.0;

    return (modus);

}

