| 132 | template CI_API dmat4 lastFrame( const dmat4 &prevMatrix, const dvec3 &prevPoint, const dvec3 &lastPoint ); |
| 133 | |
| 134 | glm::mat4 alignZAxisWithTarget( vec3 targetDir, vec3 upDir ) |
| 135 | { |
| 136 | // Ensure that the target direction is non-zero. |
| 137 | if( length2( targetDir ) == 0 ) |
| 138 | targetDir = vec3( 0, 0, 1 ); |
| 139 | |
| 140 | // Ensure that the up direction is non-zero. |
| 141 | if( length2( upDir ) == 0 ) |
| 142 | upDir = vec3( 0, 1, 0 ); |
| 143 | |
| 144 | // Check for degeneracies. If the upDir and targetDir are parallel |
| 145 | // or opposite, then compute a new, arbitrary up direction that is |
| 146 | // not parallel or opposite to the targetDir. |
| 147 | if( length2( cross( upDir, targetDir ) ) == 0 ) { |
| 148 | upDir = cross( targetDir, vec3( 1, 0, 0 ) ); |
| 149 | if( length2( upDir ) == 0 ) |
| 150 | upDir = cross( targetDir, vec3( 0, 0, 1 ) ); |
| 151 | } |
| 152 | |
| 153 | // Compute the x-, y-, and z-axis vectors of the new coordinate system. |
| 154 | vec3 targetPerpDir = cross( upDir, targetDir ); |
| 155 | vec3 targetUpDir = cross( targetDir, targetPerpDir ); |
| 156 | |
| 157 | // Rotate the x-axis into targetPerpDir (row 0), |
| 158 | // rotate the y-axis into targetUpDir (row 1), |
| 159 | // rotate the z-axis into targetDir (row 2). |
| 160 | vec3 row[3]; |
| 161 | row[0] = normalize( targetPerpDir ); |
| 162 | row[1] = normalize( targetUpDir ); |
| 163 | row[2] = normalize( targetDir ); |
| 164 | |
| 165 | const float v[16] = { row[0].x, row[0].y, row[0].z, 0, |
| 166 | row[1].x, row[1].y, row[1].z, 0, |
| 167 | row[2].x, row[2].y, row[2].z, 0, |
| 168 | 0, 0, 0, 1 }; |
| 169 | |
| 170 | |
| 171 | return glm::make_mat4( v ); |
| 172 | } |
| 173 | |
| 174 | } // namespace cinder |