( newFromOld: Sim3d, qvec: [number, number, number, number], tvec: [number, number, number] )
| 173 | * @returns Transformed qvec and tvec |
| 174 | */ |
| 175 | export function transformCameraPose( |
| 176 | newFromOld: Sim3d, |
| 177 | qvec: [number, number, number, number], |
| 178 | tvec: [number, number, number] |
| 179 | ): { qvec: [number, number, number, number]; tvec: [number, number, number] } { |
| 180 | // Step 1: Create Sim3d from camera pose with scale=1 |
| 181 | // Note: COLMAP uses [w, x, y, z], Three.js uses (x, y, z, w) |
| 182 | const camFromWorld: Sim3d = { |
| 183 | scale: 1, |
| 184 | rotation: new THREE.Quaternion(qvec[1], qvec[2], qvec[3], qvec[0]), |
| 185 | translation: new THREE.Vector3(tvec[0], tvec[1], tvec[2]), |
| 186 | }; |
| 187 | |
| 188 | // Step 2: cam_from_new_world = cam_from_old_world * Inverse(new_from_old_world) |
| 189 | const oldFromNew = inverseSim3d(newFromOld); |
| 190 | const camFromNew = composeSim3d(camFromWorld, oldFromNew); |
| 191 | |
| 192 | // Step 3: Scale translation by original scale (CRITICAL - from COLMAP source) |
| 193 | const scaledT = camFromNew.translation.clone().multiplyScalar(newFromOld.scale); |
| 194 | |
| 195 | // Step 4: Convert back to COLMAP qvec format [w, x, y, z] |
| 196 | return { |
| 197 | qvec: [camFromNew.rotation.w, camFromNew.rotation.x, camFromNew.rotation.y, camFromNew.rotation.z], |
| 198 | tvec: [scaledT.x, scaledT.y, scaledT.z], |
| 199 | }; |
| 200 | } |
| 201 | |
| 202 | // ============================================================================ |
| 203 | // Reconstruction-level Transforms |
no test coverage detected