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 struct scene *create_scene(void)
29 if(!(scn = malloc(sizeof *scn))) {
30 errormsg("failed to allocate scene\n");
33 scn->objects = darr_alloc(0, sizeof *scn->objects);
38 void free_scene(struct scene *scn)
44 for(i=0; i<darr_size(scn->objects); i++) {
45 free_object(scn->objects[i]);
47 darr_free(scn->objects);
51 int scn_add_object(struct scene *scn, struct object *obj)
53 darr_push(scn->objects, &obj);
57 int scn_rm_object(struct scene *scn, int idx)
59 int numobj = darr_size(scn->objects);
61 if(idx < 0 || idx >= numobj) {
65 free_object(scn->objects[idx]);
67 if(idx < numobj - 1) {
68 scn->objects[idx] = scn->objects[numobj - 1];
70 darr_pop(scn->objects);
74 int scn_num_objects(const struct scene *scn)
76 return darr_size(scn->objects);
79 int scn_object_index(const struct scene *scn, const struct object *obj)
81 int i, num = darr_size(scn->objects);
82 for(i=0; i<num; i++) {
83 if(scn->objects[i] == obj) {
90 int scn_intersect(const struct scene *scn, const cgm_ray *ray, struct rayhit *hit)
93 struct rayhit hit0, tmphit;
98 numobj = darr_size(scn->objects);
99 for(i=0; i<numobj; i++) {
100 if(ray_object(ray, scn->objects[i], &tmphit) && tmphit.t < hit0.t) {
112 struct object *create_object(int type)
121 if(!(obj = calloc(1, sizeof *sph))) {
124 sph = (struct sphere*)obj;
126 sprintf(buf, "sphere%03d", objid);
130 if(!(obj = calloc(1, sizeof *obj))) {
133 sprintf(buf, "object%03d", objid);
139 cgm_vcons(&obj->pos, 0, 0, 0);
140 cgm_qcons(&obj->rot, 0, 0, 0, 1);
141 cgm_vcons(&obj->scale, 1, 1, 1);
142 cgm_vcons(&obj->pivot, 0, 0, 0);
143 cgm_midentity(obj->xform);
144 cgm_midentity(obj->inv_xform);
145 obj->xform_valid = 1;
147 set_object_name(obj, buf);
152 errormsg("failed to allocate object\n");
156 void free_object(struct object *obj)
164 int set_object_name(struct object *obj, const char *name)
166 char *str = strdup(name);
174 void calc_object_matrix(struct object *obj)
178 float *mat = obj->xform;
180 cgm_mtranslation(mat, obj->pivot.x, obj->pivot.y, obj->pivot.z);
181 cgm_mrotation_quat(rmat, &obj->rot);
185 mat[4 + i] = rmat[4 + i];
186 mat[8 + i] = rmat[8 + i];
189 mat[0] *= obj->scale.x; mat[4] *= obj->scale.y; mat[8] *= obj->scale.z; mat[12] += obj->pos.x;
190 mat[1] *= obj->scale.x; mat[5] *= obj->scale.y; mat[9] *= obj->scale.z; mat[13] += obj->pos.y;
191 mat[2] *= obj->scale.x; mat[6] *= obj->scale.y; mat[10] *= obj->scale.z; mat[14] += obj->pos.z;
193 cgm_mpretranslate(mat, -obj->pivot.x, -obj->pivot.y, -obj->pivot.z);
194 /* that's basically: pivot * rotation * translation * scaling * -pivot */
196 cgm_mcopy(obj->inv_xform, mat);
197 cgm_minverse(obj->inv_xform);
199 obj->xform_valid = 1;