Click on the filename to display or download the file.
density_volume.mi
declare shader
color "density_volume" (
color "color" default 1 1 1 1,
vector "center" default 0 0 0,
scalar "radius" default 1,
scalar "unit_density" default 1,
scalar "march_increment" default 0.1 )
version 1
apply volume
end declare
density_volume.c
#include "shader.h"
#include "miaux.h"
struct density_volume {
miColor color;
miVector center;
miScalar radius;
miScalar unit_density;
miScalar march_increment;
};
DLLEXPORT
int density_volume_version(void) { return 1; }
DLLEXPORT
miBoolean density_volume (
miColor *result, miState *state, struct density_volume *params )
{
miScalar march_increment = *mi_eval_scalar(¶ms->march_increment);
miColor *color = mi_eval_color(¶ms->color);
miVector *center = mi_eval_vector(¶ms->center);
miScalar radius = *mi_eval_scalar(¶ms->radius);
miScalar unit_density = *mi_eval_scalar(¶ms->unit_density);
miScalar distance, accumulated_density = 0.0;
miVector march_point, internal_center;
mi_point_from_object(state, &internal_center, center);
for (distance = 0; distance <= state->dist; distance += march_increment) {
miaux_march_point(&march_point, state, distance);
accumulated_density +=
miaux_density_falloff(&march_point, &internal_center, radius,
unit_density, march_increment);
if (accumulated_density > 1.0) {
accumulated_density = 1.0;
break;
}
}
if (accumulated_density > 0.0)
miaux_blend_colors(result, result, color, 1.0 - accumulated_density);
return miTRUE;
}
density_volume_util.c
void miaux_march_point(
miVector *result, miState *state, miScalar distance)
{
miaux_point_along_vector(result, &state->org, &state->dir, distance);
}
void miaux_point_along_vector(
miVector *result, miVector *point, miVector *direction, miScalar distance)
{
result->x = point->x + distance * direction->x;
result->y = point->y + distance * direction->y;
result->z = point->z + distance * direction->z;
}
miScalar miaux_density_falloff(
miVector *point, miVector *center, miScalar radius,
miScalar unit_density, miScalar march_increment)
{
return march_increment * unit_density *
miaux_fit_clamp(mi_vector_dist(center, point), 0.0, radius, 1.0, 0.0);
}
double miaux_fit_clamp(
double v, double oldmin, double oldmax, double newmin, double newmax)
{
if (oldmin > oldmax) {
double temp = oldmin;
oldmin = oldmax;
oldmax = oldmin;
temp = newmin;
newmin = newmax;
newmax = newmin;
}
if (v < oldmin)
return newmin;
else if (v > oldmax)
return newmax;
else
return miaux_fit(v, oldmin, oldmax, newmin, newmax);
}
double miaux_fit(
double v, double oldmin, double oldmax, double newmin, double newmax)
{
return newmin + ((v - oldmin) / (oldmax - oldmin)) * (newmax - newmin);
}
void miaux_blend_colors(miColor *result,
miColor *color1, miColor *color2, miScalar factor)
{
result->r = miaux_blend(color1->r, color2->r, factor);
result->g = miaux_blend(color1->g, color2->g, factor);
result->b = miaux_blend(color1->b, color2->b, factor);
}
double miaux_blend(miScalar a, miScalar b, miScalar factor)
{
return a * factor + b * (1.0 - factor);
}
22 April 2008 23:40:53