Click on the filename to display or download the file.
hair_geo_row.mi
declare shader
geometry "hair_geo_row" (
string "name",
integer "count" default 1,
scalar "radius" default .01,
vector "bbox_min" default -.5 -.5 -.5,
vector "bbox_max" default .5 .5 .5,
scalar "y_offset_max" default .01,
scalar "z_offset_max" default .01,
integer "approximation" default 100,
integer "degree" default 3,
integer "random_seed" default 1955 )
version 1
apply material
end declare
hair_geo_row.c
#include "shader.h"
#include "geoshader.h"
#include "miaux.h"
typedef struct {
miTag name;
miInteger count;
miScalar radius;
miVector bbox_min;
miVector bbox_max;
miScalar y_offset_max;
miScalar z_offset_max;
miInteger approximation;
miInteger degree;
miInteger random_seed;
} hair_geo_row_t;
DLLEXPORT
int hair_geo_row_version(void) { return 1; }
void hair_geo_row_bbox(miObject *obj, void* params)
{
hair_geo_row_t *p = (hair_geo_row_t*)params;
obj->bbox_min = p->bbox_min;
obj->bbox_max = p->bbox_max;
}
miBoolean hair_geo_row_callback(miTag tag, void *ptr);
DLLEXPORT
miBoolean hair_geo_row (
miTag *result, miState *state, hair_geo_row_t *params )
{
hair_geo_row_t *p =
(hair_geo_row_t*) mi_mem_allocate(sizeof(hair_geo_row_t));
p->name = *mi_eval_tag(¶ms->name);
p->count = *mi_eval_integer(¶ms->count);
p->radius = *mi_eval_scalar(¶ms->radius);
p->bbox_min = *mi_eval_vector(¶ms->bbox_min);
p->bbox_max = *mi_eval_vector(¶ms->bbox_max);
p->y_offset_max = *mi_eval_scalar(¶ms->y_offset_max);
p->z_offset_max = *mi_eval_scalar(¶ms->z_offset_max);
p->approximation = *mi_eval_integer(¶ms->approximation);
p->degree = *mi_eval_integer(¶ms->degree);
p->random_seed = *mi_eval_integer(¶ms->random_seed);
miaux_define_hair_object(
p->name, hair_geo_row_bbox, p, result, hair_geo_row_callback);
return miTRUE;
}
miBoolean hair_geo_row_callback(miTag tag, void *ptr)
{
miHair_list *hair_list;
miGeoIndex *harray;
miScalar *hair_scalars;
int i, h, per_hair_data_count, vertex_count, vertex_size,
per_hair_scalar_count, total_scalar_count;
hair_geo_row_t *p = (hair_geo_row_t *)ptr;
miScalar x, y_offset, z_offset,
yoff_max = p->y_offset_max, zoff_max = p->z_offset_max;
mi_api_incremental(miTRUE);
miaux_define_hair_object(p->name, hair_geo_row_bbox, p, NULL, NULL);
hair_list = mi_api_hair_begin();
hair_list->approx = p->approximation;
hair_list->degree = p->degree;
mi_api_hair_info(0, 'r', 1);
mi_api_hair_info(0, 't', 1);
per_hair_data_count = 2; /* Radius and random value */
vertex_count = 4;
vertex_size = 3;
per_hair_scalar_count =
vertex_count * vertex_size + per_hair_data_count;
total_scalar_count = p->count * per_hair_scalar_count;
hair_scalars = mi_api_hair_scalars_begin(total_scalar_count);
mi_srandom(p->random_seed);
for (i = 0; i < p->count; i++) {
x = miaux_random_range(p->bbox_min.x, p->bbox_max.x);
y_offset = miaux_random_range(-yoff_max, yoff_max);
z_offset = miaux_random_range(-zoff_max, zoff_max);
*hair_scalars++ = p->radius;
*hair_scalars++ = miaux_random_range(0.0, 1.0);
*hair_scalars++ = x;
*hair_scalars++ = p->bbox_min.y + yoff_max + y_offset;
*hair_scalars++ = p->bbox_min.z + zoff_max + z_offset;
*hair_scalars++ = x;
*hair_scalars++ = p->bbox_max.y - yoff_max + y_offset;
*hair_scalars++ = p->bbox_min.z + zoff_max + z_offset;
*hair_scalars++ = x;
*hair_scalars++ = p->bbox_max.y - yoff_max + y_offset;
*hair_scalars++ = p->bbox_max.z - zoff_max + z_offset;
*hair_scalars++ = x;
*hair_scalars++ = p->bbox_min.y + yoff_max + y_offset;
*hair_scalars++ = p->bbox_max.z - zoff_max + z_offset;
}
mi_api_hair_scalars_end(total_scalar_count);
harray = mi_api_hair_hairs_begin(p->count + 1);
for (h=0; h < p->count + 1; h++)
harray[h] = h * per_hair_scalar_count;
mi_api_hair_hairs_end();
mi_api_hair_end();
mi_api_object_end();
return miTRUE;
}
hair_geo_row_util.c
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;
}
result->r += miaux_random_range(-red_variance, red_variance);
result->r = miaux_clamp(result->r, 0.0, 1.0);
result->g += miaux_random_range(-green_variance, green_variance);
result->g = miaux_clamp(result->g, 0.0, 1.0);
result->b += miaux_random_range(-blue_variance, blue_variance);
result->b = miaux_clamp(result->b, 0.0, 1.0);
}
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:42