Interpolate the surface normal of the intersection points using surface normal on the vertices. Args: mesh: raycast_results: the output of ray casting of o3d Returns: (*, 3) surface normal. Note that it fills in a random value if a ray does not hit
(
mesh: o3d.geometry.TriangleMesh,
raycast_results: T.Dict[str, T.Any],
)
| 180 | |
| 181 | |
| 182 | def interp_surface_normal_from_ray_tracing_results( |
| 183 | mesh: o3d.geometry.TriangleMesh, |
| 184 | raycast_results: T.Dict[str, T.Any], |
| 185 | ) -> np.ndarray: |
| 186 | """ |
| 187 | Interpolate the surface normal of the intersection points using surface normal on the vertices. |
| 188 | |
| 189 | Args: |
| 190 | mesh: |
| 191 | raycast_results: |
| 192 | the output of ray casting of o3d |
| 193 | |
| 194 | Returns: |
| 195 | (*, 3) surface normal. Note that it fills in a random value if a ray does not hit a surface |
| 196 | |
| 197 | """ |
| 198 | if not mesh.has_vertex_normals(): |
| 199 | return raycast_results['primitive_normals'].numpy() # (*,3) |
| 200 | |
| 201 | # barycentric coordinates of the intersection in the intersected triangle |
| 202 | barycentric_coords = raycast_results['primitive_uvs'].numpy() # (h,w,2), the third weight is 1-sum() |
| 203 | barycentric_coords = np.concatenate( |
| 204 | (1 - np.sum(barycentric_coords, axis=-1, keepdims=True), barycentric_coords), |
| 205 | # note that in open 3d, the primitive_uvs indicates last two coordinates rather than first two |
| 206 | # (barycentric_coords, 1 - np.sum(barycentric_coords, axis=-1, keepdims=True)), |
| 207 | axis=-1, |
| 208 | ) # (h,w,3) |
| 209 | |
| 210 | # the intersected triangle index |
| 211 | primitive_ids = raycast_results['primitive_ids'].numpy() # (h, w) |
| 212 | # fillin a dummy primitive_id for the rays that go to inf |
| 213 | primitive_ids[primitive_ids == o3d.t.geometry.RaycastingScene.INVALID_ID] = 0 # (h, w) |
| 214 | |
| 215 | # get triangle vertex |
| 216 | triangle_vidxs = np.asarray(mesh.triangles) # (n_triangle, 3) index of vertices |
| 217 | vertex_normals = np.asarray(mesh.vertex_normals) # (n_vertex, 3) surface normal of each vertex |
| 218 | |
| 219 | vidxs = triangle_vidxs[primitive_ids] # (h, w, 3) the vertex id of each camera ray |
| 220 | v_normals = vertex_normals[vidxs] # (h, w, 3, 3) last dimension is normal (dx, dy, dz) |
| 221 | interped_normals = np.sum(np.expand_dims(barycentric_coords, axis=-1) * v_normals, axis=-2) # (h, w, 3) |
| 222 | return interped_normals |
| 223 | |
| 224 | |
| 225 | def rasterize( |
nothing calls this directly
no outgoing calls
no test coverage detected