#include "linmath.h" #include "survive_cal.h" #include <dclapack.h> #include <linmath.h> #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <survive.h> #include <survive_reproject.h> // Dave talks about this poser here: https://www.youtube.com/watch?v=nSbEltdH9vM&feature=youtu.be&t=2h29m47s void OrthoSolve( FLT T[4][4], // OUTPUT: 4x4 transformation matrix FLT S_out[2][SENSORS_PER_OBJECT], // OUTPUT: array of screenspace points FLT S_in[2][SENSORS_PER_OBJECT], // INPUT: array of screenspace points FLT X_in[3][SENSORS_PER_OBJECT], // INPUT: array of offsets int nPoints); typedef struct { int nextaxis; float lengths[SENSORS_PER_OBJECT][NUM_LIGHTHOUSES][2]; float angles[SENSORS_PER_OBJECT][NUM_LIGHTHOUSES][2]; //Stuff } DummyData; int PoserDaveOrtho( SurviveObject * so, PoserData * pd ) { PoserType pt = pd->pt; SurviveContext * ctx = so->ctx; DummyData * dd = so->PoserData; if (!dd) so->PoserData = dd = calloc(sizeof(DummyData), 1); switch( pt ) { case POSERDATA_IMU: { PoserDataIMU * imu = (PoserDataIMU*)pd; //printf( "IMU:%s (%f %f %f) (%f %f %f)\n", so->codename, imu->accel[0], imu->accel[1], imu->accel[2], imu->gyro[0], imu->gyro[1], imu->gyro[2] ); break; } case POSERDATA_LIGHT: { PoserDataLight * l = (PoserDataLight*)pd; if (l->length > dd->lengths[l->sensor_id][l->lh][dd->nextaxis]) { dd->lengths[l->sensor_id][l->lh][dd->nextaxis] = l->length; dd->angles[l->sensor_id][l->lh][dd->nextaxis] = l->angle; } break; } case POSERDATA_SYNC: { PoserDataLight *l = (PoserDataLight *)pd; int lhid = l->lh; dd->nextaxis = l->acode & 1; if (dd->nextaxis == 0) { int i; int max_hits = 0; FLT S_in[2][SENSORS_PER_OBJECT]; FLT X_in[3][SENSORS_PER_OBJECT]; for (i = 0; i < SENSORS_PER_OBJECT; i++) { // Load all our valid points into something the LHFinder can use. if (dd->lengths[i][lhid][0] > 0 && dd->lengths[i][lhid][1] > 0) { S_in[0][max_hits] = dd->angles[i][lhid][0]; S_in[1][max_hits] = dd->angles[i][lhid][1]; dd->lengths[i][lhid][0] = -1; dd->lengths[i][lhid][1] = -1; X_in[0][max_hits] = so->sensor_locations[i * 3 + 0]; X_in[1][max_hits] = so->sensor_locations[i * 3 + 1]; X_in[2][max_hits] = so->sensor_locations[i * 3 + 2]; max_hits++; } } if (max_hits > 2) { // if( lhid == 0 ) { printf( "\033[H\033[2J" ); } // printf( "%d\n", max_hits ); FLT tOut[4][4]; FLT S_out[2][SENSORS_PER_OBJECT]; OrthoSolve(tOut, S_out, S_in, X_in, max_hits); // Now, we need to solve where we are as a function of where // the lighthouses are. SurvivePose objpose; FLT MT[4][4]; objpose.Pos[0] = tOut[0][3]; objpose.Pos[1] = tOut[1][3]; objpose.Pos[2] = tOut[2][3]; // matrix44transpose( MT, &tOut[0][0] ); matrix44copy(&MT[0][0], &tOut[0][0]); quatfrommatrix(objpose.Rot, &MT[0][0]); // printf( "QUAT: %f %f %f %f = %f\n", quat[0], quat[1], quat[2], quat[3], quatmagnitude(quat) ); // quat[2] -= 0.005; //fixes up lh0 in test data set. quatnormalize(objpose.Rot, objpose.Rot); SurvivePose lh2world = so->ctx->bsd[lhid].Pose; SurvivePose obj2world; ApplyPoseToPose(&obj2world, &lh2world, &objpose); PoserData_poser_pose_func(pd, so, &obj2world); if (0) { fprintf(stderr,"INQUAT: %f %f %f %f = %f [%f %f %f]\n", objpose.Rot[0], objpose.Rot[1], objpose.Rot[2], objpose.Rot[3], quatmagnitude(objpose.Rot), objpose.Pos[0], objpose.Pos[1], objpose.Pos[2]); // fprintf(stderr,"OUQUAT: %f %f %f %f = %f [%f %f %f]\n", poseout.Rot[0], poseout.Rot[1], poseout.Rot[2], // poseout.Rot[3], quatmagnitude(poseout.Rot), poseout.Pos[0], poseout.Pos[1], poseout.Pos[2]); } } } // if( so->codename[0] == 'H' ) printf( "LIG:%s %d @ %d rad, %f s (AX %d) (TC %d)\n", so->codename, // l->sensor_id, l->lh, l->length, dd->nextaxis, l->timecode ); break; } case POSERDATA_FULL_SCENE: { PoserDataFullScene * fs = (PoserDataFullScene*)pd; int LH_ID; SurvivePose alignLh0ToXAxis = {0}; for( LH_ID = 0; LH_ID < 2; LH_ID++ ) { int i; int max_hits = 0; FLT S_in[2][SENSORS_PER_OBJECT]; FLT X_in[3][SENSORS_PER_OBJECT]; for( i = 0; i < SENSORS_PER_OBJECT; i++ ) { //Load all our valid points into something the LHFinder can use. if( fs->lengths[i][LH_ID][0] > 0 ) { FLT out[2]; survive_apply_bsd_calibration(ctx, LH_ID, fs->angles[i][LH_ID], out); S_in[0][max_hits] = out[0]; S_in[1][max_hits] = out[1]; X_in[0][max_hits] = so->sensor_locations[i*3+0]; X_in[1][max_hits] = so->sensor_locations[i*3+1]; X_in[2][max_hits] = so->sensor_locations[i*3+2]; max_hits++; } } FLT tOut[4][4]; FLT S_out[2][SENSORS_PER_OBJECT]; OrthoSolve( tOut, S_out, S_in, X_in, max_hits ); //Now, we need to solve where we are as a function of where //the lighthouses are. // FLT quat[4]; // FLT posoff[3] = { tOut[0][3], tOut[1][3], tOut[2][3] }; SurvivePose objpose; FLT MT[4][4]; objpose.Pos[0] = tOut[0][3]; objpose.Pos[1] = tOut[1][3]; objpose.Pos[2] = tOut[2][3]; //matrix44transpose( MT, &tOut[0][0] ); matrix44copy( &MT[0][0], &tOut[0][0] ); quatfrommatrix(objpose.Rot, &MT[0][0]); //printf( "QUAT: %f %f %f %f = %f\n", quat[0], quat[1], quat[2], quat[3], quatmagnitude(quat) ); //quat[2] -= 0.005; //fixes up lh0 in test data set. quatnormalize(objpose.Rot, objpose.Rot); printf("QUAT: %f %f %f %f = %f [%f %f %f]\n", objpose.Rot[0], objpose.Rot[1], objpose.Rot[2], objpose.Rot[3], quatmagnitude(objpose.Rot), objpose.Pos[0], objpose.Pos[1], objpose.Pos[2]); if (0) ; for (i = 0; i < max_hits; i++) { FLT pt[3] = {X_in[0][i], X_in[1][i], X_in[2][i]}; quatrotatevector(pt, objpose.Rot, pt); add3d(pt, pt, objpose.Pos); printf("OUT %f %f %f ANGLE %f %f AOUT %f %f\n", pt[0], pt[1], pt[2], S_in[0][i], S_in[1][i], atan2(pt[0], pt[1]), atan2(pt[2], pt[1])); } /* so->FromLHPose[LH_ID].Pos[0] = objpose.Pos[0]; so->FromLHPose[LH_ID].Pos[1] = objpose.Pos[1]; so->FromLHPose[LH_ID].Pos[2] = objpose.Pos[2]; so->FromLHPose[LH_ID].Rot[0] = objpose.Rot[0]; so->FromLHPose[LH_ID].Rot[1] = objpose.Rot[1]; so->FromLHPose[LH_ID].Rot[2] = objpose.Rot[2]; so->FromLHPose[LH_ID].Rot[3] = objpose.Rot[3]; */ SurvivePose poseout; InvertPose(&poseout, &objpose); printf("INQUAT: %f %f %f %f = %f [%f %f %f]\n", objpose.Rot[0], objpose.Rot[1], objpose.Rot[2], objpose.Rot[3], quatmagnitude(objpose.Rot), objpose.Pos[0], objpose.Pos[1], objpose.Pos[2]); PoserData_lighthouse_pose_func(&fs->hdr, so, LH_ID, &alignLh0ToXAxis, &poseout, 0); printf("OUQUAT: %f %f %f %f = %f [%f %f %f]\n", poseout.Rot[0], poseout.Rot[1], poseout.Rot[2], poseout.Rot[3], quatmagnitude(poseout.Rot), poseout.Pos[0], poseout.Pos[1], poseout.Pos[2]); } break; } case POSERDATA_DISASSOCIATE: { free( dd ); so->PoserData = 0; //printf( "Need to disassociate.\n" ); break; } } return 0; } REGISTER_LINKTIME( PoserDaveOrtho ); #define PRINT_MAT(A,M,N) { \ int m,n; \ printf(#A "\n"); \ for (m=0; m<M; m++) { \ for (n=0; n<N; n++) { \ printf("%f\t", A[m][n]); \ } \ printf("\n"); \ } \ } #define CrossProduct(ox,oy,oz,a,b,c,x,y,z) { \ ox=(b)*(z)-(c)*(y); \ oy=(c)*(x)-(a)*(z); \ oz=(a)*(y)-(b)*(x); } void OrthoSolve(FLT T[4][4], // OUTPUT: 4x4 transformation matrix FLT S_out[2][SENSORS_PER_OBJECT], // OUTPUT: array of screenspace points (May not be populated!!!) FLT S_in[2][SENSORS_PER_OBJECT], // INPUT: array of screenspace points FLT X_in[3][SENSORS_PER_OBJECT], // INPUT: array of offsets int nPoints) { int i,j,k; FLT R[3][3]; // OUTPUT: 3x3 rotation matrix FLT trans[3]; // INPUT: x,y,z translation vector //-------------------- // Remove the center of the HMD offsets, and the screen space //-------------------- FLT xbar[3] = {0.0, 0.0, 0.0}; FLT sbar[2] = {0.0, 0.0}; FLT S[2][SENSORS_PER_OBJECT]; FLT X[3][SENSORS_PER_OBJECT]; FLT inv_nPoints = 1.0 / nPoints; for (i=0; i<nPoints; i++) { xbar[0] += X_in[0][i]; xbar[1] += X_in[1][i]; xbar[2] += X_in[2][i]; sbar[0] += S_in[0][i]; sbar[1] += S_in[1][i]; } for (j=0; j<3; j++) { xbar[j] *= inv_nPoints; } for (j=0; j<2; j++) { sbar[j] *= inv_nPoints; } for (i=0; i<nPoints; i++) { X[0][i] = X_in[0][i] - xbar[0]; X[1][i] = X_in[1][i] - xbar[1]; X[2][i] = X_in[2][i] - xbar[2]; S[0][i] = S_in[0][i] - sbar[0]; S[1][i] = S_in[1][i] - sbar[1]; } //-------------------- // Solve for the morph matrix // S = M X // thus // (SX^t)(XX^t)^-1 = M //-------------------- FLT Xt[SENSORS_PER_OBJECT][3]; FLT XXt[3][3]; FLT invXXt[3][3]; FLT SXt[2][3]; FLT M[2][3]; // Morph matrix! (2 by 3) TRANSP(Xt, X, 3, nPoints); MUL(XXt, X, Xt, 3, nPoints, 3); MUL(SXt, S, Xt, 2, nPoints, 3); INV(invXXt, XXt, 3, 3); MUL(M, SXt, invXXt, 2, 3, 3); // PRINT(M,2,3); // Double checking work FLT S_morph[2][SENSORS_PER_OBJECT]; MUL(S_morph, M, X, 2, 3, nPoints); for (i = 0; i < nPoints; i++) { S_morph[0][i] += sbar[0]; S_morph[1][i] += sbar[1]; } //-------------------- // Solve for the non-trivial vector // uf -- vector that goes into the camera //-------------------- FLT uM[3][3] = { { M[0][0], M[0][1], M[0][2] }, { M[1][0], M[1][1], M[1][2] }, { 3.14567, -1.2345, 4.32567 } }; // Morph matrix with appended row //PRINT(uM,3,3); // ToDo: Pick a number for the bottom that is NOT linearly separable with M[0] and M[1] FLT B[3][1] = { {0.0}, {0.0}, {1.0} }; FLT inv_uM[3][3]; FLT uf[3][1]; INV(inv_uM, uM, 3, 3); MUL(uf, inv_uM, B, 3, 3, 1); //-------------------- // Solve for unit length vector // f that goes into the camera //-------------------- FLT uf_len = sqrt( uf[0][0]*uf[0][0] + uf[1][0]*uf[1][0] + uf[2][0]*uf[2][0] ); FLT f[3][1] = { {uf[0][0]/uf_len}, {uf[1][0]/uf_len}, {uf[2][0]/uf_len} }; //PRINT(uf,3,1); //PRINT(f,3,1); //FLT check[3][1]; //MUL(uM,uf,check,3,3,1); //PRINT(check,3,1); //-------------------- // take cross products to get vectors u,r //-------------------- FLT u[3][1], r[3][1]; CrossProduct(u[0][0],u[1][0],u[2][0],f[0][0],f[1][0],f[2][0],1.0,0.0,0.0); FLT inv_ulen = 1.0 / sqrt( u[0][0]*u[0][0] + u[1][0]*u[1][0] + u[2][0]*u[2][0] ); u[0][0]*=inv_ulen; u[1][0]*=inv_ulen; u[2][0]*=inv_ulen; CrossProduct(r[0][0],r[1][0],r[2][0],f[0][0],f[1][0],f[2][0],u[0][0],u[1][0],u[2][0]); //PRINT(u,3,1); //PRINT(r,3,1); //-------------------- // Use morph matrix to get screen space // uhat,rhat //-------------------- FLT uhat[2][1], rhat[2][1], fhat[2][1]; MUL(fhat, M, f, 2, 3, 1); MUL(uhat, M, u, 2, 3, 1); MUL(rhat, M, r, 2, 3, 1); FLT fhat_len = sqrt( fhat[0][0]*fhat[0][0] + fhat[1][0]*fhat[1][0] ); FLT uhat_len = sqrt( uhat[0][0]*uhat[0][0] + uhat[1][0]*uhat[1][0] ); FLT rhat_len = sqrt( rhat[0][0]*rhat[0][0] + rhat[1][0]*rhat[1][0] ); FLT urhat_len = 0.5 * (uhat_len + rhat_len); /* printf("fhat %f %f (len %f)\n", fhat[0][0], fhat[1][0], fhat_len); printf("uhat %f %f (len %f)\n", uhat[0][0], uhat[1][0], uhat_len); printf("rhat %f %f (len %f)\n", rhat[0][0], rhat[1][0], rhat_len); */ // FLT ydist1 = 1.0 / uhat_len; //0.25*PI / uhat_len; // FLT ydist2 = 1.0 / rhat_len; //0.25*PI / rhat_len; FLT ydist = 1.0 / urhat_len; // TRICKY XXX Dave operates with "y forward" for some reason... // printf("ydist %f\n", ydist); // printf("ydist1 %f ydist2 %f ydist %f\n", ydist1, ydist2, ydist); //-------------------- // Rescale the axies to be of the proper length //-------------------- FLT x[3][1] = { {M[0][0]*ydist}, {0.0}, {M[1][0]*ydist} }; FLT y[3][1] = { {M[0][1]*ydist}, {0.0}, {M[1][1]*ydist} }; FLT z[3][1] = { {M[0][2]*ydist}, {0.0}, {M[1][2]*ydist} }; // we know the distance into (or out of) the camera for the z axis, // but we don't know which direction . . . FLT x_y = sqrt(1.0 - x[0][0]*x[0][0] - x[2][0]*x[2][0]); FLT y_y = sqrt(1.0 - y[0][0]*y[0][0] - y[2][0]*y[2][0]); FLT z_y = sqrt(1.0 - z[0][0]*z[0][0] - z[2][0]*z[2][0]); if( x_y != x_y ) x_y = 0; if( y_y != y_y ) y_y = 0; if( z_y != z_y ) z_y = 0; // Exhaustively flip the minus sign of the z axis until we find the right one . . . FLT bestErr = 9999.0; FLT xy_dot2 = x[0][0]*y[0][0] + x[2][0]*y[2][0]; FLT yz_dot2 = y[0][0]*z[0][0] + y[2][0]*z[2][0]; FLT zx_dot2 = z[0][0]*x[0][0] + z[2][0]*x[2][0]; for (i=0;i<2;i++) { for (j=0;j<2;j++) { for(k=0;k<2;k++) { // Calculate the error term FLT xy_dot = xy_dot2 + x_y*y_y; FLT yz_dot = yz_dot2 + y_y*z_y; FLT zx_dot = zx_dot2 + z_y*x_y; FLT err = _ABS(xy_dot) + _ABS(yz_dot) + _ABS(zx_dot); // Calculate the handedness FLT cx,cy,cz; CrossProduct(cx,cy,cz,x[0][0],x_y,x[2][0],y[0][0],y_y,y[2][0]); FLT hand = cx*z[0][0] + cy*z_y + cz*z[2][0]; // printf("err %f hand %f\n", err, hand); // If we are the best right-handed frame so far if (hand > 0 && err < bestErr) { x[1][0] = x_y; y[1][0] = y_y; z[1][0] = z_y; bestErr = err; } // if ( i == 0 && j == 0 && k == 0) { x[1][0]=x_y; y[1][0]=y_y; z[1][0]=z_y; bestErr=err; } z_y = -z_y; } y_y = -y_y; } x_y = -x_y; } // printf("bestErr %f\n", bestErr); /* //------------------------- // A test version of the rescaling to the proper length //------------------------- FLT ydist2 = ydist; FLT bestBestErr = 9999.0; FLT bestYdist = 0; for (ydist2=ydist-0.1; ydist2<ydist+0.1; ydist2+=0.0001) { FLT x2[3][1] = { {M[0][0]*ydist2}, {0.0}, {M[1][0]*ydist2} }; FLT y2[3][1] = { {M[0][1]*ydist2}, {0.0}, {M[1][1]*ydist2} }; FLT z2[3][1] = { {M[0][2]*ydist2}, {0.0}, {M[1][2]*ydist2} }; // we know the distance into (or out of) the camera for the z axis, // but we don't know which direction . . . FLT x_y = sqrt(1.0 - x2[0][0]*x2[0][0] - x2[2][0]*x2[2][0]); FLT y_y = sqrt(1.0 - y2[0][0]*y2[0][0] - y2[2][0]*y2[2][0]); FLT z_y = sqrt(1.0 - z2[0][0]*z2[0][0] - z2[2][0]*z2[2][0]); if( x_y != x_y ) x_y = 0; if( y_y != y_y ) y_y = 0; if( z_y != z_y ) z_y = 0; // printf( "---> %f %f %f\n", x_y, y_y, z_y ); // Exhaustively flip the minus sign of the z axis until we find the right one . . . FLT bestErr = 9999.0; FLT xy_dot2 = x2[0][0]*y2[0][0] + x2[2][0]*y2[2][0]; FLT yz_dot2 = y2[0][0]*z2[0][0] + y2[2][0]*z2[2][0]; FLT zx_dot2 = z2[0][0]*x2[0][0] + z2[2][0]*x2[2][0]; for (i=0;i<2;i++) { for (j=0;j<2;j++) { for(k=0;k<2;k++) { // Calculate the error term FLT xy_dot = xy_dot2 + x_y*y_y; FLT yz_dot = yz_dot2 + y_y*z_y; FLT zx_dot = zx_dot2 + z_y*x_y; FLT err = _ABS(xy_dot) + _ABS(yz_dot) + _ABS(zx_dot); // Calculate the handedness FLT cx,cy,cz; CrossProduct(cx,cy,cz,x2[0][0],x_y,x2[2][0],y2[0][0],y_y,y2[2][0]); FLT hand = cx*z2[0][0] + cy*z_y + cz*z2[2][0]; //printf("err %f hand %f\n", err, hand); // If we are the best right-handed frame so far if (hand > 0 && err < bestErr) { x2[1][0]=x_y; y2[1][0]=y_y; z2[1][0]=z_y; bestErr=err; } z_y = -z_y; } y_y = -y_y; } x_y = -x_y; } printf("ydist2 %f bestErr %f\n",ydist2,bestErr); if (bestErr < bestBestErr) { memcpy(x,x2,3*sizeof(FLT)); memcpy(y,y2,3*sizeof(FLT)); memcpy(z,z2,3*sizeof(FLT)); bestBestErr = bestErr; bestYdist = ydist2; } } ydist = bestYdist; */ /* for (i=0; i<nPoints; i++) { FLT x1 = x[0][0]*X[0][i] + y[0][0]*X[1][i] + z[0][0]*X[2][i]; FLT y1 = x[1][0]*X[0][i] + y[1][0]*X[1][i] + z[1][0]*X[2][i]; FLT z1 = x[2][0]*X[0][i] + y[2][0]*X[1][i] + z[2][0]*X[2][i]; printf("x1z1 %f %f y1 %f\n", x1, z1, y1); } */ /* //-------------------- // Combine uhat and rhat to figure out the unit x-vector //-------------------- FLT xhat[2][1] = { {0.0}, {1.0} }; FLT urhat[2][2] = { {uhat[0][0], uhat[1][0]}, {rhat[0][0], rhat[1][0]} }; FLT inv_urhat[2][2]; FLT ab[2][1]; INV(urhat,inv_urhat,2); MUL(inv_urhat,xhat,ab,2,2,1); PRINT(ab,2,1); FLT a = ab[0][0], b = ab[1][0]; //------------------- // calculate the xyz coordinate system //------------------- FLT y[3][1] = { {f[0][0]}, {f[1][0]}, {f[2][0]} }; FLT x[3][1] = { {a*u[0][0] + b*r[0][0]}, {a*u[1][0] + b*r[1][0]}, {a*u[2][0] + b*r[2][0]} }; FLT inv_xlen = 1.0 / sqrt( x[0][0]*x[0][0] + x[1][0]*x[1][0] + x[2][0]*x[2][0] ); x[0][0]*=inv_xlen; x[1][0]*=inv_xlen; x[2][0]*=inv_xlen; FLT z[3][1]; CrossProduct(z[0][0],z[1][0],z[2][0],x[0][0],x[1][0],x[2][0],y[0][0],y[1][0],y[2][0]); */ // Store into the rotation matrix for (i=0; i<3; i++) { R[i][0] = x[i][0]; R[i][1] = y[i][0]; R[i][2] = z[i][0]; } //PRINT(R,3,3); //------------------- // Calculate the translation of the centroid //------------------- trans[0]=tan(sbar[0]); trans[1]=1.0; trans[2]=tan(sbar[1]); FLT inv_translen = ydist / sqrt( trans[0]*trans[0] + trans[1]*trans[1] + trans[2]*trans[2] ); trans[0]*=inv_translen; trans[1]*=inv_translen; trans[2]*=inv_translen; //------------------- // Add in the centroid point //------------------- trans[0] -= xbar[0]*R[0][0] + xbar[1]*R[0][1] + xbar[2]*R[0][2]; trans[1] -= xbar[0]*R[1][0] + xbar[1]*R[1][1] + xbar[2]*R[1][2]; trans[2] -= xbar[0]*R[2][0] + xbar[1]*R[2][1] + xbar[2]*R[2][2]; FLT transdist = sqrt( trans[0]*trans[0] + trans[1]*trans[1] + trans[2]*trans[2] ); //------------------- // Pack into the 4x4 transformation matrix, and put into correct "world"-space. I.e. where is the object, relative to // the lighthouse. //------------------- #if 0 //Don't do any transformation to the correct space. T[0][0]=R[0][0]; T[0][1]=R[0][1]; T[0][2]=R[0][2]; T[0][3]=trans[0]; T[1][0]=R[1][0]; T[1][1]=R[1][1]; T[1][2]=R[1][2]; T[1][3]=trans[1]; T[2][0]=R[2][0]; T[2][1]=R[2][1]; T[2][2]=R[2][2]; T[2][3]=trans[2]; T[3][0]=0.0; T[3][1]=0.0; T[3][2]=0.0; T[3][3]=1.0; #else /* WRONG: This transposes. T[0][0]=-R[0][0]; T[0][1]=-R[0][1]; T[0][2]=-R[0][2]; T[0][3]=-trans[0]; T[2][0]= R[1][0]; T[2][1]= R[1][1]; T[2][2]= R[1][2]; T[2][3]=-trans[1]; T[1][0]= R[2][0]; T[1][1]= R[2][1]; T[1][2]= R[2][2]; T[1][3]=trans[2]; T[3][0]=0.0; T[3][1]=0.0; T[3][2]=0.0; T[3][3]=1.0; */ // XXX XXX XXX FOR ANYONE LOOKING TO CONTROL THE COORDINATE FRAME, THESE ARE THE LINES!!! /** This is probably all wonky and backwards but "looks" right except with multiple transforms, perhaps it's transposed. T[0][0]=-R[0][0]; T[0][1]= R[0][1]; T[0][2]= R[0][2]; T[0][3]=-trans[0]; T[2][0]=-R[1][0]; T[2][1]=-R[1][1]; T[2][2]= R[1][2]; T[2][3]=-trans[1];//This Z axis has problems with getting magnitudes. We can re=make it from the other two axes. T[1][0]=-R[2][0]; T[1][1]= R[2][1]; T[1][2]=-R[2][2]; T[1][3]= trans[2]; T[3][0]=0.0; T[3][1]=0.0; T[3][2]=0.0; T[3][3]=1.0; */ T[0][0] = -R[0][0]; T[0][1] = -R[0][1]; T[0][2] = -R[0][2]; T[0][3] = -trans[0]; T[1][0] = R[2][0]; T[1][1] = R[2][1]; T[1][2] = R[2][2]; T[2][3] = -trans[1]; T[2][0] = R[1][0]; T[2][1] = R[1][1]; T[2][2] = R[1][2]; T[1][3] = trans[2]; T[3][0] = 0.0; T[3][1] = 0.0; T[3][2] = 0.0; T[3][3] = 1.0; #endif //------------------- // Orthogonalize the matrix //------------------- // FLT temp[4][4]; // FLT quat[4], quatNorm[4]; // FLT euler[3]; //------------------- // Orthogonalize the matrix //------------------- cross3d(&T[2][0], &T[0][0], &T[1][0]); // Generate Z from X/Y because Z is kinda rekt. ///XXX TODO: Characterize how important these last two steps are. The matrix definitely is not normalized. #if 1 cross3d(&T[1][0], &T[2][0], &T[0][0] ); //Renormalize rotations... cross3d(&T[0][0], &T[1][0], &T[2][0] ); //Renormalize rotations... normalize3d( &T[0][0], &T[0][0] ); normalize3d( &T[1][0], &T[1][0] ); normalize3d( &T[2][0], &T[2][0] ); #endif // printf( " In Axis on headset \n" ); // printf( " x y z\n" ); // PRINT_MAT(T,4,4); // PRINT_MAT(T,4,4); // PRINT_MAT(T,4,4); // Fix handedness for rotations... // T[1][0]*=-1; // T[1][1]*=-1; // T[1][2]*=-1; // PRINT_MAT(T,4,4); #if 0 #if 1 //matrix44copy(T2,T); matrix44transpose((FLT*)T2,(FLT*)T); quatfrommatrix( quat, &T2[0][0] ); printf( "QM: %f\n", quatmagnitude( quat ) ); quatnormalize(quatNorm,quat); quattoeuler(euler,quatNorm); quattomatrix( &T2[0][0], quatNorm ); PRINT_MAT(T2,4,4); printf("rot %f %f %f len %f\n", euler[0], euler[1], euler[2], quatmagnitude(quat)); // PRINT(T,4,4); // matrix44copy(temp,T2); matrix44transpose((FLT*)temp,(FLT*)T2); // matrix44transpose(T2, temp); // memcpy(T2,temp,16*sizeof(float)); for (i=0; i<3; i++) { for (j=0; j<3; j++) { T[i][j] = temp[i][j]; } } /* PRINT(T2,4,4); */ #endif T[1][0]*=-1; T[1][1]*=-1; T[1][2]*=-1; /* CrossProduct(T[0][2],T[1][2],T[2][2], T[0][0],T[1][0],T[2][0], T[0][1],T[1][1],T[2][1]); CrossProduct(T[0][0],T[1][0],T[2][0], T[0][1],T[1][1],T[2][1], T[0][2],T[1][2],T[2][2]); CrossProduct(T[0][1],T[1][1],T[2][1], T[0][2],T[1][2],T[2][2], T[0][0],T[1][0],T[2][0]); float xlen = sqrt(T[0][0]*T[0][0] + T[1][0]*T[1][0] + T[2][0]*T[2][0]); float ylen = sqrt(T[0][1]*T[0][1] + T[1][1]*T[1][1] + T[2][1]*T[2][1]); float zlen = sqrt(T[0][2]*T[0][2] + T[1][0]*T[1][2] + T[2][2]*T[2][2]); T[0][0]/=xlen; T[1][0]/=xlen; T[2][0]/=xlen; T[0][1]/=ylen; T[1][1]/=ylen; T[2][1]/=ylen; T[0][2]/=zlen; T[1][2]/=zlen; T[2][2]/=zlen; */ // PRINT_MAT(T,4,4); //------------------- // Plot the output points //------------------- for (i=0; i<nPoints; i++) { FLT Tx = T[0][0]*X_in[0][i] + T[0][1]*X_in[1][i] + T[0][2]*X_in[2][i] + T[0][3]; FLT Ty = T[1][0]*X_in[0][i] + T[1][1]*X_in[1][i] + T[1][2]*X_in[2][i] + T[1][3]; FLT Tz = T[2][0]*X_in[0][i] + T[2][1]*X_in[1][i] + T[2][2]*X_in[2][i] + T[2][3]; S_out[0][i] = atan2(Tx, Ty); // horiz S_out[1][i] = atan2(Tz, Ty); // vert //S_out[0][i] = Tx; //S_out[1][i] = Tz; // printf("point %i Txyz %f %f %f in %f %f out %f %f morph %f %f\n", i, Tx,Ty,Tz, S_in[0][i], S_in[1][i], S_out[0][i], S_out[1][i], S_morph[0][i], S_morph[1][i]); } #endif }