Shader hair_geo_4v_texture

Click on the filename to display or download the file.

hair_geo_4v_texture.mi
declare shader 
    geometry "hair_geo_4v_texture" ( 
	string "name", 
	vector "v1" default -1.5 0 0, 
	vector "v2" default  -.5 0 0, 
	vector "v3" default   .5 0 0, 
	vector "v4" default  1.5 0 0, 
        scalar "root_radius" default .1, 
        color  "root_color" default 0 0 0 1, 
        scalar "tip_radius" default .01, 
        color  "tip_color"  default 1 1 1 0, 
	integer "approximation" default 2, 
	integer "degree" default 1 ) 
    version 1 
    apply material 
end declare 

hair_geo_4v_texture.c
#include "shader.h" 
#include "geoshader.h" 
#include "miaux.h" 
 
miBoolean hair_geo_4v_texture_callback(miTag tag, void *ptr); 
 
typedef struct { 
    miTag name; 
    miVector p1; 
    miVector p2; 
    miVector p3; 
    miVector p4; 
    miScalar root_radius; 
    miColor root_color; 
    miScalar tip_radius; 
    miColor tip_color; 
    miInteger approximation; 
    miInteger degree; 
} hair_geo_4v_texture_t; 
 
DLLEXPORT 
int hair_geo_4v_texture_version(void) { return 1; } 
 
void hair_geo_4v_texture_bbox(miObject *obj, void* params) 
{ 
    hair_geo_4v_texture_t *p = (hair_geo_4v_texture_t*)params; 
    double max_radius = miaux_max(p->root_radius, p->tip_radius) + .001; 
 
    miaux_init_bbox(obj); 
    miaux_adjust_bbox(obj, &p->p1, max_radius); 
    miaux_adjust_bbox(obj, &p->p2, max_radius); 
    miaux_adjust_bbox(obj, &p->p3, max_radius); 
    miaux_adjust_bbox(obj, &p->p4, max_radius); 
    miaux_describe_bbox(obj); 
} 
 
DLLEXPORT 
miBoolean hair_geo_4v_texture ( 
    miTag *result, miState *state, hair_geo_4v_texture_t *params  ) 
{ 
    hair_geo_4v_texture_t *p =  
        (hair_geo_4v_texture_t*) mi_mem_allocate(sizeof(hair_geo_4v_texture_t)); 
 
    p->p1 = *mi_eval_vector(&params->p1); 
    p->p2 = *mi_eval_vector(&params->p2); 
    p->p3 = *mi_eval_vector(&params->p3); 
    p->p4 = *mi_eval_vector(&params->p4); 
    p->root_radius = *mi_eval_scalar(&params->root_radius); 
    p->root_color = *mi_eval_color(&params->root_color); 
    p->tip_radius = *mi_eval_scalar(&params->tip_radius); 
    p->tip_color  = *mi_eval_color(&params->tip_color); 
    p->approximation = *mi_eval_integer(&params->approximation); 
    p->degree = *mi_eval_integer(&params->degree); 
 
    miaux_define_hair_object( 
        p->name, hair_geo_4v_texture_bbox, p, result,  
        hair_geo_4v_texture_callback); 
 
    return miTRUE; 
} 
 
miBoolean hair_geo_4v_texture_callback(miTag tag, void *ptr) 
{ 
    miHair_list *hair_list; 
    miScalar    *hair_scalars; 
    miGeoIndex  *hair_indices; 
    hair_geo_4v_texture_t *p = (hair_geo_4v_texture_t *)ptr; 
    int i; 
 
    int hair_count = 1; 
    int vertices_per_hair = 4; 
    int scalars_per_vertex = 8; 
    int hair_scalar_count = vertices_per_hair * scalars_per_vertex; 
 
    miVector vertices[4]; 
    vertices[0] = p->p1; 
    vertices[1] = p->p2; 
    vertices[2] = p->p3; 
    vertices[3] = p->p4; 
 
    mi_api_incremental(miTRUE); 
 
    miaux_define_hair_object( 
        p->name, hair_geo_4v_texture_bbox, p, NULL, NULL); 
 
    hair_list = mi_api_hair_begin(); 
    hair_list->approx = p->approximation; 
    hair_list->degree = p->degree; 
    mi_api_hair_info(1, 'r', 1); 
    mi_api_hair_info(1, 't', 4); 
 
    hair_scalars = mi_api_hair_scalars_begin(hair_scalar_count); 
    for (i = 0; i < vertices_per_hair; i++) 
        miaux_append_hair_data( 
            &hair_scalars, &vertices[i],  
            miaux_fit(i, 0, vertices_per_hair, 0, 1), 
            p->root_radius, &p->root_color, p->tip_radius, &p->tip_color); 
    mi_api_hair_scalars_end(hair_scalar_count); 
 
    hair_indices = mi_api_hair_hairs_begin(hair_count + 1); 
    hair_indices[0] = 0; 
    hair_indices[1] = hair_scalar_count; 
    mi_api_hair_hairs_end(); 
 
    mi_api_hair_end(); 
    mi_api_object_end(); 
 
    return miTRUE; 
} 

hair_geo_4v_texture_util.c
double miaux_max(double a, double b) 
{ 
    return a > b ? a : b; 
} 
 
void miaux_init_bbox(miObject *obj) 
{ 
    obj->bbox_min.x = miHUGE_SCALAR; 
    obj->bbox_min.y = miHUGE_SCALAR; 
    obj->bbox_min.z = miHUGE_SCALAR; 
    obj->bbox_max.x = -miHUGE_SCALAR; 
    obj->bbox_max.y = -miHUGE_SCALAR; 
    obj->bbox_max.z = -miHUGE_SCALAR; 
} 
 
void miaux_adjust_bbox(miObject *obj, miVector *v, miScalar extra) 
{ 
    miVector v_extra, vmin, vmax; 
    miaux_set_vector(&v_extra, extra, extra, extra); 
    mi_vector_sub(&vmin, v, &v_extra); 
    mi_vector_add(&vmax, v, &v_extra); 
    mi_vector_min(&obj->bbox_min, &obj->bbox_min, &vmin); 
    mi_vector_max(&obj->bbox_max, &obj->bbox_max, &vmax); 
} 
 
void miaux_set_vector(miVector *v, double x, double y, double z) 
{ 
    v->x = x; 
    v->y = y; 
    v->z = z; 
} 
 
void miaux_describe_bbox(miObject *obj) 
{ 
    mi_progress("Object bbox: %f,%f,%f  %f,%f,%f", 
		obj->bbox_min.x, obj->bbox_min.y, obj->bbox_min.z, 
		obj->bbox_max.x, obj->bbox_max.y, obj->bbox_max.z); 
} 
 
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; 
} 
 
void miaux_append_hair_data( 
    miScalar **scalar_array, miVector *v, miScalar position, 
    miScalar root_radius, miColor *root, miScalar tip_radius, miColor *tip ) 
{ 
    (*scalar_array)[0] = v->x; 
    (*scalar_array)[1] = v->y; 
    (*scalar_array)[2] = v->z; 
    (*scalar_array)[3] = miaux_fit(position, 0, 1, root_radius, tip_radius); 
    (*scalar_array)[4] = miaux_fit(position, 0, 1, root->r, tip->r); 
    (*scalar_array)[5] = miaux_fit(position, 0, 1, root->g, tip->g); 
    (*scalar_array)[6] = miaux_fit(position, 0, 1, root->b, tip->b); 
    (*scalar_array)[7] = miaux_fit(position, 0, 1, root->a, tip->a); 
    *scalar_array += 8; 
} 
 
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:40