| 129 | } |
| 130 | |
| 131 | void RotationF::lookAt(const Point3F& _origin, const Point3F& _target, const Point3F& _up) |
| 132 | { |
| 133 | MatrixF mat; |
| 134 | |
| 135 | VectorF newForward = _target - _origin; |
| 136 | newForward.normalize(); |
| 137 | |
| 138 | VectorF up(0.0f, 0.0f, 1.0f); |
| 139 | VectorF axisX; |
| 140 | VectorF axisY = newForward; |
| 141 | VectorF axisZ; |
| 142 | |
| 143 | if (_up != VectorF::Zero) |
| 144 | up = _up; |
| 145 | |
| 146 | // Validate and normalize input: |
| 147 | F32 lenSq; |
| 148 | lenSq = axisY.lenSquared(); |
| 149 | if (lenSq < 0.000001f) |
| 150 | { |
| 151 | //degenerate forward vector |
| 152 | axisY.set(0.0f, 1.0f, 0.0f); |
| 153 | } |
| 154 | else |
| 155 | { |
| 156 | axisY /= mSqrt(lenSq); |
| 157 | } |
| 158 | |
| 159 | |
| 160 | lenSq = up.lenSquared(); |
| 161 | if (lenSq < 0.000001f) |
| 162 | { |
| 163 | //degenerate up vector - too small |
| 164 | up.set(0.0f, 0.0f, 1.0f); |
| 165 | } |
| 166 | else |
| 167 | { |
| 168 | up /= mSqrt(lenSq); |
| 169 | } |
| 170 | |
| 171 | if (fabsf(mDot(up, axisY)) > 0.9999f) |
| 172 | { |
| 173 | //degenerate up vector - same as forward |
| 174 | F32 tmp = up.x; |
| 175 | up.x = -up.y; |
| 176 | up.y = up.z; |
| 177 | up.z = tmp; |
| 178 | } |
| 179 | |
| 180 | // construct the remaining axes: |
| 181 | mCross(axisY, up, &axisX); |
| 182 | mCross(axisX, axisY, &axisZ); |
| 183 | |
| 184 | mat.setColumn(0, axisX); |
| 185 | mat.setColumn(1, axisY); |
| 186 | mat.setColumn(2, axisZ); |
| 187 | |
| 188 | set(mat); |
no test coverage detected