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