Shader voxel_density

Click on the filename to display or download the file.

voxel_density.mi
declare shader 
    scalar "voxel_density" ( 
	string "filename", 
	vector "min_point" default -1 -1 -1, 
	vector "max_point" default 1 1 1, 
	color "color" default 1 1 1, ) 
    version 1 
    apply volume 
end declare 

voxel_density.c
#include "shader.h" 
#include "miaux.h" 
 
int voxel_dataset_version(void) { return 1; } 
 
#define MAX_DATASET_SIZE 400*400*400 
 
typedef struct { 
    int width, height, depth; 
    float block[MAX_DATASET_SIZE]; 
} voxel_data; 
 
 
float voxel_value(voxel_data *voxels, float x, float y, float z) 
{ 
    return voxels->block[  
        ((int)(z + .5)) * voxels->depth * voxels->height + 
        ((int)(y + .5)) * voxels->height + 
        ((int)(x + .5)) ]; 
} 
 
struct voxel_density { 
    miTag filename_tag; 
    miVector min_point; 
    miVector max_point; 
    miColor color; 
}; 
 
DLLEXPORT 
int voxel_density_version(void) { return 1; } 
 
DLLEXPORT 
miBoolean voxel_density_init( 
    miState *state, struct voxel_density *params, 
    miBoolean *instance_init_required) 
{ 
    if (!params) {  /* Main shader init (not an instance): */ 
        *instance_init_required = miTRUE; 
    } else {        /* Instance initialization: */ 
        char* filename =  
            miaux_tag_to_string(*mi_eval_tag(&params->filename_tag), NULL); 
        if (filename) { 
            voxel_data *voxels =  
                miaux_user_memory_pointer(state, sizeof(voxel_data)); 
            miaux_read_volume_block( 
                filename, &voxels->width, &voxels->height, &voxels->depth,  
                voxels->block); 
            mi_progress("Voxel dataset: %dx%dx%d",  
                        voxels->width, voxels->height, voxels->depth); 
        } 
    } 
    return miTRUE; 
} 
 
 
DLLEXPORT 
miBoolean voxel_density_exit(miState *state, void *params) 
{ 
    return miaux_release_user_memory("voxel_density", state, params); 
} 
 
 
DLLEXPORT 
miBoolean voxel_density (  
    miScalar *result, miState *state, struct voxel_density *params  ) 
{ 
    miVector *min_point = mi_eval_vector(&params->min_point); 
    miVector *max_point = mi_eval_vector(&params->max_point); 
    miVector *p = &state->point; 
 
    if (miaux_point_inside(p, min_point, max_point)) { 
        float x, y, z; 
        voxel_data *voxels = miaux_user_memory_pointer(state, 0); 
        x = miaux_fit(p->x, min_point->x, max_point->x, 0, voxels->width-1); 
        y = miaux_fit(p->y, min_point->y, max_point->y, 0, voxels->height-1); 
        z = miaux_fit(p->z, min_point->z, max_point->z, 0, voxels->depth-1); 
        *result = voxel_value(voxels, x, y, z); 
    } else  
        *result = 0.0; 
 
    return miTRUE; 
} 

voxel_density_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_user_memory_pointer(miState *state, int allocation_size) 
{ 
    void **user_pointer; 
    mi_query(miQ_FUNC_USERPTR, state, 0, &user_pointer); 
    if (allocation_size > 0) { 
	*user_pointer = mi_mem_allocate(allocation_size); 
    } 
    return *user_pointer; 
} 
 
void miaux_read_volume_block( 
    char* filename,  
    int *width, int *height, int *depth, float* block) 
{ 
    int count; 
    FILE* fp = fopen(filename, "r"); 
    if (fp == NULL) { 
	mi_fatal("Error opening file \"%s\".", filename); 
    } 
    fscanf(fp, "%d %d %d ", width, height, depth); 
    count = (*width) * (*height) * (*depth); 
    mi_progress("Volume dataset: %dx%dx%d", *width, *height, *depth); 
    fread(block, sizeof(float), count, fp); 
} 
 
miBoolean miaux_release_user_memory(char* shader_name, miState *state, void *params) 
{ 
    if (params != NULL) {  /* Shader instance exit */ 
	void **user_pointer;                            
	if (!mi_query(miQ_FUNC_USERPTR, state, 0, &user_pointer)) 
	    mi_fatal("Could not get user pointer in shader exit function %s_exit",  
		     shader_name); 
	mi_mem_release(*user_pointer); 
    } 
    return miTRUE; 
} 
 
miBoolean miaux_point_inside(miVector *p, miVector *min_p, miVector *max_p) 
{ 
    return p->x >= min_p->x && p->y >= min_p->y && p->z >= min_p->z && 
	p->x <= max_p->x && p->y <= max_p->y && p->z <= max_p->z; 
} 
 
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:57