Page tree

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

The return value of ImplicitFieldNew is an instance of a subclass of class ImplicitField, whose definition is inImplicitField.h in the PRMan include directory.

...

Code Block
languagecpp
class ImplicitVertexValue {
private:
    ImplicitVertexValue(const

...

 ImplicitVertexValue &);

...


    ImplicitVertexValue &operator=(const

...

 ImplicitVertexValue &);

...



public:

...


    ImplicitVertexValue() {}

...


    virtual ~ImplicitVertexValue() {}

...



    virtual void GetVertexValue(RtFloat *result,

...

 const

...

 RtPoint p) = 0;

...



    virtual void GetVertexValueFiltered(RtFloat *result,

...

 const

...

 RtPoint p,

...


        const RtPoint dPdu, const RtPoint dPdv, const RtPoint dPdw) {
        GetVertexValue(result, p);

...


    }

    virtual void GetVertexValueMultiple(int

...

 neval, RtFloat *result,

...


        int resultstride,

...

 const

...

 RtPoint *p)

...

 {
        for (int i = 0; i < neval; ++i)

...

 {
            GetVertexValue(result, *p++);

...


            result += resultstride;

...


        }
    }

    virtual void GetVertexValueMultipleFiltered(int neval, RtFloat *result,
        int resultstride, const RtPoint *p, const RtPoint *dPdu,
        const RtPoint *dPdv, const RtPoint *dPdw) {
        for (int i = 0; i < neval; ++i) {
            GetVertexValueFiltered(result, *p++, *dPdu++, *dPdv++, *dPdw++);
            result += resultstride;
        }
    }
};

class ImplicitField{
public:

    RtBound bbox;

private:
    ImplicitField(const ImplicitField &);
    ImplicitField &operator=(const ImplicitField &);

public:
    ImplicitField(){}
    virtual ~ImplicitField(){}

    virtual RtFloat Eval(const RtPoint p) = 0;

    virtual RtFloat EvalFiltered(const RtPoint p, const RtPoint dPdu,
        const RtPoint dPdv, const RtPoint dPdw) {
        return Eval(p);
    }

    virtual void EvalMultiple(int neval, float *result, int resultstride,
        const RtPoint *p) {
        for (int i = 0; i < neval; ++i) {
            *result = Eval(*p++);
            result += resultstride;
        }
    }

    virtual void EvalMultipleFiltered(int neval, float *result,
        int resultstride, const RtPoint *p, const RtPoint *dPdu,
        const RtPoint *dPdv, const RtPoint *dPdw) {
        EvalMultiple(neval, result, resultstride, p);
    }

    virtual void GradientEval(RtPoint result, const RtPoint p) = 0;

    virtual void GradientEvalFiltered(RtPoint result, const RtPoint p,
        const RtPoint dPdu, const RtPoint dPdv, const RtPoint dPdw) {
        GradientEval(result, p);
    }

    virtual void GradientEvalMultiple(int neval, RtPoint *result,
        const RtPoint *p) {
        for (int i = 0; i < neval; ++i) {
            GradientEval(*result++, *p++);
        }
    }

    virtual void GradientEvalMultipleFiltered(int neval, RtPoint *result,
        const RtPoint *p, const RtPoint *dPdu, const RtPoint *dPdv,
        const RtPoint *dPdw) {
        GradientEvalMultiple(neval, result, p);
    }

    virtual void Range(RtInterval result, const RtPoint corners[8],
        const RtVolumeHandle h){
        result[0] = -1e30f;
        result[1] = 1e30f;
    }

    virtual bool ShouldSplit() {
        return false;
    }

    virtual void Split(std::vector<ImplicitField *> &children) {
    }

    virtual void Motion(RtPoint result, const RtPoint p) {
        result[0] = 0.0f;
        result[1] = 0.0f;
        result[2] = 0.0f;
    }

    virtual void MotionFiltered(RtPoint result, const RtPoint p,
        const RtPoint dPdu, const RtPoint dPdv, const RtPoint dPdw) {
        Motion(result, p);
    }

    virtual void MotionMultiple(int neval, RtPoint *result, const RtPoint *p) {
        for (int i = 0; i < neval; ++i) {
            Motion(*result++, *p++);
        }
    }

    virtual void MotionMultipleFiltered(int neval, RtPoint *result,
        const RtPoint *p, const RtPoint *dPdu, const RtPoint *dPdv,
        const RtPoint *dPdw) {
        MotionMultiple(neval, result, p);
    }

    virtual void BoxMotion(RtBound result, const RtBound b){
        for (int i = 0; i < 6; i++) {
            result[i] = b[i];
        }
    }

    virtual void VolumeCompleted(const RtVolumeHandle h) {
    }

    virtual ImplicitVertexValue *CreateVertexValue(const RtToken name,
        int nvalue) {
        return 0;
    }

    virtual float MinimumVoxelSize(const RtPoint corners[8]) {
        return 0.0f;
    }
};

 

The bbox field must be filled in the constructor with a bounding box in the object coordinate system that is active at the call to RiBlobby, at shutter open, outside of which the field value is guaranteed to be identically lower than the field function threshold. Note that typeRtBound is defined in ri.h to be an array of 6 floats. bbox[0], bbox[2], and bbox[4] are the lower bounds on x, y, and z, andbbox[1], bbox[3], and bbox[5] are the upper bounds.

...

Here is a plugin for a field function whose level sets are cubes centered at the origin. The field cross-section is the same as that ofRiBlobby's sphere primitives, to make it blend nicely in compound objects. Note that this plugin implements the bare minimum required of a plugin: it does not support deformation motion blur or primitive variable evaluations, and it does not perform any filtered evaluations for anti-aliasing.

...

Code Block
languagecpp
#include <ImplicitField.h>
class Cube: public ImplicitField{
public:
    Cube();
    virtual ~Cube();
    virtual RtFloat Eval(const RtPoint p);
    virtual void GradientEval(RtPoint grad, const RtPoint p);
    virtual void Range(RtInterval r, const RtPoint corners[8],
        RtVolumeHandle h);
};
Cube::Cube(){

...


    bbox[0]=-1.;

...


    bbox[1]=1.;

...


    bbox[2]=-1.;

...


    bbox[3]=1.;

...


    bbox[4]=-1.;

...


    bbox[5]=1.;

...


}

...


/*

...


 * This is the same field falloff (as a function of the

...


 * square of distance from the center) that RiBlobby uses

...


 * for its primitive blobs.

...


 * It has

...


 *    geoff(-1)=0 geoff'(-1)=0 geoff"(-1)=0

...


 *      geoff( 0)=1 geoff'(0)=0

...


 *    geoff( 1)=0 geoff'( 1)=0 geoff"( 1)=0

...


 */

...


static

...

 float

...

 geoff(float

...

 r2){

...


    if(r2>=1.f)

...

 return

...

 0.f;

...


    return ((3.f-r2)*r2-3.f)*r2+1.f;

...


}

...


/*

...


 * d geoff(r2)

...


 * -----------

...


 *    d r2
 */
static float dgeoff(float

...

 r2){

...


    if(r2>=1.f)

...

 return

...

 0.f;

...


    return (6.f-3.f*r2)*r2-3.f;

...


}

...


/*

...


 * geoff(max(x^2, y^2, z^2))

...


 */

...


float

...

 Cube::Eval(const

...

 RtPoint p){

...


    RtPoint sq;
    float r2;

    sq[0]=p[0]*p[0];

...


    sq[1]=p[1]*p[1];

...


    sq[2]=p[2]*p[2];

...


    if(sq[0]>sq[1]) r2=sq[0]>sq[2]?sq[0]:sq[2];

...


    else r2=sq[1]>sq[2]?sq[1]:sq[2];

...


    return geoff(r2);

...


}

...


void

...

 Cube::GradientEval(RtPoint grad,

...

 const

...

 RtPoint p){

...


    RtPoint sq;

    grad[0]=0.;

...


    grad[1]=0.;

...


    grad[2]=0.;

...


    sq[0]=p[0]*p[0];

...


    sq[1]=p[1]*p[1];

...


    sq[2]=p[2]*p[2];

...


    if(sq[0]>sq[1]){

...


        if(sq[0]>sq[2]) grad[0]=2.*p[0]*dgeoff(sq[0]);

...


        else grad[2]=2.*p[2]*dgeoff(sq[2]);

...


    }
    else if(sq[1]>sq[2])

...


        grad[1]=2.*p[1]*dgeoff(sq[1]);

...


    else
        grad[2]=2.*p[2]*dgeoff(sq[2]);

...


}

...


void

...

 isq(RtInterval sq, RtInterval x){

...


    if(x[0]>=0){

...


        sq[0]=x[0]*x[0];

...


        sq[1]=x[1]*x[1];

...


    }
    else if(x[1]<=0){

...


        sq[0]=x[1]*x[1];

...


        sq[1]=x[0]*x[0];

...


    }
    else{
        sq[0]=0;

...


        sq[1]=-x[0]>x[1]?x[0]*x[0]:x[1]*x[1];

...


    }
}
void imax(RtInterval max, RtInterval a, RtInterval b){

...


    max[0]=b[0]>a[0]?b[0]:a[0];

...


    max[1]=b[1]>a[1]?b[1]:a[1];

...


}

...


void

...

 igeoff(RtInterval g, RtInterval r2){

...


    g[0]=geoff(r2[1]);

...


    g[1]=geoff(r2[0]);

...


}

...


void

...

 Cube::Range(RtInterval val,

...

 const

...

 RtPoint corners[8],

...


        RtVolumeHandle h){

...


    RtInterval r, x, y, z, xsq, ysq, zsq, maxxy, maxxyz;

...


    int i;

    x[0]=x[1]=corners[0][0];

...


    y[0]=y[1]=corners[0][0];

...


    z[0]=z[1]=corners[0][0];

...


    for(i=0;i!=8;i++){

...


        if(corners[i][0]<x[0]) x[0]=corners[i][0];

...


        if(corners[i][0]>x[1]) x[1]=corners[i][0];

...


        if(corners[i][1]<y[0]) y[0]=corners[i][1];

...


        if(corners[i][1]>y[1]) y[1]=corners[i][1];

...


        if(corners[i][2]<z[0]) z[0]=corners[i][2];

...


        if(corners[i][2]>z[1]) z[1]=corners[i][2];

...


    }
    isq(xsq, x);

...


    isq(ysq, y);

...


    isq(zsq, z);

...


    imax(maxxy, xsq, ysq);

...


    imax(maxxyz, maxxy, zsq);

...


    igeoff(val, maxxyz);

...


}

...


Cube::~Cube(){}

...


FIELDCREATE{

...


    return new Cube();

...


}

 

Here is a RIB file that uses the plugin, and the resulting image:

FrameBegin 0
    Display "cube.tif" "tiff" "rgba"
    Format 200 200 1
    Clipping 1e-3 1e5
    Projection "perspective" "fov" 3
    Hider "raytrace" "int incremental" [0] "int minsamples" [4] "int maxsamples" [16]
    Integrator "PxrDefault" "default"
    Translate 0 0 27
    DisplayFilter "PxrBackgroundDisplayFilter" "background" "color backgroundColor" [1 1 1]
    WorldBegin
        Bxdf "PxrDisney" "PxrDisney1" "color baseColor" [.9 .3 .2]
        Sides 2
        Rotate 10 0 1 0
        Rotate 10 1 1 1
        Blobby 1 [
            1004  0 0 0 0 0
                ]
        [0]
        ["cube"]
WorldEnd
FrameEnd

 

 

Image Modified

Just for amusement, here is another picture made using the same cube in various more complicated objects:

 

Image Modified

And the RIB file that made them:

...