home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Virtual Reality Zone
/
VRZONE.ISO
/
mac
/
PC
/
REND386
/
VR386
/
MANIP3D.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-01-10
|
7KB
|
251 lines
/* Handles body/head/manipulator mappings */
/* Written by Dave Stampe, August 1992 */
// modified for VRC for better viewpoint control
// and default body ssegment access
// Split up, rearranged, parially ported to VR-3866 API
/*
This code is part of the VR-386 project, created by Dave Stampe.
VR-386 is a desendent of REND386, created by Dave Stampe and
Bernie Roehl. Almost all the code has been rewritten by Dave
Stampre for VR-386.
Copyright (c) 1994 by Dave Stampe:
May be freely used to write software for release into the public domain
or for educational use; all commercial endeavours MUST contact Dave Stampe
(dstampe@psych.toronto.edu) for permission to incorporate any part of
this software or source code into their products! Usually there is no
charge for under 50-100 items for low-cost or shareware products, and terms
are reasonable. Any royalties are used for development, so equipment is
often acceptable payment.
ATTRIBUTION: If you use any part of this source code or the libraries
in your projects, you must give attribution to VR-386 and Dave Stampe,
and any other authors in your documentation, source code, and at startup
of your program. Let's keep the freeware ball rolling!
DEVELOPMENT: VR-386 is a effort to develop the process started by
REND386, improving programmer access by rewriting the code and supplying
a standard API. If you write improvements, add new functions rather
than rewriting current functions. This will make it possible to
include you improved code in the next API release. YOU can help advance
VR-386. Comments on the API are welcome.
CONTACT: dstampe@psych.toronto.edu
*/
#include <stdio.h>
#include <stdlib.h> /* atexit() */
#include <mem.h> /* memcpy() */
#include <dos.h>
#include "pointer.h"
#include "vr_api.h"
#include "segment.h"
#include "intmath.h"
#include "splits.h"
#include "pcdevice.h"
/************* SIMPLE 3D/6D OBJECT MANIPULATION *********/
static OBJECT *sel_obj;
static SEGMENT *work_seg;
static SEGMENT *old_parent;
static SEGMENT *rot_seg = NULL; /* used to rotate objects by center */
static MATRIX ogm;
static long oxp, oyp, ozp;
static long oxg, oyg, ozg;
#define FREE_DO 0 // released
#define GRASP_DO 1 // holding
#define ROTATE_DO 2 // "pinch" rotation emulation for 3D dev.
#define SELECT_DO 3 // looking for an object to grasp...
static gmode = FREE_DO; // current grasping mode
//// STILL USES SEGMENT CALLS FOR NOW
static PDRIVER *manip_pdriver = NULL;
static SEGMENT *manip_segment = NULL;
static SEGMENT *manip_sel_seg = NULL;
static POSE manip_sel_offset = ZERO_POSE;
// sets up the 3D/6D manip system
void set_3D_manip_data(PDRIVER *ptr, SEGMENT *move, SEGMENT *sel, POSE *seloffset)
{
manip_pdriver = ptr;
manip_segment = move;
manip_sel_seg = sel;
manip_sel_offset = *seloffset;
}
static SEGMENT *manip_data(long *x, long *y, long *z)
{
*x = manip_sel_offset.x;
*y = manip_sel_offset.y;
*z = manip_sel_offset.z;
matrix_point(*get_seg_pmatrix(manip_sel_seg), x, y, z);
return manip_segment;
}
void do_3D_manip(WORD command) /* glove execution loop element */
{
OBJLIST *list;
OBJECT * obj;
int s;
long d,x,y,z;
MATRIX f;
MATRIX *m;
POINTER pt;
SEGMENT *wrist_seg = manip_data(&x, &y, &z); // local manipulation
// very general call
if (manip_pdriver==NULL) return;
if (!rot_seg) rot_seg = new_seg(NULL); // initialize if needed
s = last_pointer(manip_pdriver, &pt);
newmode:
switch(gmode)
{
case FREE_DO:
switch(command)
{
case SELECT_DO:
gmode = SELECT_DO;
do_for_all_selected(unhighlight_object);
sel_obj = NULL;
world_changed++;
goto newmode;
case GRASP_DO:
if (sel_obj)
{
work_seg = object2segment(sel_obj);
old_parent = parent_segment(work_seg);
if (old_parent) detach_segment(work_seg,1);
attach_segment(work_seg, wrist_seg,1);
gmode = GRASP_DO;
world_changed++;
}
break;
case ROTATE_DO:
if (sel_obj)
{
work_seg = object2segment(sel_obj);
if (work_seg == NULL) break;
old_parent = parent_segment(work_seg);
update_segment(work_seg);
if (old_parent == NULL)
get_object_bounds(sel_obj, &oxp, &oyp, &ozp); /* center of obj */
else
{
m = get_seg_pmatrix(work_seg); /* else by origin ("joint") */
oxp = (*m)[3][0];
oyp = (*m)[3][1];
ozp = (*m)[3][2];
}
abs_rot_segment(rot_seg, 0, 0, 0, RYXZ);
abs_move_segment(rot_seg, oxp, oyp, ozp);
update_segment(rot_seg);
attach_segment(work_seg, rot_seg,1);
oxg = x-oxp;
oyg = y-oyp;
ozg = z-ozp;
vector_to_matrix(f, oxg, oyg, ozg);
inverse_matrix(f, ogm);
gmode = ROTATE_DO;
world_changed++;
}
break;
default:
break;
}
break;
case SELECT_DO:
switch(command)
{
case SELECT_DO:
list = which_area_objlist(global_world_root, x, y, z);
if (list != NULL)
{
obj = best_collision(list, x, y, z);
if (obj == NULL)
{
unhighlight_object(sel_obj);
sel_obj = NULL;
}
else
{
if (sel_obj != obj) unhighlight_object(sel_obj);
highlight_object(obj);
sel_obj = obj;
}
world_changed++;
}
break;
default:
gmode = FREE_DO;
goto newmode;
}
break;
case GRASP_DO:
switch(command)
{
case GRASP_DO:
break; /* move is automatic */
default:
if (work_seg)
{
detach_segment(work_seg,1);
if (old_parent) attach_segment(work_seg, old_parent,1);
world_changed++;
}
gmode = FREE_DO;
goto newmode;
}
break;
case ROTATE_DO:
switch(command)
{
case ROTATE_DO:
if (sel_obj && (s & PNEW_POS))
{
vector_to_matrix(f, x-oxp, y-oyp, z-ozp);
matrix_product(f, ogm, f);
f[3][0] = oxp;
f[3][1] = oyp;
f[3][2] = ozp;
abs_mat_segment(rot_seg, f);
update_segment(rot_seg);
world_changed++;
}
break;
default:
gmode = FREE_DO;
world_changed++;
detach_segment(work_seg,1);
if (old_parent) attach_segment(work_seg, old_parent,1);
goto newmode;
}
break;
default:
break;
}
}