| 674 | } |
| 675 | |
| 676 | void CKinematics::wallmark_calculate_details::add_wallmark_internal(CKinematics* parent) |
| 677 | { |
| 678 | ZoneScoped; |
| 679 | |
| 680 | Fvector S, D, normal = {0, 0, 0}; |
| 681 | // transform ray from world to model |
| 682 | Fmatrix P; |
| 683 | P.invert(*parent_xform); |
| 684 | P.transform_tiny(S, position); |
| 685 | P.transform_dir(D, direction); |
| 686 | // find pick point |
| 687 | float dist = flt_max; |
| 688 | BOOL picked = FALSE; |
| 689 | |
| 690 | DEFINE_VECTOR(Fobb, OBBVec, OBBVecIt); |
| 691 | OBBVec cache_obb; |
| 692 | cache_obb.resize(parent->LL_BoneCount()); |
| 693 | IKinematics::pick_result r; |
| 694 | r.normal = normal; |
| 695 | r.dist = dist; |
| 696 | for (u16 k = 0; k < parent->LL_BoneCount(); k++) |
| 697 | { |
| 698 | CBoneData& BD = parent->LL_GetData(k); |
| 699 | if (parent->LL_GetBoneVisible(k) && !BD.shape.flags.is(SBoneShape::sfNoPickable)) |
| 700 | { |
| 701 | Fobb& obb = cache_obb[k]; |
| 702 | obb.transform(BD.obb, parent->LL_GetBoneInstance(k).mTransform); |
| 703 | if (CDB::TestRayOBB(S, D, obb)) |
| 704 | for (u32 i = 0; i < parent->children.size(); i++) |
| 705 | { |
| 706 | if (parent->LL_GetChild(i)->PickBone(r, dist, S, D, k)) |
| 707 | { |
| 708 | picked = TRUE; |
| 709 | dist = r.dist; |
| 710 | normal = r.normal; |
| 711 | } |
| 712 | } |
| 713 | } |
| 714 | } |
| 715 | if (!picked) |
| 716 | { |
| 717 | return; |
| 718 | } |
| 719 | |
| 720 | // calculate contact point |
| 721 | Fvector cp; |
| 722 | cp.mad(S, D, dist); |
| 723 | |
| 724 | // collect collide boxes |
| 725 | Fsphere test_sphere; |
| 726 | test_sphere.set(cp, size); |
| 727 | U16Vec test_bones; |
| 728 | test_bones.reserve(parent->LL_BoneCount()); |
| 729 | for (u16 k = 0; k < parent->LL_BoneCount(); k++) |
| 730 | { |
| 731 | CBoneData& BD = parent->LL_GetData(k); |
| 732 | if (parent->LL_GetBoneVisible(k) && !BD.shape.flags.is(SBoneShape::sfNoPickable)) |
| 733 | { |
no test coverage detected