[Back]
cellbasis.c
/*
* Copyright (c) 1999-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 Toolkit
*
* FILE: cellbasis.c
*
* DESCRIPTION: Example shadeop DSO for PRMan 3.8.
*
* Contains:
*
* History:
*
* References:
* [PIXA98] Pixar, rnotes-3.8.html#shadedsos, Version 3.8,
* Richmond, CA, 1998.
* [WORL96] Worley, Steven, A Cellular Texture Basis Function,
* SIGGRAPH 96 Conference Proceedings, Addison Wesley,
* 1996, pp. 291-294.
*
*
* The RenderMan (R) Interface Procedures and Protocol are:
* Copyright 1988, 1989, Pixar
* All Rights Reserved
*
* Renderman (R) is a registered trademark of Pixar
*/
#include <stdio.h>
#include <string.h>
#include <math.h>
/*Uncomment this to build BMRT 2.6*/
/*#define BMRT2_6*/
#ifndef BMRT2_6
#include <shadeop.h>
#else
typedef struct _SHADEOP_SPEC {
char *declaration; /* if zero length string, end of table signaled. */
char *initfunctionname; /* optional */
char *cleanupfunctionname;/* optional */
} SHADEOP_SPEC;
#endif
typedef struct _point {
float x;
float y;
float z;
} point;
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
#ifdef _WIN32
#define EXTERN extern _declspec(dllexport)
#else
#define EXTERN extern
#endif
EXTERN SHADEOP_SPEC cellbasis_shadeops[];
/* For BMRT 2.6 intelnt the following export for functions
* named in the shadeops[] table is needed. Otherwise you get
* the behavior with BMRT 2.6.0.-18 intelnt of slc working
* fine and even the RIB rendering without any messages, but
* yet the code in the shaderop that should be called
* is never run during the rendering.
*/
EXTERN int cellbasis( void *initdata, int argc, void *argv[] );
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif
#ifndef BMRT2_6
/*SHADEOP_TABLE(cellbasis) = {*/
SHADEOP_SPEC cellbasis_shadeops[] = {
/* Do not use "output" in "float cellbasis(point, output float,...)"
* because "output" never allows a shader to match types and the
* argv[] pointers allow changes to the data anyway.
*
* Using arrays on the parameter list is not liked by the compiler:
*
* ...,{ "void cellbasis(point, float, point[], float[])", "", "", },
* or
* ...,{ "void cellbasis(point, float, point[9], float[9])", "", "", },
*
* Using a return type of "void" compiles but causes the following error
* when prman is used:
* S05001 Shadeop error: argument types clash in op calldso at pc 6
* in "callCellBasis". (WARNING)
* So use a return type of "float" and just ignore argv[0].
*/
{ "float cellbasis(point, "\
"point, float)", "", "", },
{ "float cellbasis(point, "\
"point, float, point, float)", "", "", },
{ "float cellbasis(point, "\
"point, float, point, float, point, float)", "", "", },
{ "float cellbasis(point, "\
"point, float, point, float, point, float, point, float)", "", "", },
{ "", "", "", }
};
#else
/* The following was tested on 2.6.0.-18 intelnt */
/* I haven't yet checked the limitations mentioned above against this
* version of BMRT.
*/
SHADEOP_SPEC cellbasis_shadeops[] = {
{ "float cellbasis(point, point, float)", "", "", },
{ "float cellbasis(point, "\
"point, float, point, float)", "", "", },
{ "float cellbasis(point, "\
"point, float, point, float, point, float)", "", "", },
{ "float cellbasis(point, "\
"point, float, point, float, point, float, point, float)", "", "", },
{ "", "", "", }
};
#endif
#define xcomp(/* point* */ p) ((p)->x)
#define ycomp(/* point* */ p) ((p)->y)
#define zcomp(/* point* */ p) ((p)->z)
float distance( point *p1, point *p2 )
{
point v;
v.x = p1->x - p2->x;
v.y = p1->y - p2->y;
v.z = p1->z - p2->z;
return (float)sqrt( v.x*v.x + v.y*v.y + v.z*v.z );
}
static unsigned int idum=1;
void scellnoise(unsigned int seed)
{
idum = seed;
}
int intcellnoise( int max )
{
/* Numerical Recipes in C, Second Edition, page 284. */
idum = 1664525*idum + 1013904223;
max++;
return idum % max;
}
float cellnoise()
{
float f;
/* Numerical Recipes in C, Second Edition, page 284. */
idum = 1664525*idum + 1013904223;
f = (float)idum / (float)0xffffffff;
return f;
}
#define Swap( p1, p2, f1, f2 ) \
{ \
point SwapP; \
float SwapF; \
\
SwapP = p1; \
SwapF = f1; \
p1 = p2; \
f1 = f2; \
p2 = SwapP; \
f2 = SwapF; \
}
void FindFeaturePoints( int n, point *P, int i, int j, int k,
point featurepoints[],
float distances[] )
{
int s = 0;
int npoints;
float dist;
point p;
int a,b;
/* Set seed for random numbers. */
scellnoise(541*i + 79*j + (31*k)%999983);
npoints = intcellnoise(5) + 4; /* npoints is a member of {4..9}. */
for ( s=0; s < npoints; s++ ) {
p.x = i+cellnoise();
p.y = j+cellnoise();
p.z = k+cellnoise();
dist = distance( &p, P );
for ( a=0; a < n; a+=1 ) {
if ( dist < distances[a] )
break;
}
for ( b=a; b < n; b+=1 ) {
Swap( p, featurepoints[b], dist, distances[b] );
}
}
}
/* Checking bounds gives a huge performance boost, but if nF gets
* greater than 4 when there are 9 points per cell the DIST bounds
* needs to be lowered.
* Note that a fancy mechanism based on the density of feature points
* in a cell could be used to automate the calculation of a good
* bounding scheme.
*/
#define DIST 0.5
int cellbasis( void *initdata, int argc, void *argv[] )
{
int nF;
int i,j,k;
float x,y,z;
float xn,yn,zn;
float largedistances[9] = {1e5,1e5,1e5,1e5,1e5,1e5,1e5,1e5,1e5};
float distances[9] = {1e5,1e5,1e5,1e5,1e5,1e5,1e5,1e5,1e5};
point featurepoints[9];
point *P;
switch (argc) {
case 4:
nF = 1;
break;
case 6:
nF = 2;
break;
case 8:
nF = 3;
break;
case 10:
nF = 4;
break;
default:
return 1;
}
P = argv[1];
x = xcomp(P);
y = ycomp(P);
z = zcomp(P);
i = (int)floor(x);
j = (int)floor(y);
k = (int)floor(z);
xn = x - i;
yn = y - j;
zn = z - k;
memcpy( distances, largedistances, nF * sizeof(float ) );
FindFeaturePoints( nF, P, i, j, k, featurepoints,distances );
#if 1
/* Cheap bounding scheme used here. */
if ( zn <= DIST )
{
FindFeaturePoints( nF, P, i, j, k-1, featurepoints,distances );
if ( yn <= DIST )
{
FindFeaturePoints( nF, P, i, j-1, k-1, featurepoints,distances );
FindFeaturePoints( nF, P, i, j-1, k, featurepoints,distances );
}
else
{
FindFeaturePoints( nF, P, i, j+1, k-1, featurepoints,distances );
FindFeaturePoints( nF, P, i, j+1, k, featurepoints,distances );
}
if ( xn <= DIST )
{
FindFeaturePoints( nF, P, i-1, j, k-1, featurepoints,distances );
FindFeaturePoints( nF, P, i-1, j, k, featurepoints,distances );
if ( yn <= DIST )
{
FindFeaturePoints( nF, P, i-1, j-1, k-1, featurepoints,distances );
FindFeaturePoints( nF, P, i-1, j-1, k, featurepoints,distances );
}
else
{
FindFeaturePoints( nF, P, i-1, j+1, k-1, featurepoints,distances );
FindFeaturePoints( nF, P, i-1, j+1, k, featurepoints,distances );
}
}
else
{
FindFeaturePoints( nF, P, i+1, j, k-1, featurepoints,distances );
FindFeaturePoints( nF, P, i+1, j, k, featurepoints,distances );
if ( yn <= DIST )
{
FindFeaturePoints( nF, P, i+1, j-1, k-1, featurepoints,distances );
FindFeaturePoints( nF, P, i+1, j-1, k, featurepoints,distances );
}
else
{
FindFeaturePoints( nF, P, i+1, j+1, k-1, featurepoints,distances );
FindFeaturePoints( nF, P, i+1, j+1, k, featurepoints,distances );
}
}
}
else
{
FindFeaturePoints( nF, P, i, j, k+1, featurepoints,distances );
if ( yn <= DIST )
{
FindFeaturePoints( nF, P, i, j-1, k+1, featurepoints,distances );
FindFeaturePoints( nF, P, i, j-1, k, featurepoints,distances );
}
else
{
FindFeaturePoints( nF, P, i, j+1, k+1, featurepoints,distances );
FindFeaturePoints( nF, P, i, j+1, k, featurepoints,distances );
}
if ( xn <= DIST )
{
FindFeaturePoints( nF, P, i-1, j, k+1, featurepoints,distances );
FindFeaturePoints( nF, P, i-1, j, k, featurepoints,distances );
if ( yn <= DIST )
{
FindFeaturePoints( nF, P, i-1, j-1, k+1, featurepoints,distances );
FindFeaturePoints( nF, P, i-1, j-1, k, featurepoints,distances );
}
else
{
FindFeaturePoints( nF, P, i-1, j+1, k+1, featurepoints,distances );
FindFeaturePoints( nF, P, i-1, j+1, k, featurepoints,distances );
}
}
else
{
FindFeaturePoints( nF, P, i+1, j, k+1, featurepoints,distances );
FindFeaturePoints( nF, P, i+1, j, k, featurepoints,distances );
if ( yn <= DIST )
{
FindFeaturePoints( nF, P, i+1, j-1, k+1, featurepoints,distances );
FindFeaturePoints( nF, P, i+1, j-1, k, featurepoints,distances );
}
else
{
FindFeaturePoints( nF, P, i+1, j+1, k+1, featurepoints,distances );
FindFeaturePoints( nF, P, i+1, j+1, k, featurepoints,distances );
}
}
}
#else
FindFeaturePoints( nF, P, i, j-1, k-1, featurepoints, distances );
FindFeaturePoints( nF, P, i, j, k-1, featurepoints, distances );
FindFeaturePoints( nF, P, i, j+1, k-1, featurepoints, distances );
FindFeaturePoints( nF, P, i-1, j-1, k-1, featurepoints, distances );
FindFeaturePoints( nF, P, i-1, j, k-1, featurepoints, distances );
FindFeaturePoints( nF, P, i-1, j+1, k-1, featurepoints, distances );
FindFeaturePoints( nF, P, i+1, j-1, k-1, featurepoints, distances );
FindFeaturePoints( nF, P, i+1, j, k-1, featurepoints, distances );
FindFeaturePoints( nF, P, i+1, j+1, k-1, featurepoints, distances );
FindFeaturePoints( nF, P, i, j-1, k, featurepoints, distances );
FindFeaturePoints( nF, P, i, j+1, k, featurepoints, distances );
FindFeaturePoints( nF, P, i-1, j-1, k, featurepoints, distances );
FindFeaturePoints( nF, P, i-1, j, k, featurepoints, distances );
FindFeaturePoints( nF, P, i-1, j+1, k, featurepoints, distances );
FindFeaturePoints( nF, P, i+1, j-1, k, featurepoints, distances );
FindFeaturePoints( nF, P, i+1, j, k, featurepoints, distances );
FindFeaturePoints( nF, P, i+1, j+1, k, featurepoints, distances );
FindFeaturePoints( nF, P, i, j-1, k+1, featurepoints, distances );
FindFeaturePoints( nF, P, i, j, k+1, featurepoints, distances );
FindFeaturePoints( nF, P, i, j+1, k+1, featurepoints, distances );
FindFeaturePoints( nF, P, i-1, j-1, k+1, featurepoints, distances );
FindFeaturePoints( nF, P, i-1, j, k+1, featurepoints, distances );
FindFeaturePoints( nF, P, i-1, j+1, k+1, featurepoints, distances );
FindFeaturePoints( nF, P, i+1, j-1, k+1, featurepoints, distances );
FindFeaturePoints( nF, P, i+1, j, k+1, featurepoints, distances );
FindFeaturePoints( nF, P, i+1, j+1, k+1, featurepoints, distances );
#endif
switch (nF) {
case 4:
*((float*)argv[9]) = distances[3];
*((point*)argv[8]) = featurepoints[3];
/* fall through */
case 3:
*((float*)argv[7]) = distances[2];
*((point*)argv[6]) = featurepoints[2];
/* fall through */
case 2:
*((float*)argv[5]) = distances[1];
*((point*)argv[4]) = featurepoints[1];
/* fall through */
case 1:
*((float*)argv[3]) = distances[0];
*((point*)argv[2]) = featurepoints[0];
}
#ifdef DEBUG
for (i=0;i < 9;i++)
printf("d:%g (%f,%f,%f)\n",distances[i],featurepoints[i].x,
featurepoints[i].y,featurepoints[i].z);
#endif
return 0;
}
tebVoronoiDSO.sl
/*
* Copyright (c) 1999 Thomas E. Burge. All rights reserved.
*
*
* FILE: tebVoronoiDSO.sl
*
*
* DESCRIPTION:
*
* Using the cellbasis DSO can double the speed over using the same code
* in the SL version tebVoronoi.sl.
*
* References:
* [WORL96] Worley, Steven, A Cellular Texture Basis Function,
* SIGGRAPH 96 Conference Proceedings, Addison Wesley,
* 1996, pp. 291-294.
*
*/
surface tebVoronoiDSO( uniform float Ka = 1.0;
uniform float Kd = .5;
/* cellbasistype can be assigned one of the following:
* "voronoi", "medialaxis", "F1", "F2", "F3", "F4",
* or "edgedvoronoi".
* voronoi == F1
* medialaxis == F2 -- has a medial-axis diagram "look"
* edgedvoronoi == F2 - F1
*/
uniform string cellbasistype = "voronoi";
)
{
normal Nf;
color Ct;
point p1=0;
point p2=0;
point p3=0;
point p4=0;
float d1=0;
float d2=0;
float d3=0;
float d4=0;
if ( cellbasistype=="voronoi" || cellbasistype=="F1" )
{
cellbasis( P, p1, d1 );
Ct = d1;
}
else if ( cellbasistype=="medialaxis" || cellbasistype=="F2" )
{
cellbasis( P, p1, d1, p2, d2 );
Ct = d2;
}
else if ( cellbasistype=="F3" )
{
cellbasis( P, p1, d1, p2, d2, p3, d3 );
Ct = d3;
}
else if ( cellbasistype=="F4" )
{
cellbasis( P, p1, d1, p2, d2, p3, d3, p4, d4 );
Ct = d4;
}
else if ( cellbasistype=="edgedvoronoi" )
{
cellbasis( P, p1, d1, p2, d2 );
Ct = d2 - d1;
}
else
Ct = 0.0;
Nf = faceforward( normalize(N), I );
Ci = Os * ( Cs * Ct * (Ka*ambient()+Kd*diffuse(Nf)) );
Oi = Os;
}
Makefile
#
# Use this only with PRMan 3.8.
#
.SUFFIXES: .sl .slo .rib .tif
INCPATHS= -I. -I/usr/local/prman/include
LIBPATHS= -L/usr/local/prman/lib
# For SGI C compiler:
CC=cc
CFLAGS= -g -ansi -fullwarn ${INCPATHS}
CFLAGS32= -n32 -mips4
LFLAGS32= -n32 -mips4
.c.o:
${CC} -n32 -mips3 -c $< ${INCPATHS}
.sl.slo:
shader $<
.rib.tif:
prman $<
all: cellbasis.so tebVoronoiDSO.slo tebVoronoi.slo
clean:
-rm ./cellbasis.so cellbasis.o so_locations \
tebVoronoi.slo tebVoronoiDSO.slo
cellbasis.so: cellbasis.o Makefile
ld -n32 -mips3 -shared -o cellbasis.so cellbasis.o
tebVoronoiDSO.slo: tebVoronoiDSO.sl Makefile cellbasis.so
tebVoronoi.slo: tebVoronoi.sl Makefile
cellbasis.mak (Windows VC++6.0 nmake)
#
# BMRT 2.6 seems to use the Unix .so naming convention.
#
cellbasis.so: cellbasis.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:"cellbasis.so" \
/implib:"cellbasis.lib" /libpath:"$(RMANTREE)/lib" cellbasis.obj
cellbasis.obj: cellbasis.c
.c.obj::
cl.exe /o cellbasis.so /nologo /MT /W3 /GX /O2 /I "$(RMANTREE)/include" /D "WIN32" /D "NDEBUG" \
/D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /YX /FD /c $<
[Affine Toolkit]
[RIB Utilities]
[Bitmap Utilities]
[Handy Little Utilities]
[Libraries]
[Using the Libraries]