+
+static void draw_rband(void)
+{
+ int i, x, y, w, h;
+ uint32_t *fbptr, *bptr;
+
+ x = rband.x;
+ y = rband.y;
+
+ if(rband.width < 0) {
+ w = -rband.width;
+ x += rband.width;
+ } else {
+ w = rband.width;
+ }
+ if(rband.height < 0) {
+ h = -rband.height;
+ y += rband.height;
+ } else {
+ h = rband.height;
+ }
+
+ fbptr = framebuf + y * win_width + x;
+ bptr = fbptr + win_width * (h - 1);
+
+ for(i=0; i<w; i++) {
+ fbptr[i] ^= 0xffffff;
+ bptr[i] ^= 0xffffff;
+ }
+ fbptr += win_width;
+ for(i=0; i<h-2; i++) {
+ fbptr[0] ^= 0xffffff;
+ fbptr[w - 1] ^= 0xffffff;
+ fbptr += win_width;
+ }
+}
+
+static void primray(cgm_ray *ray, int x, int y)
+{
+ float nx, ny;
+ cgm_vec3 npos, farpt;
+ float inv_pv[16];
+
+ y = win_height - y;
+ nx = (float)(x - viewport[0]) / (float)viewport[2];
+ ny = (float)(y - viewport[1]) / (float)viewport[3];
+
+ cgm_mcopy(inv_pv, proj_matrix_inv);
+ cgm_mmul(inv_pv, view_matrix_inv);
+
+ cgm_vcons(&npos, nx, ny, 0.0f);
+ cgm_unproject(&ray->origin, &npos, inv_pv);
+ npos.z = 1.0f;
+ cgm_unproject(&farpt, &npos, inv_pv);
+
+ ray->dir.x = farpt.x - ray->origin.x;
+ 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;
+}