22 #include "SSRhelper.h"
24 void threadsafe_enqueue_item(
s_list_t *item,
s_list_t** queue, pthread_mutex_t* queue_lock);
25 s_list_t* threadsafe_dequeue_item(
s_list_t** queue, pthread_mutex_t *queue_lock );
26 void threadsafe_enqueue_item_signal(
s_list_t *item,
s_list_t** queue, pthread_mutex_t* queue_lock, pthread_cond_t *queue_nonzero);
27 s_list_t* threadsafe_dequeue_item_wait(
s_list_t** queue, pthread_mutex_t *queue_lock, pthread_cond_t *queue_nonzero,
bool *waiting );
29 int load_file_blob(
const char *filename,
char **blob,
int *len);
31 void viewer_setpose(
double *quat4,
double *vec3);
32 void viewer_getpose(
double *quat4,
double *vec3);
33 void viewer_getbindpose(
double *quat4,
double *vec3);
39 static pthread_mutex_t ssr_queue_mutex = PTHREAD_MUTEX_INITIALIZER;
40 static pthread_cond_t ssr_queue_condition = PTHREAD_COND_INITIALIZER;
41 static bool ssr_server_waiting = FALSE;
43 void SSRserver_enqueue_request_and_wait(
void *fwctx,
SSR_request *request){
49 pthread_mutex_init(&request->requester_mutex,NULL);
50 pthread_cond_init(&request->requester_condition,NULL);
51 pthread_mutex_lock(&request->requester_mutex);
52 request->answered = 0;
55 if(1)threadsafe_enqueue_item(item,&ssr_queue, &ssr_queue_mutex);
56 if(0)threadsafe_enqueue_item_signal(item,&ssr_queue, &ssr_queue_mutex,&ssr_queue_condition);
57 while (request->answered == 0){
58 pthread_cond_wait(&request->requester_condition, &request->requester_mutex);
60 pthread_cond_destroy(&request->requester_condition);
61 pthread_mutex_destroy(&request->requester_mutex);
65 #include "../lib/internal.h"
68 #define GLDOUBLE double
70 #include "../lib/scenegraph/quaternion.h"
71 #include "../lib/scenegraph/LinearAlgebra.h"
72 static double view[16], inv_view[16], matOri[16];
74 static int vp2world_initialized = FALSE;
75 static int use_vp2world = TRUE;
77 static int reverse_sense_init = 0;
78 static int reverse_sense_quat4 = 0;
79 static int reverse_sense_vec3 = 0;
80 static int reverse_order_quat4 = 1;
81 void viewer_getview(
double *viewMatrix);
82 void vp2world_initialize()
231 if(!vp2world_initialized){
234 double wholeview[16], mat[16], mat2[16], mat3[16], mat4[16], quat4[4], vec3[3], matidentity[16];
235 viewer_getview(wholeview);
236 printmatrix2(wholeview,
"view with .pos .ori");
240 loadIdentityMatrix(matidentity);
241 loadIdentityMatrix(mat);
242 viewer_getpose(quat4,vec3);
243 printf(
"fixing view, current pose vec3=%lf %lf %lf\n",vec3[0],vec3[1],vec3[2]);
247 double2quat(&qq,quat4);
248 quaternion_normalize(&qq);
249 loadIdentityMatrix(mat2);
250 quaternion_to_matrix(mat2, &qq);
251 printmatrix2(mat2,
"matqq using quaternion_to_matrix");
253 loadIdentityMatrix(mat3);
254 mattranslate(mat3,vec3[0],vec3[1],vec3[2]);
255 printmatrix2(mat3,
"mat3 vec3 translation");
257 double matinvpos[16],matinvquat[16];
258 matinverseAFFINE(matinvquat,mat2);
259 matinverseAFFINE(matinvpos,mat3);
262 matmultiply(mat,matinvquat,matinvpos);
263 printmatrix2(mat,
"inv(vec3) x inv(quat)");
271 matmultiply(view,wholeview,mat);
272 printmatrix2(view,
"view - no .pos .ori");
274 matinverseAFFINE(inv_view, view);
275 if(reverse_sense_init){
276 matrix_to_quaternion(&viewQuat, inv_view);
277 quaternion_normalize(&viewQuat);
278 quaternion_inverse(&inv_viewQuat,&viewQuat);
280 matrix_to_quaternion(&viewQuat, view);
281 quaternion_normalize(&viewQuat);
283 quaternion_inverse(&inv_viewQuat,&viewQuat);
285 matrix_to_quaternion(&inv_viewQuat,inv_view);
286 quaternion_normalize(&inv_viewQuat);
294 double matQtmp[16],matii[16];
295 viewer_getpose(quat4,vec3);
297 double2quat(&q4,quat4);
298 quaternion_normalize(&q4);
299 quaternion_multiply(&qtmp,&q4, &viewQuat);
300 quaternion_normalize(&qtmp);
302 loadIdentityMatrix(matQtmp);
303 quaternion_to_matrix(matQtmp,&qtmp);
304 printmatrix2(matQtmp,
"matQtmp - should look like view with pos, ori in 3x3");
305 matinverseAFFINE(matii,inv_view);
306 printmatrix2(matii,
"matii inv(inv(view)) should look like view no pos ori");
307 matinverseAFFINE(matii,wholeview);
308 printf(
"from inv(wholeview) avatar coords should match '/' command:\n [%lf %lf %lf]\n",matii[12],matii[13],matii[14]);
309 viewer_getpose(quat4,vec3);
310 vecnegated(vec3,vec3);
311 transformAFFINEd(vec3, vec3, inv_view);
312 printf(
"but does it match my theory of inv(view no pos/ori) x .Pos?:\n [%lf %lf %lf]\n",vec3[0],vec3[1],vec3[2]);
315 vp2world_initialized = TRUE;
319 void SSR_reply_pose(
SSR_request *request,
int initialpose)
348 double quat4[4], vec3[3];
350 vp2world_initialize();
352 viewer_getbindpose(quat4,vec3);
355 viewer_getpose(quat4,vec3);
359 vecnegated(vec3,vec3);
360 transformAFFINEd(request->vec3, vec3, inv_view);
362 double2quat(&q4,quat4);
363 quaternion_normalize(&q4);
364 quaternion_multiply(&qtmp,&q4,&viewQuat);
365 quaternion_normalize(&qtmp);
366 quat2double(request->quat4,&qtmp);
368 memcpy(vec3,request->vec3,3*
sizeof(
double));
369 memcpy(quat4,request->quat4,4*
sizeof(
double));
375 viewer_getpose(request->quat4,request->vec3);
378 static ssr_test_initialized = FALSE;
379 static run_ssr_test = FALSE;
380 char *get_key_val(
char *
key);
381 static double incYaw;
382 static double incPitch;
383 static double incTrans[3];
384 static double incWtrans[3];
385 static int haveInc = FALSE;
386 void ssr_test_key_val(
char *
key,
char *val){
389 incTrans[0] = incTrans[1] = incTrans[2] = incYaw = incPitch = 0.0;
390 incWtrans[0] = incWtrans[1] = incWtrans[2] = 0.0;
392 ok = sscanf(val,
"%lf",&dval);
393 if(!strcmp(key,
"yaw")){
396 if(!strcmp(key,
"pitch")){
399 if(!strcmp(key,
"x")){
402 if(!strcmp(key,
"y")){
405 if(!strcmp(key,
"z")){
408 if(!strcmp(key,
"wx")){
411 if(!strcmp(key,
"wy")){
414 if(!strcmp(key,
"wz")){
424 int ssr_test(
char *
keyval){
437 sep = strchr(kv,
',');
438 if(!sep) sep = strchr(kv,
' ');
444 ssr_test_key_val(key,val);
452 #define MATH_PI 3.14159265358979323846
454 #ifndef DEGREES_PER_RADIAN
455 #define DEGREES_PER_RADIAN (double)57.2957795130823208768
483 void SSR_test_cumulative_pose(){
487 static int test_count = 0;
488 int test_full_cycle_here;
489 if(!ssr_test_initialized)
491 char *running_ssr = get_key_val(
"SSR");
494 if(!strcmp(running_ssr,
"true"))
495 run_ssr_test = FALSE;
496 ssr_test_initialized = TRUE;
498 if(!run_ssr_test)
return;
502 vp2world_initialized = FALSE;
503 vp2world_initialize();
504 test_full_cycle_here = FALSE;
505 if(test_full_cycle_here){
507 double matquat[16], matvec[16], mata[16], matcum[16], matb[16], matcuminv[16], matcumquat[16], matcumquatinv[16], matqb[16];
508 double quat4[4],vec3[3],quat4b[4],vec3b[3],zero3[3],cumpos[3],incTransb[3],vecpos[3];
509 Quaternion qa,cumquat,qb,cumquatinv, qa_inv, qc, incQuat, cumconj;
530 viewer_getpose(quat4,vec3);
531 zero3[0] = zero3[1] = zero3[2] = 0.0;
534 vecnegated(vec3,vec3);
535 transformAFFINEd(cumpos,vec3,inv_view);
536 double2quat(&qa,quat4);
537 quaternion_normalize(&qa);
538 quaternion_multiply(&cumquat,&qa,&viewQuat);
539 quaternion_normalize(&cumquat);
546 double ypr[3], axyz[3], dyaw, dpitch;
547 quaternion_print(&cumquat,
"cumquat before");
548 quaternion_inverse(&cumquatinv,&cumquat);
550 quat2yawpitch(ypr,&cumquatinv);
553 printf(
"1. yp =[%lf %lf]\n",rad2deg(dyaw),rad2deg(dpitch));
556 printf(
"2. yp =[%lf %lf]\n",rad2deg(dyaw),rad2deg(dpitch));
558 euler2quat(&cumquatinv,0.0,-dyaw,-dpitch);
559 quaternion_print(&cumquatinv,
"qi after euler2quat");
560 quaternion_inverse(&cumquat,&cumquatinv);
561 quaternion_print(&cumquat,
"cumquat after");
563 quaternion_rotationd(incTrans,&cumquatinv,incTrans);
564 vecaddd(cumpos,incTrans,cumpos);
566 vecaddd(cumpos,incWtrans,cumpos);
567 printf(
"cumpos [%lf %lf %lf]\n",cumpos[0],cumpos[1],cumpos[2]);
573 quaternion_multiply(&qb,&cumquat,&inv_viewQuat);
574 quaternion_normalize(&qb);
575 quat2double(quat4b,&qb);
577 transformAFFINEd(vec3b,cumpos,view);
578 vecnegated(vec3b,vec3b);
579 viewer_setpose(quat4b,vec3b);
586 SSR_reply_pose(&request,FALSE);
587 double2quat(&cumquat,request.quat4);
588 veccopyd(cumpos,request.vec3);
595 double ypr[3], axyz[3], dyaw, dpitch;
596 quaternion_print(&cumquat,
"cumquat before");
597 quaternion_inverse(&cumquatinv,&cumquat);
599 quat2yawpitch(ypr,&cumquatinv);
602 printf(
"1. yp =[%lf %lf]\n",rad2deg(dyaw),rad2deg(dpitch));
605 printf(
"2. yp =[%lf %lf]\n",rad2deg(dyaw),rad2deg(dpitch));
607 euler2quat(&cumquatinv,0.0,-dyaw,-dpitch);
608 quaternion_print(&cumquatinv,
"qi after euler2quat");
609 quaternion_inverse(&cumquat,&cumquatinv);
610 quaternion_print(&cumquat,
"cumquat after");
612 quaternion_rotationd(incTrans,&cumquatinv,incTrans);
613 vecaddd(cumpos,incTrans,cumpos);
615 vecaddd(cumpos,incWtrans,cumpos);
616 printf(
"cumpos [%lf %lf %lf]\n",cumpos[0],cumpos[1],cumpos[2]);
619 quat2double(request.quat4,&cumquat);
620 veccopyd(request.vec3,cumpos);
621 SSR_set_pose(&request);
637 double quat4[4], vec3[3];
639 vp2world_initialize();
640 transformAFFINEd(vec3,request->vec3,view);
641 vecnegated(vec3,vec3);
642 double2quat(&q4,request->quat4);
643 quaternion_multiply(&qtmp,&q4,&inv_viewQuat);
644 quaternion_normalize(&qtmp);
645 quat2double(quat4,&qtmp);
647 viewer_setpose(quat4,vec3);
650 viewer_setpose(request->quat4, request->vec3);
656 void dequeue_SSR_request(ttglobal tg)
671 int sleepincus = 1000;
672 int maxsleepus = 1000000;
674 while(!item && slept < maxsleepus) {
675 item = threadsafe_dequeue_item(&ssr_queue, &ssr_queue_mutex );
682 item = threadsafe_dequeue_item(&ssr_queue, &ssr_queue_mutex );
685 request = item->elem;
687 switch(request->type)
692 case SSR_POSESNAPSHOT:
693 SSR_set_pose(request);
699 ssr_current_request = request;
705 static char *snapshot_filename =
"snapshot.bmp";
707 static char *snapshot_filename =
"snapshot.png";
709 void Snapshot1(
char *fname);
713 Snapshot1(snapshot_filename);
714 iret = load_file_blob(snapshot_filename,&request->blob,&request->len);
716 printf(
"snapshot file not found %s\n",snapshot_filename);
718 unlink(snapshot_filename);
724 if(ssr_current_request){
726 switch(request->type){
728 SSR_reply_pose(request,TRUE);
break;
730 SSR_reply_pose(request,FALSE);
break;
731 case SSR_POSESNAPSHOT:
732 SSR_reply_snapshot(request);
break;
737 request->answered = 1;
738 pthread_cond_signal(&request->requester_condition);
739 ssr_current_request = NULL;