static void keyEvent( unsigned char key, int x, int y) { int i; if( key == 0x1b || key == 'q' || key == 'Q' ) { cleanup(); } if( cornerFlag && key==' ' ) { cvFindCornerSubPix( calibImageL, cornersL, chessboardCornerNumX*chessboardCornerNumY, cvSize(5,5), cvSize(-1,-1), cvTermCriteria(CV_TERMCRIT_ITER, 100, 0.1) ); for( i = 0; i < chessboardCornerNumX*chessboardCornerNumY; i++ ) { arParamObserv2Ideal(paramL.dist_factor, (double)cornersL[i].x, (double)cornersL[i].y, &calibData[capturedImageNum].screenCoordL[i].x, &calibData[capturedImageNum].screenCoordL[i].y, paramL.dist_function_version); } cvFindCornerSubPix( calibImageR, cornersR, chessboardCornerNumX*chessboardCornerNumY, cvSize(5,5), cvSize(-1,-1), cvTermCriteria(CV_TERMCRIT_ITER, 100, 0.1) ); for( i = 0; i < chessboardCornerNumX*chessboardCornerNumY; i++ ) { arParamObserv2Ideal(paramR.dist_factor, (double)cornersR[i].x, (double)cornersR[i].y, &calibData[capturedImageNum].screenCoordR[i].x, &calibData[capturedImageNum].screenCoordR[i].y, paramR.dist_function_version); } ARLOG("---------- %2d/%2d -----------\n", capturedImageNum+1, calibImageNum); for( i = 0; i < chessboardCornerNumX*chessboardCornerNumY; i++ ) { ARLOG(" %f, %f ---- %f, %f\n", calibData[capturedImageNum].screenCoordL[i].x, calibData[capturedImageNum].screenCoordL[i].y, calibData[capturedImageNum].screenCoordR[i].x, calibData[capturedImageNum].screenCoordR[i].y); } ARLOG("---------- %2d/%2d -----------\n", capturedImageNum+1, calibImageNum); capturedImageNum++; if( capturedImageNum == calibImageNum ) { calib(); cleanup(); } } }
static double get_size_factor( double dist_factor[4], int xsize, int ysize ) { double ox, oy, ix, iy; double olen, ilen; double sf, sf1; sf = 100.0; ox = 0.0; oy = dist_factor[1]; olen = dist_factor[0]; arParamObserv2Ideal( dist_factor, ox, oy, &ix, &iy ); ilen = dist_factor[0] - ix; printf("Olen = %f, Ilen = %f\n", olen, ilen); if( ilen > 0 ) { sf1 = ilen / olen; if( sf1 < sf ) sf = sf1; } ox = xsize; oy = dist_factor[1]; olen = xsize - dist_factor[0]; arParamObserv2Ideal( dist_factor, ox, oy, &ix, &iy ); ilen = ix - dist_factor[0]; printf("Olen = %f, Ilen = %f\n", olen, ilen); if( ilen > 0 ) { sf1 = ilen / olen; if( sf1 < sf ) sf = sf1; } ox = dist_factor[0]; oy = 0.0; olen = dist_factor[1]; arParamObserv2Ideal( dist_factor, ox, oy, &ix, &iy ); ilen = dist_factor[1] - iy; printf("Olen = %f, Ilen = %f\n", olen, ilen); if( ilen > 0 ) { sf1 = ilen / olen; if( sf1 < sf ) sf = sf1; } ox = dist_factor[0]; oy = ysize; olen = ysize - dist_factor[1]; arParamObserv2Ideal( dist_factor, ox, oy, &ix, &iy ); ilen = iy - dist_factor[1]; printf("Olen = %f, Ilen = %f\n", olen, ilen); if( ilen > 0 ) { sf1 = ilen / olen; if( sf1 < sf ) sf = sf1; } if( sf == 0.0 ) sf = 1.0; return sf; }
static void draw_line2( double *x, double *y, int num ) { ARMat *input, *evec; ARVec *ev, *mean; double a, b, c; int i; ev = arVecAlloc( 2 ); mean = arVecAlloc( 2 ); evec = arMatrixAlloc( 2, 2 ); input = arMatrixAlloc( num, 2 ); for( i = 0; i < num; i++ ) { arParamObserv2Ideal( dist_factor, x[i], y[i], &(input->m[i*2+0]), &(input->m[i*2+1]) ); } if( arMatrixPCA(input, evec, ev, mean) < 0 ) exit(0); a = evec->m[1]; b = -evec->m[0]; c = -(a*mean->v[0] + b*mean->v[1]); arMatrixFree( input ); arMatrixFree( evec ); arVecFree( mean ); arVecFree( ev ); draw_warp_line(a, b, c); }
static int arGetLine2(int x_coord[], int y_coord[], int coord_num, int vertex[], double line[4][3], double v[4][2], double *dist_factor) { ARMat *input, *evec; ARVec *ev, *mean; double w1; int st, ed, n; int i, j; ev = arVecAlloc( 2 ); mean = arVecAlloc( 2 ); evec = arMatrixAlloc( 2, 2 ); for( i = 0; i < 4; i++ ) { w1 = (double)(vertex[i+1]-vertex[i]+1) * 0.05 + 0.5; st = (int)(vertex[i] + w1); ed = (int)(vertex[i+1] - w1); n = ed - st + 1; input = arMatrixAlloc( n, 2 ); for( j = 0; j < n; j++ ) { arParamObserv2Ideal( dist_factor, x_coord[st+j], y_coord[st+j], &(input->m[j*2+0]), &(input->m[j*2+1]) ); } if( arMatrixPCA(input, evec, ev, mean) < 0 ) { arMatrixFree( input ); arMatrixFree( evec ); arVecFree( mean ); arVecFree( ev ); return(-1); } line[i][0] = evec->m[1]; line[i][1] = -evec->m[0]; line[i][2] = -(line[i][0]*mean->v[0] + line[i][1]*mean->v[1]); arMatrixFree( input ); } arMatrixFree( evec ); arVecFree( mean ); arVecFree( ev ); for( i = 0; i < 4; i++ ) { w1 = line[(i+3)%4][0] * line[i][1] - line[i][0] * line[(i+3)%4][1]; if( w1 == 0.0 ) return(-1); v[i][0] = ( line[(i+3)%4][1] * line[i][2] - line[i][1] * line[(i+3)%4][2] ) / w1; v[i][1] = ( line[i][0] * line[(i+3)%4][2] - line[(i+3)%4][0] * line[i][2] ) / w1; } return(0); }
static double check_error( double *x, double *y, int num, double dist_factor[4] ) { ARMat *input, *evec; ARVec *ev, *mean; double a, b, c; double error; int i; ev = arVecAlloc( 2 ); mean = arVecAlloc( 2 ); evec = arMatrixAlloc( 2, 2 ); input = arMatrixAlloc( num, 2 ); for( i = 0; i < num; i++ ) { arParamObserv2Ideal( dist_factor, x[i], y[i], &(input->m[i*2+0]), &(input->m[i*2+1]) ); } if( arMatrixPCA(input, evec, ev, mean) < 0 ) exit(0); a = evec->m[1]; b = -evec->m[0]; c = -(a*mean->v[0] + b*mean->v[1]); error = 0.0; for( i = 0; i < num; i++ ) { error += (a*input->m[i*2+0] + b*input->m[i*2+1] + c) * (a*input->m[i*2+0] + b*input->m[i*2+1] + c); } error /= (a*a + b*b); arMatrixFree( input ); arMatrixFree( evec ); arVecFree( mean ); arVecFree( ev ); return error; }
int ar2Tracking( AR2HandleT *ar2Handle, AR2SurfaceSetT *surfaceSet, ARUint8 *dataPtr, float trans[3][4], float *err ) { AR2TemplateCandidateT *candidatePtr; AR2TemplateCandidateT *cp[AR2_THREAD_MAX]; #if AR2_CAPABLE_ADAPTIVE_TEMPLATE float aveBlur; #endif int num, num2; int i, j, k; if (!ar2Handle || !surfaceSet || !dataPtr || !trans || !err) return (-1); if( surfaceSet->contNum <= 0 ) { ARLOGd("ar2Tracking() error: ar2SetInitTrans() must be called first.\n"); return -2; } *err = 0.0F; for( i = 0; i < surfaceSet->num; i++ ) { arUtilMatMulf( (const float (*)[4])surfaceSet->trans1, (const float (*)[4])surfaceSet->surface[i].trans, ar2Handle->wtrans1[i] ); if( surfaceSet->contNum > 1 ) arUtilMatMulf( (const float (*)[4])surfaceSet->trans2, (const float (*)[4])surfaceSet->surface[i].trans, ar2Handle->wtrans2[i] ); if( surfaceSet->contNum > 2 ) arUtilMatMulf( (const float (*)[4])surfaceSet->trans3, (const float (*)[4])surfaceSet->surface[i].trans, ar2Handle->wtrans3[i] ); } if( ar2Handle->trackingMode == AR2_TRACKING_6DOF ) { extractVisibleFeatures(ar2Handle->cparamLT, ar2Handle->wtrans1, surfaceSet, ar2Handle->candidate, ar2Handle->candidate2); } else { extractVisibleFeaturesHomography(ar2Handle->xsize, ar2Handle->ysize, ar2Handle->wtrans1, surfaceSet, ar2Handle->candidate, ar2Handle->candidate2); } candidatePtr = ar2Handle->candidate; #if AR2_CAPABLE_ADAPTIVE_TEMPLATE aveBlur = 0.0F; #endif i = 0; // Counts up to searchFeatureNum. num = 0; while( i < ar2Handle->searchFeatureNum ) { num2 = num; for( j = 0; j < ar2Handle->threadNum; j++ ) { if( i == ar2Handle->searchFeatureNum ) break; k = ar2SelectTemplate( candidatePtr, surfaceSet->prevFeature, num2, ar2Handle->pos, ar2Handle->xsize, ar2Handle->ysize ); if( k < 0 ) { if( candidatePtr == ar2Handle->candidate ) { candidatePtr = ar2Handle->candidate2; k = ar2SelectTemplate( candidatePtr, surfaceSet->prevFeature, num2, ar2Handle->pos, ar2Handle->xsize, ar2Handle->ysize ); if( k < 0 ) break; // PRL 2012-05-15: Give up if we can't select template from alternate candidate either. } else break; } cp[j] = &(candidatePtr[k]); ar2Handle->pos[num2][0] = candidatePtr[k].sx; ar2Handle->pos[num2][1] = candidatePtr[k].sy; ar2Handle->arg[j].ar2Handle = ar2Handle; ar2Handle->arg[j].surfaceSet = surfaceSet; ar2Handle->arg[j].candidate = &(candidatePtr[k]); ar2Handle->arg[j].dataPtr = dataPtr; threadStartSignal( ar2Handle->threadHandle[j] ); num2++; if( num2 == 5 ) num2 = num; i++; } k = j; if( k == 0 ) break; for( j = 0; j < k; j++ ) { threadEndWait( ar2Handle->threadHandle[j] ); if( ar2Handle->arg[j].ret == 0 && ar2Handle->arg[j].result.sim > ar2Handle->simThresh ) { if( ar2Handle->trackingMode == AR2_TRACKING_6DOF ) { #ifdef ARDOUBLE_IS_FLOAT arParamObserv2Ideal(ar2Handle->cparamLT->param.dist_factor, ar2Handle->arg[j].result.pos2d[0], ar2Handle->arg[j].result.pos2d[1], &ar2Handle->pos2d[num][0], &ar2Handle->pos2d[num][1], ar2Handle->cparamLT->param.dist_function_version); #else ARdouble pos2d0, pos2d1; arParamObserv2Ideal(ar2Handle->cparamLT->param.dist_factor, (ARdouble)(ar2Handle->arg[j].result.pos2d[0]), (ARdouble)(ar2Handle->arg[j].result.pos2d[1]), &pos2d0, &pos2d1, ar2Handle->cparamLT->param.dist_function_version); ar2Handle->pos2d[num][0] = (float)pos2d0; ar2Handle->pos2d[num][1] = (float)pos2d1; #endif } else { ar2Handle->pos2d[num][0] = ar2Handle->arg[j].result.pos2d[0]; ar2Handle->pos2d[num][1] = ar2Handle->arg[j].result.pos2d[1]; } ar2Handle->pos3d[num][0] = ar2Handle->arg[j].result.pos3d[0]; ar2Handle->pos3d[num][1] = ar2Handle->arg[j].result.pos3d[1]; ar2Handle->pos3d[num][2] = ar2Handle->arg[j].result.pos3d[2]; ar2Handle->pos[num][0] = cp[j]->sx; ar2Handle->pos[num][1] = cp[j]->sy; ar2Handle->usedFeature[num].snum = cp[j]->snum; ar2Handle->usedFeature[num].level = cp[j]->level; ar2Handle->usedFeature[num].num = cp[j]->num; ar2Handle->usedFeature[num].flag = 0; #if AR2_CAPABLE_ADAPTIVE_TEMPLATE aveBlur += ar2Handle->arg[j].result.blurLevel; #endif num++; } } } for( i = 0; i < num; i++ ) { surfaceSet->prevFeature[i] = ar2Handle->usedFeature[i]; } surfaceSet->prevFeature[num].flag = -1; //ARLOG("------\nNum = %d\n", num); if( ar2Handle->trackingMode == AR2_TRACKING_6DOF ) { if( num < 3 ) { surfaceSet->contNum = 0; return -3; } *err = ar2GetTransMat( ar2Handle->icpHandle, surfaceSet->trans1, ar2Handle->pos2d, ar2Handle->pos3d, num, trans, 0 ); //ARLOG("outlier 0%%: err = %f, num = %d\n", *err, num); if( *err > ar2Handle->trackingThresh ) { icpSetInlierProbability( ar2Handle->icpHandle, 0.8F ); *err = ar2GetTransMat( ar2Handle->icpHandle, trans, ar2Handle->pos2d, ar2Handle->pos3d, num, trans, 1 ); //ARLOG("outlier 20%%: err = %f, num = %d\n", *err, num); if( *err > ar2Handle->trackingThresh ) { icpSetInlierProbability( ar2Handle->icpHandle, 0.6F ); *err = ar2GetTransMat( ar2Handle->icpHandle, trans, ar2Handle->pos2d, ar2Handle->pos3d, num, trans, 1 ); //ARLOG("outlier 60%%: err = %f, num = %d\n", *err, num); if( *err > ar2Handle->trackingThresh ) { icpSetInlierProbability( ar2Handle->icpHandle, 0.4F ); *err = ar2GetTransMat( ar2Handle->icpHandle, trans, ar2Handle->pos2d, ar2Handle->pos3d, num, trans, 1 ); //ARLOG("outlier 60%%: err = %f, num = %d\n", *err, num); if( *err > ar2Handle->trackingThresh ) { icpSetInlierProbability( ar2Handle->icpHandle, 0.0F ); *err = ar2GetTransMat( ar2Handle->icpHandle, trans, ar2Handle->pos2d, ar2Handle->pos3d, num, trans, 1 ); //ARLOG("outlier Max: err = %f, num = %d\n", *err, num); if( *err > ar2Handle->trackingThresh ) { surfaceSet->contNum = 0; #if AR2_CAPABLE_ADAPTIVE_TEMPLATE if( ar2Handle->blurMethod == AR2_ADAPTIVE_BLUR ) ar2Handle->blurLevel = AR2_DEFAULT_BLUR_LEVEL; // Reset the blurLevel. #endif return -4; } } } } } } else { if( num < 3 ) { surfaceSet->contNum = 0; return -3; } *err = ar2GetTransMatHomography( surfaceSet->trans1, ar2Handle->pos2d, ar2Handle->pos3d, num, trans, 0, 1.0F ); //ARLOG("outlier 0%%: err = %f, num = %d\n", *err, num); if( *err > ar2Handle->trackingThresh ) { *err = ar2GetTransMatHomography( trans, ar2Handle->pos2d, ar2Handle->pos3d, num, trans, 1, 0.8F ); //ARLOG("outlier 20%%: err = %f, num = %d\n", *err, num); if( *err > ar2Handle->trackingThresh ) { *err = ar2GetTransMatHomography( trans, ar2Handle->pos2d, ar2Handle->pos3d, num, trans, 1, 0.6F ); //ARLOG("outlier 40%%: err = %f, num = %d\n", *err, num); if( *err > ar2Handle->trackingThresh ) { *err = ar2GetTransMatHomography( trans, ar2Handle->pos2d, ar2Handle->pos3d, num, trans, 1, 0.4F ); //ARLOG("outlier 60%%: err = %f, num = %d\n", *err, num); if( *err > ar2Handle->trackingThresh ) { *err = ar2GetTransMatHomography( trans, ar2Handle->pos2d, ar2Handle->pos3d, num, trans, 1, 0.0F ); //ARLOG("outlier Max: err = %f, num = %d\n", *err, num); if( *err > ar2Handle->trackingThresh ) { surfaceSet->contNum = 0; #if AR2_CAPABLE_ADAPTIVE_TEMPLATE if( ar2Handle->blurMethod == AR2_ADAPTIVE_BLUR ) ar2Handle->blurLevel = AR2_DEFAULT_BLUR_LEVEL; // Reset the blurLevel. #endif return -4; } } } } } } #if AR2_CAPABLE_ADAPTIVE_TEMPLATE if( ar2Handle->blurMethod == AR2_ADAPTIVE_BLUR ) { aveBlur = aveBlur/num + 0.5F; ar2Handle->blurLevel += (int)aveBlur - 1; if( ar2Handle->blurLevel < 1 ) ar2Handle->blurLevel = 1; if( ar2Handle->blurLevel >= AR2_BLUR_IMAGE_MAX-1 ) ar2Handle->blurLevel = AR2_BLUR_IMAGE_MAX-2; } #endif surfaceSet->contNum++; for( j = 0; j < 3; j++ ) { for( i = 0; i < 4; i++ ) surfaceSet->trans3[j][i] = surfaceSet->trans2[j][i]; } for( j = 0; j < 3; j++ ) { for( i = 0; i < 4; i++ ) surfaceSet->trans2[j][i] = surfaceSet->trans1[j][i]; } for( j = 0; j < 3; j++ ) { for( i = 0; i < 4; i++ ) surfaceSet->trans1[j][i] = trans[j][i]; } return 0; }
static ARdouble getSizeFactor(ARdouble dist_factor[], int xsize, int ysize, int dist_function_version) { ARdouble ox, oy, ix, iy; ARdouble olen, ilen; ARdouble sf, sf1; sf = 100.0; ox = 0.0; oy = dist_factor[7]; olen = dist_factor[6]; arParamObserv2Ideal(dist_factor, ox, oy, &ix, &iy, dist_function_version); ilen = dist_factor[6] - ix; // ARLOG("Olen = %f, Ilen = %f, s = %f\n", olen, ilen, ilen / olen); if (ilen > 0) { sf1 = ilen / olen; if (sf1 < sf) sf = sf1; } ox = xsize; oy = dist_factor[7]; olen = xsize - dist_factor[6]; arParamObserv2Ideal(dist_factor, ox, oy, &ix, &iy, dist_function_version); ilen = ix - dist_factor[6]; // ARLOG("Olen = %f, Ilen = %f, s = %f\n", olen, ilen, ilen / olen); if (ilen > 0) { sf1 = ilen / olen; if (sf1 < sf) sf = sf1; } ox = dist_factor[6]; oy = 0.0; olen = dist_factor[7]; arParamObserv2Ideal(dist_factor, ox, oy, &ix, &iy, dist_function_version); ilen = dist_factor[7] - iy; // ARLOG("Olen = %f, Ilen = %f, s = %f\n", olen, ilen, ilen / olen); if (ilen > 0) { sf1 = ilen / olen; if (sf1 < sf) sf = sf1; } ox = dist_factor[6]; oy = ysize; olen = ysize - dist_factor[7]; arParamObserv2Ideal(dist_factor, ox, oy, &ix, &iy, dist_function_version); ilen = iy - dist_factor[7]; // ARLOG("Olen = %f, Ilen = %f, s = %f\n", olen, ilen, ilen / olen); if (ilen > 0) { sf1 = ilen / olen; if (sf1 < sf) sf = sf1; } ox = 0.0; oy = 0.0; arParamObserv2Ideal(dist_factor, ox, oy, &ix, &iy, dist_function_version); ilen = dist_factor[6] - ix; olen = dist_factor[6]; // ARLOG("Olen = %f, Ilen = %f, s = %f\n", olen, ilen, ilen / olen); if (ilen > 0) { sf1 = ilen / olen; if (sf1 < sf) sf = sf1; } ilen = dist_factor[7] - iy; olen = dist_factor[7]; // ARLOG("Olen = %f, Ilen = %f, s = %f\n", olen, ilen, ilen / olen); if (ilen > 0) { sf1 = ilen / olen; if (sf1 < sf) sf = sf1; } ox = xsize; oy = 0.0; arParamObserv2Ideal(dist_factor, ox, oy, &ix, &iy, dist_function_version); ilen = ix - dist_factor[6]; olen = xsize - dist_factor[6]; // ARLOG("Olen = %f, Ilen = %f, s = %f\n", olen, ilen, ilen / olen); if (ilen > 0) { sf1 = ilen / olen; if (sf1 < sf) sf = sf1; } ilen = dist_factor[7] - iy; olen = dist_factor[7]; // ARLOG("Olen = %f, Ilen = %f, s = %f\n", olen, ilen, ilen / olen); if (ilen > 0) { sf1 = ilen / olen; if (sf1 < sf) sf = sf1; } ox = 0.0; oy = ysize; arParamObserv2Ideal(dist_factor, ox, oy, &ix, &iy, dist_function_version); ilen = dist_factor[6] - ix; olen = dist_factor[6]; // ARLOG("Olen = %f, Ilen = %f, s = %f\n", olen, ilen, ilen / olen); if (ilen > 0) { sf1 = ilen / olen; if (sf1 < sf) sf = sf1; } ilen = iy - dist_factor[7]; olen = ysize - dist_factor[7]; // ARLOG("Olen = %f, Ilen = %f, s = %f\n", olen, ilen, ilen / olen); if (ilen > 0) { sf1 = ilen / olen; if (sf1 < sf) sf = sf1; } ox = xsize; oy = ysize; arParamObserv2Ideal(dist_factor, ox, oy, &ix, &iy, dist_function_version); ilen = ix - dist_factor[6]; olen = xsize - dist_factor[6]; // ARLOG("Olen = %f, Ilen = %f, s = %f\n", olen, ilen, ilen / olen); if (ilen > 0) { sf1 = ilen / olen; if (sf1 < sf) sf = sf1; } ilen = iy - dist_factor[7]; olen = ysize - dist_factor[7]; // ARLOG("Olen = %f, Ilen = %f, s = %f\n", olen, ilen, ilen / olen); if (ilen > 0) { sf1 = ilen / olen; if (sf1 < sf) sf = sf1; } if (sf == 100.0) sf = 1.0; return sf; }
// // Blit an image to the screen using OpenGL rectangle texturing. // static void arglDispImageTexRectangle(ARUint8 *image, const ARParam *cparam, const float zoom, ARGL_CONTEXT_SETTINGS_REF contextSettings, const int texmapScaleFactor) { float px, py, py_prev; ARdouble x1, x2, y1, y2; float xx1, xx2, yy1, yy2; int i, j; if(!contextSettings->initedRectangle || contextSettings->initPlease) { contextSettings->initPlease = FALSE; // Delete previous texture and list, unless this is our first time here. if (contextSettings->initedRectangle) arglCleanupTexRectangle(contextSettings); // If we have not done so, check texturing capabilities. If they have already been // checked, and we got to here, then obviously the capabilities were insufficient, // so just return without doing anything. if (!contextSettings->textureRectangleCapabilitiesChecked) { contextSettings->textureRectangleCapabilitiesChecked = TRUE; if (!arglDispImageTexRectangleCapabilitiesCheck(cparam, contextSettings)) { ARLOGe("argl error: Your OpenGL implementation and/or hardware's texturing capabilities are insufficient to support rectangle textures.\n"); // Fall back to power of 2 texturing. contextSettings->arglTexRectangle = FALSE; arglDispImageTexPow2(image, cparam, zoom, contextSettings, texmapScaleFactor); return; } } else { return; } // Set up the rectangle texture object. glGenTextures(1, &(contextSettings->textureRectangle)); glBindTexture(GL_TEXTURE_RECTANGLE, contextSettings->textureRectangle); glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); #ifdef __APPLE__ # ifdef ARGL_USE_TEXTURE_RANGE if (arglAppleTextureRange) { glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE, cparam->xsize * cparam->ysize * contextSettings->pixSize, image); glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_STORAGE_HINT_APPLE, arglAppleTextureRangeStorageHint); } else { glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE, 0, NULL); glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_PRIVATE_APPLE); } #endif // ARGL_USE_TEXTURE_RANGE glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, arglAppleClientStorage); #endif // __APPLE__ // Specify the texture to OpenGL. if (texmapScaleFactor == 2) { // If texmapScaleFactor is 2, pretend lines in the source image are // twice as long as they are; glTexImage2D will read only the first // half of each line, effectively discarding every second line in the source image. glPixelStorei(GL_UNPACK_ROW_LENGTH, cparam->xsize*texmapScaleFactor); } glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // Our image data is tightly packed. glTexImage2D(GL_TEXTURE_RECTANGLE, 0, contextSettings->pixIntFormat, cparam->xsize, cparam->ysize/texmapScaleFactor, 0, contextSettings->pixFormat, contextSettings->pixType, image); if (texmapScaleFactor == 2) { glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); } // Set up the surface which we will texture upon. contextSettings->listRectangle = glGenLists(1); glNewList(contextSettings->listRectangle, GL_COMPILE); glEnable(GL_TEXTURE_RECTANGLE); glMatrixMode(GL_TEXTURE); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); if (contextSettings->disableDistortionCompensation) { glBegin(GL_QUADS); glTexCoord2f(0.0f, (float)(cparam->ysize/texmapScaleFactor)); glVertex2f(0.0f, 0.0f); glTexCoord2f((float)(cparam->xsize), (float)(cparam->ysize/texmapScaleFactor)); glVertex2f(cparam->xsize * zoom, 0.0f); glTexCoord2f((float)(cparam->xsize), 0.0f); glVertex2f(cparam->xsize * zoom, cparam->ysize * zoom); glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, cparam->ysize * zoom); glEnd(); } else { py_prev = 0.0f; for(j = 1; j <= 20; j++) { // Do 20 rows. py = py_prev; py_prev = cparam->ysize * j / 20.0f; glBegin(GL_QUAD_STRIP); for(i = 0; i <= 20; i++) { // Draw 21 pairs of vertices per row to make 20 columns. px = cparam->xsize * i / 20.0f; arParamObserv2Ideal(cparam->dist_factor, (ARdouble)px, (ARdouble)py, &x1, &y1, cparam->dist_function_version); arParamObserv2Ideal(cparam->dist_factor, (ARdouble)px, (ARdouble)py_prev, &x2, &y2, cparam->dist_function_version); xx1 = (float)x1 * zoom; yy1 = (cparam->ysize - (float)y1) * zoom; xx2 = (float)x2 * zoom; yy2 = (cparam->ysize - (float)y2) * zoom; glTexCoord2f(px, py/texmapScaleFactor); glVertex2f(xx1, yy1); glTexCoord2f(px, py_prev/texmapScaleFactor); glVertex2f(xx2, yy2); } glEnd(); } } glDisable(GL_TEXTURE_RECTANGLE); glEndList(); contextSettings->asInited_ysize = cparam->ysize; contextSettings->asInited_xsize = cparam->xsize; contextSettings->asInited_zoom = zoom; contextSettings->asInited_texmapScaleFactor = texmapScaleFactor; contextSettings->initedRectangle = TRUE; } glBindTexture(GL_TEXTURE_RECTANGLE, contextSettings->textureRectangle); #ifdef __APPLE__ # ifdef ARGL_USE_TEXTURE_RANGE if (arglAppleTextureRange) { glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE, cparam->xsize * cparam->ysize * contextSettings->pixSize, image); glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_STORAGE_HINT_APPLE, arglAppleTextureRangeStorageHint); } else { glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE, 0, NULL); glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_PRIVATE_APPLE); } #endif // ARGL_USE_TEXTURE_RANGE glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, arglAppleClientStorage); #endif // __APPLE__ if (texmapScaleFactor == 2) { glPixelStorei(GL_UNPACK_ROW_LENGTH, cparam->xsize*texmapScaleFactor); } glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTexSubImage2D(GL_TEXTURE_RECTANGLE, 0, 0, 0, cparam->xsize, cparam->ysize/texmapScaleFactor, contextSettings->pixFormat, contextSettings->pixType, image); glCallList(contextSettings->listRectangle); if (texmapScaleFactor == 2) { glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); } glBindTexture(GL_TEXTURE_RECTANGLE, 0); }
// // Blit an image to the screen using OpenGL power-of-two texturing. // static void arglDispImageTexPow2(ARUint8 *image, const ARParam *cparam, const float zoom, ARGL_CONTEXT_SETTINGS_REF contextSettings, const int texmapScaleFactor) { float px, py, qx, qy; ARdouble x1, x2, x3, x4, y1, y2, y3, y4; float tsx, tsy, tex, tey; float xx1, xx2, xx3, xx4, yy1, yy2, yy3, yy4; int i, j; if(!contextSettings->initedPow2 || contextSettings->initPlease) { contextSettings->initPlease = FALSE; // Delete previous texture and list, unless this is our first time here. if (contextSettings->initedPow2) arglCleanupTexPow2(contextSettings); // If we have not done so, check texturing capabilities. If they have already been // checked, and we got to here, then obviously the capabilities were insufficient, // so just return without doing anything. if (!contextSettings->texturePow2CapabilitiesChecked) { contextSettings->texturePow2CapabilitiesChecked = TRUE; if (!arglDispImageTexPow2CapabilitiesCheck(cparam, contextSettings)) { ARLOGe("argl error: Your OpenGL implementation and/or hardware's texturing capabilities are insufficient.\n"); return; } } else { return; } // Set up the texture object. glGenTextures(1, &(contextSettings->texturePow2)); glBindTexture(GL_TEXTURE_2D, contextSettings->texturePow2); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, contextSettings->texturePow2WrapMode); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, contextSettings->texturePow2WrapMode); #ifdef __APPLE__ # ifdef ARGL_USE_TEXTURE_RANGE // Can't use client storage or texture range. glTextureRangeAPPLE(GL_TEXTURE_2D, 0, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_PRIVATE_APPLE); # endif // ARGL_USE_TEXTURE_RANGE glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, FALSE); #endif // __APPLE__ // Request OpenGL allocate memory for a power-of-two texture of the appropriate size. if (texmapScaleFactor == 2) { // If texmapScaleFactor is 2, pretend lines in the source image are // twice as long as they are; glTexImage2D will read only the first // half of each line, effectively discarding every second line in the source image. glPixelStorei(GL_UNPACK_ROW_LENGTH, cparam->xsize*texmapScaleFactor); } glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTexImage2D(GL_TEXTURE_2D, 0, contextSettings->pixIntFormat, contextSettings->texturePow2SizeX, contextSettings->texturePow2SizeY/texmapScaleFactor, 0, contextSettings->pixFormat, contextSettings->pixType, NULL); if (texmapScaleFactor == 2) { glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); } // Set up the surface which we will texture upon. contextSettings->listPow2 = glGenLists(1); glNewList(contextSettings->listPow2, GL_COMPILE); // NB Texture not specified yet so don't execute. glEnable(GL_TEXTURE_2D); glMatrixMode(GL_TEXTURE); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); if (contextSettings->disableDistortionCompensation) { glBegin(GL_QUADS); glTexCoord2f(0.0f, (float)cparam->ysize/(float)contextSettings->texturePow2SizeY); glVertex2f(0.0f, 0.0f); glTexCoord2f((float)cparam->xsize/(float)contextSettings->texturePow2SizeX, (float)cparam->ysize/(float)contextSettings->texturePow2SizeY); glVertex2f((float)cparam->xsize * zoom, 0.0f); glTexCoord2f((float)cparam->xsize/(float)contextSettings->texturePow2SizeX, 0.0f); glVertex2f((float)cparam->xsize * zoom, (float)cparam->ysize * zoom); glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, (float)cparam->ysize * zoom); glEnd(); } else { qy = 0.0f; tey = 0.0f; for(j = 1; j <= 20; j++) { // Do 20 rows. py = qy; tsy = tey; qy = cparam->ysize * j / 20.0f; tey = qy / contextSettings->texturePow2SizeY; qx = 0.0f; tex = 0.0f; for(i = 1; i <= 20; i++) { // Draw 20 columns. px = qx; tsx = tex; qx = cparam->xsize * i / 20.0f; tex = qx / contextSettings->texturePow2SizeX; arParamObserv2Ideal(cparam->dist_factor, (ARdouble)px, (ARdouble)py, &x1, &y1, cparam->dist_function_version); arParamObserv2Ideal(cparam->dist_factor, (ARdouble)qx, (ARdouble)py, &x2, &y2, cparam->dist_function_version); arParamObserv2Ideal(cparam->dist_factor, (ARdouble)qx, (ARdouble)qy, &x3, &y3, cparam->dist_function_version); arParamObserv2Ideal(cparam->dist_factor, (ARdouble)px, (ARdouble)qy, &x4, &y4, cparam->dist_function_version); xx1 = (float)x1 * zoom; yy1 = (cparam->ysize - (float)y1) * zoom; xx2 = (float)x2 * zoom; yy2 = (cparam->ysize - (float)y2) * zoom; xx3 = (float)x3 * zoom; yy3 = (cparam->ysize - (float)y3) * zoom; xx4 = (float)x4 * zoom; yy4 = (cparam->ysize - (float)y4) * zoom; glBegin(GL_QUADS); glTexCoord2f(tsx, tsy); glVertex2f(xx1, yy1); glTexCoord2f(tex, tsy); glVertex2f(xx2, yy2); glTexCoord2f(tex, tey); glVertex2f(xx3, yy3); glTexCoord2f(tsx, tey); glVertex2f(xx4, yy4); glEnd(); } // columns. } // rows. } glDisable(GL_TEXTURE_2D); glEndList(); contextSettings->asInited_ysize = cparam->ysize; contextSettings->asInited_xsize = cparam->xsize; contextSettings->asInited_zoom = zoom; contextSettings->asInited_texmapScaleFactor = texmapScaleFactor; contextSettings->initedPow2 = TRUE; } glBindTexture(GL_TEXTURE_2D, contextSettings->texturePow2); #ifdef __APPLE__ # ifdef ARGL_USE_TEXTURE_RANGE // Can't use client storage or texture range. glTextureRangeAPPLE(GL_TEXTURE_2D, 0, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_PRIVATE_APPLE); #endif // ARGL_USE_TEXTURE_RANGE glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, FALSE); #endif // __APPLE__ if (texmapScaleFactor == 2) { // If texmapScaleFactor is 2, pretend lines in the source image are // twice as long as they are; glTexImage2D will read only the first // half of each line, effectively discarding every second line in the source image. glPixelStorei(GL_UNPACK_ROW_LENGTH, cparam->xsize*texmapScaleFactor); } glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, cparam->xsize, cparam->ysize/texmapScaleFactor, contextSettings->pixFormat, contextSettings->pixType, image); glCallList(contextSettings->listPow2); if (texmapScaleFactor == 2) { glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); } glBindTexture(GL_TEXTURE_2D, 0); }
static int argDrawImageTexMapRect( ARGViewportHandle *vp, ARUint8 *image, int xsize, int ysize, ARGDisplayList *dl ) { ARParam wparam; int dispMethod; int distMode; int tx, ty; int pixFormat; float s1, s2, offx, offy; ARdouble px, py, qy, z, dy; ARdouble x1, x2; ARdouble y1, y2; int i, j; dispMethod = (vp->dispMethod == AR_GL_DISP_METHOD_TEXTURE_MAPPING_FIELD)? 0: 1; distMode = (vp->distortionMode == AR_GL_DISTORTION_COMPENSATE_DISABLE)? 0: 1; if( argGetImageScale(vp, xsize, ysize, &s1, &s2, &offx, &offy) < 0 ) return -1; pixFormat = vp->pixFormat; tx = xsize; ty = ysize; glMatrixMode(GL_MODELVIEW); glPushMatrix(); glTranslatef( offx, offy, 0.0f ); glScalef( s1, s2, 1.0f ); glEnable( GL_TEXTURE_RECTANGLE ); if( dl->texId < 0 ) { dl->texId = argGenImageTexture( tx, ty, dispMethod, GL_TEXTURE_RECTANGLE ); } argUpdateImageTexture( vp, image, xsize, ysize, pixFormat, dispMethod, GL_TEXTURE_RECTANGLE, dl->texId ); glBindTexture( GL_TEXTURE_RECTANGLE, dl->texId ); glTexParameterf( GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP ); glTexParameterf( GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP ); //glTexParameterf( GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); glTexParameterf( GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL ); if( dl->listIndex < 0 ) { arParamChangeSize( vp->cparam, xsize, ysize, &wparam ); dl->listIndex = glGenLists(1); glNewList(dl->listIndex, GL_COMPILE_AND_EXECUTE); z = 1.0; dy = (dispMethod)? 1.0: 2.0; if( distMode == 1 ) { qy = ysize * 0 / (ARdouble)AR_GL_TEXTURE_MESH_NUM; for( j = 1; j <= AR_GL_TEXTURE_MESH_NUM; j++ ) { py = qy; qy = ysize * j / (ARdouble)AR_GL_TEXTURE_MESH_NUM; glBegin( GL_QUAD_STRIP ); for( i = 0; i <= AR_GL_TEXTURE_MESH_NUM; i++ ) { px = xsize * i / (ARdouble)AR_GL_TEXTURE_MESH_NUM; arParamObserv2Ideal( wparam.dist_factor, px, py, &x1, &y1, wparam.dist_function_version ); arParamObserv2Ideal( wparam.dist_factor, px, qy, &x2, &y2, wparam.dist_function_version ); glTexCoord2d( px, py/dy ); glVertex3d( x1-0.5, y1-0.5, z ); glTexCoord2d( px, qy/dy ); glVertex3d( x2-0.5, y2-0.5, z ); } glEnd(); } } else { glBegin( GL_QUAD_STRIP ); glTexCoord2d( 0.0, 0.0 ); glVertex3d(-0.5, -0.5, z ); glTexCoord2d( 0.0, (ARdouble)ysize/dy ); glVertex3d(-0.5, (ARdouble)ysize-0.5, z ); glTexCoord2d( (ARdouble)xsize, 0.0 ); glVertex3d( (ARdouble)xsize-0.5, -0.5, z ); glTexCoord2d( (ARdouble)xsize, (ARdouble)ysize/dy ); glVertex3d( (ARdouble)xsize-0.5, (ARdouble)ysize-0.5, z ); glEnd(); } glEndList(); } else { glCallList( dl->listIndex ); } glBindTexture( GL_TEXTURE_RECTANGLE, 0 ); glDisable( GL_TEXTURE_RECTANGLE ); glMatrixMode(GL_MODELVIEW); glPopMatrix(); return 0; }