+
+static void add_sphere(void)
+{
+ struct object *obj;
+
+ if(!(obj = create_object(OBJ_SPHERE))) {
+ return;
+ }
+ scn_add_object(scn, obj);
+}
+
+static void tbn_callback(rtk_widget *w, void *cls)
+{
+ int i, id = (intptr_t)cls;
+ int idx;
+
+ switch(id) {
+ case TBN_SEL:
+ case TBN_MOVE:
+ case TBN_ROT:
+ case TBN_SCALE:
+ idx = id - TBN_SEL;
+ if(0) {
+ case TBN_UNION:
+ case TBN_ISECT:
+ case TBN_DIFF:
+ idx = id - TBN_UNION + TOOL_UNION;
+ }
+ cur_tool = idx;
+ for(i=0; i<NUM_TOOLS; i++) {
+ if(i != cur_tool) {
+ rtk_set_value(tools[i], 0);
+ }
+ }
+ break;
+
+ case TBN_ADD:
+ idx = scn_num_objects(scn);
+ add_sphere();
+ selobj = idx;
+ break;
+
+ case TBN_RM:
+ if(selobj >= 0) {
+ scn_rm_object(scn, selobj);
+ selobj = -1;
+ app_redisplay();
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+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;
+}