X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;ds=sidebyside;f=src%2Fscene.c;h=36c9fba9aa0851eda4d5d903e7e62a00f9394dc7;hb=3bf187fe037df34459f04bf4e625f38afb80fcf8;hp=49942579d66c7e6cf0c10bcbf492bf17c2ebb4fa;hpb=15a4548ff09afb37dd33786cafd50b060a64f840;p=retroray diff --git a/src/scene.c b/src/scene.c index 4994257..36c9fba 100644 --- a/src/scene.c +++ b/src/scene.c @@ -18,10 +18,12 @@ along with this program. If not, see . #include #include #include "scene.h" -#include "rt.h" +#include "geom.h" #include "darray.h" #include "logger.h" +static struct material *default_material(void); + struct scene *create_scene(void) { struct scene *scn; @@ -31,7 +33,8 @@ struct scene *create_scene(void) return 0; } scn->objects = darr_alloc(0, sizeof *scn->objects); - + scn->lights = darr_alloc(0, sizeof *scn->lights); + scn->mtl = darr_alloc(0, sizeof *scn->mtl); return scn; } @@ -45,6 +48,18 @@ void free_scene(struct scene *scn) free_object(scn->objects[i]); } darr_free(scn->objects); + + for(i=0; ilights); i++) { + free_light(scn->lights[i]); + } + darr_free(scn->lights); + + for(i=0; imtl); i++) { + mtl_destroy(scn->mtl[i]); + free(scn->mtl[i]); + } + darr_free(scn->mtl); + free(scn); } @@ -87,19 +102,131 @@ int scn_object_index(const struct scene *scn, const struct object *obj) return -1; } + + +int scn_add_material(struct scene *scn, struct material *mtl) +{ + darr_push(scn->mtl, &mtl); + return 0; +} + +int scn_rm_material(struct scene *scn, struct material *mtl) +{ + int idx, num_mtl; + + if((idx = scn_material_index(scn, mtl)) == -1) { + return -1; + } + + num_mtl = darr_size(scn->mtl); + + if(idx < num_mtl - 1) { + scn->mtl[idx] = scn->mtl[num_mtl - 1]; + } + darr_pop(scn->mtl); + return 0; +} + +int scn_num_materials(const struct scene *scn) +{ + return darr_size(scn->mtl); +} + +int scn_material_index(const struct scene *scn, const struct material *mtl) +{ + int i, num_mtl; + + num_mtl = darr_size(scn->mtl); + for(i=0; imtl[i] == mtl) { + return i; + } + } + return -1; +} + +struct material *scn_find_material(const struct scene *scn, const char *mname) +{ + int i, num_mtl; + + num_mtl = darr_size(scn->mtl); + for(i=0; imtl[i]->name, mname) == 0) { + return scn->mtl[i]; + } + } + return 0; +} + +/* manage lights */ + +int scn_add_light(struct scene *scn, struct light *light) +{ + darr_push(scn->lights, &light); + return 0; +} + +int scn_rm_light(struct scene *scn, struct light *light) +{ + int idx, num_lights; + + if((idx = scn_light_index(scn, light)) == -1) { + return -1; + } + + num_lights = darr_size(scn->lights); + + if(idx < num_lights - 1) { + scn->lights[idx] = scn->lights[num_lights - 1]; + } + darr_pop(scn->lights); + return 0; +} + +int scn_num_lights(const struct scene *scn) +{ + return darr_size(scn->lights); +} + +int scn_light_index(const struct scene *scn, const struct light *light) +{ + int i, num_lights; + + num_lights = darr_size(scn->lights); + for(i=0; ilights[i] == light) { + return i; + } + } + return -1; +} + +struct light *scn_find_light(const struct scene *scn, const char *mname) +{ + int i, num_lights; + + num_lights = darr_size(scn->lights); + for(i=0; ilights[i]->name, mname) == 0) { + return scn->lights[i]; + } + } + return 0; +} + + int scn_intersect(const struct scene *scn, const cgm_ray *ray, struct rayhit *hit) { int i, numobj; - struct rayhit hit0; - struct csghit chit; + struct rayhit hit0, tmphit; hit0.t = FLT_MAX; hit0.obj = 0; numobj = darr_size(scn->objects); for(i=0; iobjects[i], &chit) && chit.ivlist[0].a.t < hit0.t) { - hit0 = chit.ivlist[0].a; + if(ray_object(ray, scn->objects[i], &tmphit) && tmphit.t < hit0.t) { + hit0 = tmphit; } } @@ -110,6 +237,9 @@ int scn_intersect(const struct scene *scn, const cgm_ray *ray, struct rayhit *hi return 0; } + +/* --- object functions --- */ + struct object *create_object(int type) { struct object *obj; @@ -117,34 +247,42 @@ struct object *create_object(int type) char buf[32]; static int objid; - if(!(obj = calloc(1, sizeof *obj))) { - errormsg("failed to allocate object\n"); - return 0; - } - obj->type = type; - - cgm_vcons(&obj->pos, 0, 0, 0); - cgm_qcons(&obj->rot, 0, 0, 0, 1); - cgm_vcons(&obj->scale, 1, 1, 1); - cgm_vcons(&obj->pivot, 0, 0, 0); - cgm_midentity(obj->xform); - cgm_midentity(obj->inv_xform); - switch(type) { case OBJ_SPHERE: + if(!(obj = calloc(1, sizeof *sph))) { + goto err; + } sph = (struct sphere*)obj; sph->rad = 1.0f; sprintf(buf, "sphere%03d", objid); break; default: + if(!(obj = calloc(1, sizeof *obj))) { + goto err; + } sprintf(buf, "object%03d", objid); break; } + obj->type = type; + + cgm_vcons(&obj->pos, 0, 0, 0); + cgm_qcons(&obj->rot, 0, 0, 0, 1); + cgm_vcons(&obj->scale, 1, 1, 1); + cgm_vcons(&obj->pivot, 0, 0, 0); + cgm_midentity(obj->xform); + cgm_midentity(obj->inv_xform); + obj->xform_valid = 1; + obj->mtl = default_material(); + set_object_name(obj, buf); objid++; return obj; + +err: + errormsg("failed to allocate object\n"); + return 0; } void free_object(struct object *obj) @@ -189,4 +327,68 @@ void calc_object_matrix(struct object *obj) cgm_mcopy(obj->inv_xform, mat); cgm_minverse(obj->inv_xform); + + obj->xform_valid = 1; +} + +/* --- lights --- */ +struct light *create_light(void) +{ + struct light *lt; + static int ltidx; + char buf[64]; + + if(!(lt = malloc(sizeof *lt))) { + return 0; + } + cgm_vcons(<->pos, 0, 0, 0); + + set_light_color(lt, 1, 1, 1); + set_light_energy(lt, 1); + + sprintf(buf, "light%03d", ltidx++); + set_light_name(lt, buf); + + return lt; +} + +void free_light(struct light *lt) +{ + if(!lt) return; + free(lt->name); + free(lt); +} + +int set_light_name(struct light *lt, const char *name) +{ + char *tmp = strdup(name); + if(!tmp) return -1; + free(lt->name); + lt->name = tmp; + return 0; +} + +void set_light_color(struct light *lt, float r, float g, float b) +{ + cgm_vcons(<->orig_color, r, g, b); + lt->color = lt->orig_color; + cgm_vscale(<->color, lt->energy); +} + +void set_light_energy(struct light *lt, float e) +{ + lt->energy = e; + lt->color = lt->orig_color; + cgm_vscale(<->color, e); +} + +static struct material *default_material(void) +{ + static struct material defmtl; + + if(!defmtl.name) { + mtl_init(&defmtl); + mtl_set_name(&defmtl, "default_mtl"); + } + return &defmtl; }