*/
#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;
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);
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;
{
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);
+}
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_ */
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;
}
}
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)
cgm_mcopy(obj->inv_xform, mat);
cgm_minverse(obj->inv_xform);
+
+ obj->xform_valid = 1;
}
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;
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 = {
static rtk_rect rband;
static int rband_valid;
+
static int mdl_init(void)
{
int i, toolidx;
{
struct sphere *sph;
- calc_object_matrix(obj);
+ if(!obj->xform_valid) {
+ calc_object_matrix(obj);
+ }
gaw_push_matrix();
gaw_mult_matrix(obj->xform);
}
} 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();
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;
+}