[Back]


menger.c

/* 
 * Copyright (c) 2000, 2001 Thomas E. Burge.  All rights reserved.
 * 
 * Affine (R) is a registered trademark of Thomas E. Burge
 *
 * THIS SOFTWARE IS DISTRIBUTED "AS-IS" WITHOUT WARRANTY OF ANY KIND
 * AND WITHOUT ANY GUARANTEE OF MERCHANTABILITY OR FITNESS FOR A 
 * PARTICULAR PURPOSE.  
 *
 * In no event shall Thomas E. Burge be liable for any indirect or
 * consequential damages or loss of data resulting from use or performance 
 * of this software.
 * 
 * Permission to use, copy, modify, distribute, and sell this software and 
 * its documentation for any purpose is hereby granted without fee, provided
 * that the following copyright notices and this permission notice appear in
 * all copies of the software and related documentation:
 *
 *                 The Affine (R) Libraries and Tools are 
 *                Copyright (c) 1995-2001 Thomas E. Burge.  
 *                          All rights reserved.
 *         Affine (R) is a registered trademark of Thomas E. Burge.
 *
 * Also refer to any additional requirements presently set by Pixar 
 * in regards to the RenderMan (R) Interface Procedures and Protocol.
 *
 *
 * Affine Menger Fractal Tool
 *
 * FILE:  menger.c
 *
 * DESCRIPTION:  Example procedural DSO for PRMan 3.8.
 *   
 *    Contains:
 *
 *     History:
 *        4-9-01  Added _WIN32 tags and missing init of lod variable. [CBONE01]
 * 
 *    References:
 *
 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ri.h>

#define ADD_COLOR
#define ADD_STATS

typedef struct _DSO_BOUND {
   RtFloat  xmin, xmax, ymin, ymax, zmin, zmax;
} DSO_BOUND;
typedef DSO_BOUND  *PDSO_BOUND;

typedef struct _DSO_PATCH {
   RtFloat  x0, y0, z0;
   RtFloat  x1, y1, z1;
   RtFloat  x2, y2, z2;
   RtFloat  x3, y3, z3;
} DSO_PATCH;
typedef DSO_PATCH  *PDSO_PATCH;

typedef struct _DSO_PROCPRIM {
   RtInt      lod;
   RtInt      remaininglevels;
   DSO_BOUND  bound;
} DSO_PROCPRIM;
typedef DSO_PROCPRIM  *PDSO_PROCPRIM;


#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif

#ifdef _WIN32
#define EXTERN extern _declspec(dllexport)
#else
#define EXTERN extern
#endif
EXTERN RtPointer ConvertParameters(RtString paramstr);
EXTERN RtVoid Subdivide(RtPointer data, RtFloat detail);
EXTERN RtVoid Free(RtPointer data);
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif

/* Do note that these global values should be moved into an instanced
 * structure so that the DSO can be used for more than one object.
 */
#ifdef ADD_COLOR
DSO_BOUND  maxbounds;
#endif

#ifdef ADD_STATS
int allocated = 0;
int last = 0;
int line = 0;
int max = 0;
#endif

RtVoid Child( PDSO_PROCPRIM p, int x, int y, int z )
{
   PDSO_PROCPRIM  data;
   DSO_BOUND      bound; /* note bound does not need to be malloced. */
   RtFloat        xl,yl,zl;

   data = (PDSO_PROCPRIM)malloc( sizeof( DSO_PROCPRIM) );
   if ( !data )
      return;

#ifdef ADD_STATS
   allocated++;
   if ( allocated / 1000 != last )
   {
      if ( allocated>max)
	 max = allocated;
      printf("%d ",allocated);
      last = allocated / 1000;
      if ( line++ > 10 )
      {
	 line = 0;
	 printf("-- %d\n",max);
      }
   }
#endif

   bound = p->bound;

   xl = (bound.xmax - bound.xmin)/3;
   yl = (bound.ymax - bound.ymin)/3;
   zl = (bound.zmax - bound.zmin)/3;
   bound.xmin += xl * x;
   bound.ymin += yl * y;
   bound.zmin += zl * z;
   bound.xmax = bound.xmin + xl;
   bound.ymax = bound.ymin + yl;
   bound.zmax = bound.zmin + zl;

   data->remaininglevels = p->remaininglevels - 1;
   data->bound = bound;
   data->lod = 1;

   RiProcedural( (RtPointer)data, (RtFloat*)&bound, Subdivide, Free );
}


RtVoid Subdivide( RtPointer data, RtFloat levelofdetail )
{
   PDSO_PROCPRIM  p = (PDSO_PROCPRIM)data;


   if ( !p )
      return;

   /* Note that PRMan sets levelofdetail to only integer values and
    * stops decreasing the size once it gets down to 4.0, so it is
    * never less than 4.0.  
    *
    * Testing it a bit more this does actually appear to be true, so as
    * a work around add a lod field to the DSO_PROCPRIM structure
    * as a counter from when levelofdetail equaled 4.0.
    */
#if 0
   if (levelofdetail<4.0)
      printf("lod: %g @ %d\n",levelofdetail, p->remaininglevels);
#endif

   if ( levelofdetail <= 4.0 )
      p->lod--;

   if ( p->remaininglevels && p->lod )
   {
      Child( p, 0, 0, 0 );
      Child( p, 1, 0, 0 );
      Child( p, 2, 0, 0 );
      Child( p, 0, 1, 0 );
      Child( p, 2, 1, 0 );
      Child( p, 0, 2, 0 );
      Child( p, 1, 2, 0 );
      Child( p, 2, 2, 0 );
      Child( p, 0, 0, 1 );
      Child( p, 2, 0, 1 );
      Child( p, 0, 2, 1 );
      Child( p, 2, 2, 1 );
      Child( p, 0, 0, 2 );
      Child( p, 1, 0, 2 );
      Child( p, 2, 0, 2 );
      Child( p, 0, 1, 2 );
      Child( p, 2, 1, 2 );
      Child( p, 0, 2, 2 );
      Child( p, 1, 2, 2 );
      Child( p, 2, 2, 2 );
   }
   else 
   {
#define b (p->bound)
      DSO_PATCH  patch;
#ifdef ADD_COLOR
      RtColor    color;
#endif

#ifdef ADD_COLOR
      color[0] = (b.xmin - maxbounds.xmin)/(maxbounds.xmax - maxbounds.xmin);
      color[1] = (b.ymin - maxbounds.ymin)/(maxbounds.ymax - maxbounds.ymin);
      color[2] = (b.zmin - maxbounds.zmin)/(maxbounds.zmax - maxbounds.zmin);
      RiColor( color );
#endif

      /* Front */
      patch.x0 = b.xmin; patch.y0 = b.ymax; patch.z0 = b.zmin; 
      patch.x1 = b.xmax; patch.y1 = b.ymax; patch.z1 = b.zmin; 
      patch.x2 = b.xmin; patch.y2 = b.ymin; patch.z2 = b.zmin; 
      patch.x3 = b.xmax; patch.y3 = b.ymin; patch.z3 = b.zmin; 
      RiPatch( "bilinear", "P", &patch, RI_NULL );

      /* Left */
      patch.x0 = b.xmin; patch.y0 = b.ymax; patch.z0 = b.zmax; 
      patch.x1 = b.xmin; patch.y1 = b.ymax; patch.z1 = b.zmin; 
      patch.x2 = b.xmin; patch.y2 = b.ymin; patch.z2 = b.zmax; 
      patch.x3 = b.xmin; patch.y3 = b.ymin; patch.z3 = b.zmin; 
      RiPatch( "bilinear", "P", &patch, RI_NULL );

      /* Right */
      patch.x0 = b.xmax; patch.y0 = b.ymax; patch.z0 = b.zmin; 
      patch.x1 = b.xmax; patch.y1 = b.ymax; patch.z1 = b.zmax; 
      patch.x2 = b.xmax; patch.y2 = b.ymin; patch.z2 = b.zmin; 
      patch.x3 = b.xmax; patch.y3 = b.ymin; patch.z3 = b.zmax; 
      RiPatch( "bilinear", "P", &patch, RI_NULL );

      /* Top */
      patch.x0 = b.xmin; patch.y0 = b.ymax; patch.z0 = b.zmax; 
      patch.x1 = b.xmax; patch.y1 = b.ymax; patch.z1 = b.zmax; 
      patch.x2 = b.xmin; patch.y2 = b.ymax; patch.z2 = b.zmin; 
      patch.x3 = b.xmax; patch.y3 = b.ymax; patch.z3 = b.zmin; 
      RiPatch( "bilinear", "P", &patch, RI_NULL );
      
      /* Bottom */
      patch.x0 = b.xmin; patch.y0 = b.ymin; patch.z0 = b.zmin; 
      patch.x1 = b.xmax; patch.y1 = b.ymin; patch.z1 = b.zmin; 
      patch.x2 = b.xmin; patch.y2 = b.ymin; patch.z2 = b.zmax; 
      patch.x3 = b.xmax; patch.y3 = b.ymin; patch.z3 = b.zmax; 
      RiPatch( "bilinear", "P", &patch, RI_NULL );
      
      /* Back */
      patch.x0 = b.xmax; patch.y0 = b.ymax; patch.z0 = b.zmax; 
      patch.x1 = b.xmin; patch.y1 = b.ymax; patch.z1 = b.zmax; 
      patch.x2 = b.xmax; patch.y2 = b.ymin; patch.z2 = b.zmax; 
      patch.x3 = b.xmin; patch.y3 = b.ymin; patch.z3 = b.zmax; 
      RiPatch( "bilinear", "P", &patch, RI_NULL );
   }
}


RtVoid Free( RtPointer data )
{
   (void)data;
   
   if (data)
   {
#ifdef ADD_STATS
      allocated--;
#endif
      free( data );
   }
}


RtPointer ConvertParameters( RtString initialstring )
{
   PDSO_PROCPRIM  p;
   int  n;

   p = (PDSO_PROCPRIM)malloc( sizeof( DSO_PROCPRIM) );
   if ( !p )
      return NULL;

   p->lod = -1;

   n = sscanf( initialstring,
	       "%d %g %g %g %g %g %g\n",
	       &(p->remaininglevels), 
	       &(p->bound.xmin), &(p->bound.xmax), 
	       &(p->bound.ymin), &(p->bound.ymax), 
	       &(p->bound.zmin), &(p->bound.zmax) );
   if ( n != 7 )
   {
      free( p );
      return NULL;
   }

#ifdef ADD_COLOR
   maxbounds = p->bound;
#endif

#ifdef ADD_STATS
   allocated = 0;
   last = 0;
   line = 0;
   max = 0;
#endif

   return (RtPointer)p;
}


Makefile.win

#
#  Contrib:  Chris Bone 4-9-01 
#  Description:  Makefile for Windows provided here untested right now, except by Chris Bone.
#
menger.dll: menger.obj
    link.exe prman.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /machine:I386 /out:"menger.dll" /implib:"menger.lib" /libpath:"$(RMANTREE)/lib" menger.obj

menger.obj: menger.c

.c.obj::
   cl.exe /nologo /MT /W3 /GX /O2 /I "$(RMANTREE)/include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /YX /FD /c $< 

Makefile.win BMRT2.6

# 
# BMRT 2.6 seems to use the Unix .so naming convention.  
#
menger.so: menger.obj 
    link.exe rendrib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib \ 
        advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib \ 
        odbccp32.lib /nologo /dll /incremental:no /machine:I386 /out:"menger.so" \ 
        /implib:"menger.lib" /libpath:"$(RMANTREE)/lib" menger.obj 

menger.obj: menger.c 

.c.obj:: 
   cl.exe /o menger.so /nologo /MT /W3 /GX /O2 /I "$(RMANTREE)/include" /D "WIN32" /D "NDEBUG" \
   	/D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /YX /FD /c $<

Makefile

# $RCSfile$  $Revision$ $Date$
# 
# Copyright (c) 2000 Thomas E. Burge.  All rights reserved.
# 
# Affine (R) is a registered trademark of Thomas E. Burge
#
# THIS SOFTWARE IS DISTRIBUTED "AS-IS" WITHOUT WARRANTY OF ANY KIND
# AND WITHOUT ANY GUARANTEE OF MERCHANTABILITY OR FITNESS FOR A 
# PARTICULAR PURPOSE.  
#
# In no event shall Thomas E. Burge be liable for any indirect or
# consequential damages or loss of data resulting from use or performance 
# of this software.
# 
# Permission to use, copy, modify, distribute, and sell this software and 
# its documentation for any purpose is hereby granted without fee, provided
# that the following copyright notices and this permission notice appear in
# all copies of the software and related documentation:
#
#                 The Affine (R) Libraries and Tools are 
#     Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000 Thomas E. Burge.  
#                          All rights reserved.
#         Affine (R) is a registered trademark of Thomas E. Burge.
#
# Also refer to any additional requirements presently set by Pixar 
# in regards to the RenderMan (R) Interface Procedures and Protocol.
#
# 
# Affine Toolkit
#
# FILE:  Makefile for Unix systems.  Refer to ../config.mak for 
#        compiler flags that may differ between flavors of Unix.
#
# PROGRAMS/LIBRARIES:  cellbasis.so cellnoiseDSO.so
#
#
#
TOP=../..

#Put all the compiler and linker flags in one place:
include ${TOP}/config.mak

TARGETPATH= ../lib
INCPATHS= -I. -I${TOP}/../../bmrt/include
LIBPATHS= -L${TOP}/lib 
LIBS=
HEADERS=
COPTS=

all:    menger.so

clean:
	-rm ./menger.so ./dsoproc.so

menger.so: menger.o Makefile
	ld ${LFLAGS32} ${DSOLFLAGS} -o menger.so menger.o 


config.mak.sun

CC= cc
CFLAGS= -g ${INCPATHS}
CFLAGS32= 
LFLAGS32= 
DSOLFLAGS=-G
COPTS=

AR= ar rc

.c.o:
	${CC} -c $< ${CFLAGS} ${CFLAGS32} ${COPTS} ${INCPATH} 


menger.rib

##RenderMan RIB
version 3.03
Option "statistics" "endofframe" [3]
Display "menger.tif" "framebuffer" "rgba"
#Display "menger.tif" "file" "rgba"
Format 512 512 1
Clipping 1 100
Projection "perspective" "fov" [18]
Translate 0 0 10
Rotate -15 1 0 0
Rotate 30 0 1 0
WorldBegin
LightSource "distantlight" 1 "intensity" [1] "from" [10 5 -10]
LightSource "ambientlight" 1 "intensity" [0.1]
Surface "plastic" 
Procedural "DynamicLoad"
           [ "menger.so" "2 -1 1  -1 1  -1 1" ]
           [ -1 1 -1 1 -1 1 ]
WorldEnd


[Affine Toolkit]
[RIB Utilities] [Bitmap Utilities] [Handy Little Utilities]
[Libraries] [Using the Libraries]