MotionField.pde 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. class MotionField {
  2. int block_size;
  3. ArrayList<PVector> motion_field;
  4. MotionField(int block_size) {
  5. this.block_size = block_size;
  6. motion_field = new ArrayList<PVector>();
  7. }
  8. void update(Camera last_cam, Camera current_cam, PointCloud point_cloud,
  9. BVH bvh) {
  10. // clear motion field
  11. motion_field = new ArrayList<PVector>();
  12. int r_num = height / block_size, c_num = width / block_size;
  13. for (int i = 0; i < r_num * c_num; i++)
  14. motion_field.add(new PVector(0, 0, 0));
  15. // estimate motion vector of each point in point cloud
  16. for (int i = 0; i < point_cloud.size(); i++) {
  17. PVector p = point_cloud.getPosition(i);
  18. PVector p0 = current_cam.project(p);
  19. PVector p1 = last_cam.project(p);
  20. int row = int((p0.y + height / 2.0f) / block_size);
  21. int col = int((p0.x + width / 2.0f) / block_size);
  22. if (row >= 0 && row < r_num && col >= 0 && col < c_num) {
  23. PVector accu = motion_field.get(row * c_num + col);
  24. accu.x += p1.x - p0.x;
  25. accu.y += p1.y - p0.y;
  26. accu.z += 1;
  27. }
  28. }
  29. // if some blocks do not have point, then use ray tracing to see if they are
  30. // in triangles
  31. for (int i = 0; i < r_num; i++)
  32. for (int j = 0; j < c_num; j++) {
  33. PVector accu = motion_field.get(i * c_num + j);
  34. if (accu.z > 0) {
  35. continue;
  36. }
  37. // use the center of the block to generate view ray
  38. float cx = j * block_size + block_size / 2.0f - width / 2.0f;
  39. float cy = i * block_size + block_size / 2.0f - height / 2.0f;
  40. float cz = 0.5f * height / tan(current_cam.fov / 2.0f);
  41. PVector dir = new PVector(cx, cy, cz);
  42. float[] camMat = current_cam.getCameraMat();
  43. dir = MatxVec3(transpose3x3(camMat), dir);
  44. dir.normalize();
  45. Ray r = new Ray(current_cam.pos, dir);
  46. // ray tracing
  47. float[] param = new float[4];
  48. param[0] = Float.POSITIVE_INFINITY;
  49. if (bvh.intersect(r, param)) {
  50. PVector p = new PVector(param[1], param[2], param[3]);
  51. PVector p0 = current_cam.project(p);
  52. PVector p1 = last_cam.project(p);
  53. accu.x += p1.x - p0.x;
  54. accu.y += p1.y - p0.y;
  55. accu.z += 1;
  56. }
  57. }
  58. // estimate the motion vector of each block
  59. for (int i = 0; i < r_num * c_num; i++) {
  60. PVector mv = motion_field.get(i);
  61. if (mv.z > 0) {
  62. motion_field.set(i, new PVector(mv.x / mv.z, mv.y / mv.z, 0));
  63. }
  64. }
  65. }
  66. void render() {
  67. int r_num = height / block_size, c_num = width / block_size;
  68. for (int i = 0; i < r_num; i++)
  69. for (int j = 0; j < c_num; j++) {
  70. PVector mv = motion_field.get(i * c_num + j);
  71. float ox = j * block_size + 0.5f * block_size;
  72. float oy = i * block_size + 0.5f * block_size;
  73. stroke(255, 0, 0);
  74. line(ox, oy, ox + mv.x, oy + mv.y);
  75. }
  76. }
  77. void save(String path) {
  78. int r_num = height / block_size;
  79. int c_num = width / block_size;
  80. String[] mvs = new String[r_num];
  81. for (int i = 0; i < r_num; i++) {
  82. mvs[i] = "";
  83. for (int j = 0; j < c_num; j++) {
  84. PVector mv = motion_field.get(i * c_num + j);
  85. mvs[i] += str(mv.x) + "," + str(mv.y);
  86. if (j != c_num - 1) mvs[i] += ";";
  87. }
  88. }
  89. saveStrings(path, mvs);
  90. }
  91. }