Click on the filename to display or download the file.
hair_geo_4v_texture.mi
declare shader
geometry "hair_geo_4v_texture" (
string "name",
vector "v1" default -1.5 0 0,
vector "v2" default -.5 0 0,
vector "v3" default .5 0 0,
vector "v4" default 1.5 0 0,
scalar "root_radius" default .1,
color "root_color" default 0 0 0 1,
scalar "tip_radius" default .01,
color "tip_color" default 1 1 1 0,
integer "approximation" default 2,
integer "degree" default 1 )
version 1
apply material
end declare
hair_geo_4v_texture.c
#include "shader.h"
#include "geoshader.h"
#include "miaux.h"
miBoolean hair_geo_4v_texture_callback(miTag tag, void *ptr);
typedef struct {
miTag name;
miVector p1;
miVector p2;
miVector p3;
miVector p4;
miScalar root_radius;
miColor root_color;
miScalar tip_radius;
miColor tip_color;
miInteger approximation;
miInteger degree;
} hair_geo_4v_texture_t;
DLLEXPORT
int hair_geo_4v_texture_version(void) { return 1; }
void hair_geo_4v_texture_bbox(miObject *obj, void* params)
{
hair_geo_4v_texture_t *p = (hair_geo_4v_texture_t*)params;
double max_radius = miaux_max(p->root_radius, p->tip_radius) + .001;
miaux_init_bbox(obj);
miaux_adjust_bbox(obj, &p->p1, max_radius);
miaux_adjust_bbox(obj, &p->p2, max_radius);
miaux_adjust_bbox(obj, &p->p3, max_radius);
miaux_adjust_bbox(obj, &p->p4, max_radius);
miaux_describe_bbox(obj);
}
DLLEXPORT
miBoolean hair_geo_4v_texture (
miTag *result, miState *state, hair_geo_4v_texture_t *params )
{
hair_geo_4v_texture_t *p =
(hair_geo_4v_texture_t*) mi_mem_allocate(sizeof(hair_geo_4v_texture_t));
p->p1 = *mi_eval_vector(¶ms->p1);
p->p2 = *mi_eval_vector(¶ms->p2);
p->p3 = *mi_eval_vector(¶ms->p3);
p->p4 = *mi_eval_vector(¶ms->p4);
p->root_radius = *mi_eval_scalar(¶ms->root_radius);
p->root_color = *mi_eval_color(¶ms->root_color);
p->tip_radius = *mi_eval_scalar(¶ms->tip_radius);
p->tip_color = *mi_eval_color(¶ms->tip_color);
p->approximation = *mi_eval_integer(¶ms->approximation);
p->degree = *mi_eval_integer(¶ms->degree);
miaux_define_hair_object(
p->name, hair_geo_4v_texture_bbox, p, result,
hair_geo_4v_texture_callback);
return miTRUE;
}
miBoolean hair_geo_4v_texture_callback(miTag tag, void *ptr)
{
miHair_list *hair_list;
miScalar *hair_scalars;
miGeoIndex *hair_indices;
hair_geo_4v_texture_t *p = (hair_geo_4v_texture_t *)ptr;
int i;
int hair_count = 1;
int vertices_per_hair = 4;
int scalars_per_vertex = 8;
int hair_scalar_count = vertices_per_hair * scalars_per_vertex;
miVector vertices[4];
vertices[0] = p->p1;
vertices[1] = p->p2;
vertices[2] = p->p3;
vertices[3] = p->p4;
mi_api_incremental(miTRUE);
miaux_define_hair_object(
p->name, hair_geo_4v_texture_bbox, p, NULL, NULL);
hair_list = mi_api_hair_begin();
hair_list->approx = p->approximation;
hair_list->degree = p->degree;
mi_api_hair_info(1, 'r', 1);
mi_api_hair_info(1, 't', 4);
hair_scalars = mi_api_hair_scalars_begin(hair_scalar_count);
for (i = 0; i < vertices_per_hair; i++)
miaux_append_hair_data(
&hair_scalars, &vertices[i],
miaux_fit(i, 0, vertices_per_hair, 0, 1),
p->root_radius, &p->root_color, p->tip_radius, &p->tip_color);
mi_api_hair_scalars_end(hair_scalar_count);
hair_indices = mi_api_hair_hairs_begin(hair_count + 1);
hair_indices[0] = 0;
hair_indices[1] = hair_scalar_count;
mi_api_hair_hairs_end();
mi_api_hair_end();
mi_api_object_end();
return miTRUE;
}
hair_geo_4v_texture_util.c
double miaux_max(double a, double b)
{
return a > b ? a : b;
}
void miaux_init_bbox(miObject *obj)
{
obj->bbox_min.x = miHUGE_SCALAR;
obj->bbox_min.y = miHUGE_SCALAR;
obj->bbox_min.z = miHUGE_SCALAR;
obj->bbox_max.x = -miHUGE_SCALAR;
obj->bbox_max.y = -miHUGE_SCALAR;
obj->bbox_max.z = -miHUGE_SCALAR;
}
void miaux_adjust_bbox(miObject *obj, miVector *v, miScalar extra)
{
miVector v_extra, vmin, vmax;
miaux_set_vector(&v_extra, extra, extra, extra);
mi_vector_sub(&vmin, v, &v_extra);
mi_vector_add(&vmax, v, &v_extra);
mi_vector_min(&obj->bbox_min, &obj->bbox_min, &vmin);
mi_vector_max(&obj->bbox_max, &obj->bbox_max, &vmax);
}
void miaux_set_vector(miVector *v, double x, double y, double z)
{
v->x = x;
v->y = y;
v->z = z;
}
void miaux_describe_bbox(miObject *obj)
{
mi_progress("Object bbox: %f,%f,%f %f,%f,%f",
obj->bbox_min.x, obj->bbox_min.y, obj->bbox_min.z,
obj->bbox_max.x, obj->bbox_max.y, obj->bbox_max.z);
}
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;
}
void miaux_append_hair_data(
miScalar **scalar_array, miVector *v, miScalar position,
miScalar root_radius, miColor *root, miScalar tip_radius, miColor *tip )
{
(*scalar_array)[0] = v->x;
(*scalar_array)[1] = v->y;
(*scalar_array)[2] = v->z;
(*scalar_array)[3] = miaux_fit(position, 0, 1, root_radius, tip_radius);
(*scalar_array)[4] = miaux_fit(position, 0, 1, root->r, tip->r);
(*scalar_array)[5] = miaux_fit(position, 0, 1, root->g, tip->g);
(*scalar_array)[6] = miaux_fit(position, 0, 1, root->b, tip->b);
(*scalar_array)[7] = miaux_fit(position, 0, 1, root->a, tip->a);
*scalar_array += 8;
}
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:40