Shader hair_geo_datafile

Click on the filename to display or download the file.

hair_geo_datafile.mi
declare shader 
    geometry "hair_geo_datafile" ( 
	string "name", 
        scalar "radius" default .1, 
	string "particle_filename" ) 
    version 1 
    apply material 
end declare 

hair_geo_datafile.c
#include "shader.h" 
#include "geoshader.h" 
#include "miaux.h" 
 
miBoolean hair_geo_datafile_callback(miTag tag, void *ptr); 
 
typedef struct { 
    miTag name; 
    miScalar radius; 
    miTag particle_filename; 
} hair_geo_datafile_t; 
 
DLLEXPORT 
int hair_geo_datafile_version(void) { return 1; } 
 
void hair_geo_datafile_bbox(miObject *obj, void* params) 
{ 
   hair_geo_datafile_t *hairdata = (hair_geo_datafile_t*)params; 
   char* particle_filename;  
   particle_filename =  
       miaux_tag_to_string(hairdata->particle_filename, NULL); 
   if (particle_filename == NULL) 
       mi_fatal("Particle filename required for hair_geo_datafile."); 
   miaux_hair_data_file_bounding_box( 
       particle_filename, 
       &obj->bbox_min.x, &obj->bbox_min.y, &obj->bbox_min.z, 
       &obj->bbox_max.x, &obj->bbox_max.y, &obj->bbox_max.z); 
} 
 
DLLEXPORT 
miBoolean hair_geo_datafile ( 
    miTag *result, miState *state, hair_geo_datafile_t *params  ) 
{ 
    hair_geo_datafile_t *hairdata =  
        (hair_geo_datafile_t*)mi_mem_allocate(sizeof(hair_geo_datafile_t)); 
    hairdata->radius = *mi_eval_scalar(&params->radius); 
    hairdata->particle_filename = *mi_eval_tag(&params->particle_filename); 
 
    miaux_define_hair_object( 
        hairdata->name, hair_geo_datafile_bbox, hairdata, result,  
        hair_geo_datafile_callback); 
 
    return miTRUE; 
} 
 
miBoolean hair_geo_datafile_callback(miTag tag, void *ptr) 
{ 
    miHair_list *hair; 
    hair_geo_datafile_t *hairdata = (hair_geo_datafile_t *)ptr; 
 
    mi_api_incremental(miTRUE); 
    miaux_define_hair_object( 
        hairdata->name, hair_geo_datafile_bbox, hairdata, NULL, NULL); 
    hair = mi_api_hair_begin(); 
    hair->approx = hair->degree = 1; 
 
    miaux_read_hair_data_file( 
        miaux_tag_to_string(hairdata->particle_filename, NULL), 
        hairdata->radius); 
    mi_api_hair_end(); 
    mi_api_object_end(); 
    return miTRUE; 
} 

hair_geo_datafile_util.c
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_hair_data_file_bounding_box( 
    char* filename, 
    float *xmin, float *ymin, float *zmin,  
    float *xmax, float *ymax, float *zmax) 
{ 
    int hair_count, data_count; 
    FILE* fp = fopen(filename, "r"); 
    fscanf(fp, "%d %d ", &hair_count, &data_count); /* Ignore. */ 
    fscanf(fp, "%f %f %f %f %f %f ", xmin, ymin, zmin, xmax, ymax, zmax); 
    fclose(fp); 
} 
 
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); 
    } 
} 
 
void miaux_read_hair_data_file(char* filename, miScalar radius) 
{ 
    int vertex_count, total_vertex_count, hair_scalar_size, vertex_total = 0, 
	index_array_size, v, *hair_indices, *hi, hair_count, per_hair_scalars; 
    float xmin, ymin, zmin, xmax, ymax, zmax, age; 
    miScalar coord, *hair_scalars; 
    miGeoIndex *harray; 
    FILE *fp; 
 
    fp = fopen(filename, "r"); 
    fscanf(fp, "%d %d ", &hair_count, &total_vertex_count); 
    fscanf(fp, "%f %f %f %f %f %f ",  
	   &xmin, &ymin, &zmin, &xmax, &ymax, &zmax); 
    mi_progress("particle bounding box: %f %f %f %f %f %f ", 
		xmin, ymin, zmin, xmax, ymax, zmax); 
 
    per_hair_scalars = 2; 
    mi_api_hair_info(0, 'r', 1); 
    mi_api_hair_info(0, 't', 1); 
 
    hair_scalar_size = hair_count * per_hair_scalars + total_vertex_count * 3; 
    hair_scalars = mi_api_hair_scalars_begin(hair_scalar_size); 
 
    index_array_size = 1 + hair_count; 
    hi = hair_indices = (int*)mi_mem_allocate(sizeof(int) * index_array_size); 
    *hi++ = 0; 
    vertex_total = 0; 
 
    while (!feof(fp)) { 
	*hair_scalars++ = radius; 
	fscanf(fp, "%f ", &age); 
	*hair_scalars++ = age;  
	fscanf(fp, "%d ", &vertex_count); 
	for (v = 0; v < vertex_count * 3; v++) { 
	    fscanf(fp, "%f ", &coord); 
	    *hair_scalars++ = coord; 
	} 
	vertex_total += vertex_count * 3 + per_hair_scalars; 
	*hi++ = vertex_total; 
    } 
    mi_api_hair_scalars_end(hair_scalar_size); 
    harray = mi_api_hair_hairs_begin(index_array_size); 
    memcpy(harray, hair_indices, index_array_size * sizeof(int)); 
    mi_api_hair_hairs_end(); 
} 

22 April 2008 23:40:45