3MFRACT.C
/****************************************************************************
                  INTERNATIONAL AVS CENTER
	(This disclaimer must remain at the top of all files)
 
WARRANTY DISCLAIMER
 
This module and the files associated with it are distributed free of charge.
It is placed in the public domain and permission is granted for anyone to use,
duplicate, modify, and redistribute it unless otherwise noted.  Some modules
may be copyrighted.  You agree to abide by the conditions also included in
the AVS Licensing Agreement, version 1.0, located in the main module
directory located at the International AVS Center ftp site and to include
the AVS Licensing Agreement when you distribute any files downloaded from 
that site.
 
The International AVS Center, MCNC, the AVS Consortium and the individual
submitting the module and files associated with said module provide absolutely
NO WARRANTY OF ANY KIND with respect to this software.  The entire risk as to
the quality and performance of this software is with the user.  IN NO EVENT
WILL The International AVS Center, MCNC, the AVS Consortium and the individual
submitting the module and files associated with said module BE LIABLE TO
ANYONE FOR ANY DAMAGES ARISING FROM THE USE OF THIS SOFTWARE, INCLUDING,
WITHOUT LIMITATION, DAMAGES RESULTING FROM LOST DATA OR LOST PROFITS, OR ANY
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES.
 
This AVS module and associated files are public domain software unless
otherwise noted.  Permission is hereby granted to do whatever you like with
it, subject to the conditions that may exist in copyrighted materials. Should
you wish to make a contribution toward the improvement, modification, or
general performance of this module, please send us your comments:  why you
liked or disliked it, how you use it, and most important, how it helps your
work. We will receive your comments at avs@ncsc.org.
 
Please send AVS module bug reports to avs@ncsc.org.
 
AUTHOR : Stardent Computer, Inc.
******************************************************************************/
/*
  AUTHOR:	Anonymous
  DATE:		1-31-89
  COMPANY:	Stardent Computers
  PHONE NUMBER:	617-964-1000
  EMAIL:	larryg@stardent.com
 
  This file contains a module for generating mid-point displacement
  [3mfractal[23ms in two- and three-dimensions
 
*/
#include  
#include 
#include 
#include 
 
#define INDEX(p,w,x,y) (*((p)+((x)*(w))+(y)))
#define INDEX3D(p,w,x,y,z) (*((p)+ (((x)*(w))+(y))*(w) + (z) ))
 
float	random();
void	seed_random();
 
[3mfractal[23m_body(output,max_width,pow_ptr)
AVSfield_char	 **output;
int	max_width;
float	*pow_ptr;
{ int		i, j, step, depth, done;
  float		*curr_ptr, *new_ptr, tmp;
  int		curr_width, new_width;
  int		dims[2];
  static int	been_here = 0;
  float		scale[32];
  float		power;
  float		curr_scale;
  static unsigned int	seed;
 
  if(pow_ptr)
    power = *pow_ptr;
  else
    power = 2.0;
 
  if(!been_here || AVSparameter_changed("Reseed"))
  {
      been_here = 1;
      seed = time(0);
  }
  for(i=1;i<32;i++)
    scale[i] = 1.0/pow((float)i,power);
 
  seed_random(seed);
  curr_width = 3;
  curr_ptr = (float *)malloc(curr_width*curr_width*sizeof(float));
  
  INDEX(curr_ptr,curr_width,0,0) = 0.0;
  INDEX(curr_ptr,curr_width,0,2) = 0.0;
  INDEX(curr_ptr,curr_width,2,0) = 0.0;
  INDEX(curr_ptr,curr_width,2,2) = 0.0;
 
  depth = 1;
  curr_scale = scale[depth];
  INDEX(curr_ptr,curr_width,0,1) = 0.5*(INDEX(curr_ptr,curr_width,0,0)+INDEX(curr_ptr,curr_width,0,2))
                                 + random(curr_scale);
  INDEX(curr_ptr,curr_width,1,0) = 0.5*(INDEX(curr_ptr,curr_width,0,0)+INDEX(curr_ptr,curr_width,2,0))
                                 + random(curr_scale);
  INDEX(curr_ptr,curr_width,2,1) = 0.5*(INDEX(curr_ptr,curr_width,2,0)+INDEX(curr_ptr,curr_width,2,2))
                                 + random(curr_scale);
  INDEX(curr_ptr,curr_width,1,2) = 0.5*(INDEX(curr_ptr,curr_width,0,2)+INDEX(curr_ptr,curr_width,2,2))
                                 + random(curr_scale);
  INDEX(curr_ptr,curr_width,1,1) = 0.25*( INDEX(curr_ptr,curr_width,0,1)
					+ INDEX(curr_ptr,curr_width,1,0)
					+ INDEX(curr_ptr,curr_width,2,1)
					+ INDEX(curr_ptr,curr_width,1,2)
					) + random(curr_scale);
 
  /*
   * I am not sure what this interpolation function is.  The bilinear one would obviously be:
   *
   *	4/9	2/9
   *	
   *	2/9	1/9
   *
   */
  depth++;
  curr_scale = scale[depth];
  while(curr_widthdata,curr_ptr,curr_width*curr_width);
 
  free(curr_ptr);
}
 
[3mfractal[23m3d_body(output,max_width,pow_ptr)
AVSfield_char	 **output;
int	max_width;
float	*pow_ptr;
{ int		i, j, k, step, depth, done;
  float		*curr_ptr, *new_ptr, tmp;
  int		curr_width, new_width;
  int		dims[2];
  static int	been_here = 0;
  float		scale[32];
  float		power;
  float		curr_scale;
  static unsigned int	seed;
 
  if(pow_ptr)
    power = *pow_ptr;
  else
    power = 2.0;
 
  if(!been_here || AVSparameter_changed("Reseed"))
  {
      been_here = 1;
      seed = time(0);
  }
  for(i=1;i<32;i++)
    scale[i] = 1.0/pow((float)i,power);
 
  seed_random(seed);
  curr_width = 3;
  curr_ptr = (float *)malloc(curr_width*curr_width*curr_width*sizeof(float));
  
  INDEX3D(curr_ptr,curr_width,0,0,0) = 0.0;
  INDEX3D(curr_ptr,curr_width,0,2,0) = 0.0;
  INDEX3D(curr_ptr,curr_width,2,0,0) = 0.0;
  INDEX3D(curr_ptr,curr_width,2,2,0) = 0.0;
  INDEX3D(curr_ptr,curr_width,0,0,2) = 0.0;
  INDEX3D(curr_ptr,curr_width,0,2,2) = 0.0;
  INDEX3D(curr_ptr,curr_width,2,0,2) = 0.0;
  INDEX3D(curr_ptr,curr_width,2,2,2) = 0.0;
 
  depth = 1;
  curr_scale = scale[depth];
  /* Edges */
  INDEX3D(curr_ptr,curr_width,1,0,0) = random(curr_scale);
  INDEX3D(curr_ptr,curr_width,0,1,0) = random(curr_scale);
  INDEX3D(curr_ptr,curr_width,1,2,0) = random(curr_scale);
  INDEX3D(curr_ptr,curr_width,2,1,0) = random(curr_scale);
  INDEX3D(curr_ptr,curr_width,0,0,1) = random(curr_scale);
  INDEX3D(curr_ptr,curr_width,2,0,1) = random(curr_scale);
  INDEX3D(curr_ptr,curr_width,0,2,1) = random(curr_scale);
  INDEX3D(curr_ptr,curr_width,2,2,1) = random(curr_scale);
  INDEX3D(curr_ptr,curr_width,1,0,2) = random(curr_scale);
  INDEX3D(curr_ptr,curr_width,0,1,2) = random(curr_scale);
  INDEX3D(curr_ptr,curr_width,2,1,2) = random(curr_scale);
  INDEX3D(curr_ptr,curr_width,1,2,2) = random(curr_scale);
 
  /* Faces */
  INDEX3D(curr_ptr,curr_width,1,1,0) = random(curr_scale)
                                     + 0.25*( INDEX3D(curr_ptr,curr_width,0,0,0)
					    + INDEX3D(curr_ptr,curr_width,2,0,0)
					    + INDEX3D(curr_ptr,curr_width,0,2,0)
					    + INDEX3D(curr_ptr,curr_width,2,2,0)
					     );
  INDEX3D(curr_ptr,curr_width,1,0,1)= random(curr_scale)
                                     + 0.25*( INDEX3D(curr_ptr,curr_width,0,0,0)
					    + INDEX3D(curr_ptr,curr_width,2,0,0)
					    + INDEX3D(curr_ptr,curr_width,0,0,2)
					    + INDEX3D(curr_ptr,curr_width,2,0,2)
					     );
  INDEX3D(curr_ptr,curr_width,0,1,1)= random(curr_scale)
                                     + 0.25*( INDEX3D(curr_ptr,curr_width,0,0,0)
					    + INDEX3D(curr_ptr,curr_width,0,0,2)
					    + INDEX3D(curr_ptr,curr_width,0,2,0)
					    + INDEX3D(curr_ptr,curr_width,0,2,2)
					     );
  INDEX3D(curr_ptr,curr_width,2,1,1)= random(curr_scale)
                                     + 0.25*( INDEX3D(curr_ptr,curr_width,2,0,0)
					    + INDEX3D(curr_ptr,curr_width,2,0,2)
					    + INDEX3D(curr_ptr,curr_width,2,2,0)
					    + INDEX3D(curr_ptr,curr_width,2,2,2)
					     );
  INDEX3D(curr_ptr,curr_width,1,2,1)= random(curr_scale)
                                     + 0.25*( INDEX3D(curr_ptr,curr_width,0,2,0)
					    + INDEX3D(curr_ptr,curr_width,2,2,0)
					    + INDEX3D(curr_ptr,curr_width,0,2,2)
					    + INDEX3D(curr_ptr,curr_width,2,2,2)
					     );
  INDEX3D(curr_ptr,curr_width,1,1,2)= random(curr_scale)
                                     + 0.25*( INDEX3D(curr_ptr,curr_width,0,0,2)
					    + INDEX3D(curr_ptr,curr_width,2,0,2)
					    + INDEX3D(curr_ptr,curr_width,0,2,2)
					    + INDEX3D(curr_ptr,curr_width,2,2,2)
					     );
 
  /* Center */
  INDEX3D(curr_ptr,curr_width,1,1,1)= random(curr_scale)
                    + 0.166666667 * ( INDEX3D(curr_ptr,curr_width,0,1,1)
                   		    + INDEX3D(curr_ptr,curr_width,2,1,1)
                   		    + INDEX3D(curr_ptr,curr_width,1,0,1)
                   		    + INDEX3D(curr_ptr,curr_width,1,2,1)
                   		    + INDEX3D(curr_ptr,curr_width,1,1,0)
                   		    + INDEX3D(curr_ptr,curr_width,1,1,2)
				     );
  /*
   * In 3D, the trilinear interpolation function would be:
   *
   *	8/27	4/27		4/27	2/27
   *
   *	4/27	2/27		2/27	1/27
   *
   */
  depth++;
  curr_scale = scale[depth];
  while(curr_widthdata,curr_ptr,curr_width*curr_width*curr_width);
 
  free(curr_ptr);
}
 
/**** Specifications ****/
[3mfractal[23m_spec()
{
    AVSset_module_name("[3mfractal[23m", MODULE_DATA);
    AVScreate_output_port("Output Field", "field 2D scalar byte");
 
    AVSadd_parameter("max width","integer",64,0,512);
    AVSadd_float_parameter("power",2.0,0.0,5.0);
    AVSadd_parameter("Reseed","oneshot",0,0,1);
    AVSset_compute_proc([3mfractal[23m_body);
}
 
[3mfractal[23m3d_spec()
{
    AVSset_module_name("3d [3mfractal[23m", MODULE_DATA);
    AVScreate_output_port("Output Field", "field 3D scalar byte");
 
    AVSadd_parameter("max width","integer",64,0,512);
    AVSadd_float_parameter("power",2.0,0.0,5.0);
    AVSadd_parameter("Reseed","oneshot",0,0,1);
    AVSset_compute_proc([3mfractal[23m3d_body);
}
 
 
int ((*module_list[])()) = {
  [3mfractal[23m_spec, [3mfractal[23m3d_spec,
};
 
AVSinit_modules()
{
    AVSinit_from_module_list(module_list, sizeof(module_list)/sizeof(module_list[0]));
}
 
pack(dst,src,n)
unsigned char	dst[];
float		src[];
int		n;
{ int	i;
  float	max, min;
  float	scale;
 
  max = min = src[0];
  for(i=1;i max)
	max = src[i];
      else if(src[i] < min)
	min = src[i];
  }
  scale = 255.0/(max-min);
  for(i=0;i 0 )
	*idum *= -1;
      ix1=(IC1-(*idum))%M1;
      ix1=(IA1*ix1+IC1)%M1;
      ix2=ix1%M2;
      ix1=(IA1*ix1+IC1)%M1;
      ix3=ix1%M3;
      for(j=1;j<97;j++)
      {   ix1=(IA1*ix1+IC1)%M1;
	  ix2=(IA2*ix2+IC2)%M2;
	  r[j]=(ix1+ix2*RM2)*RM1;
      }
      *idum=1;
  }
  ix1=(IA1*ix1+IC1)%M1;
  ix2=(IA2*ix2+IC2)%M2;
  ix3=(IA3*ix3+IC3)%M3;
  j=1+((97*ix3)/M3);
  if(j>97 || j<1)
  {
      fprintf(stderr,"Bad j in random: %d\n");
      exit(1);
  }
 
  temp=r[j];
  r[j]=(ix1+ix2*RM2)*RM1;
  
  if(debug_random)
    printf("%f\n",temp);
  return temp;
}
 
static int	rand_seed;
 
void
seed_random(seed)
int	seed;
{
    if(seed > 0)
      seed *= -1;
 
    rand_seed = seed;
    i_rand(&rand_seed);
}
 
float
random(scale)
float	scale;
{ float	ftmp;
 
  ftmp = i_rand(&rand_seed);
 
  return scale*(2.0*ftmp-1.0);
}