2 RetroRay - integrated standalone vintage modeller/renderer
3 Copyright (C) 2023 John Tsiombikas <nuclear@mutantstargoat.com>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>.
25 static struct material *default_material(void);
27 struct scene *create_scene(void)
31 if(!(scn = malloc(sizeof *scn))) {
32 errormsg("failed to allocate scene\n");
35 scn->objects = darr_alloc(0, sizeof *scn->objects);
36 scn->lights = darr_alloc(0, sizeof *scn->lights);
37 scn->mtl = darr_alloc(0, sizeof *scn->mtl);
41 void free_scene(struct scene *scn)
47 darr_free(scn->objects);
48 darr_free(scn->lights);
53 void scn_clear(struct scene *scn)
57 for(i=0; i<darr_size(scn->objects); i++) {
58 free_object(scn->objects[i]);
60 darr_clear(scn->objects);
62 for(i=0; i<darr_size(scn->lights); i++) {
63 free_light(scn->lights[i]);
65 darr_clear(scn->lights);
67 for(i=0; i<darr_size(scn->mtl); i++) {
68 mtl_destroy(scn->mtl[i]);
74 int scn_add_object(struct scene *scn, struct object *obj)
76 darr_push(scn->objects, &obj);
80 int scn_rm_object(struct scene *scn, int idx)
82 int numobj = darr_size(scn->objects);
84 if(idx < 0 || idx >= numobj) {
88 free_object(scn->objects[idx]);
90 if(idx < numobj - 1) {
91 scn->objects[idx] = scn->objects[numobj - 1];
93 darr_pop(scn->objects);
97 int scn_num_objects(const struct scene *scn)
99 return darr_size(scn->objects);
102 int scn_object_index(const struct scene *scn, const struct object *obj)
104 int i, num = darr_size(scn->objects);
105 for(i=0; i<num; i++) {
106 if(scn->objects[i] == obj) {
115 int scn_add_material(struct scene *scn, struct material *mtl)
117 darr_push(scn->mtl, &mtl);
121 int scn_rm_material(struct scene *scn, struct material *mtl)
125 if((idx = scn_material_index(scn, mtl)) == -1) {
129 num_mtl = darr_size(scn->mtl);
131 if(idx < num_mtl - 1) {
132 scn->mtl[idx] = scn->mtl[num_mtl - 1];
138 int scn_num_materials(const struct scene *scn)
140 return darr_size(scn->mtl);
143 int scn_material_index(const struct scene *scn, const struct material *mtl)
147 num_mtl = darr_size(scn->mtl);
148 for(i=0; i<num_mtl; i++) {
149 if(scn->mtl[i] == mtl) {
156 struct material *scn_find_material(const struct scene *scn, const char *mname)
160 num_mtl = darr_size(scn->mtl);
161 for(i=0; i<num_mtl; i++) {
162 if(strcmp(scn->mtl[i]->name, mname) == 0) {
171 int scn_add_light(struct scene *scn, struct light *light)
173 darr_push(scn->lights, &light);
177 int scn_rm_light(struct scene *scn, struct light *light)
181 if((idx = scn_light_index(scn, light)) == -1) {
185 num_lights = darr_size(scn->lights);
187 if(idx < num_lights - 1) {
188 scn->lights[idx] = scn->lights[num_lights - 1];
190 darr_pop(scn->lights);
194 int scn_num_lights(const struct scene *scn)
196 return darr_size(scn->lights);
199 int scn_light_index(const struct scene *scn, const struct light *light)
203 num_lights = darr_size(scn->lights);
204 for(i=0; i<num_lights; i++) {
205 if(scn->lights[i] == light) {
212 struct light *scn_find_light(const struct scene *scn, const char *mname)
216 num_lights = darr_size(scn->lights);
217 for(i=0; i<num_lights; i++) {
218 if(strcmp(scn->lights[i]->name, mname) == 0) {
219 return scn->lights[i];
226 int scn_intersect(const struct scene *scn, const cgm_ray *ray, struct rayhit *hit)
229 struct rayhit hit0, tmphit;
234 numobj = darr_size(scn->objects);
235 for(i=0; i<numobj; i++) {
236 if(ray_object(ray, scn->objects[i], &tmphit) && tmphit.t < hit0.t) {
249 /* --- object functions --- */
251 struct object *create_object(int type)
260 if(!(obj = calloc(1, sizeof *sph))) {
263 sph = (struct sphere*)obj;
265 sprintf(buf, "sphere%03d", objid);
269 if(!(obj = calloc(1, sizeof *obj))) {
272 sprintf(buf, "object%03d", objid);
278 cgm_vcons(&obj->pos, 0, 0, 0);
279 cgm_qcons(&obj->rot, 0, 0, 0, 1);
280 cgm_vcons(&obj->scale, 1, 1, 1);
281 cgm_vcons(&obj->pivot, 0, 0, 0);
282 cgm_midentity(obj->xform);
283 cgm_midentity(obj->inv_xform);
284 obj->xform_valid = 1;
285 obj->mtl = default_material();
287 set_object_name(obj, buf);
292 errormsg("failed to allocate object\n");
296 void free_object(struct object *obj)
304 int set_object_name(struct object *obj, const char *name)
306 char *str = strdup(name);
314 void calc_object_matrix(struct object *obj)
318 float *mat = obj->xform;
320 cgm_mtranslation(mat, obj->pivot.x, obj->pivot.y, obj->pivot.z);
321 cgm_mrotation_quat(rmat, &obj->rot);
325 mat[4 + i] = rmat[4 + i];
326 mat[8 + i] = rmat[8 + i];
329 mat[0] *= obj->scale.x; mat[4] *= obj->scale.y; mat[8] *= obj->scale.z; mat[12] += obj->pos.x;
330 mat[1] *= obj->scale.x; mat[5] *= obj->scale.y; mat[9] *= obj->scale.z; mat[13] += obj->pos.y;
331 mat[2] *= obj->scale.x; mat[6] *= obj->scale.y; mat[10] *= obj->scale.z; mat[14] += obj->pos.z;
333 cgm_mpretranslate(mat, -obj->pivot.x, -obj->pivot.y, -obj->pivot.z);
334 /* that's basically: pivot * rotation * translation * scaling * -pivot */
336 cgm_mcopy(obj->inv_xform, mat);
337 cgm_minverse(obj->inv_xform);
339 obj->xform_valid = 1;
343 struct light *create_light(void)
349 if(!(lt = malloc(sizeof *lt))) {
352 cgm_vcons(<->pos, 0, 0, 0);
354 set_light_color(lt, 1, 1, 1);
355 set_light_energy(lt, 1);
357 sprintf(buf, "light%03d", ltidx++);
358 set_light_name(lt, buf);
363 void free_light(struct light *lt)
370 int set_light_name(struct light *lt, const char *name)
372 char *tmp = strdup(name);
379 void set_light_color(struct light *lt, float r, float g, float b)
381 cgm_vcons(<->orig_color, r, g, b);
382 lt->color = lt->orig_color;
383 cgm_vscale(<->color, lt->energy);
386 void set_light_energy(struct light *lt, float e)
389 lt->color = lt->orig_color;
390 cgm_vscale(<->color, e);
393 static struct material *default_material(void)
395 static struct material defmtl;
399 mtl_set_name(&defmtl, "default_mtl");