// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics) // SPDX-FileCopyrightText: 2021 Jorrit Rouwe // SPDX-License-Identifier: MIT #include #include #include #include #include JPH_NAMESPACE_BEGIN JPH_IMPLEMENT_SERIALIZABLE_NON_VIRTUAL(BodyCreationSettings) { JPH_ADD_ATTRIBUTE(BodyCreationSettings, mPosition) JPH_ADD_ATTRIBUTE(BodyCreationSettings, mRotation) JPH_ADD_ATTRIBUTE(BodyCreationSettings, mLinearVelocity) JPH_ADD_ATTRIBUTE(BodyCreationSettings, mAngularVelocity) JPH_ADD_ATTRIBUTE(BodyCreationSettings, mUserData) JPH_ADD_ATTRIBUTE(BodyCreationSettings, mShape) JPH_ADD_ATTRIBUTE(BodyCreationSettings, mCollisionGroup) JPH_ADD_ENUM_ATTRIBUTE(BodyCreationSettings, mObjectLayer) JPH_ADD_ENUM_ATTRIBUTE(BodyCreationSettings, mMotionType) JPH_ADD_ENUM_ATTRIBUTE(BodyCreationSettings, mAllowedDOFs) JPH_ADD_ATTRIBUTE(BodyCreationSettings, mAllowDynamicOrKinematic) JPH_ADD_ATTRIBUTE(BodyCreationSettings, mIsSensor) JPH_ADD_ATTRIBUTE_WITH_ALIAS(BodyCreationSettings, mCollideKinematicVsNonDynamic, "mSensorDetectsStatic") // This is the old name to keep backwards compatibility JPH_ADD_ATTRIBUTE(BodyCreationSettings, mUseManifoldReduction) JPH_ADD_ATTRIBUTE(BodyCreationSettings, mApplyGyroscopicForce) JPH_ADD_ENUM_ATTRIBUTE(BodyCreationSettings, mMotionQuality) JPH_ADD_ATTRIBUTE(BodyCreationSettings, mEnhancedInternalEdgeRemoval) JPH_ADD_ATTRIBUTE(BodyCreationSettings, mAllowSleeping) JPH_ADD_ATTRIBUTE(BodyCreationSettings, mFriction) JPH_ADD_ATTRIBUTE(BodyCreationSettings, mRestitution) JPH_ADD_ATTRIBUTE(BodyCreationSettings, mLinearDamping) JPH_ADD_ATTRIBUTE(BodyCreationSettings, mAngularDamping) JPH_ADD_ATTRIBUTE(BodyCreationSettings, mMaxLinearVelocity) JPH_ADD_ATTRIBUTE(BodyCreationSettings, mMaxAngularVelocity) JPH_ADD_ATTRIBUTE(BodyCreationSettings, mGravityFactor) JPH_ADD_ATTRIBUTE(BodyCreationSettings, mNumVelocityStepsOverride) JPH_ADD_ATTRIBUTE(BodyCreationSettings, mNumPositionStepsOverride) JPH_ADD_ENUM_ATTRIBUTE(BodyCreationSettings, mOverrideMassProperties) JPH_ADD_ATTRIBUTE(BodyCreationSettings, mInertiaMultiplier) JPH_ADD_ATTRIBUTE(BodyCreationSettings, mMassPropertiesOverride) } void BodyCreationSettings::SaveBinaryState(StreamOut &inStream) const { inStream.Write(mPosition); inStream.Write(mRotation); inStream.Write(mLinearVelocity); inStream.Write(mAngularVelocity); mCollisionGroup.SaveBinaryState(inStream); inStream.Write(mObjectLayer); inStream.Write(mMotionType); inStream.Write(mAllowedDOFs); inStream.Write(mAllowDynamicOrKinematic); inStream.Write(mIsSensor); inStream.Write(mCollideKinematicVsNonDynamic); inStream.Write(mUseManifoldReduction); inStream.Write(mApplyGyroscopicForce); inStream.Write(mMotionQuality); inStream.Write(mEnhancedInternalEdgeRemoval); inStream.Write(mAllowSleeping); inStream.Write(mFriction); inStream.Write(mRestitution); inStream.Write(mLinearDamping); inStream.Write(mAngularDamping); inStream.Write(mMaxLinearVelocity); inStream.Write(mMaxAngularVelocity); inStream.Write(mGravityFactor); inStream.Write(mNumVelocityStepsOverride); inStream.Write(mNumPositionStepsOverride); inStream.Write(mOverrideMassProperties); inStream.Write(mInertiaMultiplier); mMassPropertiesOverride.SaveBinaryState(inStream); } void BodyCreationSettings::RestoreBinaryState(StreamIn &inStream) { inStream.Read(mPosition); inStream.Read(mRotation); inStream.Read(mLinearVelocity); inStream.Read(mAngularVelocity); mCollisionGroup.RestoreBinaryState(inStream); inStream.Read(mObjectLayer); inStream.Read(mMotionType); inStream.Read(mAllowedDOFs); inStream.Read(mAllowDynamicOrKinematic); inStream.Read(mIsSensor); inStream.Read(mCollideKinematicVsNonDynamic); inStream.Read(mUseManifoldReduction); inStream.Read(mApplyGyroscopicForce); inStream.Read(mMotionQuality); inStream.Read(mEnhancedInternalEdgeRemoval); inStream.Read(mAllowSleeping); inStream.Read(mFriction); inStream.Read(mRestitution); inStream.Read(mLinearDamping); inStream.Read(mAngularDamping); inStream.Read(mMaxLinearVelocity); inStream.Read(mMaxAngularVelocity); inStream.Read(mGravityFactor); inStream.Read(mNumVelocityStepsOverride); inStream.Read(mNumPositionStepsOverride); inStream.Read(mOverrideMassProperties); inStream.Read(mInertiaMultiplier); mMassPropertiesOverride.RestoreBinaryState(inStream); } Shape::ShapeResult BodyCreationSettings::ConvertShapeSettings() { // If we already have a shape, return it if (mShapePtr != nullptr) { mShape = nullptr; Shape::ShapeResult result; result.Set(const_cast(mShapePtr.GetPtr())); return result; } // Check if we have shape settings if (mShape == nullptr) { Shape::ShapeResult result; result.SetError("No shape present!"); return result; } // Create the shape Shape::ShapeResult result = mShape->Create(); if (result.IsValid()) mShapePtr = result.Get(); mShape = nullptr; return result; } const Shape *BodyCreationSettings::GetShape() const { // If we already have a shape, return it if (mShapePtr != nullptr) return mShapePtr; // Check if we have shape settings if (mShape == nullptr) return nullptr; // Create the shape Shape::ShapeResult result = mShape->Create(); if (result.IsValid()) return result.Get(); Trace("Error: %s", result.GetError().c_str()); JPH_ASSERT(false, "An error occurred during shape creation. Use ConvertShapeSettings() to convert the shape and get the error!"); return nullptr; } MassProperties BodyCreationSettings::GetMassProperties() const { // Calculate mass properties MassProperties mass_properties; switch (mOverrideMassProperties) { case EOverrideMassProperties::CalculateMassAndInertia: mass_properties = GetShape()->GetMassProperties(); mass_properties.mInertia *= mInertiaMultiplier; mass_properties.mInertia(3, 3) = 1.0f; break; case EOverrideMassProperties::CalculateInertia: mass_properties = GetShape()->GetMassProperties(); mass_properties.ScaleToMass(mMassPropertiesOverride.mMass); mass_properties.mInertia *= mInertiaMultiplier; mass_properties.mInertia(3, 3) = 1.0f; break; case EOverrideMassProperties::MassAndInertiaProvided: mass_properties = mMassPropertiesOverride; break; } return mass_properties; } void BodyCreationSettings::SaveWithChildren(StreamOut &inStream, ShapeToIDMap *ioShapeMap, MaterialToIDMap *ioMaterialMap, GroupFilterToIDMap *ioGroupFilterMap) const { // Save creation settings SaveBinaryState(inStream); // Save shape if (ioShapeMap != nullptr && ioMaterialMap != nullptr) GetShape()->SaveWithChildren(inStream, *ioShapeMap, *ioMaterialMap); else inStream.Write(~uint32(0)); // Save group filter StreamUtils::SaveObjectReference(inStream, mCollisionGroup.GetGroupFilter(), ioGroupFilterMap); } BodyCreationSettings::BCSResult BodyCreationSettings::sRestoreWithChildren(StreamIn &inStream, IDToShapeMap &ioShapeMap, IDToMaterialMap &ioMaterialMap, IDToGroupFilterMap &ioGroupFilterMap) { BCSResult result; // Read creation settings BodyCreationSettings settings; settings.RestoreBinaryState(inStream); if (inStream.IsEOF() || inStream.IsFailed()) { result.SetError("Error reading body creation settings"); return result; } // Read shape Shape::ShapeResult shape_result = Shape::sRestoreWithChildren(inStream, ioShapeMap, ioMaterialMap); if (shape_result.HasError()) { result.SetError(shape_result.GetError()); return result; } settings.SetShape(shape_result.Get()); // Read group filter Result gfresult = StreamUtils::RestoreObjectReference(inStream, ioGroupFilterMap); if (gfresult.HasError()) { result.SetError(gfresult.GetError()); return result; } settings.mCollisionGroup.SetGroupFilter(gfresult.Get()); result.Set(settings); return result; } JPH_NAMESPACE_END