RenderMan Procedural Primitives
Blobbies


return to main index



Introduction

Blobby objects, otherwise known as soft objects or iso-surfaces, are part of the RenderMan Specification. They are also refered to as RiBlobby because of the name of the function in the 'C' language binding of the RenderMan interface. Within Pixar's RenderMan Studio, there is also a Mel proc called RiBlobby. Blobby, or smooth blending effects can also be obtained with shaders. The tutorial "RSL: Blobby Effects" demonstrates how such effects can be also be obtained with a shader.


Specification of a Blobby Surface

The way that blobbies are specified in a rib file can become very complex. Using variations of the Blobby rib statement it is possible, for example, to "partition" the ellipsoids that make up a blobby surface into groups that merge with each other but do not merge with other groups. The code presented here considers a blobby to be made of a single homogeneous group whose ellipsoid elements "blob" together.

For full details of the Blobby specification refer to,
    http://renderman.pixar.com/resources/current/rps/appnote.31.html

Before looking at the implementation of a help app that generates a complex cluster of blobbies, the reader should experiment with the simple blobby given in the rib file of listing 1.


Figure 1


Listing 1


Display "untitled" "framebuffer" "rgba"
Format 250 250 1
Projection "perspective" "fov" 30
ShadingRate 1
LightSource "distantlight" 1 "intensity" 1.5 "from" [0 0 0] 
                             "to" [0 0 1]
Translate  -0.2 0 5
Rotate 0   1 0 0
Rotate 0   0 1 0
Scale 1 1 -1
WorldBegin
    TransformBegin
        Surface "plastic"
        Blobby 3
            [1001 0
             1001 16
             1001 32
             0 3   0 1 2]
            [1 0 0 0  0 1 0 0  0 0 1 0 -0.5  0.2  0.0 1
             1 0 0 0  0 1 0 0  0 0 1 0  0.9  0.5  0.0 1
             1 0 0 0  0 1 0 0  0 0 1 0  0.5 -0.5  0.0 1]
            [""]
            "Cs" [1 0 0  0 1 0  0 0 1]
    TransformEnd
WorldEnd


Blobby Helper App

Listing 2 and 3 implement a blobby helper app in Python and Tcl. A rib that references the helpers is shown in listing 4.



Figure 2
1000 ellipsoids in a volume 2 x 1 x 2 units.
The parameters in the rib file were "1000 0.5 4.0 1.0 4.0"


Listing 2 (blobby.py)


import sys, math, random
  
random.seed(5)
def randBetween(min, max):
    return random.random() * (max - min) + min
  
def getMatrix(size, width, height, depth):
    mat = '%s 0 0 0  0 %s 0 0  0 0 %s 0' % (size,size,size)
    x = randBetween(-width/2, width/2)
    y = randBetween(-height/2, height/2)
    z = randBetween(-depth/2, depth/2)
    mat += ' %s %s %s 1' % (x,y,z)
    return mat
    
def blobby(num, size, width, height, depth):
    ellipsoid_ID = "1001 "
    index = 0
    out = 'Blobby %s ' %  num
    
    # begin the "code" block
    out += "[\n"
    for n in range(num):
        out += '%s' % ellipsoid_ID
        out += '%s ' % index
        index += 16
        out += "\n"
    # define the blobby operator and indices of
    # the blobs forming a "set" ie. group
    add_ID = 0
    blob_count = num
    out += '%s %s ' % (add_ID, blob_count)
    for n in range(num):
        out += '%s ' % n
    out += "]\n"
    
    # begin the transforms block
    out += "[\n"
    for n in range(num):
        out += '%s \n' % (getMatrix(size,width,height,depth))
    out += "]\n"
    
    # begin the depth map block
    out += "[\"\"]\n"
    return out
  
def main():
    args = sys.stdin.readline()
    while args:
        arg = args.split()
        pixels = float(arg[0])
        num = int(arg[1])
        size = float(arg[2])
        width = float(arg[3])
        height = float(arg[4])
        depth = float(arg[5])
            
        print 'TransformBegin'
        print '%s' % blobby(num, size, width, height, depth)    
        print 'TransformEnd'
        sys.stdout.write('\377')
        sys.stdout.flush()
        # read the next set of inputs
        args = sys.stdin.readline()
  
if __name__ == "__main__":
    main()



Listing 2 (blobby.tcl)


fconfigure stdout -translation binary
  
#-----------------------------------------------
proc randBetween { min max } {
    return [expr rand() * ($max - $min) + $min]
    }
#-----------------------------------------------
proc getMatrix { size width height depth } {
set mat "$size 0 0 0  0 $size 0 0  0 0 $size 0  "
append mat [format "%1.3f " [randBetween -$width/2 $width/2]]
append mat [format "%1.3f " [randBetween -$height/2 $height/2]]
append mat [format "%1.3f 1\n" [randBetween -$depth/2 $depth/2]]
return $mat
}
#-----------------------------------------------
proc blobby { num size width height depth} {
set ellipsoid_ID "1001 "
set index 0
  
set out ""
append out "Blobby $num \n"
  
# begin the "code" block
append out "\[\n"
for { set n 0 } { $n < $num } { incr n 1 } {
    append out $ellipsoid_ID
    append out $index
    incr index 16
    append out "\n"
    }
  
# define the blobby operator and indices of
# the blobs forming a "set" ie. group
set add_ID 0
set blob_count $num
append out "$add_ID $blob_count "
for { set n 0 } { $n < $num } { incr n 1 } {
    append out "$n "
    }
append out "\]\n"
  
# begin the transforms block
append out "\[\n"
for { set n 0 } { $n < $num } { incr n 1 } {
    append out [getMatrix $size $width $height $depth]
    }
append out "\]\n"
  
# begin the depth map block
append out "\[ \"\" \]\n"  
return $out
}
#-----------------------------------------------
while { [gets stdin args] != -1 } {
    set pixels [lindex $args 0]
    set num [lindex $args 1]
    set size [lindex $args 2]
    set width [lindex $args 3]
    set height [lindex $args 4]
    set depth [lindex $args 5]
  
    puts "TransformBegin"
    puts [blobby $num $size $width $height $depth]
    puts "TransformEnd"
    
    puts "\377" 
    flush stdout
    }


Listing 4 (helper_test.rib)


Display "shader_tester" "framebuffer" "rgba"
Format 300 200 1
Projection "perspective" "fov" 40
ShadingRate 10
LightSource "distantlight" 1 "intensity" 1.5 "from" [0 0 0] 
                             "to" [0 0 1] 
Translate  0 0.4 18
Rotate -30   1 0 0
Rotate 30   0 1 0
Scale 1 1 -1
WorldBegin
   AttributeBegin
      Surface "plastic"
      Procedural "RunProgram" ["/usr/bin/python FULL_PATH/blobby.py" "1000 0.5 4.0 1.0 4.0"] 
                              [-2 2 -2 2 -2 2]
      #Procedural "RunProgram" ["/usr/bin/tclsh FULL_PATH/blobby.tcl" "1000 0.5 4.0 1.0 4.0"] 
      #                       [-2 2 -2 2 -2 2]
   AttributeEnd
WorldEnd




© 2002- Malcolm Kesson. All rights reserved.