summaryrefslogtreecommitdiff
path: root/src/KingSystem/Physics/System/physRayCast.cpp
diff options
context:
space:
mode:
authorLéo Lam <leo@leolam.fr>2022-03-20 18:27:06 +0100
committerLéo Lam <leo@leolam.fr>2022-03-20 22:04:58 +0100
commit0890d161e5d22a4572a2ca128c6aff6af5ab8ed4 (patch)
tree348d4e0e4b842d196e7d63b3f3aa76a8a6461418 /src/KingSystem/Physics/System/physRayCast.cpp
parent30d4a0005253ebb6d281237b6eda32e1d33a47c2 (diff)
ksys/phys: Add most remaining parts of RayCast
One last function remaining (0x0000007100fc4844) but it looks obnoxious so I'll leave it for later.
Diffstat (limited to 'src/KingSystem/Physics/System/physRayCast.cpp')
-rw-r--r--src/KingSystem/Physics/System/physRayCast.cpp117
1 files changed, 110 insertions, 7 deletions
diff --git a/src/KingSystem/Physics/System/physRayCast.cpp b/src/KingSystem/Physics/System/physRayCast.cpp
index 0983d15f..338bfe12 100644
--- a/src/KingSystem/Physics/System/physRayCast.cpp
+++ b/src/KingSystem/Physics/System/physRayCast.cpp
@@ -9,11 +9,15 @@
#include <Havok/Physics2012/Collide/Shape/Query/hkpShapeRayCastInput.h>
#include <Havok/Physics2012/Dynamics/Entity/hkpRigidBody.h>
#include <Havok/Physics2012/Dynamics/World/hkpWorld.h>
+#include <Havok/Physics2012/Internal/Collide/BvCompressedMesh/hkpBvCompressedMeshShape.h>
#include <Havok/Physics2012/Internal/Collide/StaticCompound/hkpStaticCompoundShape.h>
+#include <Havok/Physics2012/Utilities/Collide/ShapeUtils/ShapeKeyPath/hkpShapeKeyPath.h>
#include <prim/seadScopeGuard.h>
#include "KingSystem/Physics/RigidBody/physRigidBody.h"
+#include "KingSystem/Physics/StaticCompound/physStaticCompoundUtil.h"
#include "KingSystem/Physics/System/physEntityContactListener.h"
#include "KingSystem/Physics/System/physGroupFilter.h"
+#include "KingSystem/Physics/System/physPhantom.h"
#include "KingSystem/Physics/System/physSystem.h"
#include "KingSystem/Physics/physConversions.h"
#include "KingSystem/Physics/physLayerMaskBuilder.h"
@@ -95,8 +99,8 @@ void RayCast::resetCastResult() {
mHitCollidable = {};
mHitShapeKey = {};
mHasHitSpecifiedRigidBody = false;
- _58 = {};
- _60 = {};
+ mHitBodyGroup = {};
+ mHitMapObject = {};
_70 = {};
}
@@ -232,7 +236,7 @@ bool RayCast::postCast(const hkpWorldRayCastOutput& output) {
mHasHit = output.hasHit();
if (mHasHit) {
updateHitInformation(output);
- getActorInfoMaybe(output);
+ updateStaticCompoundObjectInfo(output);
}
_98 = false;
_70 = 1;
@@ -337,14 +341,113 @@ void RayCast::shapeRayCastImpl(hkpWorldRayCastOutput* output, RigidBody* body) {
}
}
+bool RayCast::phantomRayCast(Phantom* phantom) {
+ hkpWorldRayCastOutput output;
+ preCast();
+ phantomRayCastImpl(&output, phantom);
+ return postCast(output);
+}
+
+void RayCast::phantomRayCastImpl(hkpWorldRayCastOutput* output, Phantom* phantom) {
+ hkpWorldRayCastInput input;
+ auto layer_type = phantom->getLayerType();
+ fillCastInput(input, layer_type);
+
+ ScopedWorldLock lock{layer_type, "raycast", 0, OnlyLockIfNeeded::Yes};
+
+ if (mNormalCheckingMode == NormalCheckingMode::DoNotCheck) {
+ if (mIgnoredGroups.size() > 0 || int(mIgnoredGroundHit) != GroundHit::Ignore) {
+ RayHitCollector collector{output, layer_type,
+ mIgnoredGroups.size() > 0 ? &mIgnoredGroups : nullptr,
+ mIgnoredGroundHit};
+ phantom->getHavokPhantom()->castRay(input, collector);
+ } else {
+ phantom->getHavokPhantom()->castRay(input, *output);
+ }
+
+ } else {
+ sead::Vector3f ray_line = mTo - mFrom;
+ ray_line.normalize();
+
+ auto* groups = mIgnoredGroups.size() > 0 ? &mIgnoredGroups : nullptr;
+ NormalCheckingRayHitCollector collector(output, ray_line, mNormalCheckingMode, layer_type,
+ groups, mIgnoredGroundHit);
+ phantom->getHavokPhantom()->castRay(input, collector);
+ }
+}
+
+void RayCast::updateStaticCompoundObjectInfo(const hkpWorldRayCastOutput& output) {
+ hkpShapeKeyPath path{output};
+ auto iterator = path.getIterator();
+
+ sead::Vector3f hit_position;
+ getHitPosition(&hit_position);
+
+ if (iterator.isValid()) {
+ const auto& shape = *iterator.getShape();
+ const u32 raw_material = getMaterialMaskFromShape(shape, output.m_shapeKeys, hit_position);
+
+ mMaterialMask.set(raw_material);
+ if (raw_material == u32(-1))
+ mMaterialMask.reset();
+
+ if (_99) {
+ getBodyGroupAndObjectFromSCShape(&mHitBodyGroup, &mHitMapObject, shape,
+ output.m_shapeKeys);
+ }
+ } else {
+ mMaterialMask.reset();
+ }
+}
+
void RayCast::getHitPosition(sead::Vector3f* position) const {
*position = ((1 - mHitFraction) * mFrom) + (mHitFraction * mTo);
}
+static void calculateTriangleNormal(sead::Vector3f* normal, const hkpTriangleShape* triangle) {
+ const auto va = toVec3(triangle->getVertex<0>());
+ const auto vb = toVec3(triangle->getVertex<1>());
+ const auto vc = toVec3(triangle->getVertex<2>());
+ normal->setCross(vb - va, vc - va);
+}
+
+bool RayCast::getHitTriangleNormal(sead::Vector3f* normal, const hkpShape* hit_shape,
+ u32 shape_key) const {
+ if (hit_shape->getType() != hkcdShapeType::STATIC_COMPOUND) {
+ if (hit_shape->getType() != hkcdShapeType::BV_COMPRESSED_MESH)
+ return false;
+
+ auto* bv_mesh = static_cast<const hkpBvCompressedMeshShape*>(hit_shape);
+
+ hkpShapeBuffer buffer;
+ hit_shape = bv_mesh->getChildShape(shape_key, buffer);
+ if (hit_shape->getType() != hkcdShapeType::TRIANGLE)
+ return false;
+
+ calculateTriangleNormal(normal, static_cast<const hkpTriangleShape*>(hit_shape));
+ return true;
+ }
+
+ auto* sc = static_cast<const hkpStaticCompoundShape*>(hit_shape);
+ int instance_id;
+ sc->decomposeShapeKey(shape_key, instance_id, shape_key);
+ return instance_id >= 0 &&
+ getHitTriangleNormal(normal, sc->getInstances()[instance_id].getShape(), shape_key);
+}
+
void RayCast::getHitNormal(sead::Vector3f* normal) const {
*normal = mHitNormal;
}
+bool RayCast::getHitTriangleNormal(sead::Vector3f* normal) const {
+ if (!mHasHit)
+ return false;
+
+ const u32 shape_key = mHitShapeKey;
+ const hkpShape* shape = mHitCollidable->getShape();
+ return getHitTriangleNormal(normal, shape, shape_key);
+}
+
RayHitCollector::~RayHitCollector() = default;
bool RayHitCollector::isIgnoredGroup(const hkpCdBody& cdBody,
@@ -471,9 +574,9 @@ bool NormalCheckingRayHitCollector::checkNormal(
hkVector4f CminusA;
CminusA.setSub(vertexC, vertexA);
- hkVector4f triangle_line;
- triangle_line.setCross(BminusA, CminusA);
- triangle_line.normalize<3>();
+ hkVector4f triangle_normal;
+ triangle_normal.setCross(BminusA, CminusA);
+ triangle_normal.normalize<3>();
const auto body_rotation = cdBody.getRootCollidable()->getTransform().getRotation();
@@ -495,7 +598,7 @@ bool NormalCheckingRayHitCollector::checkNormal(
hkVector4f rotated_normal;
rotated_normal.setRotatedDir(rotation, hitInfo.m_normal);
- return checkDot<true>(mMode, triangle_line.dot<3>(rotated_normal));
+ return checkDot<true>(mMode, triangle_normal.dot<3>(rotated_normal));
}
} // namespace ksys::phys