Shader hair_geo_row

Click on the filename to display or download the file.

hair_geo_row.mi
declare shader 
    geometry "hair_geo_row" ( 
	string "name", 
        integer "count" default 1, 
	scalar "radius" default .01, 
        vector "bbox_min" default -.5 -.5 -.5, 
        vector "bbox_max" default .5 .5 .5, 
	scalar "y_offset_max" default .01, 
	scalar "z_offset_max" default .01, 
	integer "approximation" default 100, 
	integer "degree" default 3, 
        integer "random_seed" default 1955 ) 
    version 1 
    apply material 
end declare 

hair_geo_row.c
#include "shader.h" 
#include "geoshader.h" 
#include "miaux.h" 
 
typedef struct { 
    miTag name; 
    miInteger count; 
    miScalar radius; 
    miVector bbox_min; 
    miVector bbox_max; 
    miScalar y_offset_max; 
    miScalar z_offset_max; 
    miInteger approximation; 
    miInteger degree; 
    miInteger random_seed; 
} hair_geo_row_t; 
 
DLLEXPORT 
int hair_geo_row_version(void) { return 1; } 
 
void hair_geo_row_bbox(miObject *obj, void* params) 
{ 
    hair_geo_row_t *p = (hair_geo_row_t*)params; 
    obj->bbox_min = p->bbox_min; 
    obj->bbox_max = p->bbox_max; 
} 
 
miBoolean hair_geo_row_callback(miTag tag, void *ptr); 
 
DLLEXPORT 
miBoolean hair_geo_row ( 
    miTag *result, miState *state, hair_geo_row_t *params  ) 
{ 
    hair_geo_row_t *p =  
        (hair_geo_row_t*) mi_mem_allocate(sizeof(hair_geo_row_t)); 
    p->name          = *mi_eval_tag(&params->name); 
    p->count         = *mi_eval_integer(&params->count); 
    p->radius        = *mi_eval_scalar(&params->radius); 
    p->bbox_min      = *mi_eval_vector(&params->bbox_min); 
    p->bbox_max      = *mi_eval_vector(&params->bbox_max); 
    p->y_offset_max  = *mi_eval_scalar(&params->y_offset_max); 
    p->z_offset_max  = *mi_eval_scalar(&params->z_offset_max); 
    p->approximation = *mi_eval_integer(&params->approximation); 
    p->degree        = *mi_eval_integer(&params->degree); 
    p->random_seed   = *mi_eval_integer(&params->random_seed); 
 
    miaux_define_hair_object( 
        p->name, hair_geo_row_bbox, p, result, hair_geo_row_callback); 
 
    return miTRUE; 
} 
 
miBoolean hair_geo_row_callback(miTag tag, void *ptr) 
{ 
    miHair_list *hair_list; 
    miGeoIndex *harray; 
    miScalar *hair_scalars; 
    int i, h, per_hair_data_count, vertex_count, vertex_size, 
        per_hair_scalar_count, total_scalar_count; 
    hair_geo_row_t *p = (hair_geo_row_t *)ptr; 
    miScalar x, y_offset, z_offset, 
        yoff_max = p->y_offset_max, zoff_max = p->z_offset_max; 
 
    mi_api_incremental(miTRUE); 
    miaux_define_hair_object(p->name, hair_geo_row_bbox, p, NULL, NULL); 
 
    hair_list = mi_api_hair_begin(); 
    hair_list->approx = p->approximation; 
    hair_list->degree = p->degree; 
    mi_api_hair_info(0, 'r', 1); 
    mi_api_hair_info(0, 't', 1); 
 
    per_hair_data_count = 2;  /* Radius and random value */ 
    vertex_count = 4; 
    vertex_size = 3; 
    per_hair_scalar_count =  
        vertex_count * vertex_size + per_hair_data_count; 
    total_scalar_count = p->count * per_hair_scalar_count; 
 
    hair_scalars = mi_api_hair_scalars_begin(total_scalar_count); 
    mi_srandom(p->random_seed); 
 
    for (i = 0; i < p->count; i++) { 
        x = miaux_random_range(p->bbox_min.x, p->bbox_max.x); 
        y_offset = miaux_random_range(-yoff_max, yoff_max); 
        z_offset = miaux_random_range(-zoff_max, zoff_max); 
 
        *hair_scalars++ = p->radius;              
        *hair_scalars++ = miaux_random_range(0.0, 1.0);  
        *hair_scalars++ = x;  
        *hair_scalars++ = p->bbox_min.y + yoff_max + y_offset; 
        *hair_scalars++ = p->bbox_min.z + zoff_max + z_offset; 
        *hair_scalars++ = x;  
        *hair_scalars++ = p->bbox_max.y - yoff_max + y_offset; 
        *hair_scalars++ = p->bbox_min.z + zoff_max + z_offset; 
        *hair_scalars++ = x;  
        *hair_scalars++ = p->bbox_max.y - yoff_max + y_offset; 
        *hair_scalars++ = p->bbox_max.z - zoff_max + z_offset; 
        *hair_scalars++ = x;  
        *hair_scalars++ = p->bbox_min.y + yoff_max + y_offset; 
        *hair_scalars++ = p->bbox_max.z - zoff_max + z_offset; 
    } 
    mi_api_hair_scalars_end(total_scalar_count); 
     
    harray = mi_api_hair_hairs_begin(p->count + 1); 
    for (h=0; h < p->count + 1; h++) 
        harray[h] = h * per_hair_scalar_count; 
    mi_api_hair_hairs_end(); 
 
    mi_api_hair_end(); 
    mi_api_object_end(); 
    return miTRUE; 
} 

hair_geo_row_util.c
void miaux_define_hair_object( 
    miTag name_tag, miaux_bbox_function bbox_function, void *params, 
    miTag *geoshader_result, miApi_object_callback callback) 
{ 
    miTag tag; 
    miObject *obj; 
    char *name = miaux_tag_to_string(name_tag, "::hair"); 
    obj = mi_api_object_begin(mi_mem_strdup(name)); 
    obj->visible = miTRUE; 
    obj->shadow = obj->reflection = obj->refraction = 3; 
    bbox_function(obj, params); 
    if (geoshader_result != NULL && callback != NULL) { 
	mi_api_object_callback(callback, params); 
	tag = mi_api_object_end(); 
	mi_geoshader_add_result(geoshader_result, tag); 
	obj = (miObject *)mi_scene_edit(tag); 
	obj->geo.placeholder_list.type = miOBJECT_HAIR; 
	mi_scene_edit_end(tag); 
    } 
} 
 
char* miaux_tag_to_string(miTag tag, char *default_value) 
{ 
    char *result = default_value; 
    if (tag != 0) { 
	result = (char*)mi_db_access(tag); 
	mi_db_unpin(tag); 
    } 
    return result; 
} 
 
result->r += miaux_random_range(-red_variance, red_variance); 
    result->r = miaux_clamp(result->r, 0.0, 1.0); 
    result->g += miaux_random_range(-green_variance, green_variance); 
    result->g = miaux_clamp(result->g, 0.0, 1.0); 
    result->b += miaux_random_range(-blue_variance, blue_variance); 
    result->b = miaux_clamp(result->b, 0.0, 1.0); 
} 
 
double miaux_fit( 
    double v, double oldmin, double oldmax, double newmin, double newmax)     
{ 
    return newmin + ((v - oldmin) / (oldmax - oldmin)) * (newmax - newmin); 
} 

22 April 2008 23:40:42