cameraparams.cc
上传用户:kellyonhid
上传日期:2013-10-12
资源大小:932k
文件大小:4k
源码类别:

3D图形编程

开发平台:

Visual C++

  1. /*
  2. Szymon Rusinkiewicz
  3. Stanford Graphics Lab
  4. Digital Michelangelo Project
  5. cameraparams.cc
  6. */
  7. #include <math.h>
  8. #include <stdio.h>
  9. #include "cameraparams.h"
  10. CameraParams *CameraParams::Read(const char *tsaifile)
  11. {
  12. FILE *infile = fopen(tsaifile, "r");
  13. if (!infile) {
  14. fprintf(stderr, "Couldn't open camera calibration file.n");
  15. return NULL;
  16. }
  17. printf("Reading camera parameters file... "); fflush(stdout);
  18. double f, pixsize;
  19. double dummy1, dummy2, dummy3;
  20. double ix, iy;
  21. fscanf(infile, "%lf %lf", &ix, &iy);
  22. int imgwidth = int(ix+0.5), imgheight = int(iy+0.5);
  23. fscanf(infile, "%lf %lf %lf %lf", &pixsize, &dummy1, &dummy2, &dummy3);
  24. if ((dummy1 != pixsize) ||
  25.     (dummy2 != pixsize) ||
  26.     (dummy3 != pixsize)) {
  27. fprintf(stderr, "Yikes! The four pixel size params are not equal.n I can't deal with that.n");
  28. }
  29. double Cx, Cy;
  30. fscanf(infile, "%lf %lf", &Cx, &Cy);
  31. double S;
  32. fscanf(infile, "%lf %lf %lf", &S, &f, &dummy1);
  33. if (dummy1 != 0) {
  34. fprintf(stderr, "Yikes! The distortion is not zero.n I can't deal with that.n");
  35. }
  36. double pixels_per_radian = f/pixsize;
  37. double Tx, Ty, Tz;
  38. double Rx, Ry, Rz;
  39. fscanf(infile, "%lf %lf %lf", &Tx, &Ty, &Tz);
  40. fscanf(infile, "%lf %lf %lf", &Rx, &Ry, &Rz);
  41. fclose(infile);
  42. printf("Done.n");
  43. return new CameraParams(imgwidth, imgheight,
  44. Tx, Ty, Tz,
  45. Rx, Ry, Rz,
  46. Cx, Cy, S,
  47. pixels_per_radian);
  48. }
  49. // Just emulate the modelview transform
  50. void CameraParams::Transform(const float *in, float *out) const
  51. {
  52. out[0] = matrix[0]*in[0]+matrix[4]*in[1]+matrix[8]*in[2]+Tx;
  53. out[1] = matrix[1]*in[0]+matrix[5]*in[1]+matrix[9]*in[2]+Ty;
  54. out[2] = matrix[2]*in[0]+matrix[6]*in[1]+matrix[10]*in[2]+Tz;
  55. }
  56. // Project world coordinates to camera space.
  57. // Note that the Z coordinate this returns is not what you'd expect from
  58. // OpenGL, but is just the distance from the camera to the point in world
  59. // space.
  60. // Also note that, unlike OpenGL, this function has its origin at the
  61. // upper-left corner...
  62. void CameraParams::Project(const float *in, float *out) const
  63. {
  64. float cam[3];
  65. Transform(in, cam);
  66. out[0] = cam[0]/cam[2]*pixels_per_radian*S+Cx;
  67. out[1] = cam[1]/cam[2]*pixels_per_radian+Cy;
  68. out[2] = sqrt(cam[0]*cam[0]+cam[1]*cam[1]+cam[2]*cam[2]);
  69. }
  70. void CameraParams::compute_matrix()
  71. {
  72. matrix = new double[16];
  73. matrix[ 0] = cos(Ry)*cos(Rz);
  74. matrix[ 1] = cos(Ry)*sin(Rz);
  75. matrix[ 2] = -sin(Ry);
  76. matrix[ 3] = 0;
  77. matrix[ 4] = cos(Rz)*sin(Rx)*sin(Ry)-cos(Rx)*sin(Rz);
  78. matrix[ 5] = sin(Rx)*sin(Ry)*sin(Rz)+cos(Rx)*cos(Rz);
  79. matrix[ 6] = cos(Ry)*sin(Rx);
  80. matrix[ 7] = 0;
  81. matrix[ 8] = sin(Rx)*sin(Rz)+cos(Rx)*cos(Rz)*sin(Ry);
  82. matrix[ 9] = cos(Rx)*sin(Ry)*sin(Rz)-cos(Rz)*sin(Rx);
  83. matrix[10] = cos(Rx)*cos(Ry);
  84. matrix[11] = 0;
  85. matrix[12] = Tx;
  86. matrix[13] = Ty;
  87. matrix[14] = Tz;
  88. matrix[15] = 1;
  89. }
  90. // Use the following as:
  91. // glMatrixMode(GL_PROJECTION);   
  92. // glLoadIdentity();
  93. // glMultMatrixd(thecamera->GLprojmatrix(neardist, fardist));
  94. // glMatrixMode(GL_MODELVIEW);
  95. // glLoadIdentity();
  96. // glMultMatrixd(thecamera->GLmodelmatrix());
  97. // glViewport(0.5, 0.5, thecamera->imgwidth, thecamera->imgheight);
  98. //
  99. // Note that you have to pass 0.5 as the first two parameters to glViewport,
  100. // to match the pixels-at-integers vs. pixels-at-half-integers conventions
  101. //
  102. const double *CameraParams::GLmodelmatrix() const
  103. {
  104. return matrix;
  105. }
  106. const double *CameraParams::GLprojmatrix(double z_near, double z_far) const
  107. {
  108. static double m[16];
  109. // Emulate glFrustum()
  110. double left = -z_near/pixels_per_radian/S*Cx;
  111. double right = z_near/pixels_per_radian/S*(imgwidth-Cx);
  112. // Note to self: Yes, these really are correct!
  113. double bottom = -z_near/pixels_per_radian*(imgheight-Cy);
  114. double top = z_near/pixels_per_radian*Cy;
  115. // Straight out of the manpage
  116. double A = (2.0*z_near) / (right-left);
  117. double B = (2.0*z_near) / (top-bottom);
  118. double C = (right+left) / (right-left);
  119. double D = (top+bottom) / (top-bottom);
  120. double E = -(z_far+z_near) / (z_far-z_near);
  121. double F = -(2*z_far*z_near) / (z_far-z_near);
  122. m[ 0] = A;
  123. m[ 1] = 0;
  124. m[ 2] = 0;
  125. m[ 3] = 0;
  126. m[ 4] = 0;
  127. m[ 5] = B;
  128. m[ 6] = 0;
  129. m[ 7] = 0;
  130. m[ 8] = C;
  131. m[ 9] = D;
  132. m[10] = E;
  133. m[11] = -1;
  134. m[12] = 0;
  135. m[13] = 0;
  136. m[14] = F;
  137. m[15] = 0;
  138. // Emulate glRotated(180,1,0,0);
  139. // Deals with "Y axis points up" vs. "Y axis points down"
  140. m[ 5] *= -1;
  141. m[ 8] *= -1;
  142. m[ 9] *= -1;
  143. m[10] *= -1;
  144. m[11] *= -1;
  145. return m;
  146. }