| 278 | } |
| 279 | |
| 280 | bool IKController::Joint::UpdateLocalT(int32_t axis, std::vector<Goal> const& goals) |
| 281 | { |
| 282 | Vector3<float> U = GetAxis(axis); |
| 283 | float numer = 0.0f; |
| 284 | float denom = 0.0f; |
| 285 | float oldNorm = 0.0f; |
| 286 | for (auto g : goalIndices) |
| 287 | { |
| 288 | auto const& goal = goals[g]; |
| 289 | Vector3<float> GmE = goal.GetTargetPosition() - goal.GetEffectorPosition(); |
| 290 | oldNorm += Dot(GmE, GmE); |
| 291 | numer += goal.weight * Dot(U, GmE); |
| 292 | denom += goal.weight; |
| 293 | } |
| 294 | |
| 295 | if (denom == 0.0f) |
| 296 | { |
| 297 | return false; |
| 298 | } |
| 299 | |
| 300 | // Desired distance to translate along axis(i). |
| 301 | float t = numer / denom; |
| 302 | |
| 303 | // Clamp to range. |
| 304 | Vector3<float> trn = object->localTransform.GetTranslation(); |
| 305 | float desired = trn[axis] + t; |
| 306 | if (desired > minTranslation[axis]) |
| 307 | { |
| 308 | if (desired < maxTranslation[axis]) |
| 309 | { |
| 310 | trn[axis] = desired; |
| 311 | } |
| 312 | else |
| 313 | { |
| 314 | t = maxTranslation[axis] - trn[axis]; |
| 315 | trn[axis] = maxTranslation[axis]; |
| 316 | } |
| 317 | } |
| 318 | else |
| 319 | { |
| 320 | t = minTranslation[axis] - trn[axis]; |
| 321 | trn[axis] = minTranslation[axis]; |
| 322 | } |
| 323 | |
| 324 | // Test whether step should be taken. |
| 325 | float newNorm = 0.0f; |
| 326 | Vector3<float> step = t * U; |
| 327 | for (auto g : goalIndices) |
| 328 | { |
| 329 | auto const& goal = goals[g]; |
| 330 | Vector3<float> newE = goal.GetEffectorPosition() + step; |
| 331 | Vector3<float> diff = goal.GetTargetPosition() - newE; |
| 332 | newNorm += Dot(diff, diff); |
| 333 | } |
| 334 | if (newNorm >= oldNorm) |
| 335 | { |
| 336 | // Translation does not get effector closer to goal. |
| 337 | return false; |
no test coverage detected