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