fix dos build
[retroray] / src / scene.c
index 4f78861..0ac2e71 100644 (file)
@@ -16,7 +16,9 @@ You should have received a copy of the GNU General Public License
 along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
 #include <stdlib.h>
+#include <float.h>
 #include "scene.h"
+#include "rt.h"
 #include "darray.h"
 #include "logger.h"
 
@@ -52,11 +54,61 @@ int scn_add_object(struct scene *scn, struct object *obj)
        return 0;
 }
 
-int scn_num_objects(struct scene *scn)
+int scn_rm_object(struct scene *scn, int idx)
+{
+       int numobj = darr_size(scn->objects);
+
+       if(idx < 0 || idx >= numobj) {
+               return -1;
+       }
+
+       free_object(scn->objects[idx]);
+
+       if(idx < numobj - 1) {
+               scn->objects[idx] = scn->objects[numobj - 1];
+       }
+       darr_pop(scn->objects);
+       return 0;
+}
+
+int scn_num_objects(const struct scene *scn)
 {
        return darr_size(scn->objects);
 }
 
+int scn_object_index(const struct scene *scn, const struct object *obj)
+{
+       int i, num = darr_size(scn->objects);
+       for(i=0; i<num; i++) {
+               if(scn->objects[i] == obj) {
+                       return i;
+               }
+       }
+       return -1;
+}
+
+int scn_intersect(const struct scene *scn, const cgm_ray *ray, struct rayhit *hit)
+{
+       int i, numobj;
+       struct rayhit hit0, tmphit;
+
+       hit0.t = FLT_MAX;
+       hit0.obj = 0;
+
+       numobj = darr_size(scn->objects);
+       for(i=0; i<numobj; i++) {
+               if(ray_object(ray, scn->objects[i], &tmphit) && tmphit.t < hit0.t) {
+                       hit0 = tmphit;
+               }
+       }
+
+       if(hit0.obj) {
+               if(hit) *hit = hit0;
+               return 1;
+       }
+       return 0;
+}
+
 struct object *create_object(int type)
 {
        struct object *obj;
@@ -64,33 +116,41 @@ struct object *create_object(int type)
        char buf[32];
        static int objid;
 
-       if(!(obj = malloc(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);
-
        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;
+
        set_object_name(obj, buf);
        objid++;
        return obj;
+
+err:
+       errormsg("failed to allocate object\n");
+       return 0;
 }
 
 void free_object(struct object *obj)
@@ -131,6 +191,10 @@ void calc_object_matrix(struct object *obj)
        mat[2] *= obj->scale.x; mat[6] *= obj->scale.y; mat[10] *= obj->scale.z; mat[14] += obj->pos.z;
 
        cgm_mpretranslate(mat, -obj->pivot.x, -obj->pivot.y, -obj->pivot.z);
-
        /* that's basically: pivot * rotation * translation * scaling * -pivot */
+
+       cgm_mcopy(obj->inv_xform, mat);
+       cgm_minverse(obj->inv_xform);
+
+       obj->xform_valid = 1;
 }