34#include <libFreeWRL.h>
36#include "../vrml_parser/Structs.h"
37#include "../opengl/OpenGL_Utils.h"
38#include "../opengl/Frustum.h"
39#include "../main/headers.h"
41#include "LinearAlgebra.h"
42#include "quaternion.h"
44#include "../x3d_parser/Bindable.h"
56static void init_stereodefaults(
X3D_Viewer *Viewer)
59 Viewer->shutterGlasses = 0;
61 Viewer->sidebyside = 0;
64 Viewer->eyedist = 0.065;
70 Viewer->screendist = 0.375;
71 Viewer->stereoParameter = 0.01;
72 Viewer->dominantEye = 1;
73 Viewer->eitherDominantEye = 1;
76 Viewer->haveQuadbuffer = 0;
83 int viewer_initialized;
92 int StereoInitializedOnce;
93 GLboolean acMask[3][3];
103void *Viewer_constructor(){
104 void *v = MALLOCV(
sizeof(
struct pViewer));
105 memset(v,0,
sizeof(
struct pViewer));
108void Viewer_init(
struct tViewer *t){
112 t->prv = Viewer_constructor();
116 p->examineCounter = 5;
118 p->viewer_initialized = FALSE;
124 p->StereoInitializedOnce = 0;
125 p->acMask[0][0] = (GLboolean)1;
127 p->acMask[1][1] = (GLboolean)1;
128 p->acMask[1][2] = (GLboolean)1;
131 loadIdentityMatrix(p->old2new);
132 loadIdentityMatrix(p->identity);
134 p->StereoInitializedOnce = 1;
135 p->keychord = CHORD_XY;
136 p->dragchord = CHORD_YAWZ;
144static void handle_tick_fly(
void);
145static void handle_tick_exfly(
void);
146static void handle_tick_fly2(
double dtime);
150void getCurrentSpeed() {
156 tg->Mainloop.BrowserSpeed = tg->Mainloop.BrowserFPS * (fabs(
viewer->VPvelocity.x) + fabs(
viewer->VPvelocity.y) + fabs(
viewer->VPvelocity.z));
163 viewer->fieldofview = 45.0;
168 viewer->currentPosInModel.x = 0;
viewer->currentPosInModel.y = 0;
viewer->currentPosInModel.z = 10;
171 vrmlrot_to_quaternion (&
viewer->Quat,1.0,0.0,0.0,0.0);
173 viewer->vp2rnSaved = FALSE;
182 if(vpnodetype == NODE_OrthoViewpoint){
184 fwl_set_viewer_type0(
viewer,VIEWER_NONE);
185 viewer->orthoField[0] = -1.0;
186 viewer->orthoField[1] = -1.0;
187 viewer->orthoField[2] = 1.0;
188 viewer->orthoField[3] = 1.0;
190 viewer->farPlane = 210000.0;
194 fwl_set_viewer_type0(
viewer,VIEWER_EXAMINE);
209 bstack = getBindableStacksByLayer(tg,layerid);
214 vpnodetype = bstack->nodetype == NODE_LayoutLayer ? NODE_OrthoViewpoint : NODE_Viewpoint;
215 viewer_default0(
viewer,vpnodetype);
216 init_stereodefaults(
viewer);
219 return bstack->viewer;
225 return ViewerByLayerId(tg->Bindable.activeLayer);
228void viewer_default() {
231 viewer_default0(
viewer,NODE_Viewpoint);
240 if (!p->viewer_initialized) {
241 p->viewer_initialized = TRUE;
247 viewer->currentPosInModel.x = 0;
viewer->currentPosInModel.y = 0;
viewer->currentPosInModel.z = 10;
250 vrmlrot_to_quaternion (&
viewer->Quat,1.0,0.0,0.0,0.0);
253 viewer->collision = FALSE;
265 viewer->startSLERPtime = 0.0;
266 viewer->transitionType = 1;
267 viewer->transitionTime = 1.0;
272 viewer->doExamineModeDistanceCalculations = FALSE;
275 viewer->screenOrientation = 0;
277 viewer->nearPlane=DEFAULT_NEARPLANE;
278 viewer->farPlane=DEFAULT_FARPLANE;
279 viewer->backgroundPlane = DEFAULT_BACKGROUNDPLANE;
292void printStatsRoutes()
294 ConsoleMessage(
"%25s %d\n",
"Routes count", getCRouteCount());
297void printStatsBindingStacks();
298void printStatsResources();
299void printStatsEvents();
300void printStatsNodes();
304 printStatsResources();
308 printStatsBindingStacks();
319 quaternion_to_vrmlrot(&(
viewer->Quat), &(ori.x),&(ori.y),&(ori.z), &(ori.a));
320 ConsoleMessage(
"Viewpoint local{\n");
321 ConsoleMessage(
"\tPosition[%.4f, %.4f, %.4f]\n", (
viewer->Pos).x, (
viewer->Pos).y, (
viewer->Pos).z);
322 ConsoleMessage(
"\tQuaternion[%.4f, %.4f, %.4f, %.4f]\n", (
viewer->Quat).w, (
viewer->Quat).x, (
viewer->Quat).y, (
viewer->Quat).z);
323 ConsoleMessage(
"\tOrientation[%.4f, %.4f, %.4f, %.4f]\n", ori.x, ori.y, ori.z, ori.a);
324 ConsoleMessage(
"}\n");
325 getCurrentPosInModelB();
326 ConsoleMessage(
"World Coordinates of Avatar [%.4f, %.4f %.4f]\n",
viewer->currentPosInModel.x,
viewer->currentPosInModel.y,
viewer->currentPosInModel.z);
330int fwl_get_headlight() {
331 return(Viewer()->headlight);
334void fwl_toggle_headlight() {
338 if (
viewer->headlight == TRUE) {
339 viewer->headlight = FALSE;
346void setNoCollision() {
352 return fwl_getCollision();
354void toggle_collision() {
360int fwl_getCollision(){
365void fwl_setCollision(
int state) {
368 viewer->collision = state;
371void fwl_init_StereoDefaults()
376 if(!p->StereoInitializedOnce)
377 init_stereodefaults(
viewer);
378 p->StereoInitializedOnce = 1;
382void set_eyehalf(
const double eyehalf,
const double eyehalfangle) {
386 viewer->eyehalf = eyehalf;
387 viewer->eyehalfangle = eyehalfangle;
394 tg->Mainloop.CTRL = FALSE;
415 case VIEWER_TURNTABLE:
420 case VIEWER_SPHERICAL:
424 if(tg->Mainloop.CTRL){
425 tg->Mainloop.CTRL = FALSE;
427 tg->Mainloop.CTRL = TRUE;
439 if(tg->Mainloop.CTRL){
440 tg->Mainloop.CTRL = FALSE;
443 tg->Mainloop.CTRL = TRUE;
465 ConsoleMessage (
"Viewer type %d is not supported. See Viewer.h.\n", type);
466 viewer->type = VIEWER_NONE;
475 if (vectorSize(getActiveBindableStacks(tg)->navigation) >0)
476 if (
viewer->oktypes[type]==FALSE) {
481 if(1) viewer_init(
viewer,type);
483void fwl_set_viewer_type(
const int type) {
486 fwl_set_viewer_type0(
viewer, type);
492#define VIEWER_STRING(type) ( \
493 type == VIEWER_NONE ? "NONE" : ( \
494 type == VIEWER_EXAMINE ? "EXAMINE" : ( \
495 type == VIEWER_WALK ? "WALK" : ( \
496 type == VIEWER_EXFLY ? "EXFLY" : ( \
497 type == VIEWER_SPHERICAL ? "SPHERICAL" : (\
498 type == VIEWER_TURNTABLE ? "TURNTABLE" : (\
499 type == VIEWER_FLY ? "FLY" : "UNKNOWN"))))))
503#define strcasecmp _stricmp
510 {
"NONE",VIEWER_NONE},
511 {
"WALK",VIEWER_WALK},
513 {
"EXAMINE",VIEWER_EXAMINE},
514 {
"SPHERICAL",VIEWER_SPHERICAL},
515 {
"TURNTABLE",VIEWER_TURNTABLE},
516 {
"EXPLORE",VIEWER_EXPLORE},
517 {
"LOOKAT",VIEWER_LOOKAT},
518 {
"YAWZ",VIEWER_YAWZ},
520 {
"YAWPITCH",VIEWER_YAWPITCH},
521 {
"ROLL",VIEWER_ROLL},
522 {
"DIST",VIEWER_DIST},
525char * lookup_navmodestring(
int navmode){
538 }
while(navmodes[i].
key);
539 if(!retval) retval =
"NONE";
542int lookup_navmode(
char *cmode){
550 if(!strcasecmp(nm->key,cmode)){
555 }
while(navmodes[i].
key);
558char* fwl_getNavModeStr()
562 return lookup_navmodestring(
viewer->type);
570int fwl_setNavMode(
char *mode){
571 int imode = lookup_navmode(mode);
572 fwl_set_viewer_type(imode);
580 struct point_XYZ rot, z_axis = { 0, 0, 1 };
585 quaternion_inverse(&q_inv, &(
viewer->Quat));
586 quaternion_rotation(&rot, &q_inv, &z_axis);
588 (examine->Origin).x = (
viewer->Pos).x -
viewer->Dist * rot.x;
589 (examine->Origin).y = (
viewer->Pos).y -
viewer->Dist * rot.y;
590 (examine->Origin).z = (
viewer->Pos).z -
viewer->Dist * rot.z;
599 double cosine, sine, ulen, vlen, scale, dot, angle;
603 ulen = sqrt(vecdot(V1,V1));
604 vlen = sqrt(vecdot(V2,V2));
606 if( APPROX(scale, 0.0) )
608 rotaxis->y = rotaxis->z = 0.0;
614 veccross(&cross,*V1,*V2);
615 sine = sqrt(vecdot(&cross,&cross))/scale;
617 angle = atan2(sine,cosine);
618 vecnormal(rotaxis,&cross);
621void avatar2BoundViewpointVerticalAvatar(GLDOUBLE *matA2BVVA, GLDOUBLE *matBVVA2A)
632 viewer_fetch_user_offsets0(
viewer);
633 pointxyz2double(pp,&
viewer->Up);
634 vecscaled(pp,pp,-1.0);
635 double2pointxyz(&downvec,pp);
637 quaternion_rotation(&tilted, &
viewer->Quat, &downvec);
639 matrotate2v(matA2BVVA,downvec,tilted);
640 matrotate2v(matBVVA2A,tilted,downvec);
646void viewer_level_to_bound()
698 viewer_fetch_user_offsets0(
viewer);
699 pointxyz2double(pp,&
viewer->Up);
700 vecscaled(pp,pp,-1.0);
701 double2pointxyz(&downvec,pp);
705 quaternion_rotation(&tilted, &Quat, &downvec);
707 angle = vecangle2(&downvec,&tilted,&rotaxis);
708 if( APPROX(angle,0.0) )
return;
709 vrmlrot_to_quaternion(&q, rotaxis.x, rotaxis.y, rotaxis.z, -angle );
710 quaternion_normalize(&q);
711 quaternion_multiply(&(
viewer->Quat), &q, &Quat);
712 quaternion_normalize(&(
viewer->Quat));
714 viewer_update_user_offsets0(
viewer);
717void viewer_togl(
double fieldofview)
749 set_stereo_offset0();
755 quaternion_togl(&
viewer->Quat);
768void getCurrentPosInModelB(){
770 double mod[16], modi[16], pp[3];
773 vecsetd(pp,0.0,0.0,0.0);
774 FW_GL_GETDOUBLEV(GL_MODELVIEW_MATRIX, mod);
775 matinverseAFFINE(modi,mod);
776 transformAFFINEd(pp,pp,modi);
777 double2pointxyz(&
viewer->currentPosInModel,pp);
780double quadratic(
double x,
double a,
double b,
double c)
783 return x*x*a + x*b + c;
785double xsign_quadratic(
double x,
double a,
double b,
double c)
790 if(x < 0.0) xSign = -1.0;
else xSign = 1.0;
792 return xSign*quadratic(x,a,b,c);
794double cubic(
double x,
double a,
double b,
double c,
double d){
795 return x*x*x*a + x*x*b + x*c + d;
797double xsign_cubic(
double x,
double a,
double b,
double c,
double d)
802 if(x < 0.0) xSign = -1.0;
else xSign = 1.0;
804 return xSign*cubic(x,a,b,c,d);
806double quartic(
double x,
double a,
double b,
double c,
double d,
double e){
807 return x*x*x*x*a + x*x*x*b + x*x*c + x*d +e;
809double xsign_quartic(
double x,
double a,
double b,
double c,
double d,
double e)
815 if(x < 0.0) xSign = -1.0;
else xSign = 1.0;
817 return xSign*quartic(x,a,b,c,d,e);
819double quintic(
double x,
double a,
double b,
double c,
double d,
double e,
double f){
820 return x*x*x*x*x*a + x*x*x*x*b + x*x*x*c + x*x*d +x*e + f;
822double xsign_quintic(
double x,
double a,
double b,
double c,
double d,
double e,
double f)
828 if(x < 0.0) xSign = -1.0;
else xSign = 1.0;
830 return xSign*quintic(x,a,b,c,d,e,f);
832static void handle_walk(
const int mev,
const unsigned int button,
const float x,
const float y) {
850 if (mev == ButtonPress ) {
853 }
else if (mev == MotionNotify) {
864 walk->ZD = -xsign_quadratic(y - walk->SY,.05,5.0,0.0)*
viewer->speed;
865 walk->RD = xsign_quadratic(x - walk->SX,0.1,0.5,0.0);
868 }
else if (button == 3) {
869 walk->XD = xsign_quadratic(x - walk->SX,5.0,10.0,0.0)*
viewer->speed;
870 walk->YD = xsign_quadratic(y - walk->SY,5.0,10.0,0.0)*
viewer->speed;
874 }
else if (mev == ButtonRelease) {
878 }
else if (button == 3) {
898void handle_examine(
const int mev,
const unsigned int button,
float x,
float y) {
907 examine = &
viewer->examine;
910 if (mev == ButtonPress) {
921 xy2qua(&(examine->SQuat), x, y);
922 quaternion_set(&(examine->OQuat), &(
viewer->Quat));
937 }
else if (mev == MotionNotify) {
940 squat_norm = norm(&(examine->SQuat));
942 if (APPROX(squat_norm, 0)) {
943 fprintf(stderr,
"Viewer handle_examine: mouse event DRAG - missed press\n");
945 xy2qua(&(examine->SQuat), x, y);
947 quaternion_set(&(examine->OQuat), &(
viewer->Quat));
952 quaternion_inverse(&q_i, &(examine->SQuat));
953 quaternion_multiply(&arc, &q, &q_i);
957 quaternion_multiply(&(
viewer->Quat), &arc, &(examine->OQuat));
970 quaternion_inverse(&q_i, &(
viewer->Quat));
971 quaternion_rotation(&(
viewer->Pos), &q_i, &pp);
975 viewer->Pos.x += (examine->Origin).x;
976 viewer->Pos.y += (examine->Origin).y;
977 viewer->Pos.z += (examine->Origin).z;
985double get_viewer_dist(){
986 return Viewer()->Dist;
989void handle_dist(
const int mev,
const unsigned int button,
float x,
float y) {
1002 examine = &
viewer->examine;
1008 if (mev == ButtonPress) {
1012 examine->ODist = max(0.1,
viewer->Dist);
1014 }
else if (mev == MotionNotify) {
1018 viewer->Dist = examine->ODist * exp(4.0 * (examine->SY - yy));
1020 viewer->Dist = (0 != yy) ? examine->ODist * examine->SY / yy : 0;
1026 quaternion_inverse(&q_i, &(
viewer->Quat));
1027 quaternion_rotation(&(
viewer->Pos), &q_i, &pp);
1031 viewer->Pos.x += (examine->Origin).x;
1032 viewer->Pos.y += (examine->Origin).y;
1033 viewer->Pos.z += (examine->Origin).z;
1039double display_screenRatio();
1040double dclamp(
double fval,
double fstart,
double fend) {
1042 fret = fval > fend? fend : fval;
1043 fret = fret < fstart ? fstart : fret;
1046void handle_turntable(
const int mev,
const unsigned int button,
float x,
float y) {
1051 double frameRateAdjustment;
1058 if(APPROX(
viewer->Dist,0.0)){
1063 if( tg->Mainloop.BrowserFPS > 0)
1064 frameRateAdjustment = 20.0 / tg->Mainloop.BrowserFPS;
1066 frameRateAdjustment = 1.0;
1069 if (mev == ButtonPress) {
1070 if (button == 1 || button == 3) {
1075 else if (mev == MotionNotify)
1078 double dyaw, dpitch;
1084 if (button == 1 || button == 3){
1089 dd.x = dd.y = 0.0; dd.z =
viewer->Dist;
1090 xx.y = xx.z = 0.0; xx.x = 1.0;
1092 quaternion_inverse(&quat,&quat);
1093 quaternion_rotation(&ddr, &quat, &dd);
1094 quaternion_rotation(&xxr, &quat, &xx);
1099 vecnormal(&pp, &pp);
1100 pitch = -(acos(dclamp(vecdot(&pp, &yaxis),-1.0,1.0)) - PI*.5);
1103 if(fabs(pitch) > PI*.25){
1105 vecnormal(&xxr,&xxr);
1106 yaw = atan2(xxr.z,xxr.x);
1113 dist = veclength(pp2);
1114 if(dist > 0.0 && fabs(pitch) < (PI *.5 - .001)){
1115 vecnormal(&pp2,&pp2);
1116 yaw = -atan2(pp2.x, pp2.z);
1122 dyaw = -(ypz->x - x) *
viewer->fieldofview*PI / 180.0*
viewer->fovZoom * display_screenRatio();
1123 dpitch = (ypz->y - y) *
viewer->fieldofview*PI / 180.0*
viewer->fovZoom;
1126 }
else if (button == 3) {
1130 ypz->ypz[1] = -xsign_quadratic(y - ypz->y,100.0,10.0,0.0)*
viewer->speed * frameRateAdjustment *.15;
1133 if (button == 1 || button == 3)
1136 vrmlrot_to_quaternion(&qyaw, 0.0, 1.0, 0.0, yaw);
1137 vrmlrot_to_quaternion(&qpitch, 1.0, 0.0, 0.0, pitch);
1138 quaternion_multiply(&quat, &qpitch, &qyaw);
1139 quaternion_normalize(&quat);
1141 quaternion_set(&(
viewer->Quat), &quat);
1143 quaternion_inverse(&quat, &quat);
1147 quaternion_rotation(&(
viewer->Pos), &quat, &pp);
1155 }
else if(mev == ButtonRelease) {
1163void handle_spherical(
const int mev,
const unsigned int button,
float x,
float y) {
1174 if(ibutton == 1 && tg->Mainloop.CTRL) ibutton = 3;
1176 if (mev == ButtonPress) {
1177 if (ibutton == 1 || ibutton == 3) {
1181 }
else if (mev == MotionNotify) {
1190 dd.x = dd.y = 0.0; dd.z = 1.0;
1192 quaternion_inverse(&quat,&quat);
1193 quaternion_rotation(&ddr, &quat, &dd);
1194 yaw = -atan2(ddr.x,ddr.z);
1195 pitch = -(acos(vecdot(&ddr, &yaxis)) - PI*.5);
1198 dyaw = (ypz->x - x) *
viewer->fieldofview*PI/180.0*
viewer->fovZoom * display_screenRatio();
1199 dpitch = -(ypz->y - y) *
viewer->fieldofview*PI/180.0*
viewer->fovZoom;
1204 vrmlrot_to_quaternion(&qyaw, 0.0, 1.0, 0.0, yaw);
1205 vrmlrot_to_quaternion(&qpitch, 1.0, 0.0, 0.0, pitch);
1206 quaternion_multiply(&quat, &qpitch, &qyaw);
1207 quaternion_normalize(&quat);
1209 quaternion_set(&(
viewer->Quat), &quat);
1211 }
else if (ibutton == 3) {
1213 d = -(y - ypz->y)*.5;
1217 if(ibutton == 1 || ibutton == 3){
1234void handle_fly2(
const int mev,
const unsigned int button,
float x,
float y) {
1241 inplane = &
viewer->inplane;
1243 if (mev == ButtonPress) {
1249 }
else if (mev == MotionNotify) {
1252 }
else if (mev == ButtonRelease ) {
1259void increment_pos0(
struct point_XYZ *vec);
1260void handle_tick_fly2(
double dtime) {
1263 double frameRateAdjustment, xx, yy, yyy, zz, rot, a,b,c;
1269 inplane = &
viewer->inplane;
1271 frameRateAdjustment = dtime * 20.0;
1274 xx = inplane->xx - inplane->x;
1275 yy = inplane->yy - inplane->y;
1282 zz = -xsign_cubic(yyy,a,b,c,0.0)*
viewer->speed * dtime;
1296 rot = xsign_quadratic(xx,2.0,10.0,0.0)*dtime;
1299 vrmlrot_to_quaternion (&nq,0.0,1.0,0.0,0.4*rot);
1300 viewer_lastQ_set(&nq);
1301 quaternion_multiply(&(
viewer->Quat), &nq, &q);
1303 increment_pos0(&xyz);
1308void handle_lookat(
const int mev,
const unsigned int button,
float x,
float y) {
1325 if(
viewer->type == VIEWER_LOOKAT)
1326 fwl_set_viewer_type(VIEWER_LOOKAT);
1327 if(
viewer->type == VIEWER_EXPLORE)
1328 fwl_set_viewer_type(VIEWER_EXPLORE);
1335void handle_tick_lookat() {
1339 switch(
viewer->LookatMode){
1349void handle_explore(
const int mev,
const unsigned int button,
float x,
float y) {
1358 ctrl = tg->Mainloop.CTRL;
1363 handle_lookat(mev,button,x,y);
1366 if(APPROX(
viewer->Dist,0.0)){
1368 handle_spherical(mev,button,x,y);
1371 handle_turntable(mev, button, x, y);
1374void handle_tplane(
const int mev,
const unsigned int button,
float x,
float y) {
1383 inplane = &
viewer->inplane;
1386 if (mev == ButtonPress) {
1390 }
else if (mev == MotionNotify) {
1393 }
else if(mev == ButtonRelease){
1399void handle_tick_tplane(
double dtime){
1405 inplane = &
viewer->inplane;
1407 double xxx,yyy,a,b,c,d,e;
1408 xxx = (inplane->xx - inplane->x)*1.0;
1409 yyy = (inplane->yy - inplane->y)*1.0;
1414 pp.x = xsign_cubic(xxx,a,b,c,0.0) * dtime *
viewer->speed;
1415 pp.y = xsign_cubic(yyy,a,b,c,0.0) * dtime *
viewer->speed;
1428 increment_pos0(&pp);
1432void handle_rtplane(
const int mev,
const unsigned int button,
float x,
float y) {
1441 double xx,yy, frameRateAdjustment;
1444 inplane = &
viewer->inplane;
1446 if( tg->Mainloop.BrowserFPS > 0)
1447 frameRateAdjustment = 20.0 / tg->Mainloop.BrowserFPS;
1449 frameRateAdjustment = 1.0;
1451 if (mev == ButtonPress) {
1454 }
else if (mev == MotionNotify) {
1456 inplane->xx = xsign_quadratic(x - inplane->x,0.1,0.5,0.0)*frameRateAdjustment;
1457 inplane->yy = xsign_quadratic(y - inplane->y,0.1,0.5,0.0)*frameRateAdjustment;
1459 }
else if (mev == ButtonRelease) {
1467void handle_tick_rplane(
double dtime){
1474 inplane = &
viewer->inplane;
1476 roll = xsign_quadratic(inplane->xx - inplane->x,2.0,2.0,0.0)*dtime;
1477 vrmlrot_to_quaternion (&quatr,0.0,0.0,1.0,roll);
1478 quaternion_multiply(&(
viewer->Quat), &quatr, &(
viewer->Quat));
1479 quaternion_normalize(&(
viewer->Quat));
1483void handle_tick_tilt(
double dtime) {
1490 inplane = &
viewer->inplane;
1492 yaw = xsign_quadratic(inplane->xx - inplane->x,2.0,2.0,0.0)*dtime;
1493 vrmlrot_to_quaternion (&quatt,0.0,1.0,0.0,yaw);
1494 quaternion_multiply(&(
viewer->Quat), &quatt, &(
viewer->Quat));
1495 pitch = -xsign_quadratic(inplane->yy - inplane->y,2.0,2.0,0.0)*dtime;
1496 vrmlrot_to_quaternion (&quatt,1.0,0.0,0.0,pitch);
1497 quaternion_multiply(&(
viewer->Quat), &quatt, &(
viewer->Quat));
1498 quaternion_normalize(&(
viewer->Quat));
1505void handle0(
const int mev,
const unsigned int button,
const float x,
const float yup)
1513 case VIEWER_SPHERICAL:
1514 case VIEWER_TURNTABLE:
1515 case VIEWER_EXAMINE:
1517 viewer_fetch_user_offsets0(
viewer);
break;
1519 viewer_fetch_LCS(
viewer);
break;
1530 case VIEWER_EXAMINE:
1531 handle_examine(mev, button, ((
float) x), ((
float) yup));
1534 handle_walk(mev, button, ((
float) x), ((
float) yup));
1539 handle_fly2(mev, button, ((
float) x), ((
float) yup));
1552 case VIEWER_SPHERICAL:
1553 handle_spherical(mev,button,((
float) x),((
float)yup));
1555 case VIEWER_TURNTABLE:
1556 handle_turntable(mev, button, ((
float)x), ((
float)yup));
1559 handle_lookat(mev, button, ((
float)x), ((
float)yup));
1561 case VIEWER_EXPLORE:
1562 handle_explore(mev, button, ((
float)x), ((
float)yup));
1565 handle_dist(mev,button,(
float)x,(
float)yup);
1573 case VIEWER_SPHERICAL:
1574 case VIEWER_TURNTABLE:
1575 case VIEWER_EXAMINE:
1577 viewer_update_user_offsets0(
viewer);
break;
1579 viewer_update_LCS(
viewer);
break;
1584#define FLYREMAP {{'a',NUM0},{'z',NUMDEC},{'j',LEFT_KEY},{'l',RIGHT_KEY},{'p',UP_KEY},{';',DOWN_KEY},{'8',NUM8},{'k',NUM2},{'u',NUM4},{'o',NUM6 },{'7',NUM7},{'9',NUM9}}
1590Key FLYREMAP2 [] = {{
'a',NUM0},{
'z',NUMDEC},{
'j',LEFT_KEY},{
'l',RIGHT_KEY},{
'p',UP_KEY},{
';',DOWN_KEY},{
'8',NUM8},{
'k',NUM2},{
'u',NUM4},{
'o',NUM6 },{
'7',NUM7},{
'9',NUM9}};
1591int FLYREMAP2SIZE = 12;
1592Key FLYCHORDREMAP [] = {
1593{
'j',LEFT_KEY},{
'l',RIGHT_KEY},{
'p',UP_KEY},{
';',DOWN_KEY}
1595int arrowkeys [] = {LEFT_KEY,RIGHT_KEY,UP_KEY,DOWN_KEY};
1603int indexArrowkey(
int key){
1607 if(
key == arrowkeys[i]) iret = i;
1623 FLY_ROLL_COUNTERCLOCKWISE,
1626Key fly_normalkeys [] = {
1631 {
'a',FLY_Z_FORWARD},
1632 {
'z',FLY_Z_REVERSE},
1634 {
'8',FLY_PITCH_DOWN},
1636 {
'o',FLY_YAW_RIGHT},
1637 {
'7',FLY_ROLL_COUNTERCLOCKWISE},
1638 {
'9',FLY_ROLL_CLOCKWISE},
1642char *chordnames [] = {
"YAWZ",
"YAWPITCH",
"ROLL",
"XY"};
1649 {CHORD_YAWZ, {{FLY_YAW_LEFT,LEFT_KEY},{FLY_YAW_RIGHT,RIGHT_KEY},{FLY_Z_FORWARD,UP_KEY},{FLY_Z_REVERSE,DOWN_KEY}}},
1650 {CHORD_YAWPITCH,{{FLY_YAW_LEFT,LEFT_KEY},{FLY_YAW_RIGHT,RIGHT_KEY},{FLY_PITCH_UP,UP_KEY},{FLY_PITCH_DOWN,DOWN_KEY}}},
1651 {CHORD_ROLL, {{FLY_ROLL_COUNTERCLOCKWISE,LEFT_KEY},{FLY_ROLL_CLOCKWISE,RIGHT_KEY},{FLY_ROLL_COUNTERCLOCKWISE,UP_KEY},{FLY_ROLL_CLOCKWISE,DOWN_KEY}}},
1652 {CHORD_XY, {{FLY_X_LEFT,LEFT_KEY},{FLY_X_RIGHT,RIGHT_KEY},{FLY_Y_UP,UP_KEY},{FLY_Y_DOWN,DOWN_KEY}}},
1655int viewer_getKeyChord(){
1659void viewer_setKeyChord(
int chord){
1663 if(chord1 > 3) chord1 = 0;
1664 if(chord1 < 0) chord1 = 3;
1665 p->keychord = chord1;
1667char *fwl_getKeyChord(){
1668 return chordnames[viewer_getKeyChord()];
1671int fwl_setKeyChord(
char *chordname){
1675 if(!strcasecmp(chordname,chordnames[i])){
1676 viewer_setKeyChord(i);
1683int viewer_getDragChord(){
1685 return p->dragchord;
1687void viewer_setDragChord(
int chord){
1689 p->dragchord = chord;
1691void viewer_setNextDragChord(){
1693 p->dragchord = p->dragchord == CHORD_XY ? CHORD_YAWZ : p->dragchord + 1;
1695char *fwl_getDragChord(){
1696 return chordnames[viewer_getDragChord()];
1698int fwl_setDragChord(
char *chordname){
1702 if(!strcasecmp(chordname,chordnames[i])){
1703 viewer_setDragChord(i);
1713int lookup_fly_arrow(
int key){
1717 int idxarrow, idxnormal;
1719 idxarrow = indexArrowkey(
key);
1722 idxnormal = FLYCHORDREMAP2[p->keychord].arrows[idxarrow].key;
1724 iret = fly_normalkeys[idxnormal].key;
1729char lookup_fly_extended(
int key){
1732 Key ps[KEYS_HANDLED] = FLYREMAP;
1733 for(i=0;i<KEYS_HANDLED;i++){
1741char lookup_fly_key(
int key){
1744 kp = lookup_fly_arrow(
key);
1746 kp = lookup_fly_extended(
key);
1749static struct flykey_lookup_type {
1755} flykey_lookup [] = {
1756 {
'j', 0, 0, -1, FLY_X_LEFT},
1757 {
'l', 0, 0, 1, FLY_X_RIGHT},
1758 {
';', 0, 1, -1, FLY_Y_DOWN},
1759 {
'p', 0, 1, 1, FLY_Y_UP,},
1760 {
'a', 0, 2, -1, FLY_Z_FORWARD},
1761 {
'z', 0, 2, 1, FLY_Z_REVERSE},
1763 {
'k', 1, 0, -1, FLY_YAW_LEFT},
1764 {
'8', 1, 0, 1, FLY_YAW_RIGHT},
1765 {
'u', 1, 1, -1, FLY_PITCH_UP},
1766 {
'o', 1, 1, 1, FLY_PITCH_DOWN},
1767 {
'7', 1, 2, -1, FLY_ROLL_COUNTERCLOCKWISE},
1768 {
'9', 1, 2, 1, FLY_ROLL_CLOCKWISE}
1772struct flykey_lookup_type *getFlyIndex(
char key){
1773 struct flykey_lookup_type *flykey;
1776 for(index=0;index<KEYS_HANDLED;index++){
1777 if(
key == flykey_lookup[index].
key )
break;
1780 flykey = &flykey_lookup[index];
1783int isFlyKey(
char key){
1785 index = indexArrowkey(
key);
1787 for(i=0;i<KEYS_HANDLED;i++)
1788 if(
key == flykey_lookup[i].
key ){
1792 return index > -1 ? 1 : 0;
1794void handle_key(
const char key,
double keytime)
1799 struct flykey_lookup_type *flykey;
1804 _key = (char) tolower((
int)
key);
1805 if(!isFlyKey(_key)){
1810 flykey = getFlyIndex(_key);
1812 if(flykey->motion > -1 && flykey->motion < 2 && flykey->axis > -1 && flykey->axis < 3){
1813 fly->down[flykey->motion][flykey->axis].direction = flykey->sign;
1814 fly->down[flykey->motion][flykey->axis].epoch = keytime;
1815 fly->down[flykey->motion][flykey->axis].era = keytime;
1816 fly->down[flykey->motion][flykey->axis].once = 1;
1822void handle_keyrelease(
const char key,
double keytime)
1827 struct flykey_lookup_type *flykey;
1834 _key = (char) tolower((
int)
key);
1835 if(!isFlyKey(_key))
return;
1836 flykey = getFlyIndex(_key);
1838 if(flykey->motion > -1 && flykey->motion < 2 && flykey->axis > -1 && flykey->axis < 3){
1839 int *ndown = &fly->ndown[flykey->motion][flykey->axis];
1842 fly->wasDown[flykey->motion][flykey->axis][*ndown].direction = fly->down[flykey->motion][flykey->axis].direction;
1843 fly->wasDown[flykey->motion][flykey->axis][*ndown].epoch = keytime - fly->down[flykey->motion][flykey->axis].epoch;
1844 fly->wasDown[flykey->motion][flykey->axis][*ndown].era = keytime - fly->down[flykey->motion][flykey->axis].era;
1845 fly->wasDown[flykey->motion][flykey->axis][*ndown].once = fly->down[flykey->motion][flykey->axis].once;
1848 fly->down[flykey->motion][flykey->axis].direction = 0;
1860void viewer_lastP_clear()
1864 p->viewer_lastP.x = p->viewer_lastP.y = p->viewer_lastP.z = 0.0;
1869 quaternion_rotation(&p->viewer_lastP,lastQ,&p->viewer_lastP);
1871void viewer_lastP_add(
struct point_XYZ *vec)
1876 VECADD(p->viewer_lastP,*vec);
1879 viewer_lastP_clear();
1888 vecscale(&nv,&nv,-1.0);
1909static void handle_tick_walk()
1913 double frame_rate_adjustment;
1924 frame_rate_adjustment = 10.0 * (TickTime() - lastTime());
1927 pp.x = frame_rate_adjustment * walk->XD;
1928 pp.y = frame_rate_adjustment * walk->YD;
1929 pp.z = frame_rate_adjustment * walk->ZD;
1985 vrmlrot_to_quaternion (&nq,0.0,1.0,0.0,0.4*walk->RD * 2.0 * frame_rate_adjustment);
1986 viewer_lastQ_set(&nq);
1991 quaternion_multiply(&(
viewer->Quat), &q, &nq);
1992 quaternion_normalize(&(
viewer->Quat));
2001 pointxyz2double(dd,&
viewer->Up);
2002 double2pointxyz(&rotaxis,dd);
2003 vecscaled(dd,dd,-1.0);
2004 double2pointxyz(&down,dd);
2007 quaternion_rotation(&tilted,&q,&down);
2008 angle = vecangle2(&down,&tilted, &rotaxis);
2009 vrmlrot_to_quaternion (&qlevel,rotaxis.x,rotaxis.y,rotaxis.z,-angle);
2011 quaternion_multiply(&qplanar,&qlevel,&q);
2022 viewer_lastP_add(&vec);
2025 quaternion_inverse(&q_i, &qplanar);
2026 quaternion_rotation(&nv, &q_i, &vec);
2029 viewer->VPvelocity.x = nv.x;
viewer->VPvelocity.y = nv.y;
viewer->VPvelocity.z = nv.z;
2047static int negate_pos = TRUE;
2048void viewer_setpose(
double *quat4,
double *vec3){
2056 viewer_fetch_user_offsets0(
viewer);
2058 if(negate_pos) vecnegated(vec,vec);
2059 double2pointxyz(&
viewer->Pos,vec);
2060 double2quat(&
viewer->Quat,quat4);
2061 viewer_update_user_offsets0(
viewer);
2063void viewer_getpose(
double *quat4,
double *vec3){
2071 viewer_fetch_user_offsets0(
viewer);
2072 pointxyz2double(vec3,&
viewer->Pos);
2074 vecnegated(vec3,vec3);
2075 quat2double(quat4,&
viewer->Quat);
2078void viewer_getbindpose(
double *quat4,
double *vec3){
2089 viewer_fetch_bindtime_pose0(
viewer,&quat,&pos);
2090 quat2double(quat4,&quat);
2091 pointxyz2double(vec3,&pos);
2095void viewer_getview(
double *viewMatrix){
2099 FW_GL_GETDOUBLEV(GL_MODELVIEW_MATRIX, viewMatrix);
2102void viewer_setview(
double *viewMatrix){
2103 FW_GL_SETDOUBLEV(GL_MODELVIEW_MATRIX, viewMatrix);
2119static void handle_tick_exfly()
2123 char string[STRING_SIZE];
2124 float px,py,pz,q1,q2,q3,q4;
2131 memset(
string, 0, STRING_SIZE *
sizeof(
char));
2133 if ((p->exfly_in_file = fopen(IN_FILE,
"r")) == NULL) {
2135 "Viewer handle_tick_exfly: could not open %s for read, returning to EXAMINE mode.\nSee the FreeWRL man page for further details on the usage of Fly - External Sensor input mode.\n",
2139 viewer->type = VIEWER_EXAMINE;
2143 rv = fread(
string,
sizeof(
char), IN_FILE_BYTES, p->exfly_in_file);
2144 if (ferror(p->exfly_in_file)) {
2146 "Viewer handle_tick_exfly: error reading from file %s.",
2148 fclose(p->exfly_in_file);
2151 fclose(p->exfly_in_file);
2154 if ((len = strlen(
string)) > 0) {
2155 if(p->exflyMethod == 0)
2158 len = sscanf (
string,
"%f %f %f %f %f %f %f",&px,&py,&pz,
2162 if (len != 7)
return;
2172 }
else if(p->exflyMethod == 1){
2174 static int lastbut = 0;
2176 len = sscanf (
string,
"%d %f %f ",&but,&px,&py);
2177 if (len != 3)
return;
2178 mev = ButtonRelease;
2179 if(but) mev = MotionNotify;
2182 mev = (but==1 || but==4)? ButtonPress : ButtonRelease;
2187 handle_walk(mev,but,px,py);
2208static void handle_tick_fly()
2214 double changed = 0.0, time_diff = -1.0;
2221 if (fly->lasttime < 0) {
2222 fly->lasttime = TickTime();
2225 double dtime = TickTime();
2226 time_diff = dtime - fly->lasttime;
2227 if (APPROX(time_diff, 0)) {
2230 fly->lasttime = dtime;
2231 if(time_diff < 0.0)
return;
2238 for (i = 0; i < 3; i++) {
2240 if(!fly->down[0][i].direction){
2241 double dtime = fly->lasttime - fly->down[0][i].epoch;
2243 fly->Velocity[0][i] *= pow(0.04, time_diff);
2246 if(fabs(fly->Velocity[0][i]) < .001){
2247 fly->Velocity[0][i] = 0.0;
2250 if(fly->down[0][i].direction){
2252 fly->Velocity[0][i] += (fly->ndown[0][i]+fly->down[0][i].once)*fly->down[0][i].direction *
viewer->speed * .1 * max(
viewer->Dist,1.0);
2253 fly->down[0][i].once = 0;
2254 fly->ndown[0][i] = 0;
2257 changed += fly->Velocity[0][i];
2270 for (i = 0; i < 3; i++) {
2271 static double radians_per_second = .6;
2272 fly->Velocity[1][i] = 0.0;
2273 if(!fly->down[1][i].direction){
2274 fly->Velocity[1][i] *= pow(0.04, time_diff);
2277 double rps = radians_per_second;
2280 double era = fly->lasttime - fly->down[1][i].era;
2281 fly->Velocity[1][i] += era * fly->down[1][i].direction * rps;
2282 fly->down[1][i].era += era;
2285 if(fly->ndown[1][i]){
2288 double rps = radians_per_second * .33;
2289 for(k=0; k<fly->ndown[1][i]; k++){
2290 double era = fly->wasDown[1][i][k].era;
2291 double pressedEra = fly->wasDown[1][i][k].epoch;
2293 if(pressedEra <= .1)
2296 fly->Velocity[1][i] += era * fly->wasDown[1][i][k].direction * rps;
2298 fly->ndown[1][i] = 0;
2300 if (fabs(fly->Velocity[1][i]) > 0.8) {
2301 fly->Velocity[1][i] /= (fabs(fly->Velocity[1][i]) / 0.8);
2303 changed += fly->Velocity[1][i];
2308 if (APPROX(changed,0.0))
return;
2309 v.x = fly->Velocity[0][0] * time_diff;
2310 v.y = fly->Velocity[0][1] * time_diff;
2311 v.z = fly->Velocity[0][2] * time_diff;
2314 nq.x = fly->Velocity[1][0];
2315 nq.y = fly->Velocity[1][1];
2316 nq.z = fly->Velocity[1][2];
2317 quaternion_normalize(&nq);
2319 quaternion_set(&q_v, &(
viewer->Quat));
2320 quaternion_multiply(&(
viewer->Quat), &nq, &q_v);
2321 quaternion_normalize(&(
viewer->Quat));
2335 case VIEWER_SPHERICAL:
2336 case VIEWER_TURNTABLE:
2337 viewer_fetch_user_offsets0(
viewer);
break;
2339 viewer_fetch_LCS(
viewer);
break;
2341 dtime = TickTime() - lastTime();
2346 case VIEWER_EXAMINE:
2352 handle_tick_exfly();
2355 switch(p->dragchord){
2356 case CHORD_YAWPITCH:
2357 handle_tick_tilt(dtime);
2360 handle_tick_rplane(dtime);
2363 handle_tick_tplane(dtime);
2367 handle_tick_fly2(dtime);
2385 handle_tick_lookat();
2387 case VIEWER_EXPLORE:
2389 case VIEWER_SPHERICAL:
2392 case VIEWER_TURNTABLE:
2402 case VIEWER_SPHERICAL:
2403 case VIEWER_TURNTABLE:
2404 viewer_update_user_offsets0(
viewer);
break;
2406 viewer_update_LCS(
viewer);
break;
2408 if(
viewer->type != VIEWER_NONE){
2409 viewer_fetch_user_offsets0(
viewer);
2411 viewer_update_user_offsets0(
viewer);
2413 if(0)
if (
viewer->doExamineModeDistanceCalculations) {
2417 CALCULATE_EXAMINE_DISTANCE
2418 p->examineCounter --;
2420 if (p->examineCounter < 0) {
2421 viewer->doExamineModeDistanceCalculations = FALSE;
2422 p->examineCounter = 5;
2441xy2qua(
Quaternion *ret,
const double x,
const double y)
2443 double _x = x - 0.5, _y = y - 0.5, _z, dist;
2447 dist = sqrt((_x * _x) + (_y * _y));
2460 quaternion_normalize(ret);
2466void setmask(GLboolean *mask,
int r,
int g,
int b)
2468 mask[0] = (GLboolean)r;
2469 mask[1] = (GLboolean)g;
2470 mask[2] = (GLboolean)b;
2472void Viewer_anaglyph_setSide(
int iside)
2478 glColorMask(p->acMask[iside][0],p->acMask[iside][1],p->acMask[iside][2],t);
2480void Viewer_anaglyph_clearSides()
2482 glColorMask(1,1,1,1);
2485static char * RGBACM =
"RGBACM";
2486static int indexRGBACM(
int a)
2488 return (
int) (strchr(RGBACM,a)-RGBACM);
2490int getAnaglyphPrimarySide(
int primary,
int iside){
2494 return (
int)p->acMask[iside][primary];
2497void setAnaglyphPrimarySide(
int primary,
int iside){
2512 p->acMask[i][primary] = (GLboolean)1;
2514 p->acMask[i][primary] = (GLboolean)0;
2516void setAnaglyphSideColor(
char val,
int iside)
2521 viewer->iprog[iside] = indexRGBACM(val);
2522 if(
viewer->iprog[iside] == -1 )
2524 printf (
"warning, command line anaglyph parameter incorrect - was %c need something like RG\n",val);
2525 viewer->iprog[iside] = iside;
2528 switch (
viewer->iprog[iside]) {
2530 setmask(p->acMask[iside],1,0,0);
2533 setmask(p->acMask[iside],0,1,0);
2536 setmask(p->acMask[iside],0,0,1);
2539 setmask(p->acMask[iside],1,1,0);
2542 setmask(p->acMask[iside],0,1,1);
2545 setmask(p->acMask[iside],1,0,1);
2549void fwl_set_AnaglyphParameter(
const char *optArg) {
2554 const char* glasses;
2559 len = (int) strlen(optArg);
2560 if(len !=2 && len != 3)
2562 printf (
"warning, command line anaglyph parameter incorrect - was %s need something like RC or LRN\n",optArg);
2563 glasses =
"RC"; len = 2;
2566 setAnaglyphSideColor(glasses[0],0);
2567 setAnaglyphSideColor(glasses[1],1);
2572 case 'L': iside = 0;
break;
2573 case 'R': iside = 1;
break;
2574 case 'N': iside = 2;
break;
2578 setAnaglyphPrimarySide(i,iside);
2582 viewer->shutterGlasses = 0;
2586 setStereoBufferStyle(1);
2590void fwl_init_Shutter (
void)
2600 tg->display.shutterGlasses = 2;
2601 viewer->shutterGlasses = 2;
2602 setStereoBufferStyle(1);
2603 if(
viewer->haveQuadbuffer)
2605 tg->display.shutterGlasses = 1;
2606 viewer->shutterGlasses = 1;
2607 setStereoBufferStyle(0);
2613void fwl_init_SideBySide()
2618 setStereoBufferStyle(1);
2622 viewer->stereoParameter = min(
viewer->stereoParameter,.01);
2624void fwl_init_UpDown()
2629 setStereoBufferStyle(1);
2633 viewer->stereoParameter = min(
viewer->stereoParameter,.01);
2636void clear_shader_table();
2645 clear_shader_table();
2646 setStereoBufferStyle(1);
2657 glColorMask(1,1,1,1);
2658 clear_shader_table();
2663 viewer->shutterGlasses = 0;
2664 tg->display.shutterGlasses = 0;
2676static void setStereo(
int type)
2680 gglobal()->Viewer.stereotype = type;
2684 case VIEWER_STEREO_OFF: {;
break;}
2685 case VIEWER_STEREO_SHUTTERGLASSES: {fwl_init_Shutter();
break;}
2686 case VIEWER_STEREO_SIDEBYSIDE: {fwl_init_SideBySide();
break;}
2687 case VIEWER_STEREO_ANAGLYPH: {setAnaglyph();
break;}
2688 case VIEWER_STEREO_UPDOWN: {fwl_init_UpDown();
break;}
2692void toggleOrSetStereo(
int type)
2700 shut =
viewer->shutterGlasses ? 1 : 0;
2702 if(type != curtype) {
2706 gglobal()->Viewer.stereotype = 0;
2710void fwl_setPickraySide(
int ipreferredSide,
int either){
2713 viewer->dominantEye = ipreferredSide;
2714 viewer->eitherDominantEye = either;
2717void fwl_getPickraySide(
int *ipreferredSide,
int *either){
2720 *ipreferredSide =
viewer->dominantEye ;
2721 *either =
viewer->eitherDominantEye;
2727 if(
viewer->screendist != 0.0)
2749 set_eyehalf(
viewer->eyedist/2.0,atan(
viewer->stereoParameter)*180.0/3.1415926);
2753void viewer_postGLinit_init(
void)
2761 rdr_caps = tg->display.rdr_caps;
2764 viewer->haveQuadbuffer = (rdr_caps->quadBuffer== GL_TRUE);
2770 type = VIEWER_STEREO_OFF;
2771 if(
viewer->shutterGlasses ) type = VIEWER_STEREO_SHUTTERGLASSES;
2772 if(
viewer->sidebyside ) type = VIEWER_STEREO_SIDEBYSIDE;
2773 if(
viewer->updown ) type = VIEWER_STEREO_UPDOWN;
2774 if(
viewer->anaglyph ==1 ) type = VIEWER_STEREO_ANAGLYPH;
2776 if(type==VIEWER_STEREO_SHUTTERGLASSES)
2780 if (!
viewer->haveQuadbuffer ) {
2781 ConsoleMessage(
"Unable to get quadbuffer stereo visual, switching to flutter mode\n");
2790void fwl_set_StereoParameter (
const char *optArg) {
2796 i = sscanf(optArg,
"%lf",&
viewer->stereoParameter);
2797 if (i==0) printf (
"warning, command line stereo parameter incorrect - was %s\n",optArg);
2798 else updateEyehalf();
2801void fwl_set_EyeDist (
const char *optArg) {
2806 i= sscanf(optArg,
"%lf",&
viewer->eyedist);
2807 if (i==0) printf (
"warning, command line eyedist parameter incorrect - was %s\n",optArg);
2808 else updateEyehalf();
2811void fwl_set_ScreenDist (
const char *optArg) {
2816 i= sscanf(optArg,
"%lf",&
viewer->screendist);
2817 if (i==0) printf (
"warning, command line screendist parameter incorrect - was %s\n",optArg);
2818 else updateEyehalf();
2822void set_stereo_offset0()
2824 double x = 0.0, angle = 0.0;
2828 if (
viewer->iside == 0) {
2831 angle =
viewer->eyehalfangle;
2832 }
else if (
viewer->iside == 1) {
2835 angle = -
viewer->eyehalfangle;
2837 FW_GL_TRANSLATE_D(x, 0.0, 0.0);
2838 FW_GL_ROTATE_D(angle, 0.0, 1.0, 0.0);
2848 boundvp = getActiveLayerBoundViewpoint();
2850 switch(boundvp->_nodeType){
2851 case NODE_OrthoViewpoint:
2856 quaternion_to_vrmlrot(&
viewer->Quat,&oo[0],&oo[1],&oo[2],&oo[3]);
2858 double2float(vp->orientation.c,oo,4);
2861 case NODE_Viewpoint:
2866 quaternion_to_vrmlrot(&
viewer->Quat,&oo[0],&oo[1],&oo[2],&oo[3]);
2868 double2float(vp->orientation.c,oo,4);
2871 case NODE_GeoViewpoint:
2873 double pos[3],pos0[3],quat[4],quat0[4];
2875 pointxyz2double(pos,&
viewer->Pos);
2876 pointxyz2double(pos0,&
viewer->Pos0);
2877 quat2double(quat,&
viewer->Quat);
2878 quat2double(quat0,&
viewer->Quat0);
2879 if(veclengthd(vecdifd(pos,pos,pos0)) > .002 || veclength4d(vecdif4d(quat,quat,quat0)) > .00002)
2880 geoviewpoint_update_TCS(vp,&
viewer->Quat,&
viewer->Pos);
2892 boundvp = getActiveLayerBoundViewpoint();
2894 switch(boundvp->_nodeType){
2895 case NODE_OrthoViewpoint:
2898 double oo[4], pp[3];
2899 float2double(pp,vp->position.c,3);
2900 double2pointxyz(&
viewer->Pos,pp);
2902 float2double(oo,vp->orientation.c,4);
2903 vrmlrot_to_quaternion(&
viewer->Quat,oo[0],oo[1],oo[2],-oo[3]);
2906 case NODE_Viewpoint:
2910 double oo[4], pp[3];
2911 float2double(pp,vp->position.c,3);
2912 double2pointxyz(&
viewer->Pos,pp);
2913 float2double(oo,vp->orientation.c,4);
2914 vrmlrot_to_quaternion(&
viewer->Quat,oo[0],oo[1],oo[2],-oo[3]);
2917 case NODE_GeoViewpoint:
2941 boundvp = getActiveLayerBoundViewpoint();
2943 switch(boundvp->_nodeType){
2944 case NODE_OrthoViewpoint:
2945 case NODE_Viewpoint:
2946 viewer_fetch_user_offsets0(
viewer);
2948 case NODE_GeoViewpoint:
2965 boundvp = getActiveLayerBoundViewpoint();
2967 switch(boundvp->_nodeType){
2968 case NODE_OrthoViewpoint:
2969 case NODE_Viewpoint:
2970 viewer_update_user_offsets0(
viewer);
2972 case NODE_GeoViewpoint:
2974 double pos[3],pos0[3],quat[4],quat0[4];
2976 pointxyz2double(pos,&
viewer->Pos);
2977 pointxyz2double(pos0,&
viewer->Pos0);
2978 quat2double(quat,&
viewer->Quat);
2979 quat2double(quat0,&
viewer->Quat0);
2980 if(veclengthd(vecdifd(pos,pos,pos0)) > .002 || veclength4d(vecdif4d(quat,quat,quat0)) > .00002)
2981 geoviewpoint_update_LCS(vp,&
viewer->Quat,&
viewer->Pos);
2995 boundvp = getActiveLayerBoundViewpoint();
2997 switch(boundvp->_nodeType){
2998 case NODE_OrthoViewpoint:
3001 double oo[4], pp[3];
3002 float2double(pp,vp->_position.c,3);
3003 double2pointxyz(&
viewer->Pos,pp);
3005 float2double(oo,vp->_orientation.c,4);
3006 vrmlrot_to_quaternion(&
viewer->Quat,oo[0],oo[1],oo[2],-oo[3]);
3009 case NODE_Viewpoint:
3013 double oo[4], pp[3];
3014 float2double(pp,vp->_position.c,3);
3015 double2pointxyz(&
viewer->Pos,pp);
3016 float2double(oo,vp->_orientation.c,4);
3017 vrmlrot_to_quaternion(&
viewer->Quat,oo[0],oo[1],oo[2],-oo[3]);
3020 case NODE_GeoViewpoint:
3024 float2double(oo,vp->_orientation.c,4);
3025 vrmlrot_to_quaternion(Quat,oo[0],oo[1],oo[2], -oo[3]);
3026 double2pointxyz(Pos,vp->_position.c);
3037void increment_pos0(
struct point_XYZ *vec) {
3042 viewer_lastP_add(vec);
3045 quaternion_inverse(&q_i, &(
viewer->Quat));
3046 quaternion_rotation(&nv, &q_i, vec);
3049 viewer->VPvelocity.x = nv.x;
viewer->VPvelocity.y = nv.y;
viewer->VPvelocity.z = nv.z;
3060void increment_pos(
struct point_XYZ *vec) {
3063 viewer_fetch_user_offsets0(
viewer);
3064 increment_pos0(vec);
3065 viewer_update_user_offsets0(
viewer);
3074 viewer = ViewerByLayerId(vp->_layerId);
3078 if (!(vp->isBound))
return;
3079 if(!vp->_initializedOnce) {
3081 veccopy3f(vp->_position.c,vp->position.c);
3082 veccopy4f(vp->_orientation.c,vp->orientation.c);
3083 vp->_initializedOnce = TRUE;
3086 if(!vp->retainUserOffsets){
3087 veccopy3f(vp->position.c,vp->_position.c);
3088 veccopy4f(vp->orientation.c,vp->_orientation.c);
3090 viewer = ViewerByLayerId(vp->_layerId);
3094 if (
viewer->transitionType != VIEWER_TRANSITION_TELEPORT &&
viewer->wasBound) {
3096 viewer->vp2rnSaved = TRUE;
3101 matcopy(
viewer->slerp_viewmatrix,bstack->viewtransformmatrix);
3102 matcopy(
viewer->slerp_posorimatrix,bstack->posorimatrix);
3106 viewer->SLERPing = FALSE;
3107 viewer->startSLERPtime = TickTime();
3109 viewer->SLERPing2 = TRUE;
3110 viewer->SLERPing2justStarted = TRUE;
3114 viewer->SLERPing = FALSE;
3115 viewer->SLERPing2 = FALSE;
3124 if (vp->fieldOfView.n == 4) {
3127 viewer->orthoField[0] = (double) vp->fieldOfView.p[0];
3128 viewer->orthoField[1] = (double) vp->fieldOfView.p[1];
3129 viewer->orthoField[2] = (double) vp->fieldOfView.p[2];
3130 viewer->orthoField[3] = (double) vp->fieldOfView.p[3];
3132 ERROR_MSG(
"OrthoViewpoint - fieldOfView must have 4 parameters");
3133 viewer->orthoField[0] = -1.0;
3134 viewer->orthoField[1] = -1.0;
3135 viewer->orthoField[2] = 1.0;
3136 viewer->orthoField[3] = 1.0;
3142 INITIATE_ROTATION_ORIGIN
3171 viewer_lastP_clear();
3172 setMenuStatusVP (vp->description->strptr);
3177int slerp_viewpoint2()
3186 if(
viewer->SLERPing2 &&
viewer->vp2rnSaved && itype==2) {
3187 double mat_to[16],mat_from[16];
3190 bstack = getActiveBindableStacks(tg);
3192 matmultiplyAFFINE(mat_to,bstack->viewtransformmatrix,bstack->posorimatrix);
3193 matmultiplyAFFINE(mat_from,
viewer->slerp_viewmatrix,
viewer->slerp_posorimatrix);
3207 if(
viewer->SLERPing2justStarted)
3209 viewer->SLERPing2justStarted = FALSE;
3213 double matnow[16],matdif[16], matid[16], mat_toi[16], matview[16], matnew[16];;
3214 tickFrac = (TickTime() -
viewer->startSLERPtime)/
viewer->transitionTime;
3215 tickFrac = DOUBLE_MIN(tickFrac,1.0);
3216 tickFrac = DOUBLE_MAX(tickFrac,0.0);
3218 loadIdentityMatrix(matid);
3219 matinverseAFFINE(mat_toi,mat_to);
3220 matmultiplyAFFINE(matdif,mat_from,mat_toi);
3221 general_slerp(matnow,matdif,matid,16,tickFrac);
3222 matmultiplyAFFINE(matnew,matnow,bstack->viewtransformmatrix);
3223 matcopy(bstack->viewtransformmatrix, matnew);
3227 viewer->SLERPing2 = FALSE;
3234 if(
viewer->SLERPing2justStarted)
3239 double vpn2rn[16],rn2vpn[16];
3242 matcopy(vpo2rn,mat_from);
3246 matcopy(vpn2rn,mat_to);
3249 matinverseAFFINE(rn2vpn,vpn2rn);
3254 matmultiplyAFFINE(diffrn,vpo2rn,rn2vpn);
3260 matrix_to_quaternion(&p->sq,diffrn);
3261 quaternion_normalize(&p->sq);
3262 p->sp[0] = diffrn[12];
3263 p->sp[1] = diffrn[13];
3264 p->sp[2] = diffrn[14];
3265 viewer->SLERPing2justStarted = FALSE;
3273 double vzero[3], vshift[3], matdif[16], matnew[16];
3275 tickFrac = (TickTime() -
viewer->startSLERPtime)/
viewer->transitionTime;
3276 tickFrac = DOUBLE_MIN(tickFrac,1.0);
3277 tickFrac = DOUBLE_MAX(tickFrac,0.0);
3279 vzero[0] = vzero[1] = vzero[2] = 0.0;
3280 vrmlrot_to_quaternion(&qzero, 0.0,1.0,0.0,0.0);
3281 quaternion_slerp(&qdif,&p->sq,&qzero,tickFrac);
3282 general_slerp(vshift,p->sp,vzero,3,tickFrac);
3283 FW_GL_PUSH_MATRIX();
3284 FW_GL_LOAD_IDENTITY();
3285 FW_GL_TRANSLATE_D(vshift[0],vshift[1],vshift[2]);
3286 quaternion_togl(&qdif);
3287 fw_glGetDoublev(GL_MODELVIEW_MATRIX, matdif);
3289 matmultiplyAFFINE(matnew,matdif,bstack->viewtransformmatrix);
3290 matcopy(bstack->viewtransformmatrix, matnew);
3293 viewer->SLERPing2 = FALSE;
3300int slerp_viewpoint3()
3310 if(
viewer->SLERPing3 && itype==3){
3314 tickFrac = (TickTime() -
viewer->startSLERPtime)/
viewer->transitionTime;
3315 tickFrac = min(1.0,tickFrac);
3317 viewer_fetch_LCS(
viewer);
3318 quaternion_slerp(&
viewer->Quat,&
viewer->startSLERPQuat,&
viewer->endSLERPQuat,tickFrac);
3321 viewer_update_LCS(
viewer);
3322 general_slerp(&
viewer->Dist,&
viewer->startSLERPDist,&
viewer->endSLERPDist,1,tickFrac);
3323 if(tickFrac >= 1.0) {
3333void setup_viewpoint_slerp3(
double* center,
double pivot_radius,
double vp_radius){
3348 double pos[3] = {0.0,0.0,0.0};
3352 veccopyd(pos,center);
3354 vecnormald(pos,pos);
3355 vecscaled(pos,pos,vp_radius);
3366 viewer_fetch_LCS(
viewer);
3370 viewer->startSLERPtime = TickTime();
3385 viewer->endSLERPDist = vp_radius;
3389 quaternion_normalize(&
viewer->startSLERPQuat);
3390 quaternion_inverse( &q_i,&
viewer->startSLERPQuat);
3391 vecdifd(pos,center,pos);
3392 double2pointxyz(&pp,pos);
3393 quaternion_rotation(&qq, &q_i, &pp);
3394 vecadd(&
viewer->endSLERPPos,&
viewer->startSLERPPos,&qq);
3402 if( APPROX( vecnormald(C,C), 0.0) )
3406 vecscaled(C,C,-1.0);
3407 yaw = -atan2(C[0],C[2]);
3409 vrmlrot_to_quaternion(&qyaw, 0.0,1.0,0.0,yaw);
3410 double2pointxyz(&PC,C);
3411 quaternion_rotation(&PC,&qyaw,&PC);
3413 pitch = atan2(PC.y,PC.z);
3414 vrmlrot_to_quaternion(&qpitch,1.0,0.0,0.0,pitch);
3416 quaternion_multiply(&qtmp,&qyaw,&qpitch);
3417 quaternion_multiply(&
viewer->endSLERPQuat,&qtmp,&
viewer->startSLERPQuat);
3420void viewer_viewall(){
3421 double dcenter[3], pivot_radius, vp_radius;
3427 float scene_diameter, vpradius;
3429 float vpf[3], center[3], vpoffset[3];
3430 FW_GL_GETDOUBLEV(GL_MODELVIEW_MATRIX, MM);
3431 extent6f_copy(extent6,rn->_extent);
3432 extent6f_mattransform4d(extent6,extent6,MM);
3435 vecset3f(vpf,0.0f,0.0f,0.0f);
3436 extent6f_get_center3f(extent6,center);
3437 float2double(dcenter,center,3);
3438 vecdif3f(vpoffset,center,vpf);
3439 pivot_radius = extent6f_get_maxradius(extent6);
3440 vp_radius = vpradius = veclength3f(vpoffset) * 1.5;
3441 Viewer()->Dist = vp_radius;
3443 setup_viewpoint_slerp3(dcenter,pivot_radius, vp_radius);
3454 if (!(vp->isBound))
return;
3455 if(!vp->_initializedOnce) {
3456 veccopy3f(vp->_position.c,vp->position.c);
3457 veccopy4f(vp->_orientation.c,vp->orientation.c);
3458 vp->_initializedOnce = TRUE;
3607 if(!vp->retainUserOffsets){
3608 veccopy3f(vp->position.c,vp->_position.c);
3609 veccopy4f(vp->orientation.c,vp->_orientation.c);
3611 viewer = ViewerByLayerId(vp->_layerId);
3615 if (
viewer->transitionType != VIEWER_TRANSITION_TELEPORT &&
viewer->wasBound) {
3617 viewer->vp2rnSaved = TRUE;
3622 matcopy(
viewer->slerp_viewmatrix,bstack->viewtransformmatrix);
3623 matcopy(
viewer->slerp_posorimatrix,bstack->posorimatrix);
3627 viewer->SLERPing = FALSE;
3628 viewer->startSLERPtime = TickTime();
3630 viewer->SLERPing2 = TRUE;
3631 viewer->SLERPing2justStarted = TRUE;
3633 viewer->SLERPing = FALSE;
3634 viewer->SLERPing2 = FALSE;
3648 INITIATE_ROTATION_ORIGIN
3678 viewer_lastP_clear();
3679 setMenuStatusVP (vp->description->strptr);
3683int fwl_getAnaglyphSide(
int whichSide) {
3687 if ((whichSide<0) || (whichSide>1)) {
3702 return (p->acMask[whichSide][0] << 2) | (p->acMask[whichSide][1] << 1) | (p->acMask[whichSide][2]);
3709void Android_reset_viewer_to_defaults() {
3715 p->viewer_initialized = FALSE;
3718 viewer->SLERPing2 = FALSE;
3719 viewer->SLERPing = FALSE;
3723 return Viewer()->iside;