From: John Tsiombikas Date: Mon, 12 Jun 2023 23:14:28 +0000 (+0300) Subject: object move tool X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=commitdiff_plain;h=070c37ff23e40cc9ca992f25af41e4cbdcb28add;p=retroray object move tool --- diff --git a/src/rt.c b/src/rt.c index e94ac19..f917836 100644 --- a/src/rt.c +++ b/src/rt.c @@ -17,8 +17,20 @@ along with this program. If not, see . */ #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); +} diff --git a/src/rt.h b/src/rt.h index 4252281..9390bd9 100644 --- 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_ */ diff --git a/src/scene.c b/src/scene.c index 4994257..0ac2e71 100644 --- a/src/scene.c +++ b/src/scene.c @@ -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; 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; } } @@ -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; } diff --git a/src/scene.h b/src/scene.h index d12dae6..7d4cd22 100644 --- a/src/scene.h +++ b/src/scene.h @@ -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; diff --git a/src/scr_mod.c b/src/scr_mod.c index 0a17745..680c754 100644 --- a/src/scr_mod.c +++ b/src/scr_mod.c @@ -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; +}