Shader newblocks (C++)

Home
Click on the filename to display or download the file.

newblocks.mi
# Simple geometry objects for use in the example scenes of 
# "Writing mental ray shaders".  http://www.writingshaders.com/ 
 
declare shader 
    geometry "bw_square" (  
	string "name", 
	scalar "x" default 0, 
	scalar "y" default 0, 
	scalar "z" default 0, 
	scalar "sx" default 1, 
	scalar "sy" default 1 ) 
    version 1 
    apply geometry 
end declare 
 
declare shader 
    geometry "bw_cube" (  
        string "name" ) 
    version 1 
    apply geometry 
end declare 
 
declare shader 
    geometry "bw_cylinder" (  
	string "name", 
	integer "sides" default 60, 
	scalar "radius" default 0.5, 
	scalar "start_angle" default 0, 
        boolean "average_normals" default on ) 
    version 1 
    apply geometry 
end declare 
 
declare shader 
    geometry "bw_cone" ( 
        string "name", 
	integer "sides" default 120, 
	scalar "radius" default 0.5, 
        boolean "average_normals" default on ) 
    version 1 
    apply geometry 
end declare 
 
declare shader 
    geometry "bw_ball" (  
        string "name", 
	integer "div_u" default 60, 
	integer "div_v" default 30, 
        boolean "average_normals" default on ) 
    version 1 
    apply geometry 
end declare 

newblocks.cpp
// Simple geometry objects for use in the example scenes of 
// "Writing mental ray shaders".  http://www.writingshaders.com/ 
 
#include "mrpoly.h" 
 
// -------------------------------------------------------------------------------- 
// SQUARE 
 
struct bw_square { 
    miTag name; 
    miScalar x, y, z, sx, sy; 
}; 
 
extern "C" DLLEXPORT  
int bw_square_version(void) { return 1; } 
 
extern "C" DLLEXPORT  
miBoolean bw_square (miTag *result, miState *state, struct bw_square *params) 
{ 
    polygon_object obj; 
    polygon_group group; 
    tlist t; 
    matrix scale; 
    scale.s(*mi_eval_scalar(&params->sx), *mi_eval_scalar(&params->sy)); 
 
    obj.mi_begin(get_string(state, &params->name, "square")); 
    group = obj.new_group(); 
    t.square(*mi_eval_scalar(&params->x), 
             *mi_eval_scalar(&params->y), 
             *mi_eval_scalar(&params->z)); 
    t.transform(scale); 
    polygon p(t); 
    group.add_polygon(p.set_bounding_uvs().set_bump_basis()); 
    group.mi(false); 
 
    return obj.mi_end(result); 
} 
 
 
// -------------------------------------------------------------------------------- 
// CUBE 
 
struct bw_cube { 
    miTag name; 
}; 
 
extern "C" DLLEXPORT  
int bw_cube_version(void) { return 1; } 
 
extern "C" DLLEXPORT  
miBoolean bw_cube (miTag *result, miState *state, struct bw_cube *params) 
{ 
    polygon_object obj; 
    polygon_group group; 
    tlist s; 
 
    polygon p(s.square(0.0, 0.0, 0.5)); 
    p.set_bounding_uvs().set_bump_basis(); 
    matrix rotate; 
    rotate.ry(90); 
 
    obj.mi_begin(get_string(state, &params->name, "cube")); 
    group = obj.new_group(); 
    for (int i = 0; i < 4; i++) {  // Sides 
        group.add_polygon(p.transform(rotate)); 
    } 
    group.add_polygon(p.transform(rotate.i().rx(90)));  // Top 
    group.add_polygon(p.transform(rotate.i().s(-1).sx(-1)));  // Bottom 
 
    group.mi(false); 
    return obj.mi_end(result); 
} 
 
// -------------------------------------------------------------------------------- 
// Utility functions can also be constructed from the mrpoly library 
// to simplify the creation of related shaders.  The "cylinder" 
// function is used in the following "bw_cylinder" and "bw_cone" 
// shaders. 
 
miBoolean cylinder(miTag *result, const char* name, int sides,  
                   float bottom_radius=0.5, float top_radius=0.5, 
                   float start_angle=0, bool average_normals=true) 
{ 
    polygon_object obj; 
    polygon_group ring, caps; 
    tlist t, b, uvs; 
    matrix m; 
 
    obj.mi_begin(name); 
 
    t.arc(sides, top_radius, 0, 0, 0, start_angle, start_angle + 360.0); 
    t[t.size()-1] = t[0]; // Guarantee last and first points equal despite precision. 
 
    uvs = t.bounding_uvs(); 
 
    polygon top(t); 
    top.set_uvs(uvs).set_bump_basis().transform(m.rx(-90).ty(0.5)); 
 
    b.arc(sides, bottom_radius, 0, 0, 0, start_angle, start_angle + 360.0); 
    b[b.size()-1] = b[0]; 
    uvs = b.bounding_uvs(); 
    uvs.transform(m.i().sy(-1)); 
    polygon bottom(b); 
    bottom.set_uvs(uvs).transform(m.i().rx(-90).ty(-0.5)); 
 
    caps = obj.new_group(); 
    caps.add_polygon(top); 
    caps.add_polygon(bottom); 
    caps.mi(); 
 
    ring = obj.new_group(); 
    tlist bt, tp; 
    bottom.get_positions(bt); 
    top.get_positions(tp); 
 
    ring.zipper(bt, tp, 0.0, 0.0, 1.0, 1.0, bt[1], tp[1]); 
 
    ring.mi(average_normals); 
 
    return obj.mi_end(result); 
} 
 
 
// -------------------------------------------------------------------------------- 
// CYLINDER 
 
struct bw_cylinder { 
    miTag name; 
    miInteger sides; 
    miScalar radius; 
    miScalar start_angle; 
    miBoolean average_normals; 
}; 
 
extern "C" DLLEXPORT  
int bw_cylinder_version(void) { return 1; } 
 
extern "C" DLLEXPORT  
miBoolean bw_cylinder (miTag *result, miState *state, struct bw_cylinder *params) 
{ 
    miScalar radius = *mi_eval_scalar(&params->radius); 
    return cylinder(result,  
                    get_string(state, &params->name, "cylinder"), 
                    *mi_eval_integer(&params->sides), 
                    radius, radius, 
                    *mi_eval_scalar(&params->start_angle), 
                    *mi_eval_boolean(&params->average_normals)); 
} 
 
 
// -------------------------------------------------------------------------------- 
// CONE 
 
struct bw_cone { 
    miTag name; 
    miInteger sides; 
    miScalar radius; 
    miBoolean average_normals; 
}; 
 
extern "C" DLLEXPORT  
int bw_cone_version(void) { return 1; } 
 
extern "C" DLLEXPORT  
miBoolean bw_cone (miTag *result, miState *state, struct bw_cone *params) 
{ 
    return cylinder(result, 
                    get_string(state, &params->name, "cone"), 
                    *mi_eval_integer(&params->sides),  
                    *mi_eval_scalar(&params->radius), 
                    0.001, 0,  
                    *mi_eval_boolean(&params->average_normals)); 
} 
 
 
// -------------------------------------------------------------------------------- 
// BALL 
 
struct bw_ball { 
    miTag name; 
    miInteger div_u, div_v; 
    miBoolean average_normals; 
}; 
 
extern "C" DLLEXPORT  
int bw_ball_version(void) { return 1; } 
 
extern "C" DLLEXPORT  
miBoolean bw_ball (miTag *result, miState *state, struct bw_ball *params) 
{ 
    miInteger div_u = *mi_eval_integer(&params->div_u); 
    miInteger div_v = *mi_eval_integer(&params->div_v); 
    polygon_object obj; 
    polygon_group group; 
    tlist semicircle; 
    semicircle.arc(div_v, 1, 0, 0, 0, -89.9, 89.9); // Allow for caps as small polygons. 
 
    obj.mi_begin(get_string(state, &params->name, "ball")); 
 
    group = obj.new_group(); 
    group.revolver(semicircle, div_u, triple::y_axis, 0.0, 0.0, 1.0, 1.0, true); 
 
    group.mi(*mi_eval_boolean(&params->average_normals)); 
 
    return obj.mi_end(result); 
} 

3 March 2008 20:23:09