ABERDEEN SHANG
  • MY CHANNEL
  • Personal Projects
  • GAME REEL
  • Blogs
    • Mentor Project
    • MatchtoLive
    • VSFX 755 Class Blog >
      • C: debris procedural primitive
      • C++: side-mask pattern node
      • OSL: renderman moom shading
  • Other Art Works
  • About
  • Award
/*
GenSaturnRingsProc.cpp
 
A relatively simple example of a RiProcedural. For info see,
https://rmanwiki.pixar.com/display/REN22/Procedural+Primitives
 
In Cutter, make the DSO using the keyboard shortcut Alt+e or Control+e.
In Maya, select the RenderMan menu and choose,
                Archive->Create Procedual Node
In Maya's attribute editor,
                browse for the DSO ("DSO Name"),
                enter this text into the "Data" field "200 0.2"
Assign a material, say, PxrConstant and render the scene. Image Tool
will display an image consisting of 200 small spheres.
 
M.A.Kesson
Jan 13 2019
*/
 
#include <ri.h>
#include <RixInterfaces.h>
#include <RiTypesHelper.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#define DEFAULT_RAD 1
#define DEFAULT_NUM 1
#define DEFAULT_INRAD 1
#define DEFAULT_OUTRAD 2
#define DEFAULT_H1 2
#define DEFAULT_H2 -1
#define DEFAULT_OFFSETX 0.1
#define DEFAULT_OFFSETZ 0.1
#define DEFAULT_DIS 1
 
// A RiProcedural must implement these functions. This is a fixed requirement.
extern "C"
{
                PRMANEXPORT RtPointer ConvertParameters ( RtString paramStr              );
                PRMANEXPORT RtVoid    Subdivide         ( RtPointer data, RtFloat detail );
                PRMANEXPORT RtVoid    Free              ( RtPointer data                 );
}
 
// A custom data structure for defining an arbitrary number of spheres
typedef struct {
                RtFloat radius;
                RtInt      num;
                RtFloat inner_radius;
                RtFloat outer_radius;
                RtFloat h1;
                RtFloat h2;
                RtFloat offsetx;
                RtFloat offsetz;
                RtFloat disintegration;
                } SpheresData;
 
// Declare our utility functions...              
RtFloat randBetween(RtFloat min, RtFloat max);
 
// ----------------------------------------------------
// A RiProcedural required function
// ----------------------------------------------------
// stderr strpbrk remainder
 
RtPointer ConvertParameters(RtString paramStr) {
                // Allocate a block of memory to store one instance of our custom data structure.
                SpheresData *dataPtr = (SpheresData*)malloc(sizeof(SpheresData));
               
                // The user has forgotten to specify the number and size of the spheres in the
                // RenderManProcedural's data text field - so we use our default values.
                if(paramStr == NULL || strlen(paramStr) == 0) {
                                dataPtr->radius = DEFAULT_RAD;
                                dataPtr->num = DEFAULT_NUM;
                                dataPtr->num = DEFAULT_INRAD;
                                dataPtr->num = DEFAULT_OUTRAD;
                                dataPtr->num = DEFAULT_H1;
                                dataPtr->num = DEFAULT_H2;
                                dataPtr->num = DEFAULT_OFFSETX;
                                dataPtr->num = DEFAULT_OFFSETZ;
                                dataPtr->num = DEFAULT_DIS;
                                }
                else
                                // We assume the input string consists of an integer and one float.
                                // For example, "200 0.2".
                                // The sscanf function reads the data from the parameter string, converts
                                // each item to the appropriate datatype and assigns their values to the
                                // appropriate "field" of our custom data structure.
                                sscanf(paramStr, "%d %f %f %f %f %f %f %f %f", &dataPtr->num, &dataPtr->radius,
                                                                                                                                                                                &dataPtr->inner_radius, &dataPtr->outer_radius,
                                                                                                                                                                                &dataPtr->h1, &dataPtr->h2,
                                                                                                                                                                                &dataPtr->offsetx, &dataPtr->offsetz, &dataPtr->disintegration);
                return (RtPointer)dataPtr;
}
 
// ----------------------------------------------------
// A RiProcedural required function
// ----------------------------------------------------
RtVoid Subdivide(RtPointer data, RtFloat detail) {
    RtFloat radius = ((SpheresData*)data)->radius;
                RtInt      num = ((SpheresData*)data)->num;
                RtFloat inner_radius = ((SpheresData*)data)->inner_radius;
                RtFloat outer_radius = ((SpheresData*)data)->outer_radius;
                RtFloat h1 = ((SpheresData*)data)->h1;
                RtFloat h2 = ((SpheresData*)data)->h2;
                RtFloat offsetx = ((SpheresData*)data)->offsetx;
                RtFloat offsetz = ((SpheresData*)data)->offsetz;
                RtFloat disintegration = ((SpheresData*)data)->disintegration;
                srand(1);
    // Output randomly located spheres
                for(int n = 0; n < num; n++) {
                                RtFloat sr = randBetween(0.1,0.5) * radius;
                                RtFloat x = randBetween(-5,5);
                                RtFloat y = 0;
                                RtFloat z = randBetween(-5,5);
                                RtFloat r = randBetween(inner_radius,outer_radius);
                                RtFloat h = sin((x - disintegration)/3.14) * randBetween(h1,h2);
                                RtFloat offx = randBetween(0.8,offsetx);
                                RtFloat offz = randBetween(0.8,offsetz);
                                RtFloat dis = disintegration;
                                RtFloat color = sqrt(x * x + z * z);
                                RtVector3 vec(x,y,z);
                                //sin((x - disintegration)/3.14) *
                                vec.Normalize();
                                vec = vec * r;
                                if(x < dis)
                                                {              RiTransformBegin();
                                                                                RiTranslate(vec[0],vec[1],vec[2]);
                                                                                // To assign a color to each sphere
                                                                                RtColor cs[1] = { {r,r,r } } ;
                                                                                RiSphere(sr, -sr, sr, 360, "constant color Cs", (RtPointer)cs, RI_NULL);
                                                                RiTransformEnd();
                                                }
                                                else if (x >= dis)
                                                {              RiTransformBegin();
                                                                                RiTranslate(vec[0]*offx,h,vec[2]*offz);
                                                                                RtColor cs[1] = { { r,r,r } } ;
                                                                                RiSphere(sr*0.8, -sr*0.8, sr*0.8, 360, "constant color Cs", (RtPointer)cs, RI_NULL);
                                                                RiTransformEnd();
                                                }
                               
                               
                                }
                }
// ----------------------------------------------------
// A RiProcedural required function
// ----------------------------------------------------
RtVoid Free(RtPointer data) {
    free(data);
                }
               
// ----------------------------------------------------
// Our utility functions begin here
// ----------------------------------------------------
RtFloat randBetween(RtFloat min, RtFloat max) {
    return ((RtFloat)rand()/RAND_MAX) * (max - min) + min;
    }
 

  • MY CHANNEL
  • Personal Projects
  • GAME REEL
  • Blogs
    • Mentor Project
    • MatchtoLive
    • VSFX 755 Class Blog >
      • C: debris procedural primitive
      • C++: side-mask pattern node
      • OSL: renderman moom shading
  • Other Art Works
  • About
  • Award