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(¶ms->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(¶ms->min_point);
miVector *max_point = mi_eval_vector(¶ms->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