object move tool
authorJohn Tsiombikas <nuclear@member.fsf.org>
Mon, 12 Jun 2023 23:14:28 +0000 (02:14 +0300)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Mon, 12 Jun 2023 23:14:28 +0000 (02:14 +0300)
src/rt.c
src/rt.h
src/scene.c
src/scene.h
src/scr_mod.c

index e94ac19..f917836 100644 (file)
--- a/src/rt.c
+++ b/src/rt.c
@@ -17,8 +17,20 @@ along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
 #include "rt.h"
 
+int ray_object(const cgm_ray *ray, const struct object *obj, struct rayhit *hit)
+{
+       struct csghit csghit;
 
-int ray_object(const cgm_ray *ray, const struct object *obj, struct csghit *hit)
+       if(!ray_object_csg(ray, obj, &csghit)) {
+               return 0;
+       }
+       if(hit) {
+               *hit = csghit.ivlist[0].a;
+       }
+       return 1;
+}
+
+int ray_object_csg(const cgm_ray *ray, const struct object *obj, struct csghit *hit)
 {
        int i, res;
        cgm_ray localray = *ray;
@@ -48,7 +60,7 @@ int ray_object(const cgm_ray *ray, const struct object *obj, struct csghit *hit)
 int ray_sphere(const cgm_ray *ray, const struct sphere *sph, struct csghit *hit)
 {
        int i;
-       float a, b, c, d, sqrt_d, t1, t2, invrad;
+       float a, b, c, d, sqrt_d, t1, t2;/*, invrad;*/
        struct rayhit *rhptr;
 
        a = cgm_vdot(&ray->dir, &ray->dir);
@@ -83,14 +95,16 @@ int ray_sphere(const cgm_ray *ray, const struct sphere *sph, struct csghit *hit)
                hit->ivcount = 1;
                hit->ivlist[0].a.t = t1;
                hit->ivlist[0].b.t = t2;
-               invrad = 1.0f / sph->rad;
+               /*invrad = 1.0f / sph->rad;*/
 
                rhptr = &hit->ivlist[0].a;
                for(i=0; i<2; i++) {
                        cgm_raypos(&rhptr->pos, ray, rhptr->t);
-                       rhptr->norm.x = rhptr->pos.x * invrad;
+                       rhptr->norm = rhptr->pos;
+                       cgm_vnormalize(&rhptr->norm);
+                       /*rhptr->norm.x = rhptr->pos.x * invrad;
                        rhptr->norm.y = rhptr->pos.y * invrad;
-                       rhptr->norm.z = rhptr->pos.z * invrad;
+                       rhptr->norm.z = rhptr->pos.z * invrad;*/
                        rhptr->uv.x = (atan2(rhptr->norm.z, rhptr->norm.x) + CGM_PI) / (2.0 * CGM_PI);
                        rhptr->uv.y = acos(rhptr->norm.y) / CGM_PI;
                        rhptr->obj = (struct object*)sph;
@@ -104,3 +118,22 @@ int ray_csg(const cgm_ray *ray, const struct csgnode *csg, struct csghit *hit)
 {
        return 0;
 }
+
+float ray_object_dist(const cgm_ray *ray, const struct object *obj)
+{
+       /*struct rayhit hit;*/
+       cgm_vec3 norm, pvec;
+
+       /*if(ray_object(ray, obj, &hit)) {
+               return cgm_vdist(&hit.pos, &ray->origin);
+       }*/
+
+       /* if we can't hit the object for some reason, fallback to computing the
+        * distance of obj->pos from the plane perpendicular to the ray at the origin
+        */
+       norm = ray->dir;
+       /*cgm_vnormalize(&norm);*/
+       pvec = obj->pos;
+       cgm_vsub(&pvec, &ray->origin);
+       return cgm_vdot(&pvec, &norm);
+}
index 4252281..9390bd9 100644 (file)
--- a/src/rt.h
+++ b/src/rt.h
@@ -39,8 +39,12 @@ struct csghit {
        int ivcount;
 };
 
-int ray_object(const cgm_ray *ray, const struct object *obj, struct csghit *hit);
+int ray_object(const cgm_ray *ray, const struct object *obj, struct rayhit *hit);
+int ray_object_csg(const cgm_ray *ray, const struct object *obj, struct csghit *hit);
+
 int ray_sphere(const cgm_ray *ray, const struct sphere *sph, struct csghit *hit);
 int ray_csg(const cgm_ray *ray, const struct csgnode *csg, struct csghit *hit);
 
+float ray_object_dist(const cgm_ray *ray, const struct object *obj);
+
 #endif /* RT_H_ */
index 4994257..0ac2e71 100644 (file)
@@ -90,16 +90,15 @@ int scn_object_index(const struct scene *scn, const struct object *obj)
 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; i<numobj; i++) {
-               if(ray_object(ray, scn->objects[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;
                }
        }
 
@@ -117,34 +116,41 @@ 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;
+
        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 +195,6 @@ void calc_object_matrix(struct object *obj)
 
        cgm_mcopy(obj->inv_xform, mat);
        cgm_minverse(obj->inv_xform);
+
+       obj->xform_valid = 1;
 }
index d12dae6..7d4cd22 100644 (file)
@@ -31,7 +31,8 @@ enum {
        char *name; \
        cgm_vec3 pos, scale, pivot; \
        cgm_quat rot; \
-       float xform[16], inv_xform[16]
+       float xform[16], inv_xform[16]; \
+       int xform_valid
 
 struct object {
        OBJ_COMMON_ATTR;
index 0a17745..680c754 100644 (file)
@@ -83,6 +83,7 @@ static void tbn_callback(rtk_widget *w, void *cls);
 
 static void draw_rband(void);
 static void primray(cgm_ray *ray, int x, int y);
+static void moveobj(struct object *obj, int px0, int py0, int px1, int py1);
 
 
 struct app_screen scr_model = {
@@ -110,6 +111,7 @@ static int selobj = -1;
 static rtk_rect rband;
 static int rband_valid;
 
+
 static int mdl_init(void)
 {
        int i, toolidx;
@@ -233,7 +235,9 @@ static void draw_object(struct object *obj)
 {
        struct sphere *sph;
 
-       calc_object_matrix(obj);
+       if(!obj->xform_valid) {
+               calc_object_matrix(obj);
+       }
        gaw_push_matrix();
        gaw_mult_matrix(obj->xform);
 
@@ -362,10 +366,24 @@ static void mdl_motion(int x, int y)
                }
        } else {
                if(mouse_state[0]) {
-                       if(rband.x != x || rband.y != y) {
-                               rband.width = x - rband.x;
-                               rband.height = y - rband.y;
-                               rband_valid = 1;
+                       switch(cur_tool) {
+                       case TOOL_SEL:
+                               if(rband.x != x || rband.y != y) {
+                                       rband.width = x - rband.x;
+                                       rband.height = y - rband.y;
+                                       rband_valid = 1;
+                               }
+                               break;
+
+                       case TOOL_MOVE:
+                               if(selobj >= 0) {
+                                       struct object *obj = scn->objects[selobj];
+                                       moveobj(obj, mouse_x, mouse_y, x, y);
+                               }
+                               break;
+
+                       default:
+                               break;
                        }
                }
                app_redisplay();
@@ -484,3 +502,22 @@ static void primray(cgm_ray *ray, int x, int y)
        ray->dir.y = farpt.y - ray->origin.y;
        ray->dir.z = farpt.z - ray->origin.z;
 }
+
+static void moveobj(struct object *obj, int px0, int py0, int px1, int py1)
+{
+       cgm_ray ray;
+       float dist;
+       cgm_vec3 p0, p1;
+
+       primray(&ray, px0, py0);
+       cgm_vnormalize(&ray.dir);
+       dist = ray_object_dist(&ray, obj);
+       cgm_raypos(&p0, &ray, dist);
+       primray(&ray, px1, py1);
+       cgm_vnormalize(&ray.dir);
+       cgm_raypos(&p1, &ray, dist);
+
+       cgm_vsub(&p1, &p0);
+       cgm_vadd(&obj->pos, &p1);
+       obj->xform_valid = 0;
+}