jrouwe / JoltPhysics

A multi core friendly rigid body physics and collision detection library. Written in C++. Suitable for games and VR applications. Used by Horizon Forbidden West.
MIT License
6.42k stars 414 forks source link

Why the character cannot collide with the floor ? #1082

Closed ChivenZhang closed 4 months ago

ChivenZhang commented 4 months ago

I integrated the character control to my project, and it cannot collide with the floor which consisted with triangle mesh shapes. When I ran the program, it went down through the floor. I have no idea how to solve it after long time debug. Help.

This is how to create character:

auto transform = IEngineActor::GetComponent<ITransformComponent>(this);
auto location = transform->getLocation();
auto rotation = transform->getRotation();
auto scaling = transform->getScaling();
auto preTranslate = getMassOffset();
auto preRotate = getMassRotate();
auto preScaling = scaling;
m_NativeShape = JPH::ScaledShapeSettings(new JPH::RotatedTranslatedShapeSettings({ preTranslate.x, preTranslate.y, preTranslate.z }, JPH::Quat::sEulerAngles({ preRotate.x, preRotate.y, preRotate.z }), new JPH::CapsuleShapeSettings(0.5f * m_Height.getValue(), m_Radius.getValue())), { scaling.x, scaling.y, scaling.z }).Create().Get();

JPH::Ref<JPH::CharacterSettings> settings = new JPH::CharacterSettings();
settings->mMass = getMass();
settings->mFriction = getFriction();
settings->mUp = JPH::Vec3::sAxisZ();
settings->mLayer = Layers::MOVING;
settings->mShape = m_NativeShape;
settings->mGravityFactor = getGravity();
settings->mMaxSlopeAngle = JPH::DegreesToRadians(getMaxSlope());
settings->mSupportingVolume = JPH::Plane(JPH::Vec3::sAxisZ(), -m_Radius.getValue());
m_NativeEntity = new JPH::Character(settings,
    { location.x, location.y, location.z },
    { rotation.x, rotation.y, rotation.z, rotation.w },
    (uint64_t)(void*)CastRef<JoltPhysicsEntity>(this), m_NativeContext);
m_NativeEntity->AddToPhysicsSystem(m_EnableEntity.getValue() ? JPH::EActivation::Activate : JPH::EActivation::DontActivate);

This is how to create floor mesh:

auto& point = meshAsset->getPointList();
auto& index = meshAsset->getIndexList();
JPH::Array<JPH::Float3> pointList(point.size());
JPH::Array<JPH::IndexedTriangle> indexList(index.size() / 3);
for (size_t i = 0; i < point.size(); ++i) pointList[i] = JPH::Float3(point[i].x, point[i].y, point[i].z);
for (size_t i = 0, k = 0; i + 3 < index.size(); i += 3, ++k) indexList[k] = JPH::IndexedTriangle(index[i], index[i + 1], index[i + 2]);
auto transform = IEngineActor::GetComponent<ITransformComponent>(this);
auto location = transform->getLocation();
auto rotation = transform->getRotation();
auto scaling = transform->getScaling();
auto preTranslate = m_MassOffset.getValue();
auto preRotate = m_MassRotate.getValue();
auto preScaling = scaling;
auto settings = JPH::BodyCreationSettings(
    new JPH::ScaledShapeSettings(new JPH::RotatedTranslatedShapeSettings({ preTranslate.x, preTranslate.y, preTranslate.z }, JPH::Quat::sEulerAngles({ preRotate.x, preRotate.y, preRotate.z }), new JPH::MeshShapeSettings(pointList, indexList)), { scaling.x, scaling.y, scaling.z }),
    { location.x, location.y, location.z },
    { rotation.x, rotation.y, rotation.z, rotation.w },
    JPH::EMotionType::Dynamic, Layers::NON_MOVING);
settings.mMassPropertiesOverride.mMass = getMass();
settings.mMassPropertiesOverride.mInertia = JPH::Mat44::sIdentity();
if (0.0f < getMass()) settings.mOverrideMassProperties = JPH::EOverrideMassProperties::CalculateInertia;
settings.mIsSensor = m_Sensor.getValue();
settings.mFriction = getFriction();
settings.mRestitution = getRestitution();
settings.mGravityFactor = getGravity();
settings.mLinearDamping = getLinearDamping();
settings.mAngularDamping = getAngularDamping();
settings.mMotionQuality = JPH::EMotionQuality::LinearCast;
settings.mMotionType = (JPH::EMotionType)m_MotionType.getValue();
settings.mObjectLayer = Layers::NON_MOVING;
settings.mUserData = (uint64_t)(void*)CastRef<JoltPhysicsEntity>(this);
m_NativeEntity = m_NativeContext->GetBodyInterface().CreateBody(settings);
m_NativeContext->GetBodyInterface().AddBody(m_NativeEntity->GetID(), m_EnableEntity.getValue() ? JPH::EActivation::Activate : JPH::EActivation::DontActivate);
ChivenZhang commented 4 months ago

I have found my error.