no message

This commit is contained in:
gem
2025-02-18 15:21:31 +08:00
commit 2d133e56d7
1980 changed files with 465595 additions and 0 deletions

View File

@@ -0,0 +1,31 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "physics/sdk/Joint.h"
#include "physics/sdk/RigidBody.h"
#include "physics/sdk/Shape.h"
#include "physics/sdk/World.h"
#include "physics/sdk/CharacterController.h"

View File

@@ -0,0 +1,47 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#if defined(USE_PHYSICS_BULLET)
#include "physics/bullet/Bullet.h"
#else
#include "physics/physx/PhysX.h"
#define WrappedWorld PhysXWorld
#define WrappedRigidBody PhysXRigidBody
#define WrappedSphereShape PhysXSphere
#define WrappedBoxShape PhysXBox
#define WrappedPlaneShape PhysXPlane
#define WrappedCapsuleShape PhysXCapsule
#define WrappedTrimeshShape PhysXTrimesh
#define WrappedTerrainShape PhysXTerrain
#define WrappedConeShape PhysXCone
#define WrappedCylinderShape PhysXCylinder
#define WrappedRevoluteJoint PhysXRevolute
#define WrappedFixedJoint PhysXFixedJoint
#define WrappedSphericalJoint PhysXSpherical
#define WrappedGenericJoint PhysXGenericJoint
#define WrappedCapsuleCharacterController PhysXCapsuleCharacterController
#define WrappedBoxCharacterController PhysXBoxCharacterController
#endif

View File

@@ -0,0 +1,46 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "physics/physx/PhysXWorld.h"
#include "physics/physx/PhysXRigidBody.h"
#include "physics/physx/shapes/PhysXBox.h"
#include "physics/physx/shapes/PhysXCapsule.h"
#include "physics/physx/shapes/PhysXCone.h"
#include "physics/physx/shapes/PhysXCylinder.h"
#include "physics/physx/shapes/PhysXPlane.h"
#include "physics/physx/shapes/PhysXSphere.h"
#include "physics/physx/shapes/PhysXTerrain.h"
#include "physics/physx/shapes/PhysXTrimesh.h"
#include "physics/physx/joints/PhysXFixedJoint.h"
#include "physics/physx/joints/PhysXGenericJoint.h"
#include "physics/physx/joints/PhysXRevolute.h"
#include "physics/physx/joints/PhysXSpherical.h"
#include "physics/physx/character-controllers/PhysXBoxCharacterController.h"
#include "physics/physx/character-controllers/PhysXCapsuleCharacterController.h"

View File

@@ -0,0 +1,195 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "physics/physx/PhysXEventManager.h"
#include <algorithm>
#include "physics/physx/PhysXInc.h"
#include "physics/physx/PhysXUtils.h"
#include "physics/physx/PhysXWorld.h"
#include "physics/physx/shapes/PhysXShape.h"
namespace cc {
namespace physics {
void PhysXEventManager::SimulationEventCallback::onTrigger(physx::PxTriggerPair *pairs, physx::PxU32 count) {
for (physx::PxU32 i = 0; i < count; i++) {
const physx::PxTriggerPair &triggerPair = pairs[i];
if (triggerPair.flags & (physx::PxTriggerPairFlag::eREMOVED_SHAPE_TRIGGER | physx::PxTriggerPairFlag::eREMOVED_SHAPE_OTHER)) {
continue;
}
bool processed = false;
//collider trigger event
if (!processed) {
const auto &selfIter = getPxShapeMap().find(reinterpret_cast<uintptr_t>(triggerPair.triggerShape));
const auto &otherIter = getPxShapeMap().find(reinterpret_cast<uintptr_t>(triggerPair.otherShape));
if (selfIter != getPxShapeMap().end() && otherIter != getPxShapeMap().end()) {
processed = true;
const auto &self = selfIter->second;
const auto &other = otherIter->second;
auto &pairs = mManager->getTriggerPairs();
const auto &iter = std::find_if(pairs.begin(), pairs.end(), [self, other](std::shared_ptr<TriggerEventPair> &pair) {
return (pair->shapeA == self || pair->shapeA == other) && (pair->shapeB == self || pair->shapeB == other);
});
if (triggerPair.status & physx::PxPairFlag::eNOTIFY_TOUCH_FOUND) {
if (iter == pairs.end()) pairs.push_back(std::shared_ptr<TriggerEventPair>(ccnew TriggerEventPair{self, other}));
} else if (triggerPair.status & physx::PxPairFlag::eNOTIFY_TOUCH_LOST) {
if (iter != pairs.end()) iter->get()->state = ETouchState::EXIT;
}
}
}
//cct trigger event
if (!processed) {
const auto &shapeIter = getPxShapeMap().find(reinterpret_cast<uintptr_t>(triggerPair.triggerShape));
const auto &cctIter = getPxCCTMap().find(reinterpret_cast<uintptr_t>(triggerPair.otherShape));
if (shapeIter != getPxShapeMap().end() && cctIter != getPxCCTMap().end()) {
processed = true;
const auto &shape = shapeIter->second;
const auto &cct = cctIter->second;
auto &pairs = mManager->getCCTTriggerPairs();
const auto &iter = std::find_if(pairs.begin(), pairs.end(), [shape, cct](std::shared_ptr<CCTTriggerEventPair> &pair) {
return (pair->shape == shape && pair->cct == cct);
});
if (triggerPair.status & physx::PxPairFlag::eNOTIFY_TOUCH_FOUND) {
if (iter == pairs.end()) pairs.push_back(std::shared_ptr<CCTTriggerEventPair>(ccnew CCTTriggerEventPair{cct, shape}));
} else if (triggerPair.status & physx::PxPairFlag::eNOTIFY_TOUCH_LOST) {
if (iter != pairs.end()) iter->get()->state = ETouchState::EXIT;
}
}
}
//cct trigger event
if (!processed) {
const auto &cctIter = getPxCCTMap().find(reinterpret_cast<uintptr_t>(triggerPair.triggerShape));
const auto &shapeIter = getPxShapeMap().find(reinterpret_cast<uintptr_t>(triggerPair.otherShape));
if (shapeIter != getPxShapeMap().end() && cctIter != getPxCCTMap().end()) {
processed = true;
const auto &shape = shapeIter->second;
const auto &cct = cctIter->second;
auto &pairs = mManager->getCCTTriggerPairs();
const auto &iter = std::find_if(pairs.begin(), pairs.end(), [shape, cct](std::shared_ptr<CCTTriggerEventPair> &pair) {
return (pair->shape == shape && pair->cct == cct);
});
if (triggerPair.status & physx::PxPairFlag::eNOTIFY_TOUCH_FOUND) {
if (iter == pairs.end()) pairs.push_back(std::shared_ptr<CCTTriggerEventPair>(ccnew CCTTriggerEventPair{cct, shape}));
} else if (triggerPair.status & physx::PxPairFlag::eNOTIFY_TOUCH_LOST) {
if (iter != pairs.end()) iter->get()->state = ETouchState::EXIT;
}
}
}
}
}
void PhysXEventManager::SimulationEventCallback::onContact(const physx::PxContactPairHeader & /*header*/, const physx::PxContactPair *pairs, physx::PxU32 count) {
for (physx::PxU32 i = 0; i < count; i++) {
const physx::PxContactPair &cp = pairs[i];
if (cp.flags & (physx::PxContactPairFlag::eREMOVED_SHAPE_0 | physx::PxContactPairFlag::eREMOVED_SHAPE_1)) {
continue;
}
const auto &selfIter = getPxShapeMap().find(reinterpret_cast<uintptr_t>(cp.shapes[0]));
const auto &otherIter = getPxShapeMap().find(reinterpret_cast<uintptr_t>(cp.shapes[1]));
if (selfIter == getPxShapeMap().end() || otherIter == getPxShapeMap().end()) {
continue;
}
const auto &self = selfIter->second;
const auto &other = otherIter->second;
auto &pairs = mManager->getConatctPairs();
auto iter = std::find_if(pairs.begin(), pairs.end(), [self, other](std::shared_ptr<ContactEventPair> &pair) {
return (pair->shapeA == self || pair->shapeA == other) && (pair->shapeB == self || pair->shapeB == other);
});
if (iter == pairs.end()) {
pairs.push_back(std::shared_ptr<ContactEventPair>(ccnew ContactEventPair{self, other}));
iter = pairs.end() - 1;
}
if (cp.events & physx::PxPairFlag::eNOTIFY_TOUCH_PERSISTS) {
iter->get()->state = ETouchState::STAY;
} else if (cp.events & physx::PxPairFlag::eNOTIFY_TOUCH_FOUND) {
iter->get()->state = ETouchState::ENTER;
} else if (cp.events & physx::PxPairFlag::eNOTIFY_TOUCH_LOST) {
iter->get()->state = ETouchState::EXIT;
}
const physx::PxU8 &contactCount = cp.contactCount;
iter->get()->contacts.resize(contactCount);
if (contactCount > 0) {
cp.extractContacts(reinterpret_cast<physx::PxContactPairPoint *>(&iter->get()->contacts[0]), contactCount);
}
}
}
void PhysXEventManager::refreshPairs() {
for (auto iter = getTriggerPairs().begin(); iter != getTriggerPairs().end();) {
uintptr_t wrapperPtrShapeA = PhysXWorld::getInstance().getWrapperPtrWithObjectID(iter->get()->shapeA);
uintptr_t wrapperPtrShapeB = PhysXWorld::getInstance().getWrapperPtrWithObjectID(iter->get()->shapeB);
if (wrapperPtrShapeA == 0 || wrapperPtrShapeB == 0) {
iter = getTriggerPairs().erase(iter);
continue;
}
const auto &selfIter = getPxShapeMap().find(reinterpret_cast<uintptr_t>(&(reinterpret_cast<PhysXShape *>(wrapperPtrShapeA)->getShape())));
const auto &otherIter = getPxShapeMap().find(reinterpret_cast<uintptr_t>(&(reinterpret_cast<PhysXShape *>(wrapperPtrShapeB)->getShape())));
if (selfIter == getPxShapeMap().end() || otherIter == getPxShapeMap().end()) {
iter = getTriggerPairs().erase(iter);
} else if (iter->get()->state == ETouchState::EXIT) {
iter = getTriggerPairs().erase(iter);
} else {
iter->get()->state = ETouchState::STAY;
iter++;
}
}
for (auto iter = getCCTTriggerPairs().begin(); iter != getCCTTriggerPairs().end();) {
uintptr_t wrapperPtrCCT = PhysXWorld::getInstance().getWrapperPtrWithObjectID(iter->get()->cct);
uintptr_t wrapperPtrShape = PhysXWorld::getInstance().getWrapperPtrWithObjectID(iter->get()->shape);
if (wrapperPtrCCT == 0 || wrapperPtrShape == 0) {
iter = getCCTTriggerPairs().erase(iter);
continue;
}
const auto& cctIter = getPxCCTMap().find(reinterpret_cast<uintptr_t>(&(reinterpret_cast<PhysXCharacterController*>(wrapperPtrCCT)->getCCT())));
const auto& shapeIter = getPxShapeMap().find(reinterpret_cast<uintptr_t>(&(reinterpret_cast<PhysXShape*>(wrapperPtrShape)->getShape())));
if (cctIter == getPxCCTMap().end() || shapeIter == getPxShapeMap().end()) {
iter = getCCTTriggerPairs().erase(iter);
}
else if (iter->get()->state == ETouchState::EXIT) {
iter = getCCTTriggerPairs().erase(iter);
}
else {
iter->get()->state = ETouchState::STAY;
iter++;
}
}
getConatctPairs().clear();
getCCTShapePairs().clear();
}
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,76 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include <memory>
#include "base/Macros.h"
#include "base/memory/Memory.h"
#include "base/std/container/vector.h"
#include "physics/physx/PhysXInc.h"
#include "physics/spec/IWorld.h"
namespace cc {
namespace physics {
class PhysXEventManager final {
public:
PhysXEventManager() {
_mCallback = ccnew SimulationEventCallback(this);
}
~PhysXEventManager() {
delete _mCallback;
}
struct SimulationEventCallback : public physx::PxSimulationEventCallback {
void onConstraintBreak(physx::PxConstraintInfo * /*constraints*/, physx::PxU32 /*count*/) override{};
void onWake(physx::PxActor ** /*actors*/, physx::PxU32 /*count*/) override{};
void onSleep(physx::PxActor ** /*actors*/, physx::PxU32 /*count*/) override{};
void onTrigger(physx::PxTriggerPair * /*pairs*/, physx::PxU32 /*count*/) override;
void onContact(const physx::PxContactPairHeader & /*pairHeader*/, const physx::PxContactPair * /*pairs*/, physx::PxU32 /*nbPairs*/) override;
void onAdvance(const physx::PxRigidBody *const * /*bodyBuffer*/, const physx::PxTransform * /*poseBuffer*/, const physx::PxU32 /*count*/) override{};
PhysXEventManager *mManager;
public:
explicit SimulationEventCallback(PhysXEventManager *m) : mManager(m) {}
};
inline SimulationEventCallback &getEventCallback() { return *_mCallback; }
inline ccstd::vector<std::shared_ptr<TriggerEventPair>> &getTriggerPairs() { return _mTriggerPairs; }
inline ccstd::vector<std::shared_ptr<ContactEventPair>>& getConatctPairs() { return _mConatctPairs; }
inline ccstd::vector<std::shared_ptr<CCTShapeEventPair>>& getCCTShapePairs() { return _mCCTShapePairs; }
inline ccstd::vector<std::shared_ptr<CCTTriggerEventPair>> &getCCTTriggerPairs() { return _mCCTTriggerPairs; }
void refreshPairs();
private:
ccstd::vector<std::shared_ptr<TriggerEventPair>> _mTriggerPairs;
ccstd::vector<std::shared_ptr<ContactEventPair>> _mConatctPairs;
ccstd::vector<std::shared_ptr<CCTShapeEventPair>> _mCCTShapePairs;
ccstd::vector<std::shared_ptr<CCTTriggerEventPair>> _mCCTTriggerPairs;
SimulationEventCallback *_mCallback;
};
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,114 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "physics/physx/PhysXFilterShader.h"
#include "physics/physx/PhysXInc.h"
namespace cc {
namespace physics {
physx::PxFilterFlags simpleFilterShader(
physx::PxFilterObjectAttributes attributes0, physx::PxFilterData fd0,
physx::PxFilterObjectAttributes attributes1, physx::PxFilterData fd1,
physx::PxPairFlags &pairFlags, const void *constantBlock, physx::PxU32 constantBlockSize) {
PX_UNUSED(constantBlock);
PX_UNUSED(constantBlockSize);
// group mask filter
if (!(fd0.word0 & fd1.word1) || !(fd0.word1 & fd1.word0)) {
return physx::PxFilterFlag::eSUPPRESS;
}
if (physx::PxFilterObjectIsTrigger(attributes0) || physx::PxFilterObjectIsTrigger(attributes1)) {
pairFlags |= physx::PxPairFlag::eTRIGGER_DEFAULT | physx::PxPairFlag::eNOTIFY_TOUCH_CCD;
return physx::PxFilterFlag::eDEFAULT;
}
if (!physx::PxFilterObjectIsKinematic(attributes0) || !physx::PxFilterObjectIsKinematic(attributes1)) {
pairFlags |= physx::PxPairFlag::eSOLVE_CONTACT;
}
pairFlags |= physx::PxPairFlag::eDETECT_DISCRETE_CONTACT |
physx::PxPairFlag::eNOTIFY_TOUCH_FOUND | physx::PxPairFlag::eNOTIFY_TOUCH_LOST | physx::PxPairFlag::eNOTIFY_TOUCH_PERSISTS |
physx::PxPairFlag::eDETECT_CCD_CONTACT | physx::PxPairFlag::eNOTIFY_CONTACT_POINTS;
return physx::PxFilterFlag::eDEFAULT;
}
physx::PxFilterFlags advanceFilterShader(
physx::PxFilterObjectAttributes attributes0, physx::PxFilterData fd0,
physx::PxFilterObjectAttributes attributes1, physx::PxFilterData fd1,
physx::PxPairFlags &pairFlags, const void *constantBlock, physx::PxU32 constantBlockSize) {
PX_UNUSED(constantBlock);
PX_UNUSED(constantBlockSize);
// group mask filter
if (!(fd0.word0 & fd1.word1) || !(fd0.word1 & fd1.word0)) {
return physx::PxFilterFlag::eSUPPRESS;
}
pairFlags = physx::PxPairFlags(0);
// trigger filter
if (physx::PxFilterObjectIsTrigger(attributes0) || physx::PxFilterObjectIsTrigger(attributes1)) {
pairFlags |= physx::PxPairFlag::eDETECT_DISCRETE_CONTACT;
// need trigger event?
const physx::PxU16 needTriggerEvent = (fd0.word3 & DETECT_TRIGGER_EVENT) | (fd1.word3 & DETECT_TRIGGER_EVENT);
if (needTriggerEvent) {
pairFlags |= physx::PxPairFlag::eNOTIFY_TOUCH_FOUND | physx::PxPairFlag::eNOTIFY_TOUCH_LOST;
return physx::PxFilterFlag::eDEFAULT;
}
return physx::PxFilterFlag::eSUPPRESS;
}
// need detect ccd contact?
const physx::PxU16 needDetectCCD = (fd0.word3 & DETECT_CONTACT_CCD) | (fd1.word3 & DETECT_CONTACT_CCD);
if (needDetectCCD) pairFlags |= physx::PxPairFlag::eDETECT_CCD_CONTACT;
if (!physx::PxFilterObjectIsKinematic(attributes0) || !physx::PxFilterObjectIsKinematic(attributes1)) {
pairFlags |= physx::PxPairFlag::eSOLVE_CONTACT;
}
// simple collision process
pairFlags |= physx::PxPairFlag::eDETECT_DISCRETE_CONTACT;
// need contact event?
const physx::PxU16 needContactEvent = (fd0.word3 & DETECT_CONTACT_EVENT) | (fd1.word3 & DETECT_CONTACT_EVENT);
if (needContactEvent) pairFlags |= physx::PxPairFlag::eNOTIFY_TOUCH_FOUND | physx::PxPairFlag::eNOTIFY_TOUCH_LOST | physx::PxPairFlag::eNOTIFY_TOUCH_PERSISTS;
// need contact point?
const physx::PxU16 needContactPoint = (fd0.word3 & DETECT_CONTACT_POINT) | (fd1.word3 & DETECT_CONTACT_POINT);
if (needContactPoint) pairFlags |= physx::PxPairFlag::eNOTIFY_CONTACT_POINTS;
return physx::PxFilterFlag::eDEFAULT;
}
physx::PxQueryHitType::Enum QueryFilterShader::preFilter(const physx::PxFilterData &filterData, const physx::PxShape *shape,
const physx::PxRigidActor *actor, physx::PxHitFlags &queryFlags) {
PX_UNUSED(actor);
PX_UNUSED(queryFlags);
if ((filterData.word3 & QUERY_CHECK_TRIGGER) && shape->getFlags().isSet(physx::PxShapeFlag::eTRIGGER_SHAPE)) {
return physx::PxQueryHitType::eNONE;
}
return filterData.word3 & QUERY_SINGLE_HIT ? physx::PxQueryHitType::eBLOCK : physx::PxQueryHitType::eTOUCH;
}
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,62 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "physics/physx/PhysXInc.h"
namespace cc {
namespace physics {
constexpr physx::PxU32 QUERY_FILTER = 1 << 0;
constexpr physx::PxU32 QUERY_CHECK_TRIGGER = 1 << 1;
constexpr physx::PxU32 QUERY_SINGLE_HIT = 1 << 2;
constexpr physx::PxU32 DETECT_TRIGGER_EVENT = 1 << 3;
constexpr physx::PxU32 DETECT_CONTACT_EVENT = 1 << 4;
constexpr physx::PxU32 DETECT_CONTACT_POINT = 1 << 5;
constexpr physx::PxU32 DETECT_CONTACT_CCD = 1 << 6;
physx::PxFilterFlags simpleFilterShader(
physx::PxFilterObjectAttributes attributes0, physx::PxFilterData fd0,
physx::PxFilterObjectAttributes attributes1, physx::PxFilterData fd1,
physx::PxPairFlags &pairFlags, const void *constantBlock, physx::PxU32 constantBlockSize);
physx::PxFilterFlags advanceFilterShader(
physx::PxFilterObjectAttributes attributes0, physx::PxFilterData fd0,
physx::PxFilterObjectAttributes attributes1, physx::PxFilterData fd1,
physx::PxPairFlags &pairFlags, const void *constantBlock, physx::PxU32 constantBlockSize);
class QueryFilterShader : public physx::PxSceneQueryFilterCallback {
public:
physx::PxQueryHitType::Enum preFilter(const physx::PxFilterData &filterData, const physx::PxShape *shape,
const physx::PxRigidActor *actor, physx::PxHitFlags &queryFlags) override;
physx::PxQueryHitType::Enum postFilter(const physx::PxFilterData &filterData, const physx::PxQueryHit &hit) override {
PX_UNUSED(filterData);
PX_UNUSED(hit);
return physx::PxQueryHitType::eNONE;
};
};
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,45 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#if defined(_MSC_VER)
#pragma warning(disable : 4250)
#pragma warning(disable : 4996)
#endif
#include "base/Macros.h"
#if !defined(NDEBUG) ^ defined(_DEBUG)
#ifdef CC_DEBUG
#define _DEBUG
#else
#define NDEBUG
#endif
#endif
#include <PxConfig.h>
#include <PxPhysicsAPI.h>
#include <extensions/PxDefaultAllocator.h>
#include <extensions/PxDefaultErrorCallback.h>

View File

@@ -0,0 +1,269 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "physics/physx/PhysXRigidBody.h"
#include "physics/physx/PhysXInc.h"
#include "physics/physx/PhysXUtils.h"
#include "physics/physx/PhysXWorld.h"
using physx::PxActorFlag;
using physx::PxForceMode;
using physx::PxReal;
using physx::PxTransform;
using physx::PxVec3;
namespace cc {
namespace physics {
PhysXRigidBody::PhysXRigidBody() {
_mObjectID = PhysXWorld::getInstance().addWrapperObject(reinterpret_cast<uintptr_t>(this));
}
void PhysXRigidBody::initialize(Node *node, ERigidBodyType t, uint32_t g) {
_mGroup = g;
PhysXWorld &ins = PhysXWorld::getInstance();
_mSharedBody = ins.getSharedBody(node, this);
getSharedBody().reference(true);
getSharedBody().setType(t);
}
void PhysXRigidBody::onEnable() {
_mEnabled = true;
getSharedBody().enabled(true);
}
void PhysXRigidBody::onDisable() {
_mEnabled = false;
getSharedBody().enabled(false);
}
void PhysXRigidBody::onDestroy() {
getSharedBody().reference(false);
PhysXWorld::getInstance().removeWrapperObject(_mObjectID);
}
bool PhysXRigidBody::isAwake() {
if (!getSharedBody().isInWorld() || getSharedBody().isStatic()) return false;
return !getSharedBody().getImpl().rigidDynamic->isSleeping();
}
bool PhysXRigidBody::isSleepy() {
return false;
}
bool PhysXRigidBody::isSleeping() {
if (!getSharedBody().isInWorld() || getSharedBody().isStatic()) return true;
return getSharedBody().getImpl().rigidDynamic->isSleeping();
}
void PhysXRigidBody::setType(ERigidBodyType v) {
getSharedBody().setType(v);
}
void PhysXRigidBody::setMass(float v) {
getSharedBody().setMass(v);
}
void PhysXRigidBody::setLinearDamping(float v) {
if (getSharedBody().isStatic()) return;
getSharedBody().getImpl().rigidDynamic->setLinearDamping(v);
}
void PhysXRigidBody::setAngularDamping(float v) {
if (getSharedBody().isStatic()) return;
getSharedBody().getImpl().rigidDynamic->setAngularDamping(v);
}
void PhysXRigidBody::useGravity(bool v) {
if (getSharedBody().isStatic()) return;
getSharedBody().getImpl().rigidDynamic->setActorFlag(PxActorFlag::eDISABLE_GRAVITY, !v);
}
void PhysXRigidBody::useCCD(bool v) {
if (getSharedBody().isStatic()) return;
getSharedBody().getImpl().rigidDynamic->setRigidBodyFlag(physx::PxRigidBodyFlag::eENABLE_CCD, v);
}
void PhysXRigidBody::setLinearFactor(float x, float y, float z) {
if (getSharedBody().isStatic()) return;
getSharedBody().getImpl().rigidDynamic->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_LINEAR_X, x == 0.);
getSharedBody().getImpl().rigidDynamic->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_LINEAR_Y, y == 0.);
getSharedBody().getImpl().rigidDynamic->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_LINEAR_Z, z == 0.);
}
void PhysXRigidBody::setAngularFactor(float x, float y, float z) {
if (getSharedBody().isStatic()) return;
getSharedBody().getImpl().rigidDynamic->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_ANGULAR_X, x == 0.);
getSharedBody().getImpl().rigidDynamic->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_ANGULAR_Y, y == 0.);
getSharedBody().getImpl().rigidDynamic->setRigidDynamicLockFlag(physx::PxRigidDynamicLockFlag::eLOCK_ANGULAR_Z, z == 0.);
}
void PhysXRigidBody::setAllowSleep(bool v) {
if (!getSharedBody().isDynamic()) return;
PxReal wc = v ? 0.0001F : FLT_MAX;
getSharedBody().getImpl().rigidDynamic->setWakeCounter(wc);
}
void PhysXRigidBody::wakeUp() {
if (!getSharedBody().isInWorld() || getSharedBody().isStatic()) return;
getSharedBody().getImpl().rigidDynamic->wakeUp();
}
void PhysXRigidBody::sleep() {
if (!getSharedBody().isInWorld() || getSharedBody().isStatic()) return;
getSharedBody().getImpl().rigidDynamic->putToSleep();
}
void PhysXRigidBody::clearState() {
if (!getSharedBody().isInWorld()) return;
clearForces();
clearVelocity();
}
void PhysXRigidBody::clearForces() {
if (!getSharedBody().isInWorld()) return;
getSharedBody().clearForces();
}
void PhysXRigidBody::clearVelocity() {
getSharedBody().clearVelocity();
}
void PhysXRigidBody::setSleepThreshold(float v) {
if (getSharedBody().isStatic()) return;
//(approximated) mass-normalized kinetic energy
float ke = 0.5F * v * v;
getSharedBody().getImpl().rigidDynamic->setSleepThreshold(ke);
}
float PhysXRigidBody::getSleepThreshold() {
float ke = getSharedBody().getImpl().rigidDynamic->getSleepThreshold();
float v = sqrtf(2.F * ke);
return v;
}
cc::Vec3 PhysXRigidBody::getLinearVelocity() {
if (getSharedBody().isStatic()) return cc::Vec3::ZERO;
cc::Vec3 cv;
pxSetVec3Ext(cv, getSharedBody().getImpl().rigidDynamic->getLinearVelocity());
return cv;
}
void PhysXRigidBody::setLinearVelocity(float x, float y, float z) {
if (getSharedBody().isStatic()) return;
getSharedBody().getImpl().rigidDynamic->setLinearVelocity(PxVec3{x, y, z});
}
cc::Vec3 PhysXRigidBody::getAngularVelocity() {
if (getSharedBody().isStatic()) return cc::Vec3::ZERO;
cc::Vec3 cv;
pxSetVec3Ext(cv, getSharedBody().getImpl().rigidDynamic->getAngularVelocity());
return cv;
}
void PhysXRigidBody::setAngularVelocity(float x, float y, float z) {
if (getSharedBody().isStatic()) return;
getSharedBody().getImpl().rigidDynamic->setAngularVelocity(PxVec3{x, y, z});
}
void PhysXRigidBody::applyForce(float x, float y, float z, float rx, float ry, float rz) {
if (!getSharedBody().isInWorld() || getSharedBody().isStaticOrKinematic()) return;
const PxVec3 force{x, y, z};
if (force.isZero()) return;
auto *body = getSharedBody().getImpl().rigidDynamic;
body->addForce(force, PxForceMode::eFORCE, true);
const PxVec3 torque = (PxVec3{rx, ry, rz}).cross(force);
if (!torque.isZero()) body->addTorque(torque, PxForceMode::eFORCE, true);
}
void PhysXRigidBody::applyLocalForce(float x, float y, float z, float rx, float ry, float rz) {
if (!getSharedBody().isInWorld() || getSharedBody().isStaticOrKinematic()) return;
const PxVec3 force{x, y, z};
if (force.isZero()) return;
auto *body = getSharedBody().getImpl().rigidDynamic;
const PxTransform bodyPose = body->getGlobalPose();
const PxVec3 worldForce = bodyPose.rotate(force);
const PxVec3 worldPos = bodyPose.rotate(PxVec3{rx, ry, rz});
body->addForce(worldForce, PxForceMode::eFORCE, true);
const PxVec3 torque = worldPos.cross(worldForce);
if (!torque.isZero()) body->addTorque(torque, PxForceMode::eFORCE, true);
}
void PhysXRigidBody::applyImpulse(float x, float y, float z, float rx, float ry, float rz) {
if (!getSharedBody().isInWorld() || getSharedBody().isStaticOrKinematic()) return;
const PxVec3 impulse{x, y, z};
if (impulse.isZero()) return;
auto *body = getSharedBody().getImpl().rigidDynamic;
const PxVec3 torque = (PxVec3{rx, ry, rz}).cross(impulse);
body->addForce(impulse, PxForceMode::eIMPULSE, true);
if (!torque.isZero()) body->addTorque(torque, PxForceMode::eIMPULSE, true);
}
void PhysXRigidBody::applyLocalImpulse(float x, float y, float z, float rx, float ry, float rz) {
if (!getSharedBody().isInWorld() || getSharedBody().isStaticOrKinematic()) return;
const PxVec3 impulse{x, y, z};
if (impulse.isZero()) return;
auto *body = getSharedBody().getImpl().rigidDynamic;
const PxTransform bodyPose = body->getGlobalPose();
const PxVec3 worldImpulse = bodyPose.rotate(impulse);
const PxVec3 worldPos = bodyPose.rotate(PxVec3{rx, ry, rz});
body->addForce(worldImpulse, PxForceMode::eIMPULSE, true);
const PxVec3 torque = worldPos.cross(worldImpulse);
if (!torque.isZero()) body->addTorque(torque, PxForceMode::eIMPULSE, true);
}
void PhysXRigidBody::applyTorque(float x, float y, float z) {
if (!getSharedBody().isInWorld() || getSharedBody().isStaticOrKinematic()) return;
PxVec3 torque{x, y, z};
if (torque.isZero()) return;
getSharedBody().getImpl().rigidDynamic->addTorque(torque, PxForceMode::eFORCE, true);
}
void PhysXRigidBody::applyLocalTorque(float x, float y, float z) {
if (!getSharedBody().isInWorld() || getSharedBody().isStaticOrKinematic()) return;
PxVec3 torque{x, y, z};
if (torque.isZero()) return;
auto *body = getSharedBody().getImpl().rigidDynamic;
const PxTransform bodyPose = body->getGlobalPose();
body->addTorque(bodyPose.rotate(PxVec3{x, y, z}), PxForceMode::eFORCE, true);
}
uint32_t PhysXRigidBody::getGroup() {
return getSharedBody().getGroup();
}
void PhysXRigidBody::setGroup(uint32_t g) {
getSharedBody().setGroup(g);
}
uint32_t PhysXRigidBody::getMask() {
return getSharedBody().getMask();
}
void PhysXRigidBody::setMask(uint32_t m) {
getSharedBody().setMask(m);
}
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,91 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "base/Macros.h"
#include "physics/physx//PhysXInc.h"
#include "physics/physx/PhysXSharedBody.h"
#include "physics/spec/IBody.h"
namespace cc {
namespace physics {
class PhysXRigidBody final : public IRigidBody {
public:
PhysXRigidBody();
~PhysXRigidBody() override = default;
inline bool isEnabled() const { return _mEnabled; }
inline const PhysXSharedBody &getSharedBody() const { return *_mSharedBody; }
inline PhysXSharedBody &getSharedBody() { return *_mSharedBody; }
void initialize(Node *node, ERigidBodyType t, uint32_t g) override;
void onEnable() override;
void onDisable() override;
void onDestroy() override;
bool isAwake() override;
bool isSleepy() override;
bool isSleeping() override;
void setType(ERigidBodyType v) override;
void setMass(float v) override;
void setLinearDamping(float v) override;
void setAngularDamping(float v) override;
void useGravity(bool v) override;
void useCCD(bool v) override;
void setLinearFactor(float x, float y, float z) override;
void setAngularFactor(float x, float y, float z) override;
void setAllowSleep(bool v) override;
void wakeUp() override;
void sleep() override;
void clearState() override;
void clearForces() override;
void clearVelocity() override;
void setSleepThreshold(float v) override;
float getSleepThreshold() override;
cc::Vec3 getLinearVelocity() override;
void setLinearVelocity(float x, float y, float z) override;
cc::Vec3 getAngularVelocity() override;
void setAngularVelocity(float x, float y, float z) override;
void applyForce(float x, float y, float z, float rx, float ry, float rz) override;
void applyLocalForce(float x, float y, float z, float rx, float ry, float rz) override;
void applyImpulse(float x, float y, float z, float rx, float ry, float rz) override;
void applyLocalImpulse(float x, float y, float z, float rx, float ry, float rz) override;
void applyTorque(float x, float y, float z) override;
void applyLocalTorque(float x, float y, float z) override;
uint32_t getGroup() override;
uint32_t getMask() override;
void setGroup(uint32_t g) override;
void setMask(uint32_t m) override;
inline uint32_t getInitialGroup() const { return _mGroup; }
uint32_t getObjectID() const override { return _mObjectID; };
protected:
// physx::PhysXWorld* mWrappedWorld;
PhysXSharedBody *_mSharedBody{nullptr};
uint32_t _mGroup{1};
bool _mEnabled{false};
uint32_t _mObjectID{0};
};
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,354 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "physics/physx/PhysXSharedBody.h"
#include <cmath>
#include "base/memory/Memory.h"
#include "physics/physx/PhysXInc.h"
#include "physics/physx/PhysXUtils.h"
#include "physics/physx/PhysXWorld.h"
#include "physics/physx/joints/PhysXJoint.h"
#include "physics/physx/shapes/PhysXShape.h"
using physx::PxFilterData;
using physx::PxForceMode;
using physx::PxIdentity;
using physx::PxJointActorIndex;
using physx::PxPhysics;
using physx::PxQuat;
using physx::PxRigidActor;
using physx::PxRigidBodyExt;
using physx::PxRigidBodyFlag;
using physx::PxTransform;
using physx::PxVec3;
namespace cc {
namespace physics {
ccstd::unordered_map<Node *, PhysXSharedBody *> PhysXSharedBody::sharedBodesMap;
static int idCounter = 0;
PhysXSharedBody::PhysXSharedBody(
Node *node,
PhysXWorld *const world,
PhysXRigidBody *const body) : _mID(idCounter++),
_mRef(0),
_mType(ERigidBodyType::STATIC),
_mIsStatic(true),
_mIndex(-1),
_mFilterData(1, 1, 1, 0),
_mStaticActor(nullptr),
_mDynamicActor(nullptr),
_mWrappedWorld(world),
_mWrappedBody(body) {
_mImpl.ptr = 0;
_mNode = node;
};
PhysXSharedBody *PhysXSharedBody::getSharedBody(const Node *node, PhysXWorld *const world, PhysXRigidBody *const body) {
auto iter = sharedBodesMap.find(const_cast<Node *>(node));
PhysXSharedBody *newSB;
if (iter != sharedBodesMap.end()) {
newSB = iter->second;
} else {
newSB = ccnew PhysXSharedBody(const_cast<Node *>(node), world, body);
newSB->_mFilterData.word0 = 1;
newSB->_mFilterData.word1 = world->getMaskByIndex(0);
sharedBodesMap.insert(std::pair<Node *, PhysXSharedBody *>(const_cast<Node *>(node), newSB));
}
if (body != nullptr) {
auto g = body->getInitialGroup();
newSB->_mFilterData.word0 = g;
newSB->_mFilterData.word1 = world->getMaskByIndex(static_cast<uint32_t>(log2(g)));
}
return newSB;
}
PhysXSharedBody::~PhysXSharedBody() {
sharedBodesMap.erase(_mNode);
if (_mStaticActor != nullptr) PX_RELEASE(_mStaticActor);
if (_mDynamicActor != nullptr) PX_RELEASE(_mDynamicActor);
}
PhysXSharedBody::UActor PhysXSharedBody::getImpl() {
initActor();
_mImpl.ptr = isStatic() ? reinterpret_cast<uintptr_t>(_mStaticActor) : reinterpret_cast<uintptr_t>(_mDynamicActor);
return _mImpl;
}
void PhysXSharedBody::setType(ERigidBodyType v) {
if (_mType == v) return;
_mType = v;
initActor();
if (isStatic()) {
_mImpl.ptr = reinterpret_cast<uintptr_t>(_mStaticActor);
} else {
_mImpl.ptr = reinterpret_cast<uintptr_t>(_mDynamicActor);
_mImpl.rigidDynamic->setRigidBodyFlag(physx::PxRigidBodyFlag::eKINEMATIC, _mType == ERigidBodyType::KINEMATIC);
}
}
void PhysXSharedBody::reference(bool v) {
v ? _mRef++ : _mRef--;
if (_mRef == 0) delete this;
}
void PhysXSharedBody::enabled(bool v) {
if (v) {
if (_mIndex < 0) {
_mIndex = 1;
_mWrappedWorld->addActor(*this);
}
} else {
auto *wb = _mWrappedBody;
auto ws = _mWrappedShapes;
auto isRemove = ws.empty() && (wb == nullptr || (wb != nullptr && !wb->isEnabled()));
if (isRemove) {
_mIndex = -1;
if (!isStaticOrKinematic()) {
clearVelocity();
}
_mWrappedWorld->removeActor(*this);
}
}
}
void PhysXSharedBody::initActor() {
const bool temp = _mIsStatic;
if (isStatic()) {
_mIsStatic = true;
initStaticActor();
} else {
_mIsStatic = false;
initDynamicActor();
}
if (temp != _mIsStatic) switchActor(temp);
}
void PhysXSharedBody::switchActor(const bool isStaticBefore) {
if (_mStaticActor == nullptr || _mDynamicActor == nullptr) return;
PxRigidActor &a0 = isStaticBefore ? *reinterpret_cast<PxRigidActor *>(_mStaticActor) : *reinterpret_cast<PxRigidActor *>(_mDynamicActor);
PxRigidActor &a1 = !isStaticBefore ? *reinterpret_cast<PxRigidActor *>(_mStaticActor) : *reinterpret_cast<PxRigidActor *>(_mDynamicActor);
if (_mIndex >= 0) {
_mWrappedWorld->getScene().removeActor(a0, false);
_mWrappedWorld->getScene().addActor(a1);
}
for (auto const &ws : _mWrappedShapes) {
a0.detachShape(ws->getShape(), false);
a1.attachShape(ws->getShape());
}
if (isStaticBefore) {
if (isDynamic()) _mDynamicActor->wakeUp();
_mDynamicActor->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, isKinematic());
PxRigidBodyExt::setMassAndUpdateInertia(*_mDynamicActor, _mMass);
}
}
void PhysXSharedBody::initStaticActor() {
if (_mStaticActor == nullptr) {
PxTransform transform{PxIdentity};
getNode()->updateWorldTransform();
pxSetVec3Ext(transform.p, getNode()->getWorldPosition());
pxSetQuatExt(transform.q, getNode()->getWorldRotation());
if (!transform.p.isFinite()) transform.p = PxVec3{PxIdentity};
if (!transform.q.isUnit()) transform.q = PxQuat{PxIdentity};
PxPhysics &phy = PxGetPhysics();
_mStaticActor = phy.createRigidStatic(transform);
}
}
void PhysXSharedBody::initDynamicActor() {
if (_mDynamicActor == nullptr) {
PxTransform transform{PxIdentity};
getNode()->updateWorldTransform();
pxSetVec3Ext(transform.p, getNode()->getWorldPosition());
pxSetQuatExt(transform.q, getNode()->getWorldRotation());
if (!transform.p.isFinite()) transform.p = PxVec3{PxIdentity};
if (!transform.q.isUnit()) transform.q = PxQuat{PxIdentity};
PxPhysics &phy = PxGetPhysics();
_mDynamicActor = phy.createRigidDynamic(transform);
_mDynamicActor->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, isKinematic());
}
}
void PhysXSharedBody::syncScale() {
for (auto const &sb : _mWrappedShapes) {
sb->updateScale();
}
for (auto const &sb : _mWrappedJoints0) {
sb->updateScale0();
}
for (auto const &sb : _mWrappedJoints1) {
sb->updateScale1();
}
}
void PhysXSharedBody::syncSceneToPhysics() {
uint32_t getChangedFlags = getNode()->getChangedFlags();
if (getChangedFlags) {
if (getChangedFlags & static_cast<uint32_t>(TransformBit::SCALE)) syncScale();
auto wp = getImpl().rigidActor->getGlobalPose();
if (getChangedFlags & static_cast<uint32_t>(TransformBit::POSITION)) {
getNode()->updateWorldTransform();
pxSetVec3Ext(wp.p, getNode()->getWorldPosition());
}
if (getChangedFlags & static_cast<uint32_t>(TransformBit::ROTATION)) {
getNode()->updateWorldTransform();
pxSetQuatExt(wp.q, getNode()->getWorldRotation());
}
if (isKinematic()) {
getImpl().rigidDynamic->setKinematicTarget(wp);
} else {
getImpl().rigidActor->setGlobalPose(wp, true);
}
}
}
void PhysXSharedBody::syncSceneWithCheck() {
if (getNode()->getChangedFlags() & static_cast<uint32_t>(TransformBit::SCALE)) syncScale();
auto wp = getImpl().rigidActor->getGlobalPose();
bool needUpdate = false;
getNode()->updateWorldTransform();
if (wp.p != getNode()->getWorldPosition()) {
pxSetVec3Ext(wp.p, getNode()->getWorldPosition());
needUpdate = true;
}
const auto nr = getNode()->getWorldRotation();
if (wp.q.x != nr.x && wp.q.y != nr.y && wp.q.z != nr.z) {
pxSetQuatExt(wp.q, getNode()->getWorldRotation());
needUpdate = true;
}
if (needUpdate) {
getImpl().rigidActor->setGlobalPose(wp, true);
}
}
void PhysXSharedBody::syncPhysicsToScene() {
if (isStaticOrKinematic()) return;
if (_mDynamicActor->isSleeping()) return;
const PxTransform &wp = getImpl().rigidActor->getGlobalPose();
getNode()->setWorldPosition(wp.p.x, wp.p.y, wp.p.z);
getNode()->setWorldRotation(wp.q.x, wp.q.y, wp.q.z, wp.q.w);
getNode()->setChangedFlags(getNode()->getChangedFlags() | static_cast<uint32_t>(TransformBit::POSITION) | static_cast<uint32_t>(TransformBit::ROTATION));
}
void PhysXSharedBody::addShape(const PhysXShape &shape) {
auto beg = _mWrappedShapes.begin();
auto end = _mWrappedShapes.end();
auto iter = find(beg, end, &shape);
if (iter == end) {
shape.getShape().setSimulationFilterData(_mFilterData);
shape.getShape().setQueryFilterData(_mFilterData);
getImpl().rigidActor->attachShape(shape.getShape());
_mWrappedShapes.push_back(&const_cast<PhysXShape &>(shape));
if (!shape.isTrigger()) {
if (isDynamic()) PxRigidBodyExt::setMassAndUpdateInertia(*getImpl().rigidDynamic, _mMass);
}
}
}
void PhysXSharedBody::removeShape(const PhysXShape &shape) {
auto beg = _mWrappedShapes.begin();
auto end = _mWrappedShapes.end();
auto iter = find(beg, end, &shape);
if (iter != end) {
_mWrappedShapes.erase(iter);
getImpl().rigidActor->detachShape(shape.getShape(), true);
if (!const_cast<PhysXShape &>(shape).isTrigger()) {
if (isDynamic()) PxRigidBodyExt::setMassAndUpdateInertia(*getImpl().rigidDynamic, _mMass);
}
}
}
void PhysXSharedBody::addJoint(const PhysXJoint &joint, const PxJointActorIndex::Enum index) {
if (index == PxJointActorIndex::eACTOR1) {
auto beg = _mWrappedJoints1.begin();
auto end = _mWrappedJoints1.end();
auto iter = find(beg, end, &joint);
if (iter == end) _mWrappedJoints1.push_back(&const_cast<PhysXJoint &>(joint));
} else {
auto beg = _mWrappedJoints0.begin();
auto end = _mWrappedJoints0.end();
auto iter = find(beg, end, &joint);
if (iter == end) _mWrappedJoints0.push_back(&const_cast<PhysXJoint &>(joint));
}
}
void PhysXSharedBody::removeJoint(const PhysXJoint &joint, const PxJointActorIndex::Enum index) {
if (index == PxJointActorIndex::eACTOR1) {
auto beg = _mWrappedJoints1.begin();
auto end = _mWrappedJoints1.end();
auto iter = find(beg, end, &joint);
if (iter != end) _mWrappedJoints1.erase(iter);
} else {
auto beg = _mWrappedJoints0.begin();
auto end = _mWrappedJoints0.end();
auto iter = find(beg, end, &joint);
if (iter != end) _mWrappedJoints0.erase(iter);
}
}
void PhysXSharedBody::setMass(float v) {
if (v <= 0) v = 1e-7F;
_mMass = v;
if (isDynamic()) PxRigidBodyExt::setMassAndUpdateInertia(*getImpl().rigidDynamic, _mMass);
}
void PhysXSharedBody::setGroup(uint32_t v) {
_mFilterData.word0 = v;
setCollisionFilter(_mFilterData);
}
void PhysXSharedBody::setMask(uint32_t v) {
_mFilterData.word1 = v;
setCollisionFilter(_mFilterData);
}
void PhysXSharedBody::setCollisionFilter(const PxFilterData &data) {
if (isDynamic()) _mDynamicActor->wakeUp();
for (auto const &ws : _mWrappedShapes) {
ws->getShape().setQueryFilterData(data);
ws->getShape().setSimulationFilterData(data);
}
}
void PhysXSharedBody::clearForces() {
if (!isInWorld()) return;
if (isStaticOrKinematic()) return;
_mDynamicActor->clearForce(PxForceMode::eFORCE);
_mDynamicActor->clearForce(PxForceMode::eIMPULSE);
_mDynamicActor->clearTorque(PxForceMode::eFORCE);
_mDynamicActor->clearTorque(PxForceMode::eIMPULSE);
}
void PhysXSharedBody::clearVelocity() {
if (isStaticOrKinematic()) return;
_mDynamicActor->setLinearVelocity(PxVec3{PxIdentity}, false);
_mDynamicActor->setAngularVelocity(PxVec3{PxIdentity}, false);
}
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,109 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "base/Macros.h"
#include "base/std/container/unordered_map.h"
#include "core/scene-graph/Node.h"
#include "physics/physx/PhysXInc.h"
#include "physics/spec/IBody.h"
namespace cc {
namespace physics {
class PhysXWorld;
class PhysXShape;
class PhysXJoint;
class PhysXRigidBody;
class PhysXSharedBody final {
public:
static PhysXSharedBody *getSharedBody(const Node *node, PhysXWorld *world, PhysXRigidBody *body);
PhysXSharedBody() = delete;
PhysXSharedBody(const PhysXSharedBody &other) = delete;
PhysXSharedBody(PhysXSharedBody &&other) = delete;
void reference(bool v);
void enabled(bool v);
inline bool isInWorld() { return _mIndex >= 0; }
inline bool isStatic() { return static_cast<int>(_mType) & static_cast<int>(ERigidBodyType::STATIC); }
inline bool isKinematic() { return static_cast<int>(_mType) & static_cast<int>(ERigidBodyType::KINEMATIC); }
inline bool isStaticOrKinematic() { return static_cast<int>(_mType) & static_cast<int>(ERigidBodyType::STATIC) || static_cast<int>(_mType) & static_cast<int>(ERigidBodyType::KINEMATIC); }
inline bool isDynamic() { return !isStaticOrKinematic(); }
inline Node *getNode() const { return _mNode; }
inline PhysXWorld &getWorld() const { return *_mWrappedWorld; }
union UActor {
uintptr_t ptr;
physx::PxRigidActor *rigidActor;
physx::PxRigidStatic *rigidStatic;
physx::PxRigidDynamic *rigidDynamic;
};
UActor getImpl();
void setType(ERigidBodyType v);
void setMass(float v);
void syncScale();
void syncSceneToPhysics();
void syncSceneWithCheck();
void syncPhysicsToScene();
void addShape(const PhysXShape &shape);
void removeShape(const PhysXShape &shape);
void addJoint(const PhysXJoint &joint, physx::PxJointActorIndex::Enum index);
void removeJoint(const PhysXJoint &joint, physx::PxJointActorIndex::Enum index);
void setCollisionFilter(const physx::PxFilterData &data);
void clearForces();
void clearVelocity();
void setGroup(uint32_t v);
void setMask(uint32_t v);
inline uint32_t getGroup() const { return _mFilterData.word0; }
inline uint32_t getMask() const { return _mFilterData.word1; }
private:
static ccstd::unordered_map<Node *, PhysXSharedBody *> sharedBodesMap;
const uint32_t _mID;
uint8_t _mRef;
bool _mIsStatic;
ERigidBodyType _mType;
float _mMass;
int _mIndex;
physx::PxFilterData _mFilterData;
Node *_mNode;
UActor _mImpl;
physx::PxRigidStatic *_mStaticActor;
physx::PxRigidDynamic *_mDynamicActor;
PhysXWorld *_mWrappedWorld;
PhysXRigidBody *_mWrappedBody;
ccstd::vector<PhysXShape *> _mWrappedShapes;
ccstd::vector<PhysXJoint *> _mWrappedJoints0;
ccstd::vector<PhysXJoint *> _mWrappedJoints1;
PhysXSharedBody(Node *node, PhysXWorld *world, PhysXRigidBody *body);
~PhysXSharedBody();
void initActor();
void switchActor(bool isStaticBefore);
void initStaticActor();
void initDynamicActor();
};
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,47 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "physics/physx/PhysXUtils.h"
namespace cc {
namespace physics {
void pxSetFromTwoVectors(physx::PxQuat &out, const physx::PxVec3 &a, const physx::PxVec3 &b) {
float dot = a.dot(b);
if (dot < -0.999999) {
physx::PxVec3 c = (physx::PxVec3{1., 0., 0.}).cross(a);
if (c.magnitude() < 0.000001) c = (physx::PxVec3{0., 1., 0.}).cross(a);
c.normalize();
out = physx::PxQuat(physx::PxPi, c);
} else if (dot > 0.999999) {
out = physx::PxQuat{physx::PxIdentity};
} else {
physx::PxVec3 c = a.cross(b);
out = physx::PxQuat{c.x, c.y, c.z, 1 + dot};
out.normalize();
}
}
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,170 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "base/Macros.h"
#include "base/std/container/unordered_map.h"
#include "base/std/container/vector.h"
#include "renderer/pipeline/Define.h"
#include "math/Vec3.h"
#include "math/Vec4.h"
#include "physics/physx/PhysXFilterShader.h"
#include "physics/physx/PhysXInc.h"
#define PX_RELEASE(x) \
if (x) { \
(x)->release(); \
(x) = NULL; \
}
namespace cc {
namespace physics {
inline bool operator!=(const physx::PxVec3 &a, const cc::Vec3 &b) {
return a.x != b.x || a.y == b.y || a.z == b.z;
}
inline bool operator!=(const cc::Vec3 &a, const physx::PxVec3 &b) {
return a.x != b.x || a.y == b.y || a.z == b.z;
}
inline bool operator==(const physx::PxVec3 &a, const cc::Vec3 &b) {
return a.x == b.x && a.y == b.y && a.z == b.z;
}
inline bool operator==(const cc::Vec3 &a, const physx::PxVec3 &b) {
return a.x == b.x && a.y == b.y && a.z == b.z;
}
inline physx::PxVec3 operator*(const physx::PxVec3 &a, const cc::Vec3 &b) {
return physx::PxVec3{a.x * b.x, a.y * b.y, a.z * b.z};
}
inline cc::Vec3 operator*(const cc::Vec3 &a, const physx::PxVec3 &b) {
return cc::Vec3{a.x * b.x, a.y * b.y, a.z * b.z};
}
inline physx::PxVec3 operator+(const physx::PxVec3 &a, const cc::Vec3 &b) {
return physx::PxVec3{a.x + b.x, a.y + b.y, a.z + b.z};
}
inline cc::Vec3 operator+(const cc::Vec3 &a, const physx::PxVec3 &b) {
return cc::Vec3{a.x + b.x, a.y + b.y, a.z + b.z};
}
inline physx::PxVec3 &operator*=(physx::PxVec3 &a, const cc::Vec3 &b) {
a.x *= b.x;
a.y *= b.y;
a.z *= b.z;
return a;
}
inline cc::Vec3 &operator*=(cc::Vec3 &a, const physx::PxVec3 &b) {
a.x *= b.x;
a.y *= b.y;
a.z *= b.z;
return a;
}
inline bool operator!=(const physx::PxQuat &a, const cc::Vec4 &b) {
return a.x != b.x || a.y == b.y || a.z == b.z || a.w == b.w;
}
inline bool operator!=(const cc::Vec4 &a, const physx::PxQuat &b) {
return a.x != b.x || a.y == b.y || a.z == b.z || a.w == b.w;
}
inline bool operator==(const physx::PxQuat &a, const cc::Vec4 &b) {
return a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w;
}
inline bool operator==(const cc::Vec4 &a, const physx::PxQuat &b) {
return a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w;
}
inline void pxSetVec3Ext(physx::PxVec3 &v, const cc::Vec3 &cv) {
v = physx::PxVec3(cv.x, cv.y, cv.z);
}
inline void pxSetVec3Ext(cc::Vec3 &v, const physx::PxVec3 &cv) {
v = cc::Vec3(cv.x, cv.y, cv.z);
}
template <typename T1 = physx::PxQuat, typename T2 = cc::Vec4>
inline void pxSetQuatExt(T1 &p, const T2 &cp) {
p = T1(cp.x, cp.y, cp.z, cp.w);
}
inline void pxSetColor(gfx::Color& color, physx::PxU32 rgba) {
color.z = ((rgba >> 16) & 0xff);
color.y = ((rgba >> 8) & 0xff);
color.x = ((rgba) & 0xff);
color.w = 255;
}
template <typename T>
inline T pxAbsMax(const T &a, const T &b) {
return physx::PxAbs(a) > physx::PxAbs(b) ? a : b;
}
void pxSetFromTwoVectors(physx::PxQuat &out, const physx::PxVec3 &a, const physx::PxVec3 &b);
inline ccstd::unordered_map<uintptr_t, uint32_t> &getPxShapeMap() {
static ccstd::unordered_map<uintptr_t, uint32_t> m;
return m;
}
//physx::PxCharacterController ptr <--> PhysxCharacterController ObjectID
inline ccstd::unordered_map<uintptr_t, uint32_t>& getPxCCTMap() {
static ccstd::unordered_map<uintptr_t, uint32_t> m;
return m;
}
inline ccstd::unordered_map<uint16_t, uintptr_t> &getPxMaterialMap() {
static ccstd::unordered_map<uint16_t, uintptr_t> m;
return m;
}
inline physx::PxMaterial &getDefaultMaterial() {
return *(reinterpret_cast<physx::PxMaterial *>(getPxMaterialMap()[0]));
}
inline ccstd::vector<physx::PxRaycastHit> &getPxRaycastHitBuffer() {
static ccstd::vector<physx::PxRaycastHit> m{12};
return m;
}
inline ccstd::vector<physx::PxSweepHit> &getPxSweepHitBuffer() {
static ccstd::vector<physx::PxSweepHit> m{12};
return m;
}
inline QueryFilterShader &getQueryFilterShader() {
static QueryFilterShader shader;
return shader;
}
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,619 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "physics/physx/PhysXWorld.h"
#include "base/memory/Memory.h"
#include "physics/physx/PhysXFilterShader.h"
#include "physics/physx/PhysXInc.h"
#include "physics/physx/PhysXUtils.h"
#include "physics/physx/joints/PhysXJoint.h"
#include "physics/spec/IWorld.h"
#include "core/Root.h"
#include "scene/Camera.h"
#include "scene/RenderWindow.h"
#include "renderer/pipeline/Define.h"
#include "renderer/pipeline/RenderPipeline.h"
namespace cc {
namespace physics {
PhysXWorld *PhysXWorld::instance = nullptr;
uint32_t PhysXWorld::_msWrapperObjectID = 1; // starts from 1 because 0 means null
uint32_t PhysXWorld::_msPXObjectID = 0;
PhysXWorld &PhysXWorld::getInstance() {
return *instance;
}
physx::PxFoundation &PhysXWorld::getFundation() {
return *getInstance()._mFoundation;
}
physx::PxCooking &PhysXWorld::getCooking() {
return *getInstance()._mCooking;
}
physx::PxPhysics &PhysXWorld::getPhysics() {
return *getInstance()._mPhysics;
}
physx::PxControllerManager &PhysXWorld::getControllerManager() {
return *getInstance()._mControllerManager;
}
PhysXWorld::PhysXWorld() {
instance = this;
static physx::PxDefaultAllocator gAllocator;
static physx::PxDefaultErrorCallback gErrorCallback;
_mFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gAllocator, gErrorCallback);
physx::PxTolerancesScale scale{};
_mCooking = PxCreateCooking(PX_PHYSICS_VERSION, *_mFoundation, physx::PxCookingParams(scale));
physx::PxPvd *pvd = nullptr;
#ifdef CC_DEBUG
pvd = _mPvd = physx::PxCreatePvd(*_mFoundation);
physx::PxPvdTransport *transport = physx::PxDefaultPvdSocketTransportCreate("127.0.0.1", 5425, 10);
_mPvd->connect(*transport, physx::PxPvdInstrumentationFlag::eALL);
#endif
_mPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *_mFoundation, scale, true, pvd);
PxInitExtensions(*_mPhysics, pvd);
_mDispatcher = physx::PxDefaultCpuDispatcherCreate(0);
_mEventMgr = ccnew PhysXEventManager();
physx::PxSceneDesc sceneDesc(_mPhysics->getTolerancesScale());
sceneDesc.gravity = physx::PxVec3(0.0F, -10.0F, 0.0F);
sceneDesc.cpuDispatcher = _mDispatcher;
sceneDesc.kineKineFilteringMode = physx::PxPairFilteringMode::eKEEP;
sceneDesc.staticKineFilteringMode = physx::PxPairFilteringMode::eKEEP;
sceneDesc.flags |= physx::PxSceneFlag::eENABLE_CCD;
sceneDesc.filterShader = simpleFilterShader;
sceneDesc.simulationEventCallback = &_mEventMgr->getEventCallback();
_mScene = _mPhysics->createScene(sceneDesc);
_mScene->setVisualizationParameter(physx::PxVisualizationParameter::eSCALE, 1.0F);
_mControllerManager = PxCreateControllerManager(*_mScene);
_mCollisionMatrix[0] = 1;
createMaterial(0, 0.6F, 0.6F, 0.1F, 2, 2);
}
PhysXWorld::~PhysXWorld() {
auto &materialMap = getPxMaterialMap();
// clear material cache
materialMap.clear();
delete _mEventMgr;
PhysXJoint::releaseTempRigidActor();
PX_RELEASE(_mControllerManager);
PX_RELEASE(_mScene);
PX_RELEASE(_mDispatcher);
PX_RELEASE(_mPhysics);
#ifdef CC_DEBUG
physx::PxPvdTransport *transport = _mPvd->getTransport();
PX_RELEASE(_mPvd);
PX_RELEASE(transport);
#endif
// release cooking before foundation
PX_RELEASE(_mCooking);
PxCloseExtensions();
PX_RELEASE(_mFoundation);
}
void PhysXWorld::step(float fixedTimeStep) {
_mScene->simulate(fixedTimeStep);
_mScene->fetchResults(true);
syncPhysicsToScene();
#if CC_USE_GEOMETRY_RENDERER
debugDraw();
#endif
}
#if CC_USE_GEOMETRY_RENDERER
pipeline::GeometryRenderer* PhysXWorld::getDebugRenderer () {
auto cameras = Root::getInstance()->getMainWindow()->getCameras();
scene::Camera* camera = nullptr;
for (int c = 0; c < cameras.size(); c++) {
if (!cameras[c])
continue;
const bool defaultCamera = cameras[c]->getVisibility() & static_cast<uint32_t>(pipeline::LayerList::DEFAULT);
if (defaultCamera) {
camera = cameras[c];
break;
}
}
if (camera) {
camera->initGeometryRenderer();
return camera->getGeometryRenderer();
}
return nullptr;
}
void PhysXWorld::debugDraw () {
pipeline::GeometryRenderer* debugRenderer = getDebugRenderer();
if (!debugRenderer) return;
_debugLineCount = 0;
static Vec3 v0, v1;
static gfx::Color c;
auto& rb = _mScene->getRenderBuffer();
// lines
for (int i = 0; i < rb.getNbLines(); i++) {
if (_debugLineCount < _MAX_DEBUG_LINE_COUNT){
_debugLineCount++;
const physx::PxDebugLine& line = rb.getLines()[i];
pxSetColor(c, line.color0);
pxSetVec3Ext(v0, line.pos0);
pxSetVec3Ext(v1, line.pos1);
debugRenderer->addLine(v0, v1, c);
}
}
// triangles
for (int i = 0; i < rb.getNbTriangles(); i++) {
if (_debugLineCount < _MAX_DEBUG_LINE_COUNT - 3) {
_debugLineCount = _debugLineCount + 3;
const physx::PxDebugTriangle& triangle = rb.getTriangles()[i];
pxSetColor(c, triangle.color0);
pxSetVec3Ext(v0, triangle.pos0);
pxSetVec3Ext(v1, triangle.pos1);
debugRenderer->addLine(v0, v1, c);
pxSetVec3Ext(v0, triangle.pos1);
pxSetVec3Ext(v1, triangle.pos2);
debugRenderer->addLine(v0, v1, c);
pxSetVec3Ext(v0, triangle.pos2);
pxSetVec3Ext(v1, triangle.pos0);
debugRenderer->addLine(v0, v1, c);
}
}
}
void PhysXWorld::setDebugDrawMode() {
if (uint32_t(_debugDrawFlags) & uint32_t(EPhysicsDrawFlags::WIRE_FRAME)) {
_mScene->setVisualizationParameter(physx::PxVisualizationParameter::eCOLLISION_SHAPES, 1);
} else {
_mScene->setVisualizationParameter(physx::PxVisualizationParameter::eCOLLISION_SHAPES, 0);
}
bool drawConstraint = bool(uint32_t(_debugDrawFlags) & uint32_t(EPhysicsDrawFlags::CONSTRAINT));
float internalConstraintSize = drawConstraint ? _debugConstraintSize : 0;
_mScene->setVisualizationParameter(physx::PxVisualizationParameter::eJOINT_LOCAL_FRAMES, internalConstraintSize);
_mScene->setVisualizationParameter(physx::PxVisualizationParameter::eJOINT_LIMITS, internalConstraintSize);
if (uint32_t(_debugDrawFlags) & uint32_t(EPhysicsDrawFlags::AABB)) {
_mScene->setVisualizationParameter(physx::PxVisualizationParameter::eCOLLISION_AABBS, 1);
} else {
_mScene->setVisualizationParameter(physx::PxVisualizationParameter::eCOLLISION_AABBS, 0);
}
}
void PhysXWorld::setDebugDrawFlags(EPhysicsDrawFlags flags) {
_debugDrawFlags = flags;
setDebugDrawMode();
}
EPhysicsDrawFlags PhysXWorld::getDebugDrawFlags() {
return _debugDrawFlags;
}
void PhysXWorld::setDebugDrawConstraintSize(float size) {
_debugConstraintSize = size;
setDebugDrawMode();
}
float PhysXWorld::getDebugDrawConstraintSize() {
return _debugConstraintSize;
}
#endif
void PhysXWorld::setGravity(float x, float y, float z) {
_mScene->setGravity(physx::PxVec3(x, y, z));
}
void PhysXWorld::destroy() {
}
void PhysXWorld::setCollisionMatrix(uint32_t index, uint32_t mask) {
if (index > 31) return;
_mCollisionMatrix[index] = mask;
}
uint32_t PhysXWorld::createConvex(ConvexDesc &desc) {
physx::PxConvexMeshDesc convexDesc;
convexDesc.points.count = desc.positionLength;
convexDesc.points.stride = sizeof(physx::PxVec3);
convexDesc.points.data = static_cast<physx::PxVec3 *>(desc.positions);
convexDesc.flags = physx::PxConvexFlag::eCOMPUTE_CONVEX;
physx::PxConvexMesh *convexMesh = getCooking().createConvexMesh(convexDesc, PxGetPhysics().getPhysicsInsertionCallback());
uint32_t pxObjectID = addPXObject(reinterpret_cast<uintptr_t>(convexMesh));
return pxObjectID;
}
uint32_t PhysXWorld::createTrimesh(TrimeshDesc &desc) {
physx::PxTriangleMeshDesc meshDesc;
meshDesc.points.count = desc.positionLength;
meshDesc.points.stride = sizeof(physx::PxVec3);
meshDesc.points.data = static_cast<physx::PxVec3 *>(desc.positions);
meshDesc.triangles.count = desc.triangleLength;
if (desc.isU16) {
meshDesc.triangles.stride = 3 * sizeof(physx::PxU16);
meshDesc.triangles.data = static_cast<physx::PxU16 *>(desc.triangles);
meshDesc.flags = physx::PxMeshFlag::e16_BIT_INDICES;
} else {
meshDesc.triangles.stride = 3 * sizeof(physx::PxU32);
meshDesc.triangles.data = static_cast<physx::PxU32 *>(desc.triangles);
}
physx::PxTriangleMesh *triangleMesh = getCooking().createTriangleMesh(meshDesc, PxGetPhysics().getPhysicsInsertionCallback());
uint32_t pxObjectID = addPXObject(reinterpret_cast<uintptr_t>(triangleMesh));
return pxObjectID;
}
uint32_t PhysXWorld::createHeightField(HeightFieldDesc &desc) {
const auto rows = desc.rows;
const auto columns = desc.columns;
const physx::PxU32 counts = rows * columns;
auto *samples = ccnew physx::PxHeightFieldSample[counts];
for (physx::PxU32 r = 0; r < rows; r++) {
for (physx::PxU32 c = 0; c < columns; c++) {
const auto index = c + r * columns;
auto v = (static_cast<int16_t *>(desc.samples))[index];
samples[index].height = v;
}
}
physx::PxHeightFieldDesc hfDesc;
hfDesc.nbRows = rows;
hfDesc.nbColumns = columns;
hfDesc.samples.data = samples;
hfDesc.samples.stride = sizeof(physx::PxHeightFieldSample);
physx::PxHeightField *hf = getCooking().createHeightField(hfDesc, PxGetPhysics().getPhysicsInsertionCallback());
delete[] samples;
uint32_t pxObjectID = addPXObject(reinterpret_cast<uintptr_t>(hf));
return pxObjectID;
}
bool PhysXWorld::createMaterial(uint16_t id, float f, float df, float r,
uint8_t m0, uint8_t m1) {
physx::PxMaterial *mat;
auto &m = getPxMaterialMap();
if (m.find(id) == m.end()) {
mat = PxGetPhysics().createMaterial(f, df, r);
// add reference count avoid auto releasing by physx
mat->acquireReference();
m[id] = reinterpret_cast<uintptr_t>(mat);
mat->setFrictionCombineMode(physx::PxCombineMode::Enum(m0));
mat->setRestitutionCombineMode(physx::PxCombineMode::Enum(m1));
} else {
mat = reinterpret_cast<physx::PxMaterial *>(m[id]);
mat->setStaticFriction(f);
mat->setDynamicFriction(df);
mat->setRestitution(r);
mat->setFrictionCombineMode(physx::PxCombineMode::Enum(m0));
mat->setRestitutionCombineMode(physx::PxCombineMode::Enum(m1));
}
return true;
}
uintptr_t PhysXWorld::getPXMaterialPtrWithMaterialID(uint32_t materialID) {
auto &m = getPxMaterialMap();
auto const &it = m.find(materialID);
if (it == m.end()) {
return 0;
} else {
return it->second;
}
}
void PhysXWorld::emitEvents() {
_mEventMgr->refreshPairs();
}
void PhysXWorld::syncSceneToPhysics() {
for (auto const &sb : _mSharedBodies) {
sb->syncSceneToPhysics();
}
for (auto const &cct : _mCCTs) {
cct->syncSceneToPhysics();
}
}
uint32_t PhysXWorld::getMaskByIndex(uint32_t i) {
if (i > 31) i = 0;
return _mCollisionMatrix[i];
}
void PhysXWorld::syncPhysicsToScene() {
for (auto const &sb : _mSharedBodies) {
sb->syncPhysicsToScene();
}
}
void PhysXWorld::syncSceneWithCheck() {
for (auto const &sb : _mSharedBodies) {
sb->syncSceneWithCheck();
}
}
void PhysXWorld::setAllowSleep(bool val) {
}
void PhysXWorld::addActor(const PhysXSharedBody &sb) {
auto beg = _mSharedBodies.begin();
auto end = _mSharedBodies.end();
auto iter = find(beg, end, &sb);
if (iter == end) {
_mScene->addActor(*(const_cast<PhysXSharedBody &>(sb).getImpl().rigidActor));
_mSharedBodies.push_back(&const_cast<PhysXSharedBody &>(sb));
}
}
void PhysXWorld::removeActor(const PhysXSharedBody &sb) {
auto beg = _mSharedBodies.begin();
auto end = _mSharedBodies.end();
auto iter = find(beg, end, &sb);
if (iter != end) {
_mScene->removeActor(*(const_cast<PhysXSharedBody &>(sb).getImpl().rigidActor), true);
_mSharedBodies.erase(iter);
}
}
void PhysXWorld::addCCT (const PhysXCharacterController &cct) {
auto beg = _mCCTs.begin();
auto end = _mCCTs.end();
auto iter = find(beg, end, &cct);
if (iter == end) {
_mCCTs.push_back(&const_cast<PhysXCharacterController &>(cct));
}
}
void PhysXWorld::removeCCT(const PhysXCharacterController&cct) {
auto beg = _mCCTs.begin();
auto end = _mCCTs.end();
auto iter = find(beg, end, &cct);
if (iter != end) {
_mCCTs.erase(iter);
}
}
bool PhysXWorld::raycast(RaycastOptions &opt) {
physx::PxQueryCache *cache = nullptr;
const auto o = opt.origin;
const auto ud = opt.unitDir;
physx::PxVec3 origin{o.x, o.y, o.z};
physx::PxVec3 unitDir{ud.x, ud.y, ud.z};
unitDir.normalize();
physx::PxHitFlags flags = physx::PxHitFlag::ePOSITION | physx::PxHitFlag::eNORMAL;
physx::PxSceneQueryFilterData filterData;
filterData.data.word0 = opt.mask;
filterData.data.word3 = QUERY_FILTER | (opt.queryTrigger ? 0 : QUERY_CHECK_TRIGGER);
filterData.flags = physx::PxQueryFlag::eSTATIC | physx::PxQueryFlag::eDYNAMIC | physx::PxQueryFlag::ePREFILTER;
auto &hitBuffer = getPxRaycastHitBuffer();
bool result = false;
const auto nbTouches = physx::PxSceneQueryExt::raycastMultiple(
getScene(), origin, unitDir, opt.distance, flags, hitBuffer.data(),
static_cast<physx::PxU32>(hitBuffer.size()), result, filterData, &getQueryFilterShader(), cache);
if (nbTouches == 0 || nbTouches == -1) return false;
auto &r = raycastResult();
r.resize(nbTouches);
for (physx::PxI32 i = 0; i < nbTouches; i++) {
const auto &shapeIter = getPxShapeMap().find(reinterpret_cast<uintptr_t>(hitBuffer[i].shape));
if (shapeIter == getPxShapeMap().end()) return false;
r[i].shape = shapeIter->second;
r[i].distance = hitBuffer[i].distance;
pxSetVec3Ext(r[i].hitNormal, hitBuffer[i].normal);
pxSetVec3Ext(r[i].hitPoint, hitBuffer[i].position);
}
return true;
}
ccstd::vector<RaycastResult> &PhysXWorld::raycastResult() {
static ccstd::vector<RaycastResult> hits;
return hits;
}
bool PhysXWorld::raycastClosest(RaycastOptions &opt) {
physx::PxRaycastHit hit;
physx::PxQueryCache *cache = nullptr;
const auto o = opt.origin;
const auto ud = opt.unitDir;
physx::PxVec3 origin{o.x, o.y, o.z};
physx::PxVec3 unitDir{ud.x, ud.y, ud.z};
unitDir.normalize();
physx::PxHitFlags flags = physx::PxHitFlag::ePOSITION | physx::PxHitFlag::eNORMAL;
physx::PxSceneQueryFilterData filterData;
filterData.data.word0 = opt.mask;
filterData.data.word3 = QUERY_FILTER | (opt.queryTrigger ? 0 : QUERY_CHECK_TRIGGER) | QUERY_SINGLE_HIT;
filterData.flags = physx::PxQueryFlag::eSTATIC | physx::PxQueryFlag::eDYNAMIC | physx::PxQueryFlag::ePREFILTER;
const auto result = physx::PxSceneQueryExt::raycastSingle(
getScene(), origin, unitDir, opt.distance, flags,
hit, filterData, &getQueryFilterShader(), cache);
if (result) {
auto &r = raycastClosestResult();
const auto &shapeIter = getPxShapeMap().find(reinterpret_cast<uintptr_t>(hit.shape));
if (shapeIter == getPxShapeMap().end()) return false;
r.shape = shapeIter->second;
r.distance = hit.distance;
pxSetVec3Ext(r.hitPoint, hit.position);
pxSetVec3Ext(r.hitNormal, hit.normal);
}
return result;
}
RaycastResult &PhysXWorld::raycastClosestResult() {
static RaycastResult hit;
return hit;
}
bool PhysXWorld::sweepBox(RaycastOptions &opt, float halfExtentX, float halfExtentY, float halfExtentZ,
float orientationW, float orientationX, float orientationY, float orientationZ) {
return sweep(opt, physx::PxBoxGeometry{ halfExtentX, halfExtentY, halfExtentZ},
physx::PxQuat(orientationX, orientationY, orientationZ, orientationW));
}
bool PhysXWorld::sweepBoxClosest(RaycastOptions &opt, float halfExtentX, float halfExtentY, float halfExtentZ,
float orientationW, float orientationX, float orientationY, float orientationZ) {
return sweepClosest(opt, physx::PxBoxGeometry{ halfExtentX, halfExtentY, halfExtentZ},
physx::PxQuat(orientationX, orientationY, orientationZ, orientationW));
}
bool PhysXWorld::sweepSphere(RaycastOptions &opt, float radius) {
return sweep(opt, physx::PxSphereGeometry{ radius }, physx::PxQuat(0, 0, 0, 1));
}
bool PhysXWorld::sweepSphereClosest(RaycastOptions &opt, float radius) {
return sweepClosest(opt, physx::PxSphereGeometry{ radius }, physx::PxQuat(0, 0, 0, 1));
}
bool PhysXWorld::sweepCapsule(RaycastOptions &opt, float radius, float height,
float orientationW, float orientationX, float orientationY, float orientationZ) {
//add an extra 90 degree rotation to PxCapsuleGeometry whose axis is originally along the X axis
physx::PxQuat finalOrientation = physx::PxQuat(physx::PxPiDivTwo, physx::PxVec3{0.F, 0.F, 1.F});
finalOrientation = physx::PxQuat(orientationX, orientationY, orientationZ, orientationW) * finalOrientation;
return sweep(opt, physx::PxCapsuleGeometry{ radius, height/2.f }, finalOrientation);
}
bool PhysXWorld::sweepCapsuleClosest(RaycastOptions &opt, float radius, float height,
float orientationW, float orientationX, float orientationY, float orientationZ) {
//add an extra 90 degree rotation to PxCapsuleGeometry whose axis is originally along the X axis
physx::PxQuat finalOrientation = physx::PxQuat(physx::PxPiDivTwo, physx::PxVec3{0.F, 0.F, 1.F});
finalOrientation = physx::PxQuat(orientationX, orientationY, orientationZ, orientationW) * finalOrientation;
return sweepClosest(opt, physx::PxCapsuleGeometry{ radius, height/2.f }, finalOrientation);
}
bool PhysXWorld::sweep(RaycastOptions &opt, const physx::PxGeometry &geometry, const physx::PxQuat &orientation) {
physx::PxQueryCache *cache = nullptr;
const auto o = opt.origin;
const auto ud = opt.unitDir;
physx::PxVec3 origin{o.x, o.y, o.z};
physx::PxVec3 unitDir{ud.x, ud.y, ud.z};
unitDir.normalize();
physx::PxTransform pose{origin, orientation};
physx::PxHitFlags flags = physx::PxHitFlag::ePOSITION | physx::PxHitFlag::eNORMAL;
physx::PxSceneQueryFilterData filterData;
filterData.data.word0 = opt.mask;
filterData.data.word3 = QUERY_FILTER | (opt.queryTrigger ? 0 : QUERY_CHECK_TRIGGER);
filterData.flags = physx::PxQueryFlag::eSTATIC | physx::PxQueryFlag::eDYNAMIC | physx::PxQueryFlag::ePREFILTER;
auto &hitBuffer = getPxSweepHitBuffer();
bool result = false;
const auto nbTouches = physx::PxSceneQueryExt::sweepMultiple(
getScene(), geometry, pose, unitDir, opt.distance, flags, hitBuffer.data(),
static_cast<physx::PxU32>(hitBuffer.size()), result, filterData, &getQueryFilterShader(), cache);
if (nbTouches == 0 || nbTouches == -1) return false;
auto &r = sweepResult();
r.resize(nbTouches);
for (physx::PxI32 i = 0; i < nbTouches; i++) {
const auto &shapeIter = getPxShapeMap().find(reinterpret_cast<uintptr_t>(hitBuffer[i].shape));
if (shapeIter == getPxShapeMap().end()) return false;
r[i].shape = shapeIter->second;
r[i].distance = hitBuffer[i].distance;
pxSetVec3Ext(r[i].hitNormal, hitBuffer[i].normal);
pxSetVec3Ext(r[i].hitPoint, hitBuffer[i].position);
}
return true;
}
ccstd::vector<RaycastResult> &PhysXWorld::sweepResult() {
static ccstd::vector<RaycastResult> hits;
return hits;
}
bool PhysXWorld::sweepClosest(RaycastOptions &opt, const physx::PxGeometry &geometry, const physx::PxQuat &orientation) {
physx::PxSweepHit hit;
physx::PxQueryCache *cache = nullptr;
const auto o = opt.origin;
const auto ud = opt.unitDir;
physx::PxVec3 origin{o.x, o.y, o.z};
physx::PxVec3 unitDir{ud.x, ud.y, ud.z};
unitDir.normalize();
physx::PxTransform pose{origin, orientation};
physx::PxHitFlags flags = physx::PxHitFlag::ePOSITION | physx::PxHitFlag::eNORMAL;
physx::PxSceneQueryFilterData filterData;
filterData.data.word0 = opt.mask;
filterData.data.word3 = QUERY_FILTER | (opt.queryTrigger ? 0 : QUERY_CHECK_TRIGGER) | QUERY_SINGLE_HIT;
filterData.flags = physx::PxQueryFlag::eSTATIC | physx::PxQueryFlag::eDYNAMIC | physx::PxQueryFlag::ePREFILTER;
const auto result = physx::PxSceneQueryExt::sweepSingle(
getScene(), geometry, pose, unitDir, opt.distance, flags,
hit, filterData, &getQueryFilterShader(), cache, 0);
if (result) {
auto &r = sweepClosestResult();
const auto &shapeIter = getPxShapeMap().find(reinterpret_cast<uintptr_t>(hit.shape));
if (shapeIter == getPxShapeMap().end()) return false;
r.shape = shapeIter->second;
r.distance = hit.distance;
pxSetVec3Ext(r.hitPoint, hit.position);
pxSetVec3Ext(r.hitNormal, hit.normal);
}
return result;
}
RaycastResult &PhysXWorld::sweepClosestResult() {
static RaycastResult hit;
return hit;
}
uint32_t PhysXWorld::addPXObject(uintptr_t PXObjectPtr) {
uint32_t pxObjectID = _msPXObjectID;
_msPXObjectID++;
assert(_msPXObjectID < 0xffffffff);
_mPXObjects[pxObjectID] = PXObjectPtr;
return pxObjectID;
};
void PhysXWorld::removePXObject(uint32_t pxObjectID) {
_mPXObjects.erase(pxObjectID);
}
uintptr_t PhysXWorld::getPXPtrWithPXObjectID(uint32_t pxObjectID) {
auto const &iter = _mPXObjects.find(pxObjectID);
if (iter == _mPXObjects.end()) {
return 0;
}
return iter->second;
};
uint32_t PhysXWorld::addWrapperObject(uintptr_t wrapperObjectPtr) {
uint32_t wrapprtObjectID = _msWrapperObjectID;
_msWrapperObjectID++;
assert(_msWrapperObjectID < 0xffffffff);
_mWrapperObjects[wrapprtObjectID] = wrapperObjectPtr;
return wrapprtObjectID;
};
void PhysXWorld::removeWrapperObject(uint32_t wrapperObjectID) {
_mWrapperObjects.erase(wrapperObjectID);
}
uintptr_t PhysXWorld::getWrapperPtrWithObjectID(uint32_t wrapperObjectID) {
if (wrapperObjectID == 0) {
return 0;
}
auto const &iter = _mWrapperObjects.find(wrapperObjectID);
if (iter == _mWrapperObjects.end())
return 0;
return iter->second;
};
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,177 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include <memory>
#include "base/Macros.h"
#include "base/std/container/vector.h"
#include "core/scene-graph/Node.h"
#include "physics/physx/PhysXEventManager.h"
#include "physics/physx/PhysXFilterShader.h"
#include "physics/physx/PhysXInc.h"
#include "physics/physx/PhysXRigidBody.h"
#include "physics/physx/PhysXSharedBody.h"
#include "physics/physx/character-controllers/PhysXCharacterController.h"
#include "physics/spec/IWorld.h"
#include "renderer/pipeline/GeometryRenderer.h"
namespace cc {
namespace physics {
class PhysXWorld final : virtual public IPhysicsWorld {
public:
static PhysXWorld &getInstance();
static physx::PxFoundation &getFundation();
static physx::PxCooking &getCooking();
static physx::PxPhysics &getPhysics();
static physx::PxControllerManager &getControllerManager();
PhysXWorld();
~PhysXWorld() override;
void step(float fixedTimeStep) override;
void setGravity(float x, float y, float z) override;
void setAllowSleep(bool v) override;
void emitEvents() override;
void setCollisionMatrix(uint32_t index, uint32_t mask) override;
bool raycast(RaycastOptions &opt) override;
bool raycastClosest(RaycastOptions &opt) override;
ccstd::vector<RaycastResult> &raycastResult() override;
RaycastResult &raycastClosestResult() override;
bool sweep(RaycastOptions &opt, const physx::PxGeometry &geometry, const physx::PxQuat &orientation);
bool sweepClosest(RaycastOptions &opt, const physx::PxGeometry &geometry, const physx::PxQuat &orientation);
bool sweepBox(RaycastOptions &opt, float halfExtentX, float halfExtentY, float halfExtentZ,
float orientationW, float orientationX, float orientationY, float orientationZ) override;
bool sweepBoxClosest(RaycastOptions &opt, float halfExtentX, float halfExtentY, float halfExtentZ,
float orientationW, float orientationX, float orientationY, float orientationZ) override;
bool sweepSphere(RaycastOptions &opt, float radius) override;
bool sweepSphereClosest(RaycastOptions &opt, float radius) override;
bool sweepCapsule(RaycastOptions &opt, float radius, float height,
float orientationW, float orientationX, float orientationY, float orientationZ) override;
bool sweepCapsuleClosest(RaycastOptions &opt, float radius, float height,
float orientationW, float orientationX, float orientationY, float orientationZ) override;
ccstd::vector<RaycastResult> &sweepResult() override;
RaycastResult &sweepClosestResult() override;
uint32_t createConvex(ConvexDesc &desc) override;
uint32_t createTrimesh(TrimeshDesc &desc) override;
uint32_t createHeightField(HeightFieldDesc &desc) override;
bool createMaterial(uint16_t id, float f, float df, float r,
uint8_t m0, uint8_t m1) override;
inline ccstd::vector<std::shared_ptr<TriggerEventPair>> &getTriggerEventPairs() override {
return _mEventMgr->getTriggerPairs();
}
inline ccstd::vector<std::shared_ptr<ContactEventPair>> &getContactEventPairs() override {
return _mEventMgr->getConatctPairs();
}
inline ccstd::vector<std::shared_ptr<CCTShapeEventPair>> &getCCTShapeEventPairs() override {
return _mEventMgr->getCCTShapePairs();
}
inline ccstd::vector<std::shared_ptr<CCTTriggerEventPair>> &getCCTTriggerEventPairs() override {
return _mEventMgr->getCCTTriggerPairs();
}
void syncSceneToPhysics() override;
void syncSceneWithCheck() override;
void destroy() override;
inline PhysXSharedBody *getSharedBody(
const Node *node,
PhysXRigidBody *const body = nullptr) {
return PhysXSharedBody::getSharedBody(node, this, body);
}
inline physx::PxScene &getScene() const { return *_mScene; }
uint32_t getMaskByIndex(uint32_t i);
void syncPhysicsToScene();
void addActor(const PhysXSharedBody &sb);
void removeActor(const PhysXSharedBody &sb);
void addCCT(const PhysXCharacterController &cct);
void removeCCT(const PhysXCharacterController &cct);
// Mapping PhysX Object ID and Pointer
uint32_t addPXObject(uintptr_t PXObjectPtr);
void removePXObject(uint32_t pxObjectID);
uintptr_t getPXPtrWithPXObjectID(uint32_t pxObjectID);
// Mapping Wrapper PhysX Object ID and Pointer
uint32_t addWrapperObject(uintptr_t wrapperObjectPtr);
void removeWrapperObject(uint32_t wrapperObjectID);
uintptr_t getWrapperPtrWithObjectID(uint32_t wrapperObjectID);
uintptr_t getPXMaterialPtrWithMaterialID(uint32_t materialID);
float getFixedTimeStep() const override { return _fixedTimeStep; }
void setFixedTimeStep(float fixedTimeStep) override { _fixedTimeStep = fixedTimeStep; }
#if CC_USE_GEOMETRY_RENDERER
void setDebugDrawFlags(EPhysicsDrawFlags flags) override;
EPhysicsDrawFlags getDebugDrawFlags() override;
void setDebugDrawConstraintSize(float size) override;
float getDebugDrawConstraintSize() override;
private:
pipeline::GeometryRenderer *getDebugRenderer();
void debugDraw();
void setDebugDrawMode();
#else
void setDebugDrawFlags(EPhysicsDrawFlags flags) override{};
EPhysicsDrawFlags getDebugDrawFlags() override { return EPhysicsDrawFlags::NONE; };
void setDebugDrawConstraintSize(float size) override{};
float getDebugDrawConstraintSize() override { return 0.0; };
#endif
private:
static PhysXWorld *instance;
physx::PxFoundation *_mFoundation;
physx::PxCooking *_mCooking;
physx::PxPhysics *_mPhysics;
physx::PxControllerManager *_mControllerManager = NULL;
#ifdef CC_DEBUG
physx::PxPvd *_mPvd;
#endif
physx::PxDefaultCpuDispatcher *_mDispatcher;
physx::PxScene *_mScene;
PhysXEventManager *_mEventMgr;
uint32_t _mCollisionMatrix[31];
ccstd::vector<PhysXSharedBody *> _mSharedBodies;
ccstd::vector<PhysXCharacterController *> _mCCTs;
static uint32_t _msWrapperObjectID;
static uint32_t _msPXObjectID;
ccstd::unordered_map<uint32_t, uintptr_t> _mPXObjects;
ccstd::unordered_map<uint32_t, uintptr_t> _mWrapperObjects;
float _fixedTimeStep{1 / 60.0F};
uint32_t _debugLineCount = 0;
uint32_t _MAX_DEBUG_LINE_COUNT = 16384;
EPhysicsDrawFlags _debugDrawFlags = EPhysicsDrawFlags::NONE;
float _debugConstraintSize = 0.3;
};
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,104 @@
/****************************************************************************
Copyright (c) 2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "physics/physx/character-controllers/PhysXBoxCharacterController.h"
#include "physics/physx/PhysXUtils.h"
#include "physics/physx/PhysXWorld.h"
#include "math/Utils.h"
namespace cc {
namespace physics {
PhysXBoxCharacterController::PhysXBoxCharacterController() :
_mHalfHeight(0.5F), _mHalfSideExtent(0.5F), _mHalfForwardExtent(0.5F) {
}
void PhysXBoxCharacterController::setHalfHeight(float v) {
_mHalfHeight = v;
updateScale();
}
void PhysXBoxCharacterController::setHalfSideExtent(float v) {
_mHalfSideExtent = v;
updateScale();
}
void PhysXBoxCharacterController::setHalfForwardExtent(float v) {
_mHalfForwardExtent = v;
updateScale();
}
void PhysXBoxCharacterController::onComponentSet() {
create();
}
void PhysXBoxCharacterController::create() {
release();
physx::PxControllerManager& controllerManager = PhysXWorld::getInstance().getControllerManager();
auto pxMtl = reinterpret_cast<physx::PxMaterial *>(PhysXWorld::getInstance().getPXMaterialPtrWithMaterialID(0));
physx::PxBoxControllerDesc boxDesc;
boxDesc.halfHeight = _mHalfSideExtent;
boxDesc.halfSideExtent = _mHalfSideExtent;
boxDesc.halfForwardExtent = _mHalfForwardExtent;
boxDesc.density = 10.0;
boxDesc.scaleCoeff = 0.8;
boxDesc.volumeGrowth = 1.5;
boxDesc.contactOffset = fmaxf(0.f, _mContactOffset);
boxDesc.stepOffset = _mStepOffset;
boxDesc.slopeLimit = cos(_mSlopeLimit * mathutils::D2R);
boxDesc.upDirection = physx::PxVec3(0, 1, 0);
//node is at capsule's center
Vec3 worldPos = _mNode->getWorldPosition();
worldPos += scaledCenter();
boxDesc.position = physx::PxExtendedVec3(worldPos.x, worldPos.y, worldPos.z);
boxDesc.material = pxMtl;
boxDesc.userData = this;
boxDesc.reportCallback = &report;
_impl = static_cast<physx::PxBoxController*>(controllerManager.createController(boxDesc));
updateScale();
insertToCCTMap();
updateFilterData();
}
void PhysXBoxCharacterController::updateScale(){
updateGeometry();
}
void PhysXBoxCharacterController::updateGeometry(){
if(!_impl) return;
auto *node = _mNode;
node->updateWorldTransform();
float s = _mHalfSideExtent * physx::PxAbs(node->getWorldScale().x);
float h = _mHalfHeight * physx::PxAbs(node->getWorldScale().y);
float f = _mHalfForwardExtent * physx::PxAbs(node->getWorldScale().z);
static_cast<physx::PxBoxController*>(_impl)->setHalfSideExtent(physx::PxMax(s, PX_NORMALIZATION_EPSILON));
static_cast<physx::PxBoxController*>(_impl)->setHalfHeight(physx::PxMax(h, PX_NORMALIZATION_EPSILON));
static_cast<physx::PxBoxController*>(_impl)->setHalfForwardExtent(physx::PxMax(f, PX_NORMALIZATION_EPSILON));
}
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,54 @@
/****************************************************************************
Copyright (c) 2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "physics/physx/character-controllers/PhysXCharacterController.h"
namespace cc {
namespace physics {
class PhysXBoxCharacterController final : public PhysXCharacterController, public IBoxCharacterController {
public:
PhysXBoxCharacterController();
~PhysXBoxCharacterController() override = default;
// IBoxCharacterController
void setHalfHeight(float v) override;
void setHalfSideExtent(float v) override;
void setHalfForwardExtent(float v) override;
// IBoxCharacterController END
private:
float _mHalfHeight;
float _mHalfSideExtent;
float _mHalfForwardExtent;
void create() override;
void onComponentSet() override;
void updateScale() override;
void updateGeometry();
};
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,97 @@
/****************************************************************************
Copyright (c) 2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "physics/physx/character-controllers/PhysXCapsuleCharacterController.h"
#include "physics/physx/PhysXUtils.h"
#include "physics/physx/PhysXWorld.h"
#include "math/Utils.h"
namespace cc {
namespace physics {
PhysXCapsuleCharacterController::PhysXCapsuleCharacterController() :
_mRadius(0.5F), _mHeight(1.0F) {
}
void PhysXCapsuleCharacterController::setRadius(float v) {
_mRadius = v;
updateScale();
}
void PhysXCapsuleCharacterController::setHeight(float v) {
_mHeight = v;
updateScale();
}
void PhysXCapsuleCharacterController::onComponentSet() {
create();
}
void PhysXCapsuleCharacterController::create() {
release();
physx::PxControllerManager& controllerManager = PhysXWorld::getInstance().getControllerManager();
auto pxMtl = reinterpret_cast<physx::PxMaterial *>(PhysXWorld::getInstance().getPXMaterialPtrWithMaterialID(0));
physx::PxCapsuleControllerDesc capsuleDesc;
capsuleDesc.height = _mHeight;
capsuleDesc.radius = _mRadius;
capsuleDesc.climbingMode = physx::PxCapsuleClimbingMode::eCONSTRAINED;
capsuleDesc.density = 10.0;
capsuleDesc.scaleCoeff = 0.8;
capsuleDesc.volumeGrowth = 1.5;
capsuleDesc.contactOffset = fmaxf(0.f, _mContactOffset);
capsuleDesc.stepOffset = _mStepOffset;
capsuleDesc.slopeLimit = cos(_mSlopeLimit * mathutils::D2R);
capsuleDesc.upDirection = physx::PxVec3(0, 1, 0);
//node is at capsule's center
Vec3 worldPos = _mNode->getWorldPosition();
worldPos += scaledCenter();
capsuleDesc.position = physx::PxExtendedVec3(worldPos.x, worldPos.y, worldPos.z);
capsuleDesc.material = pxMtl;
capsuleDesc.userData = this;
capsuleDesc.reportCallback = &report;
_impl = static_cast<physx::PxCapsuleController*>(controllerManager.createController(capsuleDesc));
updateScale();
insertToCCTMap();
updateFilterData();
}
void PhysXCapsuleCharacterController::updateScale(){
updateGeometry();
}
void PhysXCapsuleCharacterController::updateGeometry() {
if(!_impl) return;
auto *node = _mNode;
node->updateWorldTransform();
float r = _mRadius * pxAbsMax(node->getWorldScale().x, node->getWorldScale().z);
float h = _mHeight * physx::PxAbs(node->getWorldScale().y);
static_cast<physx::PxCapsuleController*>(_impl)->setRadius(physx::PxMax(r, PX_NORMALIZATION_EPSILON));
static_cast<physx::PxCapsuleController*>(_impl)->setHeight(physx::PxMax(h, PX_NORMALIZATION_EPSILON));
}
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,52 @@
/****************************************************************************
Copyright (c) 2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "physics/physx/character-controllers/PhysXCharacterController.h"
namespace cc {
namespace physics {
class PhysXCapsuleCharacterController final : public PhysXCharacterController, public ICapsuleCharacterController {
public:
PhysXCapsuleCharacterController();
~PhysXCapsuleCharacterController() override = default;
// ICapsuleCharacterController
void setRadius(float v) override;
void setHeight(float v) override;
// ICapsuleCharacterController END
private:
float _mRadius;
float _mHeight;
void create() override;
void onComponentSet() override;
void updateScale() override;
void updateGeometry();
};
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,288 @@
/****************************************************************************
Copyright (c) 2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "physics/physx/character-controllers/PhysXCharacterController.h"
#include "base/std/container/unordered_map.h"
#include "physics/physx/shapes/PhysXShape.h"
#include "physics/physx/PhysXUtils.h"
#include "physics/physx/PhysXWorld.h"
namespace cc {
namespace physics {
//PxShape --> PhysXShape
static PhysXShape* convertPxShape2PhysXShape(physx::PxShape* shape) {
//PxShape --> PhysXShape ID
const auto& hitShape = getPxShapeMap().find(reinterpret_cast<uintptr_t>(shape));
if (hitShape == getPxShapeMap().end()) {
return nullptr;
}
//PhysXShape ID --> PhysXShape pointer
uintptr_t wrapperPtrShape = PhysXWorld::getInstance().getWrapperPtrWithObjectID(hitShape->second);
if (wrapperPtrShape == 0) {
return nullptr;
}
return reinterpret_cast<PhysXShape*>(wrapperPtrShape);
}
void ControllerHitReport::onShapeHit(const physx::PxControllerShapeHit& hit) {
const auto& hitShape = getPxShapeMap().find(reinterpret_cast<uintptr_t>(hit.shape));
assert(hitShape!= getPxShapeMap().end());
uint32_t shapeObjectID = hitShape->second;
const auto& cct = getPxCCTMap().find(reinterpret_cast<uintptr_t>(hit.controller));
assert(cct != getPxCCTMap().end());
uint32_t cctObjectID = cct->second;
CharacterControllerContact contact;
contact.worldPosition = cc::Vec3(hit.worldPos.x, hit.worldPos.y, hit.worldPos.z);
contact.worldNormal = cc::Vec3(hit.worldNormal.x, hit.worldNormal.y, hit.worldNormal.z);
contact.motionDirection = cc::Vec3(hit.dir.x, hit.dir.y, hit.dir.z);
contact.motionLength = hit.length;
std::shared_ptr<CCTShapeEventPair> pair = std::make_shared<CCTShapeEventPair>(cctObjectID, shapeObjectID);
pair->contacts.push_back(contact);
auto& pairs = PhysXWorld::getInstance().getCCTShapeEventPairs();
pairs.push_back(pair);
}
void ControllerHitReport::onControllerHit(const physx::PxControllersHit& hit) {
}
void ControllerHitReport::onObstacleHit(const physx::PxControllerObstacleHit& hit) {
}
physx::PxQueryHitType::Enum QueryFilterCallback::preFilter(const physx::PxFilterData& filterData,
const physx::PxShape* shape, const physx::PxRigidActor* actor, physx::PxHitFlags& queryFlags) {
//PxShape --> PhysXShape ID
const auto &hitShape = getPxShapeMap().find(reinterpret_cast<uintptr_t>(shape));
if (hitShape == getPxShapeMap().end()) {
return physx::PxQueryHitType::eNONE;
}
//PhysXShape ID --> PhysXShape pointer
uintptr_t wrapperPtrShape = PhysXWorld::getInstance().getWrapperPtrWithObjectID(hitShape->second);
if(wrapperPtrShape == 0){
return physx::PxQueryHitType::eNONE;
}
PhysXShape* wrapperShape = reinterpret_cast<PhysXShape*>(wrapperPtrShape);
if (!(filterData.word0 & wrapperShape->getMask()) || !(filterData.word1 & wrapperShape->getGroup())) {
return physx::PxQueryHitType::eNONE;
}
return physx::PxQueryHitType::eBLOCK;
}
physx::PxQueryHitType::Enum QueryFilterCallback::postFilter(const physx::PxFilterData& filterData, const physx::PxQueryHit& hit){
PX_UNUSED(filterData);
PX_UNUSED(hit);
return physx::PxQueryHitType::eNONE;
}
PhysXCharacterController::PhysXCharacterController() {
_mObjectID = PhysXWorld::getInstance().addWrapperObject(reinterpret_cast<uintptr_t>(this));
_mFilterData = physx::PxFilterData(1, 1, 1, 0 );
};
void PhysXCharacterController::release() {
eraseFromCCTMap();
if(_impl){
_impl->release();
_impl = nullptr;
}
}
bool PhysXCharacterController::initialize(Node *node) {
_mNode = node;
onComponentSet();
if (_impl == nullptr) {
return false;
} else {
PhysXWorld::getInstance().addCCT(*this);
return true;
}
}
void PhysXCharacterController::onEnable() {
_mEnabled = true;
}
void PhysXCharacterController::onDisable() {
_mEnabled = false;
}
void PhysXCharacterController::onDestroy() {
release();
PhysXWorld::getInstance().removeCCT(*this);
PhysXWorld::getInstance().removeWrapperObject(_mObjectID);
}
cc::Vec3 PhysXCharacterController::getPosition() {
const physx::PxExtendedVec3& pos = _impl->getPosition();
cc::Vec3 cv(pos.x, pos.y, pos.z);
return cv;
}
void PhysXCharacterController::setPosition(float x, float y, float z) {
_impl->setPosition(physx::PxExtendedVec3{x, y, z});
}
bool PhysXCharacterController::onGround() {
return (_pxCollisionFlags & physx::PxControllerCollisionFlag::Enum::eCOLLISION_DOWN);
}
void PhysXCharacterController::syncSceneToPhysics() {
uint32_t getChangedFlags = _mNode->getChangedFlags();
if (getChangedFlags & static_cast<uint32_t>(TransformBit::SCALE)) syncScale();
//teleport
if (getChangedFlags & static_cast<uint32_t>(TransformBit::POSITION)) {
const auto & cctPos = _mNode->getWorldPosition() + scaledCenter();
setPosition(cctPos.x, cctPos.y, cctPos.z);
}
}
void PhysXCharacterController::syncScale () {
updateScale();
}
//move
void PhysXCharacterController::move(float x, float y, float z, float minDist, float elapsedTime) {
physx::PxVec3 disp{x, y, z};
controllerFilter.mFilterData = &_mFilterData;
controllerFilter.mFilterCallback = &_mFilterCallback;
PhysXWorld::getInstance().getControllerManager().setOverlapRecoveryModule(_mOverlapRecovery);
_pxCollisionFlags = _impl->move(disp, minDist, elapsedTime, controllerFilter);
}
void PhysXCharacterController::setStepOffset(float v) {
_mStepOffset = v;
_impl->setStepOffset(v);
}
float PhysXCharacterController::getStepOffset() {
return _mStepOffset;
}
void PhysXCharacterController::setSlopeLimit(float v) {
_mSlopeLimit = v;
_impl->setSlopeLimit(cos(_mSlopeLimit * mathutils::D2R));
}
float PhysXCharacterController::getSlopeLimit() {
return _mSlopeLimit;
}
void PhysXCharacterController::setContactOffset(float v) {
_mContactOffset = v;
_impl->setContactOffset(v);
}
float PhysXCharacterController::getContactOffset() {
return _mContactOffset;
}
void PhysXCharacterController::setDetectCollisions(bool v) {
physx::PxRigidDynamic* actor = _impl->getActor();
physx::PxShape* shape;
actor->getShapes(&shape, 1);
shape->setFlag(physx::PxShapeFlag::eSIMULATION_SHAPE, v);
}
void PhysXCharacterController::setOverlapRecovery(bool v) {
_mOverlapRecovery = v;
}
void PhysXCharacterController::setCenter(float x, float y, float z){
_mCenter = Vec3(x, y, z);
}
uint32_t PhysXCharacterController::getGroup() {
return _mFilterData.word0;
}
void PhysXCharacterController::setGroup(uint32_t g) {
_mFilterData.word0 = g;
updateFilterData();
}
uint32_t PhysXCharacterController::getMask() {
return _mFilterData.word1;
}
void PhysXCharacterController::setMask(uint32_t m) {
_mFilterData.word1 = m;
updateFilterData();
}
void PhysXCharacterController::updateEventListener(EShapeFilterFlag flag) {
_mFilterData.word3 |= physx::PxU32(flag);
updateFilterData();
}
void PhysXCharacterController::updateFilterData() {
setSimulationFilterData(_mFilterData);
}
void PhysXCharacterController::setSimulationFilterData(physx::PxFilterData filterData) {
physx::PxRigidDynamic* actor = _impl->getActor();
physx::PxShape* shape;
actor->getShapes(&shape, 1);
shape->setSimulationFilterData(filterData);
}
void PhysXCharacterController::syncPhysicsToScene() {
_mNode->setWorldPosition(getPosition() - scaledCenter());
}
void PhysXCharacterController::insertToCCTMap() {
if (_impl) {
getPxCCTMap().insert(std::pair<uintptr_t, uint32_t>(reinterpret_cast<uintptr_t>(_impl), getObjectID()));
getPxCCTMap().insert(std::pair<uintptr_t, uint32_t>(reinterpret_cast<uintptr_t>(getShape()), getObjectID()));
}
}
void PhysXCharacterController::eraseFromCCTMap() {
if (_impl) {
getPxCCTMap().erase(reinterpret_cast<uintptr_t>(_impl));
getPxCCTMap().erase(reinterpret_cast<uintptr_t>(getShape()));
}
}
cc::Vec3 PhysXCharacterController::scaledCenter() {
return _mNode->getWorldScale() * _mCenter;
}
physx::PxShape* PhysXCharacterController::getShape() {
if (_impl) {
//cct's shape
physx::PxRigidDynamic* actor = _impl->getActor();
physx::PxShape* shape;
actor->getShapes(&shape, 1);
return shape;
}
return nullptr;
}
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,123 @@
/****************************************************************************
Copyright (c) 2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "base/Macros.h"
#include "core/scene-graph/Node.h"
#include "physics/physx/PhysXInc.h"
#include "physics/spec/ICharacterController.h"
namespace cc {
namespace physics {
class ControllerHitReport : public physx::PxUserControllerHitReport {
public:
virtual void onShapeHit(const physx::PxControllerShapeHit& hit) override;
virtual void onControllerHit(const physx::PxControllersHit& hit) override;
virtual void onObstacleHit(const physx::PxControllerObstacleHit& hit) override;
};
class QueryFilterCallback : public physx::PxQueryFilterCallback {
public:
virtual physx::PxQueryHitType::Enum preFilter(const physx::PxFilterData& filterData, const physx::PxShape* shape,
const physx::PxRigidActor* actor, physx::PxHitFlags& queryFlags) override;
virtual physx::PxQueryHitType::Enum postFilter(const physx::PxFilterData& filterData, const physx::PxQueryHit& hit) override;
};
class PhysXCharacterController : virtual public IBaseCharacterController {
PX_NOCOPY(PhysXCharacterController)
PhysXCharacterController();
public:
~PhysXCharacterController() override = default;
void syncScale();
void syncSceneToPhysics();
virtual void syncPhysicsToScene() override;
//ILifecycle
void onEnable() override;
void onDisable() override;
void onDestroy() override;
//ILifecycle END
//ICharacterController
bool initialize(Node* node) override;
virtual cc::Vec3 getPosition() override;
virtual void setPosition(float x, float y, float z) override;
virtual bool onGround() override;
virtual void move(float x, float y, float z, float minDist, float elapsedTime) override;
virtual void setStepOffset(float v) override;
virtual float getStepOffset() override;
virtual void setSlopeLimit(float v) override;
virtual float getSlopeLimit() override;
virtual void setContactOffset(float v) override;
virtual float getContactOffset() override;
virtual void setDetectCollisions(bool v) override;
virtual void setOverlapRecovery(bool v) override;
virtual void setCenter(float x, float y, float z) override;
uint32_t getGroup() override;
void setGroup(uint32_t g) override;
uint32_t getMask() override;
void setMask(uint32_t m) override;
void updateEventListener(EShapeFilterFlag flag) override;
uint32_t getObjectID() const override { return _mObjectID; };
//ICharacterController END
inline physx::PxController& getCCT() { return *_impl; };
protected:
physx::PxController* _impl{ nullptr };
uint8_t _mFlag{ 0 };
bool _mEnabled{ false };
uint32_t _mObjectID{ 0 };
Node* _mNode{ nullptr };
physx::PxFilterData _mFilterData;
ControllerHitReport report;
QueryFilterCallback _mFilterCallback;
physx::PxControllerFilters controllerFilter;
physx::PxControllerCollisionFlags _pxCollisionFlags;
bool _mOverlapRecovery{ true };
float _mContactOffset{ 0.01f };
float _mStepOffset{ 1.f };
float _mSlopeLimit{ 45.f };
cc::Vec3 _mCenter{ 0.f, 0.f, 0.f };
void release();
void updateFilterData();
void setSimulationFilterData(physx::PxFilterData filterData);
virtual void create() = 0;
virtual void onComponentSet() = 0;
virtual void updateScale() = 0;
void insertToCCTMap();
void eraseFromCCTMap();
cc::Vec3 scaledCenter();
physx::PxShape* getShape();
};
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,83 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "physics/physx/joints/PhysXFixedJoint.h"
#include "math/Quaternion.h"
#include "physics/physx/PhysXSharedBody.h"
#include "physics/physx/PhysXUtils.h"
namespace cc {
namespace physics {
void PhysXFixedJoint::onComponentSet() {
_transA = physx::PxTransform(physx::PxIdentity);
_transB = physx::PxTransform(physx::PxIdentity);
physx::PxRigidActor *actor0 = _mSharedBody->getImpl().rigidActor;
physx::PxRigidActor *actor1 = nullptr;
if (_mConnectedBody) {
actor1 = _mConnectedBody->getImpl().rigidActor;
}
_mJoint = PxFixedJointCreate(PxGetPhysics(), actor0, _transA, actor1, _transB);
updatePose();
setEnableDebugVisualization(true);
}
void PhysXFixedJoint::setBreakForce(float force) {
_breakForce = force;
_mJoint->setBreakForce(_breakForce, _breakTorque);
}
void PhysXFixedJoint::setBreakTorque(float torque) {
_breakTorque = torque;
_mJoint->setBreakForce(_breakForce, _breakTorque);
}
void PhysXFixedJoint::updateScale0() {
updatePose();
}
void PhysXFixedJoint::updateScale1() {
updatePose();
}
void PhysXFixedJoint::updatePose() {
_transA = physx::PxTransform(physx::PxIdentity);
_transB = physx::PxTransform(physx::PxIdentity);
pxSetVec3Ext(_transA.p, _mSharedBody->getNode()->getWorldPosition());
pxSetQuatExt(_transA.q, _mSharedBody->getNode()->getWorldRotation());
if (_mConnectedBody) {
pxSetVec3Ext(_transB.p, _mConnectedBody->getNode()->getWorldPosition());
pxSetQuatExt(_transB.q, _mConnectedBody->getNode()->getWorldRotation());
}
_mJoint->setLocalPose(physx::PxJointActorIndex::eACTOR0, _transA.getInverse());
_mJoint->setLocalPose(physx::PxJointActorIndex::eACTOR1, _transB.getInverse());
}
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,53 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "physics/physx/joints/PhysXJoint.h"
namespace cc {
namespace physics {
class PhysXFixedJoint final : public PhysXJoint, public IFixedJoint {
public:
PhysXFixedJoint() {}
~PhysXFixedJoint() override = default;
void setBreakForce(float force) override;
void setBreakTorque(float torque) override;
void updateScale0() override;
void updateScale1() override;
private:
void onComponentSet() override;
void updatePose();
float _breakForce = 0.0F;
float _breakTorque = 0.0F;
physx::PxTransform _transA;
physx::PxTransform _transB;
};
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,508 @@
/****************************************************************************
Copyright (c) 2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "physics/physx/joints/PhysXGenericJoint.h"
#include <physics/sdk/Joint.h>
#include "math/Mat4.h"
#include "math/Quaternion.h"
#include "math/Utils.h"
#include "math/Vec3.h"
#include "physics/physx/PhysXSharedBody.h"
#include "physics/physx/PhysXUtils.h"
namespace cc {
namespace physics {
void PhysXGenericJoint::onComponentSet() {
_mJoint = PxD6JointCreate(PxGetPhysics(), &getTempRigidActor(), physx::PxTransform{physx::PxIdentity}, nullptr, physx::PxTransform{physx::PxIdentity});
setEnableDebugVisualization(true);
}
inline auto mapAxis(uint32_t index) -> physx::PxD6Axis::Enum {
switch (index) {
case 0:
return physx::PxD6Axis::Enum::eX;
case 1:
return physx::PxD6Axis::Enum::eY;
case 2:
return physx::PxD6Axis::Enum::eZ;
case 3:
return physx::PxD6Axis::Enum::eTWIST;
case 4:
return physx::PxD6Axis::Enum::eSWING1;
case 5:
return physx::PxD6Axis::Enum::eSWING2;
default:
assert(false && "unsupported axis");
return physx::PxD6Axis::Enum::eX;
}
}
void PhysXGenericJoint::setConstraintMode(uint32_t index, uint32_t mode) {
physx::PxD6Axis::Enum axis{mapAxis(index)};
physx::PxD6Motion::Enum motion{};
switch (mode) {
case 0:
motion = physx::PxD6Motion::Enum::eFREE;
break;
case 1:
motion = physx::PxD6Motion::Enum::eLIMITED;
break;
case 2:
motion = physx::PxD6Motion::Enum::eLOCKED;
break;
default:
motion = physx::PxD6Motion::Enum::eFREE;
break;
}
switch (index) {
case 0:
_linearLimit.x = motion;
break;
case 1:
_linearLimit.y = motion;
break;
case 2:
_linearLimit.z = motion;
break;
case 3:
_angularLimit.eTwist = motion;
break;
case 4:
case 5:
_angularLimit.eSwing = motion;
break;
default:
break;
}
auto* _joint{static_cast<physx::PxD6Joint*>(_mJoint)};
_joint->setMotion(axis, motion);
}
void PhysXGenericJoint::setLinearLimit(uint32_t index, float lower, float upper) {
assert(index < 3); // linear index should be 1, 2, or 3
_linearLimit.lower[index] = lower;
_linearLimit.upper[index] = upper;
updateLinearLimit();
}
void PhysXGenericJoint::setAngularExtent(float twist, float swing1, float swing2) {
_angularLimit.twistExtent = mathutils::toRadian(std::fmax(twist, 1e-9));
_angularLimit.swing1Extent = mathutils::toRadian(std::fmax(swing1, 1e-9));
_angularLimit.swing2Extent = mathutils::toRadian(std::fmax(swing2, 1e-9));
updateTwistLimit();
updateSwingLimit();
}
void PhysXGenericJoint::setLinearSoftConstraint(bool enable) {
_linearLimit.soft = enable;
updateLinearLimit();
}
void PhysXGenericJoint::setLinearStiffness(float stiffness) {
_linearLimit.stiffness = stiffness;
updateLinearLimit();
}
void PhysXGenericJoint::setLinearDamping(float damping) {
_linearLimit.damping = damping;
updateLinearLimit();
}
void PhysXGenericJoint::setLinearRestitution(float restitution) {
_linearLimit.restitution = restitution;
updateLinearLimit();
}
void PhysXGenericJoint::setSwingSoftConstraint(bool enable) {
_angularLimit.swingSoft = enable;
updateSwingLimit();
}
void PhysXGenericJoint::setSwingStiffness(float stiffness) {
_angularLimit.swingStiffness = stiffness;
updateSwingLimit();
}
void PhysXGenericJoint::setSwingDamping(float damping) {
_angularLimit.swingDamping = damping;
updateSwingLimit();
}
void PhysXGenericJoint::setSwingRestitution(float restitution) {
_angularLimit.swingRestitution = restitution;
updateSwingLimit();
}
void PhysXGenericJoint::setTwistSoftConstraint(bool enable) {
_angularLimit.twistSoft = enable;
updateTwistLimit();
}
void PhysXGenericJoint::setTwistStiffness(float stiffness) {
_angularLimit.twistStiffness = stiffness;
updateTwistLimit();
}
void PhysXGenericJoint::setTwistDamping(float damping) {
_angularLimit.twistDamping = damping;
updateTwistLimit();
}
void PhysXGenericJoint::setTwistRestitution(float restitution) {
_angularLimit.twistRestitution = restitution;
updateTwistLimit();
}
void PhysXGenericJoint::setDriverMode(uint32_t index, uint32_t mode) {
switch (index) {
case 0:
_linearMotor.xDrive = mode;
break;
case 1:
_linearMotor.yDrive = mode;
break;
case 2:
_linearMotor.zDrive = mode;
break;
case 3:
_angularMotor.twistDrive = mode;
break;
case 4:
_angularMotor.swingDrive1 = mode;
break;
case 5:
_angularMotor.swingDrive2 = mode;
break;
default:
break;
}
this->updateDrive(index);
}
void PhysXGenericJoint::setLinearMotorTarget(float x, float y, float z) {
auto& p = _linearMotor.target;
p.x = x;
p.y = y;
p.z = z;
this->updateDrivePosition();
}
void PhysXGenericJoint::setLinearMotorVelocity(float x, float y, float z) {
auto& v = _linearMotor.velocity;
v.x = x;
v.y = y;
v.z = z;
this->updateDriveVelocity();
}
void PhysXGenericJoint::setLinearMotorForceLimit(float limit) {
_linearMotor.forceLimit = limit;
updateDrive(0);
updateDrive(1);
updateDrive(2);
}
void PhysXGenericJoint::setAngularMotorTarget(float x, float y, float z) {
auto& p = _angularMotor.target;
p.x = x;
p.y = y;
p.z = z;
this->updateDrivePosition();
}
void PhysXGenericJoint::setAngularMotorVelocity(float x, float y, float z) {
auto& v = _angularMotor.velocity;
v.x = -mathutils::toRadian(x);
v.y = -mathutils::toRadian(y);
v.z = -mathutils::toRadian(z);
this->updateDriveVelocity();
}
void PhysXGenericJoint::setAngularMotorForceLimit(float limit) {
_angularMotor.forceLimit = limit;
this->updateDrive(3);
this->updateDrive(4);
this->updateDrive(5);
}
void PhysXGenericJoint::setPivotA(float x, float y, float z) {
_mPivotA.x = x;
_mPivotA.y = y;
_mPivotA.z = z;
updatePose();
}
void PhysXGenericJoint::setPivotB(float x, float y, float z) {
_mPivotB.x = x;
_mPivotB.y = y;
_mPivotB.z = z;
updatePose();
}
void PhysXGenericJoint::setAutoPivotB(bool autoPivot) {
_mAutoPivotB = autoPivot;
updatePose();
}
void PhysXGenericJoint::setAxis(float x, float y, float z) {
_mAxis.x = x;
_mAxis.y = y;
_mAxis.z = z;
updatePose();
}
void PhysXGenericJoint::setSecondaryAxis(float x, float y, float z) {
_mSecondary.x = x;
_mSecondary.y = y;
_mSecondary.z = z;
updatePose();
}
void PhysXGenericJoint::setBreakForce(float force) {
_breakForce = force;
physx::PxD6Joint* joint{static_cast<physx::PxD6Joint*>(_mJoint)};
joint->getBreakForce(_breakForce, _breakTorque);
}
void PhysXGenericJoint::setBreakTorque(float torque) {
_breakTorque = torque;
physx::PxD6Joint* joint{static_cast<physx::PxD6Joint*>(_mJoint)};
joint->getBreakForce(_breakForce, _breakTorque);
}
void PhysXGenericJoint::updateScale0() {
this->updatePose();
}
void PhysXGenericJoint::updateScale1() {
this->updatePose();
}
void PhysXGenericJoint::updateLinearLimit() {
physx::PxD6Joint* joint{static_cast<physx::PxD6Joint*>(_mJoint)};
const auto lower = _linearLimit.lower;
const auto upper = _linearLimit.upper;
auto limitx = joint->getLinearLimit(physx::PxD6Axis::Enum::eX);
auto limity = joint->getLinearLimit(physx::PxD6Axis::Enum::eY);
auto limitz = joint->getLinearLimit(physx::PxD6Axis::Enum::eZ);
if (_linearLimit.soft) {
limitx.stiffness = _linearLimit.stiffness;
limitx.damping = _linearLimit.damping;
} else {
limitx.stiffness = 0.0;
limitx.damping = 0.0;
}
limitx.contactDistance = 0.1;
limitx.bounceThreshold = 0.1;
limitx.restitution = _linearLimit.restitution;
limity = limitx;
limitz = limitx;
if (_linearLimit.x == physx::PxD6Motion::Enum::eLIMITED) {
limitx.upper = upper[0];
limitx.lower = lower[0];
joint->setLinearLimit(physx::PxD6Axis::Enum::eX, limitx);
}
if (_linearLimit.y == physx::PxD6Motion::Enum::eLIMITED) {
limity.upper = upper[1];
limity.lower = lower[1];
joint->setLinearLimit(physx::PxD6Axis::Enum::eY, limity);
}
if (_linearLimit.z == physx::PxD6Motion::Enum::eLIMITED) {
limitz.upper = upper[2];
limitz.lower = lower[2];
joint->setLinearLimit(physx::PxD6Axis::Enum::eZ, limitz);
}
}
void PhysXGenericJoint::updateSwingLimit() {
if (_angularLimit.eSwing != physx::PxD6Motion::Enum::eLIMITED) {
return;
}
physx::PxD6Joint* joint{static_cast<physx::PxD6Joint*>(_mJoint)};
auto coneLimit = joint->getSwingLimit();
if (_angularLimit.swingSoft) {
coneLimit.stiffness = _angularLimit.swingStiffness;
coneLimit.damping = _angularLimit.swingDamping;
} else {
coneLimit.stiffness = 0;
coneLimit.damping = 0;
}
coneLimit.bounceThreshold = 0.1;
coneLimit.contactDistance = 0.1;
coneLimit.restitution = _angularLimit.swingRestitution;
coneLimit.yAngle = math::PI;
coneLimit.zAngle = math::PI;
if (_angularLimit.eSwing == 1) {
coneLimit.yAngle = _angularLimit.swing1Extent * 0.5;
coneLimit.zAngle = _angularLimit.swing2Extent * 0.5;
joint->setSwingLimit(coneLimit);
}
}
void PhysXGenericJoint::updateTwistLimit() {
if (_angularLimit.eTwist != physx::PxD6Motion::Enum::eLIMITED) {
return;
}
physx::PxD6Joint* joint{static_cast<physx::PxD6Joint*>(_mJoint)};
auto twistLimit = joint->getTwistLimit();
twistLimit.bounceThreshold = 0.1;
twistLimit.contactDistance = 0.1;
twistLimit.restitution = _angularLimit.twistRestitution;
if (_angularLimit.twistSoft) {
twistLimit.stiffness = _angularLimit.twistStiffness;
twistLimit.damping = _angularLimit.twistDamping;
} else {
twistLimit.damping = 0;
twistLimit.stiffness = _angularLimit.twistStiffness;
}
if (_angularLimit.eTwist == 1) {
twistLimit.lower = _angularLimit.twistExtent * -0.5;
twistLimit.upper = _angularLimit.twistExtent * 0.5;
joint->setTwistLimit(twistLimit);
}
}
void PhysXGenericJoint::updateDrive(uint32_t axis) {
assert(axis < 6 && "axis should be in [0, 5]");
physx::PxD6Joint* joint{static_cast<physx::PxD6Joint*>(_mJoint)};
auto drive = joint->getDrive(static_cast<physx::PxD6Drive::Enum>(axis));
uint32_t mode = 0;
physx::PxD6Drive::Enum driveAxis = physx::PxD6Drive::Enum::eX;
switch (axis) {
case 0:
mode = _linearMotor.xDrive;
driveAxis = physx::PxD6Drive::Enum::eX;
break;
case 1:
mode = _linearMotor.yDrive;
driveAxis = physx::PxD6Drive::Enum::eY;
break;
case 2:
mode = _linearMotor.zDrive;
driveAxis = physx::PxD6Drive::Enum::eZ;
break;
case 3:
mode = _angularMotor.twistDrive;
driveAxis = physx::PxD6Drive::Enum::eTWIST;
break;
case 4:
case 5:
if (_angularMotor.swingDrive1 == 2 || _angularMotor.swingDrive2 == 2) {
mode = 2;
} else if (_angularMotor.swingDrive1 == 1 || _angularMotor.swingDrive2 == 1) {
mode = 1;
} else {
mode = 0;
}
driveAxis = physx::PxD6Drive::Enum::eSWING;
break;
default:
break;
};
if (axis < 3) {
drive.forceLimit = _linearMotor.forceLimit;
} else if (axis == 3) {
drive.forceLimit = _angularMotor.forceLimit;
} else if (axis < 6) {
drive.forceLimit = _angularMotor.forceLimit;
}
if (mode == 0) { // disabled
drive.forceLimit = 0;
} else if (mode == 1) { // servo
drive.damping = 0.0;
drive.stiffness = 1000.0;
} else if (mode == 2) { // induction
drive.damping = 1000.0;
drive.stiffness = 0.0;
}
joint->setDrive(driveAxis, drive);
}
void PhysXGenericJoint::updateDrivePosition() {
physx::PxD6Joint* joint{static_cast<physx::PxD6Joint*>(_mJoint)};
physx::PxTransform trans{};
const auto& ld = _linearMotor.target;
const auto& ad = _angularMotor.target;
Quaternion quat;
Quaternion::fromEuler(ad.x, ad.y, ad.z, &quat);
pxSetVec3Ext(trans.p, Vec3(ld.x, ld.y, ld.z));
pxSetQuatExt(trans.q, quat);
joint->setDrivePosition(trans, true);
}
void PhysXGenericJoint::updateDriveVelocity() {
physx::PxD6Joint* joint{static_cast<physx::PxD6Joint*>(_mJoint)};
joint->setDriveVelocity(_linearMotor.velocity, _angularMotor.velocity, true);
}
void PhysXGenericJoint::updatePose() {
physx::PxTransform pose0{physx::PxIdentity};
physx::PxTransform pose1{physx::PxIdentity};
auto* node0 = _mSharedBody->getNode();
node0->updateWorldTransform();
_mTertiary = _mAxis.cross(_mSecondary);
Mat4 transform(
_mAxis.x, _mAxis.y, _mAxis.z, 0.F,
_mSecondary.x, _mSecondary.y, _mSecondary.z, 0.F,
_mTertiary.x, _mTertiary.y, _mTertiary.z, 0.F,
0.F, 0.F, 0.F, 1.F);
Quaternion quat{transform};
pose0.q = physx::PxQuat{quat.x, quat.y, quat.z, quat.w};
Vec3 pos = Vec3(_mPivotA.x, _mPivotA.y, _mPivotA.z) * node0->getWorldScale();
pose0.p = physx::PxVec3{pos.x, pos.y, pos.z};
_mJoint->setLocalPose(physx::PxJointActorIndex::eACTOR0, pose0);
if (_mConnectedBody) {
auto* node1 = _mConnectedBody->getNode();
node1->updateWorldTransform();
const auto& rot_1_i = node1->getWorldRotation().getInversed();
if (_mAutoPivotB) {
pos.transformQuat(node0->getWorldRotation());
pos += node0->getWorldPosition();
pos -= node1->getWorldPosition();
pos.transformQuat(rot_1_i);
pxSetVec3Ext(pose1.p, pos);
} else {
pose1.p = _mPivotB * node1->getWorldScale();
}
Quaternion::multiply(node0->getWorldRotation(), quat, &quat);
Quaternion::multiply(rot_1_i, quat, &quat);
pxSetQuatExt(pose1.q, quat);
} else {
pos.transformQuat(node0->getWorldRotation());
pos += node0->getWorldPosition();
Quaternion::multiply(node0->getWorldRotation(), quat, &quat);
pose1.p = physx::PxVec3{pos.x, pos.y, pos.z};
pose1.q = physx::PxQuat{quat.x, quat.y, quat.z, quat.w};
}
_mJoint->setLocalPose(physx::PxJointActorIndex::eACTOR1, pose1);
}
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,143 @@
/****************************************************************************
Copyright (c) 2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "physics/physx/joints/PhysXJoint.h"
namespace cc {
namespace physics {
class PhysXGenericJoint final : public PhysXJoint, public IGenericJoint {
public:
PhysXGenericJoint() = default;
~PhysXGenericJoint() = default;
void setConstraintMode(uint32_t index, uint32_t mode) override;
void setLinearLimit(uint32_t index, float lower, float upper) override; // linear only, angular use extent is better
void setAngularExtent(float twist, float swing1, float swing2) override;
void setLinearSoftConstraint(bool enable) override;
void setLinearStiffness(float stiffness) override;
void setLinearDamping(float damping) override;
void setLinearRestitution(float restitution) override;
// TODO (yiwenxue): add new function to set angular limit
void setSwingSoftConstraint(bool enable) override;
void setTwistSoftConstraint(bool enable) override;
void setSwingStiffness(float stiffness) override;
void setSwingDamping(float damping) override;
void setSwingRestitution(float restitution) override;
void setTwistStiffness(float stiffness) override;
void setTwistDamping(float damping) override;
void setTwistRestitution(float restitution) override;
void setDriverMode(uint32_t index, uint32_t mode) override;
void setLinearMotorTarget(float x, float y, float z) override;
void setLinearMotorVelocity(float x, float y, float z) override;
void setLinearMotorForceLimit(float limit) override;
void setAngularMotorTarget(float x, float y, float z) override;
void setAngularMotorVelocity(float x, float y, float z) override;
void setAngularMotorForceLimit(float limit) override;
void setPivotA(float x, float y, float z) override;
void setPivotB(float x, float y, float z) override;
void setAutoPivotB(bool autoPivot) override;
void setAxis(float x, float y, float z) override;
void setSecondaryAxis(float x, float y, float z) override;
void setBreakForce(float force) override;
void setBreakTorque(float torque) override;
void updateScale0() override;
void updateScale1() override;
private:
void onComponentSet() override;
void updatePose();
void updateLinearLimit();
void updateSwingLimit();
void updateTwistLimit();
void updateDrive(uint32_t axis);
void updateDrivePosition();
void updateDriveVelocity();
physx::PxVec3 _mPivotA{physx::PxZero};
physx::PxVec3 _mPivotB{physx::PxZero};
bool _mAutoPivotB{false};
physx::PxVec3 _mAxis{physx::PxZero};
physx::PxVec3 _mSecondary{physx::PxZero};
physx::PxVec3 _mTertiary{physx::PxZero};
float _breakForce{0.F};
float _breakTorque{0.F};
struct {
physx::PxD6Motion::Enum x, y, z;
float lower[3];
float upper[3];
bool soft;
float stiffness;
float damping;
float restitution;
float forceLimit;
} _linearLimit;
struct {
physx::PxD6Motion::Enum eTwist, eSwing, eSlerp;
float swing1Extent, swing2Extent, twistExtent;
bool swingSoft, twistSoft;
float swingStiffness;
float swingDamping;
float swingRestitution;
float twistStiffness;
float twistDamping;
float twistRestitution;
} _angularLimit;
struct {
uint32_t xDrive;
uint32_t yDrive;
uint32_t zDrive;
float forceLimit;
physx::PxVec3 target;
physx::PxVec3 velocity;
} _linearMotor;
struct {
uint32_t twistDrive;
uint32_t swingDrive1;
uint32_t swingDrive2;
float forceLimit;
physx::PxVec3 target;
physx::PxVec3 velocity;
} _angularMotor;
};
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,129 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "physics/physx/joints/PhysXJoint.h"
#include "physics/physx/PhysXSharedBody.h"
#include "physics/physx/PhysXUtils.h"
#include "physics/physx/PhysXWorld.h"
namespace cc {
namespace physics {
physx::PxRigidActor *PhysXJoint::tempRigidActor = nullptr;
PhysXJoint::PhysXJoint() {
_mObjectID = PhysXWorld::getInstance().addWrapperObject(reinterpret_cast<uintptr_t>(this));
};
void PhysXJoint::initialize(Node *node) {
auto &ins = PhysXWorld::getInstance();
_mSharedBody = ins.getSharedBody(node);
_mSharedBody->reference(true);
onComponentSet();
}
void PhysXJoint::onEnable() {
_mSharedBody->addJoint(*this, physx::PxJointActorIndex::eACTOR0);
if (_mConnectedBody) {
_mConnectedBody->addJoint(*this, physx::PxJointActorIndex::eACTOR1);
_mJoint->setActors(_mSharedBody->getImpl().rigidActor, _mConnectedBody->getImpl().rigidActor);
} else {
_mJoint->setActors(_mSharedBody->getImpl().rigidActor, nullptr);
}
}
void PhysXJoint::onDisable() {
_mJoint->setActors(&getTempRigidActor(), nullptr);
_mSharedBody->removeJoint(*this, physx::PxJointActorIndex::eACTOR0);
if (_mConnectedBody) _mConnectedBody->removeJoint(*this, physx::PxJointActorIndex::eACTOR1);
}
void PhysXJoint::onDestroy() {
_mSharedBody->reference(false);
PhysXWorld::getInstance().removeWrapperObject(_mObjectID);
}
void PhysXJoint::setConnectedBody(uint32_t rigidBodyID) {
PhysXRigidBody *pxRigidBody = reinterpret_cast<PhysXRigidBody *>(PhysXWorld::getInstance().getWrapperPtrWithObjectID(rigidBodyID));
if (pxRigidBody == nullptr)
return;
auto *oldConnectedBody = _mConnectedBody;
if (oldConnectedBody) {
oldConnectedBody->removeJoint(*this, physx::PxJointActorIndex::eACTOR1);
}
uintptr_t nodePtr = reinterpret_cast<uintptr_t>(pxRigidBody->getSharedBody().getNode());
if (nodePtr) {
auto &ins = PhysXWorld::getInstance();
_mConnectedBody = ins.getSharedBody(reinterpret_cast<Node *>(nodePtr));
_mConnectedBody->addJoint(*this, physx::PxJointActorIndex::eACTOR1);
} else {
_mConnectedBody = nullptr;
}
if (_mJoint) {
_mJoint->setActors(_mSharedBody->getImpl().rigidActor, _mConnectedBody ? _mConnectedBody->getImpl().rigidActor : nullptr);
}
if (oldConnectedBody) {
if (oldConnectedBody->isDynamic()) {
oldConnectedBody->getImpl().rigidDynamic->wakeUp();
}
}
updateScale0();
updateScale1();
}
void PhysXJoint::setEnableCollision(const bool v) {
_mEnableCollision = v;
if (_mJoint) {
_mJoint->setConstraintFlag(physx::PxConstraintFlag::eCOLLISION_ENABLED, _mEnableCollision);
}
}
void PhysXJoint::setEnableDebugVisualization(const bool v) {
_mEnableDebugVisualization = v;
if (_mJoint) {
_mJoint->setConstraintFlag(physx::PxConstraintFlag::eVISUALIZATION, _mEnableDebugVisualization);
}
}
physx::PxRigidActor &PhysXJoint::getTempRigidActor() {
if (!PhysXJoint::tempRigidActor) {
PhysXJoint::tempRigidActor = PxGetPhysics().createRigidDynamic(physx::PxTransform{physx::PxIdentity});
}
return *PhysXJoint::tempRigidActor;
};
void PhysXJoint::releaseTempRigidActor() {
if (PhysXJoint::tempRigidActor) {
PhysXJoint::tempRigidActor->release();
PhysXJoint::tempRigidActor = nullptr;
}
}
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,69 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "base/Macros.h"
#include "core/scene-graph/Node.h"
#include "physics/physx/PhysXInc.h"
#include "physics/spec/IJoint.h"
namespace cc {
namespace physics {
class PhysXSharedBody;
class PhysXJoint : virtual public IBaseJoint {
PX_NOCOPY(PhysXJoint)
public:
PhysXJoint();
~PhysXJoint() override = default;
void initialize(Node *node) override;
void onEnable() override;
void onDisable() override;
void onDestroy() override;
void setConnectedBody(uint32_t rigidBodyID) override;
void setEnableCollision(bool v) override;
void setEnableDebugVisualization(bool v);
virtual void updateScale0() = 0;
virtual void updateScale1() = 0;
static physx::PxRigidActor &getTempRigidActor();
static void releaseTempRigidActor();
uint32_t getObjectID() const override { return _mObjectID; };
protected:
physx::PxJoint *_mJoint{nullptr};
PhysXSharedBody *_mSharedBody{nullptr};
PhysXSharedBody *_mConnectedBody{nullptr};
bool _mEnableCollision{false};
bool _mEnableDebugVisualization{ false };
virtual void onComponentSet() = 0;
uint32_t _mObjectID{0};
private:
static physx::PxRigidActor *tempRigidActor;
};
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,181 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "physics/physx/joints/PhysXRevolute.h"
#include "math/Quaternion.h"
#include "math/Utils.h"
#include "math/Vec3.h"
#include "physics/physx/PhysXSharedBody.h"
#include "physics/physx/PhysXUtils.h"
#include "physics/physx/PhysXWorld.h"
namespace cc {
namespace physics {
void PhysXRevolute::onComponentSet() {
_mJoint = PxRevoluteJointCreate(PxGetPhysics(), &getTempRigidActor(), physx::PxTransform{physx::PxIdentity}, nullptr, physx::PxTransform{physx::PxIdentity});
_mlimit.stiffness = 0;
_mlimit.damping = 0;
_mlimit.restitution = 0.4;
_mlimit.contactDistance = 0.01;
auto *joint = static_cast<physx::PxRevoluteJoint *>(_mJoint);
joint->setConstraintFlag(physx::PxConstraintFlag::ePROJECTION, true);
joint->setConstraintFlag(physx::PxConstraintFlag::eDRIVE_LIMITS_ARE_FORCES, true);
joint->setProjectionAngularTolerance(0.2);
joint->setProjectionLinearTolerance(0.2);
setEnableDebugVisualization(true);
}
void PhysXRevolute::setPivotA(float x, float y, float z) {
_mPivotA = physx::PxVec3{x, y, z};
updatePose();
}
void PhysXRevolute::setPivotB(float x, float y, float z) {
_mPivotB = physx::PxVec3{x, y, z};
updatePose();
}
void PhysXRevolute::setAxis(float x, float y, float z) {
_mAxis = physx::PxVec3{x, y, z};
updatePose();
}
void PhysXRevolute::setLimitEnabled(bool v) {
_limitEnabled = v;
auto *joint = static_cast<physx::PxRevoluteJoint *>(_mJoint);
joint->setRevoluteJointFlag(physx::PxRevoluteJointFlag::eLIMIT_ENABLED, _limitEnabled);
if (v) {
joint->setLimit(_mlimit);
}
}
void PhysXRevolute::setLowerLimit(float v) {
_lowerLimit = v;
_mlimit.lower = mathutils::toRadian(_lowerLimit);
if (_limitEnabled) {
auto *joint = static_cast<physx::PxRevoluteJoint *>(_mJoint);
joint->setLimit(_mlimit);
}
}
void PhysXRevolute::setUpperLimit(float v) {
_upperLimit = v;
_mlimit.upper = mathutils::toRadian(_upperLimit);
if (_limitEnabled) {
auto *joint = static_cast<physx::PxRevoluteJoint *>(_mJoint);
joint->setLimit(_mlimit);
}
}
void PhysXRevolute::setMotorEnabled(bool v) {
_motorEnabled = v;
auto *joint = static_cast<physx::PxRevoluteJoint *>(_mJoint);
joint->setRevoluteJointFlag(physx::PxRevoluteJointFlag::eDRIVE_ENABLED, _motorEnabled);
if (v) {
joint->setDriveVelocity(_motorVelocity / 60.0);
joint->setDriveForceLimit(_motorForceLimit);
}
}
void PhysXRevolute::setMotorVelocity(float v) {
_motorVelocity = v;
if (_motorEnabled) {
auto *joint = static_cast<physx::PxRevoluteJoint *>(_mJoint);
joint->setDriveVelocity(_motorVelocity / 60.0);
}
}
void PhysXRevolute::setMotorForceLimit(float v) {
_motorForceLimit = v;
if (_motorEnabled) {
auto *joint = static_cast<physx::PxRevoluteJoint *>(_mJoint);
joint->setDriveForceLimit(_motorForceLimit);
}
}
void PhysXRevolute::updateScale0() {
updatePose();
}
void PhysXRevolute::updateScale1() {
updatePose();
}
void PhysXRevolute::updatePose() {
physx::PxTransform pose0{physx::PxIdentity};
physx::PxTransform pose1{physx::PxIdentity};
auto xAxis = _mAxis.getNormalized();
auto yAxis = physx::PxVec3(0, 1, 0);
auto zAxis = _mAxis.cross(yAxis);
if (zAxis.magnitude() < 0.0001) {
yAxis = physx::PxVec3(0, 0, 1).cross(xAxis);
zAxis = xAxis.cross(yAxis);
} else {
yAxis = zAxis.cross(xAxis);
}
yAxis = yAxis.getNormalized();
zAxis = zAxis.getNormalized();
Mat4 transform(
xAxis.x, xAxis.y, xAxis.z, 0,
yAxis.x, yAxis.y, yAxis.z, 0,
zAxis.x, zAxis.y, zAxis.z, 0,
0.F, 0.F, 0.F, 1.F);
auto quat = Quaternion();
transform.getRotation(&quat);
// pos and rot in with respect to bodyA
auto *node0 = _mSharedBody->getNode();
node0->updateWorldTransform();
pose0.p = _mPivotA * node0->getWorldScale();
pose0.q = physx::PxQuat(quat.x, quat.y, quat.z, quat.w);
_mJoint->setLocalPose(physx::PxJointActorIndex::eACTOR0, pose0);
if (_mConnectedBody) {
auto *node1 = _mConnectedBody->getNode();
node1->updateWorldTransform();
pose1.p = _mPivotB * node1->getWorldScale();
const auto &rot_0 = node0->getWorldRotation();
const auto &rot_1_i = node1->getWorldRotation().getInversed();
pose1.q = physx::PxQuat(rot_1_i.x, rot_1_i.y, rot_1_i.z, rot_1_i.w) * physx::PxQuat(rot_0.x, rot_0.y, rot_0.z, rot_0.w) * pose0.q;
} else {
const auto &wr = node0->getWorldRotation();
auto pos = Vec3(_mPivotA.x, _mPivotA.y, _mPivotA.z);
pos.multiply(node0->getWorldScale());
pos.transformQuat(node0->getWorldRotation());
pos.add(node0->getWorldPosition());
pose1.p = physx::PxVec3(pos.x, pos.y, pos.z);
pose1.q = physx::PxQuat{wr.x, wr.y, wr.z, wr.w} * pose0.q;
}
_mJoint->setLocalPose(physx::PxJointActorIndex::eACTOR1, pose1);
}
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,67 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "physics/physx/joints/PhysXJoint.h"
namespace cc {
namespace physics {
class PhysXRevolute final : public PhysXJoint, public IRevoluteJoint {
public:
PhysXRevolute() : _mPivotA(physx::PxZero),
_mPivotB(physx::PxZero),
_mAxis(physx::PxZero) {}
~PhysXRevolute() override = default;
void setPivotA(float x, float y, float z) override;
void setPivotB(float x, float y, float z) override;
void setAxis(float x, float y, float z) override;
void setLimitEnabled(bool v) override;
void setLowerLimit(float v) override;
void setUpperLimit(float v) override;
void setMotorEnabled(bool v) override;
void setMotorVelocity(float v) override;
void setMotorForceLimit(float v) override;
void updateScale0() override;
void updateScale1() override;
private:
void onComponentSet() override;
void updatePose();
physx::PxVec3 _mPivotA;
physx::PxVec3 _mPivotB;
physx::PxVec3 _mAxis;
physx::PxJointAngularLimitPair _mlimit{0, 0};
bool _limitEnabled{false};
float _lowerLimit{0.0F};
float _upperLimit{0.0F};
bool _motorEnabled{false};
float _motorVelocity{0.0F};
float _motorForceLimit{0.0F};
};
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,80 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "physics/physx/joints/PhysXSpherical.h"
#include "math/Quaternion.h"
#include "physics/physx/PhysXSharedBody.h"
#include "physics/physx/PhysXUtils.h"
namespace cc {
namespace physics {
void PhysXSpherical::onComponentSet() {
_mJoint = PxSphericalJointCreate(PxGetPhysics(), &getTempRigidActor(), physx::PxTransform{physx::PxIdentity}, nullptr, physx::PxTransform{physx::PxIdentity});
setEnableDebugVisualization(true);
}
void PhysXSpherical::setPivotA(float x, float y, float z) {
_mPivotA = physx::PxVec3{x, y, z};
updatePose();
}
void PhysXSpherical::setPivotB(float x, float y, float z) {
_mPivotB = physx::PxVec3{x, y, z};
updatePose();
}
void PhysXSpherical::updateScale0() {
updatePose();
}
void PhysXSpherical::updateScale1() {
updatePose();
}
void PhysXSpherical::updatePose() {
physx::PxTransform pose0{physx::PxIdentity};
physx::PxTransform pose1{physx::PxIdentity};
auto *node0 = _mSharedBody->getNode();
node0->updateWorldTransform();
pose0.p = _mPivotA * node0->getWorldScale();
_mJoint->setLocalPose(physx::PxJointActorIndex::eACTOR0, pose0);
if (_mConnectedBody) {
auto *node1 = _mConnectedBody->getNode();
node1->updateWorldTransform();
pose1.p = _mPivotB * node1->getWorldScale();
} else {
const auto &wr = node0->getWorldRotation();
auto pos = Vec3(_mPivotA.x, _mPivotA.y, _mPivotA.z);
pos.multiply(node0->getWorldScale());
pos.transformQuat(node0->getWorldRotation());
pos.add(node0->getWorldPosition());
pose1.p = physx::PxVec3(pos.x, pos.y, pos.z);
pose1.q = physx::PxQuat{wr.x, wr.y, wr.z, wr.w} * pose0.q;
}
_mJoint->setLocalPose(physx::PxJointActorIndex::eACTOR1, pose1);
}
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,51 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "physics/physx/joints/PhysXJoint.h"
namespace cc {
namespace physics {
class PhysXSpherical final : public PhysXJoint, public ISphericalJoint {
public:
PhysXSpherical() : _mPivotA(physx::PxZero),
_mPivotB(physx::PxZero){};
~PhysXSpherical() override = default;
void setPivotA(float x, float y, float z) override;
void setPivotB(float x, float y, float z) override;
void updateScale0() override;
void updateScale1() override;
private:
void onComponentSet() override;
void updatePose();
physx::PxVec3 _mPivotA;
physx::PxVec3 _mPivotB;
};
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,65 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "physics/physx/shapes/PhysXBox.h"
#include "physics/physx/PhysXUtils.h"
#include "physics/physx/PhysXWorld.h"
#include "physics/physx/shapes/PhysXShape.h"
namespace cc {
namespace physics {
PhysXBox::PhysXBox() : _mHalfExtents(0.5){};
void PhysXBox::setSize(float x, float y, float z) {
_mHalfExtents = physx::PxVec3{x / 2, y / 2, z / 2};
updateGeometry();
getShape().setGeometry(getPxGeometry<physx::PxBoxGeometry>());
}
void PhysXBox::onComponentSet() {
updateGeometry();
_mShape = PxGetPhysics().createShape(getPxGeometry<physx::PxBoxGeometry>(), getDefaultMaterial(), true);
}
void PhysXBox::updateScale() {
updateGeometry();
getShape().setGeometry(getPxGeometry<physx::PxBoxGeometry>());
updateCenter();
}
void PhysXBox::updateGeometry() {
auto *node = getSharedBody().getNode();
auto &geo = getPxGeometry<physx::PxBoxGeometry>();
geo.halfExtents = _mHalfExtents;
node->updateWorldTransform();
geo.halfExtents *= node->getWorldScale();
geo.halfExtents = geo.halfExtents.abs();
if (geo.halfExtents.minElement() <= 0.0) {
geo.halfExtents = geo.halfExtents.maximum(physx::PxVec3{PX_NORMALIZATION_EPSILON});
}
}
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,46 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "physics/physx/shapes/PhysXShape.h"
namespace cc {
namespace physics {
class PhysXBox final : public PhysXShape, public IBoxShape {
public:
PhysXBox();
~PhysXBox() override = default;
void setSize(float x, float y, float z) override;
void updateScale() override;
private:
physx::PxVec3 _mHalfExtents;
void updateGeometry();
void onComponentSet() override;
};
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,95 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "physics/physx/shapes/PhysXCapsule.h"
#include "physics/physx/PhysXUtils.h"
#include "physics/physx/PhysXWorld.h"
#include "physics/physx/shapes/PhysXShape.h"
namespace cc {
namespace physics {
PhysXCapsule::PhysXCapsule() : _mRadius(0.5F),
_mCylinderHeight(1.0F),
_mDirection(EAxisDirection::Y_AXIS){};
void PhysXCapsule::setRadius(float r) {
_mRadius = r;
updateGeometry();
getShape().setGeometry(getPxGeometry<physx::PxCapsuleGeometry>());
}
void PhysXCapsule::setCylinderHeight(float v) {
_mCylinderHeight = v;
updateGeometry();
getShape().setGeometry(getPxGeometry<physx::PxCapsuleGeometry>());
}
void PhysXCapsule::setDirection(EAxisDirection v) {
_mDirection = v;
updateGeometry();
getShape().setGeometry(getPxGeometry<physx::PxCapsuleGeometry>());
}
void PhysXCapsule::onComponentSet() {
updateGeometry();
_mShape = PxGetPhysics().createShape(getPxGeometry<physx::PxCapsuleGeometry>(), getDefaultMaterial(), true);
}
void PhysXCapsule::updateScale() {
updateGeometry();
getShape().setGeometry(getPxGeometry<physx::PxCapsuleGeometry>());
updateCenter();
}
void PhysXCapsule::updateGeometry() {
auto *node = getSharedBody().getNode();
auto &geo = getPxGeometry<physx::PxCapsuleGeometry>();
float rs = 1.F;
float hs = 1.F;
node->updateWorldTransform();
switch (_mDirection) {
case EAxisDirection::X_AXIS:
hs = physx::PxAbs(node->getWorldScale().x);
rs = pxAbsMax(node->getWorldScale().y, node->getWorldScale().z);
_mRotation = physx::PxQuat{physx::PxIdentity};
break;
case EAxisDirection::Z_AXIS:
hs = physx::PxAbs(node->getWorldScale().z);
rs = pxAbsMax(node->getWorldScale().x, node->getWorldScale().y);
_mRotation = physx::PxQuat(physx::PxPiDivTwo, physx::PxVec3{0.F, 1.F, 0.F});
break;
case EAxisDirection::Y_AXIS:
default:
hs = physx::PxAbs(node->getWorldScale().y);
rs = pxAbsMax(node->getWorldScale().x, node->getWorldScale().z);
_mRotation = physx::PxQuat(physx::PxPiDivTwo, physx::PxVec3{0.F, 0.F, 1.F});
break;
}
geo.radius = physx::PxMax(physx::PxAbs(_mRadius * rs), PX_NORMALIZATION_EPSILON);
geo.halfHeight = physx::PxMax(physx::PxAbs(_mCylinderHeight / 2 * hs), PX_NORMALIZATION_EPSILON);
}
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,50 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "physics/physx/shapes/PhysXShape.h"
namespace cc {
namespace physics {
class PhysXCapsule final : public PhysXShape, public ICapsuleShape {
public:
PhysXCapsule();
~PhysXCapsule() override = default;
void setRadius(float r) override;
void setCylinderHeight(float v) override;
void setDirection(EAxisDirection v) override;
void updateScale() override;
private:
float _mRadius;
float _mCylinderHeight;
EAxisDirection _mDirection;
void updateGeometry();
void onComponentSet() override;
};
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,102 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "physics/physx/shapes/PhysXCone.h"
#include <algorithm>
#include "math/Quaternion.h"
#include "physics/physx/PhysXUtils.h"
#include "physics/physx/PhysXWorld.h"
#include "physics/physx/shapes/PhysXShape.h"
namespace cc {
namespace physics {
PhysXCone::PhysXCone() : _mMesh(nullptr){};
void PhysXCone::setConvex(uint32_t objectID) {
uintptr_t handle = PhysXWorld::getInstance().getPXPtrWithPXObjectID(objectID);
if (handle == 0) return;
if (reinterpret_cast<uintptr_t>(_mMesh) == handle) return;
_mMesh = reinterpret_cast<physx::PxConvexMesh *>(handle);
if (_mShape) {
}
}
void PhysXCone::onComponentSet() {
if (_mMesh) {
physx::PxConvexMeshGeometry geom;
geom.convexMesh = _mMesh;
// geom.meshFlags = PxConvexMeshGeometryFlags::eTIGHT_BOUNDS;
_mShape = PxGetPhysics().createShape(geom, getDefaultMaterial(), true);
updateGeometry();
}
}
void PhysXCone::setCone(float r, float h, EAxisDirection d) {
_mData.radius = r;
_mData.height = h;
_mData.direction = d;
updateGeometry();
}
void PhysXCone::updateGeometry() {
if (!_mShape) return;
static physx::PxMeshScale scale;
auto *node = getSharedBody().getNode();
node->updateWorldTransform();
pxSetVec3Ext(scale.scale, node->getWorldScale());
scale.scale.y *= std::max(0.0001F, _mData.height / 2);
const auto radius = std::max(0.0001F, _mData.radius * 2);
const auto xzMaxNorm = std::max(scale.scale.x, scale.scale.z);
scale.scale.x = scale.scale.z = radius * xzMaxNorm;
Quaternion quat;
switch (_mData.direction) {
case EAxisDirection::X_AXIS:
quat.set(Vec3::UNIT_Z, physx::PxPiDivTwo);
pxSetQuatExt(scale.rotation, quat);
break;
case EAxisDirection::Y_AXIS:
default:
scale.rotation = physx::PxQuat{physx::PxIdentity};
break;
case EAxisDirection::Z_AXIS:
quat.set(Vec3::UNIT_X, physx::PxPiDivTwo);
pxSetQuatExt(scale.rotation, quat);
break;
}
physx::PxConvexMeshGeometry geom;
if (getShape().getConvexMeshGeometry(geom)) {
geom.scale = scale;
getShape().setGeometry(geom);
}
pxSetQuatExt(_mRotation, quat);
}
void PhysXCone::updateScale() {
updateGeometry();
updateCenter();
}
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,54 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "physics/physx/shapes/PhysXShape.h"
namespace cc {
namespace physics {
class PhysXCone final : public PhysXShape, public IConeShape {
public:
PhysXCone();
~PhysXCone() override = default;
void setConvex(uint32_t objectID) override;
void setCone(float r, float h, EAxisDirection d) override;
void updateScale() override;
struct Cone {
float radius;
float height;
EAxisDirection direction;
};
private:
physx::PxConvexMesh *_mMesh;
Cone _mData;
void updateGeometry();
void onComponentSet() override;
};
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,103 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "physics/physx/shapes/PhysXCylinder.h"
#include <algorithm>
#include "math/Quaternion.h"
#include "physics/physx/PhysXUtils.h"
#include "physics/physx/PhysXWorld.h"
#include "physics/physx/shapes/PhysXShape.h"
namespace cc {
namespace physics {
PhysXCylinder::PhysXCylinder() : _mMesh(nullptr){};
void PhysXCylinder::setConvex(uint32_t objectID) {
uintptr_t handle = PhysXWorld::getInstance().getPXPtrWithPXObjectID(objectID);
if (handle == 0) return;
if (reinterpret_cast<uintptr_t>(_mMesh) == handle) return;
_mMesh = reinterpret_cast<physx::PxConvexMesh *>(handle);
if (_mShape) {
// TODO(Administrator): ...
}
}
void PhysXCylinder::onComponentSet() {
if (_mMesh) {
physx::PxConvexMeshGeometry geom;
geom.convexMesh = _mMesh;
// geom.meshFlags = PxConvexMeshGeometryFlags::eTIGHT_BOUNDS;
_mShape = PxGetPhysics().createShape(geom, getDefaultMaterial(), true);
updateGeometry();
}
}
void PhysXCylinder::setCylinder(float r, float h, EAxisDirection d) {
_mData.radius = r;
_mData.height = h;
_mData.direction = d;
updateGeometry();
}
void PhysXCylinder::updateGeometry() {
if (!_mShape) return;
static physx::PxMeshScale scale;
auto *node = getSharedBody().getNode();
node->updateWorldTransform();
pxSetVec3Ext(scale.scale, node->getWorldScale());
scale.scale.y *= std::max(0.0001F, _mData.height / 2);
const auto radius = std::max(0.0001F, _mData.radius * 2);
const auto xzMaxNorm = std::max(scale.scale.x, scale.scale.z);
scale.scale.x = scale.scale.z = radius * xzMaxNorm;
Quaternion quat;
switch (_mData.direction) {
case EAxisDirection::X_AXIS:
quat.set(Vec3::UNIT_Z, physx::PxPiDivTwo);
pxSetQuatExt(scale.rotation, quat);
break;
case EAxisDirection::Y_AXIS:
default:
scale.rotation = physx::PxQuat{physx::PxIdentity};
break;
case EAxisDirection::Z_AXIS:
quat.set(Vec3::UNIT_X, physx::PxPiDivTwo);
pxSetQuatExt(scale.rotation, quat);
break;
}
physx::PxConvexMeshGeometry geom;
if (getShape().getConvexMeshGeometry(geom)) {
geom.scale = scale;
getShape().setGeometry(geom);
}
pxSetQuatExt(_mRotation, quat);
}
void PhysXCylinder::updateScale() {
updateGeometry();
updateCenter();
}
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,54 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "physics/physx/shapes/PhysXShape.h"
namespace cc {
namespace physics {
class PhysXCylinder final : public PhysXShape, public ICylinderShape {
public:
PhysXCylinder();
~PhysXCylinder() override = default;
void setConvex(uint32_t objectID) override;
void setCylinder(float r, float h, EAxisDirection d) override;
void updateScale() override;
struct Cylinder {
float radius;
float height;
EAxisDirection direction;
};
private:
physx::PxConvexMesh *_mMesh;
Cylinder _mData;
void updateGeometry();
void onComponentSet() override;
};
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,65 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "physics/physx/shapes/PhysXPlane.h"
#include "physics/physx/PhysXUtils.h"
#include "physics/physx/PhysXWorld.h"
#include "physics/physx/shapes/PhysXShape.h"
namespace cc {
namespace physics {
PhysXPlane::PhysXPlane() : _mConstant(0.F),
_mNormal(0.F, 1.F, 0.F){};
void PhysXPlane::setConstant(float x) {
_mConstant = x;
updateCenter();
}
void PhysXPlane::setNormal(float x, float y, float z) {
_mNormal = physx::PxVec3{x, y, z};
updateCenter();
}
void PhysXPlane::onComponentSet() {
_mShape = PxGetPhysics().createShape(getPxGeometry<physx::PxPlaneGeometry>(), getDefaultMaterial(), true);
updateCenter();
}
void PhysXPlane::updateScale() {
updateCenter();
}
void PhysXPlane::updateCenter() {
auto* node = getSharedBody().getNode();
auto& geo = getPxGeometry<physx::PxPlaneGeometry>();
physx::PxTransform local;
pxSetFromTwoVectors(local.q, physx::PxVec3{1.F, 0.F, 0.F}, _mNormal);
local.p = _mNormal * _mConstant + _mCenter;
getShape().setLocalPose(local);
}
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,48 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "physics/physx/shapes/PhysXShape.h"
namespace cc {
namespace physics {
class PhysXPlane final : public PhysXShape, public IPlaneShape {
public:
PhysXPlane();
~PhysXPlane() override = default;
void setConstant(float x) override;
void setNormal(float x, float y, float z) override;
void updateScale() override;
private:
physx::PxVec3 _mNormal;
physx::PxReal _mConstant;
void updateCenter() override;
void onComponentSet() override;
};
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,157 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "physics/physx/shapes/PhysXShape.h"
#include "base/std/container/unordered_map.h"
#include "physics/physx/PhysXSharedBody.h"
#include "physics/physx/PhysXUtils.h"
#include "physics/physx/PhysXWorld.h"
namespace cc {
namespace physics {
PhysXShape::PhysXShape() : _mCenter(physx::PxIdentity), _mRotation(physx::PxIdentity) {
_mObjectID = PhysXWorld::getInstance().addWrapperObject(reinterpret_cast<uintptr_t>(this));
};
void PhysXShape::initialize(Node *node) {
PhysXWorld &ins = PhysXWorld::getInstance();
_mSharedBody = ins.getSharedBody(node);
getSharedBody().reference(true);
onComponentSet();
insertToShapeMap();
}
void PhysXShape::onEnable() {
_mEnabled = true;
if (_mShape) getSharedBody().addShape(*this);
getSharedBody().enabled(true);
}
void PhysXShape::onDisable() {
_mEnabled = false;
if (_mShape) getSharedBody().removeShape(*this);
getSharedBody().enabled(false);
}
void PhysXShape::onDestroy() {
getSharedBody().reference(false);
eraseFromShapeMap();
PhysXWorld::getInstance().removeWrapperObject(_mObjectID);
}
void PhysXShape::setMaterial(uint16_t id, float f, float df, float r,
uint8_t m0, uint8_t m1) {
if (!_mShape) return;
PhysXWorld::getInstance().createMaterial(id, f, df, r, m0, m1);
auto *mat = reinterpret_cast<physx::PxMaterial *>(PhysXWorld::getInstance().getPXMaterialPtrWithMaterialID(id));
getShape().setMaterials(&mat, 1);
}
void PhysXShape::setAsTrigger(bool v) {
if (v) {
getShape().setFlag(physx::PxShapeFlag::eSIMULATION_SHAPE, !v);
getShape().setFlag(physx::PxShapeFlag::eTRIGGER_SHAPE, v);
} else {
getShape().setFlag(physx::PxShapeFlag::eTRIGGER_SHAPE, v);
getShape().setFlag(physx::PxShapeFlag::eSIMULATION_SHAPE, !v);
}
if (_mEnabled) {
getSharedBody().removeShape(*this);
getSharedBody().addShape(*this);
}
}
void PhysXShape::setCenter(float x, float y, float z) {
_mCenter = physx::PxVec3{x, y, z};
updateCenter();
}
uint32_t PhysXShape::getGroup() {
return getSharedBody().getGroup();
}
void PhysXShape::setGroup(uint32_t g) {
getSharedBody().setGroup(g);
}
uint32_t PhysXShape::getMask() {
return getSharedBody().getMask();
}
void PhysXShape::setMask(uint32_t m) {
getSharedBody().setMask(m);
}
void PhysXShape::updateEventListener(EShapeFilterFlag flag) {
}
geometry::AABB &PhysXShape::getAABB() {
static IntrusivePtr<geometry::AABB> aabb; // this variable is shared with JS with refcounter
if (!aabb) {
aabb = new geometry::AABB;
}
if (_mShape) {
auto bounds = physx::PxShapeExt::getWorldBounds(getShape(), *getSharedBody().getImpl().rigidActor);
pxSetVec3Ext(aabb->center, (bounds.maximum + bounds.minimum) / 2);
pxSetVec3Ext(aabb->halfExtents, (bounds.maximum - bounds.minimum) / 2);
}
return *aabb;
}
geometry::Sphere &PhysXShape::getBoundingSphere() {
static IntrusivePtr<geometry::Sphere> sphere; // this variable is shared with JS with refcounter
if (!sphere) {
sphere = new geometry::Sphere;
}
if (_mShape) sphere->define(getAABB());
return *sphere;
}
void PhysXShape::updateFilterData(const physx::PxFilterData &data) {
}
void PhysXShape::updateCenter() {
if (!_mShape) return;
auto &sb = getSharedBody();
auto *node = sb.getNode();
node->updateWorldTransform();
physx::PxTransform local{_mCenter * node->getWorldScale(), _mRotation};
getShape().setLocalPose(local);
}
void PhysXShape::insertToShapeMap() {
if (_mShape) {
getPxShapeMap().insert(std::pair<uintptr_t, uint32_t>(reinterpret_cast<uintptr_t>(&getShape()), getObjectID()));
}
}
void PhysXShape::eraseFromShapeMap() {
if (_mShape) {
getPxShapeMap().erase(reinterpret_cast<uintptr_t>(&getShape()));
}
}
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,89 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "base/Macros.h"
#include "core/scene-graph/Node.h"
#include "physics/physx/PhysXInc.h"
#include "physics/spec/IShape.h"
namespace cc {
namespace physics {
class PhysXSharedBody;
template <typename T>
inline T &getPxGeometry() {
static T geo;
return geo;
}
class PhysXShape : virtual public IBaseShape {
PX_NOCOPY(PhysXShape)
PhysXShape();
public:
~PhysXShape() override = default;
void initialize(Node *node) override;
void onEnable() override;
void onDisable() override;
void onDestroy() override;
void setMaterial(uint16_t id, float f, float df, float r,
uint8_t m0, uint8_t m1) override;
void setAsTrigger(bool v) override;
void setCenter(float x, float y, float z) override;
geometry::AABB &getAABB() override;
geometry::Sphere &getBoundingSphere() override;
void updateEventListener(EShapeFilterFlag flag) override;
uint32_t getGroup() override;
void setGroup(uint32_t g) override;
uint32_t getMask() override;
void setMask(uint32_t m) override;
virtual void updateScale() = 0;
inline physx::PxVec3 &getCenter() { return _mCenter; }
inline physx::PxShape &getShape() const { return *_mShape; }
inline PhysXSharedBody &getSharedBody() const { return *_mSharedBody; }
inline bool isTrigger() const {
return getShape().getFlags().isSet(physx::PxShapeFlag::eTRIGGER_SHAPE);
}
void updateFilterData(const physx::PxFilterData &data);
uint32_t getObjectID() const override { return _mObjectID; };
protected:
PhysXSharedBody *_mSharedBody{nullptr};
physx::PxShape *_mShape{nullptr};
physx::PxVec3 _mCenter;
physx::PxQuat _mRotation;
uint8_t _mFlag{0};
bool _mEnabled{false};
uint32_t _mObjectID{0};
virtual void updateCenter();
virtual void onComponentSet() = 0;
virtual void insertToShapeMap();
virtual void eraseFromShapeMap();
};
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,62 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "physics/physx/shapes/PhysXSphere.h"
#include "physics/physx/PhysXUtils.h"
#include "physics/physx/PhysXWorld.h"
#include "physics/physx/shapes/PhysXShape.h"
namespace cc {
namespace physics {
PhysXSphere::PhysXSphere() : _mRadius(0.5F) {}
void PhysXSphere::setRadius(float r) {
_mRadius = r;
updateGeometry();
getShape().setGeometry(getPxGeometry<physx::PxSphereGeometry>());
}
void PhysXSphere::onComponentSet() {
updateGeometry();
_mShape = PxGetPhysics().createShape(getPxGeometry<physx::PxSphereGeometry>(), getDefaultMaterial(), true);
}
void PhysXSphere::updateScale() {
updateGeometry();
getShape().setGeometry(getPxGeometry<physx::PxSphereGeometry>());
updateCenter();
}
void PhysXSphere::updateGeometry() {
physx::PxVec3 scale;
auto *node = getSharedBody().getNode();
node->updateWorldTransform();
pxSetVec3Ext(scale, node->getWorldScale());
auto &geo = getPxGeometry<physx::PxSphereGeometry>();
geo.radius = physx::PxMax(_mRadius * scale.abs().maxElement(), PX_NORMALIZATION_EPSILON);
}
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,46 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "physics/physx/shapes/PhysXShape.h"
namespace cc {
namespace physics {
class PhysXSphere final : public PhysXShape, public ISphereShape {
public:
PhysXSphere();
~PhysXSphere() override = default;
void setRadius(float r) override;
void updateScale() override;
private:
float _mRadius;
void updateGeometry();
void onComponentSet() override;
};
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,85 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "physics/physx/shapes/PhysXTerrain.h"
#include "physics/physx/PhysXUtils.h"
#include "physics/physx/PhysXWorld.h"
#include "physics/physx/shapes/PhysXShape.h"
namespace cc {
namespace physics {
PhysXTerrain::PhysXTerrain() : _mTerrain(nullptr),
_mRowScale(1.F),
_mColScale(1.F),
_mHeightScale(1.F),
_mIsTrigger(false){};
void PhysXTerrain::setTerrain(uint32_t objectID, float rs, float cs, float hs) {
uintptr_t handle = PhysXWorld::getInstance().getPXPtrWithPXObjectID(objectID);
if (handle == 0) return;
if (_mShape) return;
if (reinterpret_cast<uintptr_t>(_mTerrain) == handle) return;
_mTerrain = reinterpret_cast<physx::PxHeightField *>(handle);
_mRowScale = rs;
_mColScale = cs;
_mHeightScale = hs;
if (_mSharedBody && _mTerrain) {
onComponentSet();
insertToShapeMap();
if (_mEnabled) getSharedBody().addShape(*this);
setAsTrigger(_mIsTrigger);
updateCenter();
}
}
void PhysXTerrain::onComponentSet() {
if (_mTerrain) {
physx::PxHeightFieldGeometry geom;
geom.rowScale = _mRowScale;
geom.columnScale = _mColScale;
geom.heightScale = _mHeightScale;
geom.heightField = _mTerrain;
_mShape = PxGetPhysics().createShape(geom, getDefaultMaterial(), true);
}
}
void PhysXTerrain::updateScale() {
// updateCenter(); needed?
}
void PhysXTerrain::updateCenter() {
if (!_mShape) return;
getShape().setLocalPose(physx::PxTransform{_mCenter, _mRotation});
}
void PhysXTerrain::setAsTrigger(bool v) {
_mIsTrigger = v;
if (_mShape) {
PhysXShape::setAsTrigger(v);
}
}
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,51 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "physics/physx/shapes/PhysXShape.h"
namespace cc {
namespace physics {
class PhysXTerrain final : public PhysXShape, public ITerrainShape {
public:
PhysXTerrain();
~PhysXTerrain() override = default;
void setTerrain(uint32_t objectID, float rs, float cs, float hs) override;
void updateScale() override;
void updateCenter() override;
void setAsTrigger(bool v) override;
private:
physx::PxHeightField *_mTerrain;
float _mRowScale;
float _mColScale;
float _mHeightScale;
bool _mIsTrigger;
void onComponentSet() override;
};
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,114 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "physics/physx/shapes/PhysXTrimesh.h"
#include "physics/physx/PhysXUtils.h"
#include "physics/physx/PhysXWorld.h"
#include "physics/physx/shapes/PhysXShape.h"
namespace cc {
namespace physics {
PhysXTrimesh::PhysXTrimesh() : _mMeshHandle(0),
_mConvex(false),
_mIsTrigger(false){};
void PhysXTrimesh::setMesh(uint32_t objectID) {
uintptr_t handle = PhysXWorld::getInstance().getPXPtrWithPXObjectID(objectID);
if (handle == 0) return;
if (_mShape) {
getSharedBody().removeShape(*this);
eraseFromShapeMap();
_mShape->release();
_mShape = nullptr;
}
if (_mMeshHandle == handle) return;
_mMeshHandle = handle;
if (_mSharedBody && _mMeshHandle) {
onComponentSet();
insertToShapeMap();
if (_mEnabled) getSharedBody().addShape(*this);
setAsTrigger(_mIsTrigger);
updateCenter();
}
}
void PhysXTrimesh::useConvex(bool v) {
_mConvex = v;
}
void PhysXTrimesh::onComponentSet() {
if (_mMeshHandle) {
const auto &mat = getDefaultMaterial();
if (_mConvex) {
physx::PxConvexMeshGeometry geom;
geom.convexMesh = reinterpret_cast<physx::PxConvexMesh *>(_mMeshHandle);
// geom.meshFlags = PxConvexMeshGeometryFlags::eTIGHT_BOUNDS;
_mShape = PxGetPhysics().createShape(geom, mat, true);
} else {
physx::PxTriangleMeshGeometry geom;
geom.triangleMesh = reinterpret_cast<physx::PxTriangleMesh *>(_mMeshHandle);
// geom.meshFlags = PxMeshGeometryFlag::eDOUBLE_SIDED;
_mShape = PxGetPhysics().createShape(geom, mat, true);
}
updateGeometry();
}
}
void PhysXTrimesh::updateScale() {
updateGeometry();
updateCenter();
}
void PhysXTrimesh::updateGeometry() {
static physx::PxMeshScale scale;
scale.rotation = physx::PxQuat{physx::PxIdentity};
auto *node = getSharedBody().getNode();
node->updateWorldTransform();
pxSetVec3Ext(scale.scale, node->getWorldScale());
const auto &type = _mShape->getGeometryType();
if (type == physx::PxGeometryType::eCONVEXMESH) {
physx::PxConvexMeshGeometry geom;
if (getShape().getConvexMeshGeometry(geom)) {
geom.scale = scale;
getShape().setGeometry(geom);
}
} else if (type == physx::PxGeometryType::eTRIANGLEMESH) {
physx::PxTriangleMeshGeometry geom;
if (getShape().getTriangleMeshGeometry(geom)) {
geom.scale = scale;
getShape().setGeometry(geom);
}
}
}
void PhysXTrimesh::setAsTrigger(bool v) {
_mIsTrigger = v;
if (_mShape) {
PhysXShape::setAsTrigger(v);
}
}
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,50 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "physics/physx/shapes/PhysXShape.h"
namespace cc {
namespace physics {
class PhysXTrimesh final : public PhysXShape, public ITrimeshShape {
public:
PhysXTrimesh();
~PhysXTrimesh() override = default;
void setMesh(uint32_t objectID) override;
void useConvex(bool v) override;
void updateScale() override;
void setAsTrigger(bool v) override;
private:
bool _mConvex;
uintptr_t _mMeshHandle;
bool _mIsTrigger;
void updateGeometry();
void onComponentSet() override;
};
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,161 @@
/****************************************************************************
Copyright (c) 2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "physics/sdk/CharacterController.h"
#include <memory>
#include "physics/PhysicsSelector.h"
#define CC_PHYSICS_CCT_DEFINITION(CLASS, WRAPPED) \
\
CLASS::CLASS() { \
_impl.reset(ccnew WRAPPED()); \
} \
\
CLASS::~CLASS() { \
_impl.reset(nullptr); \
} \
\
bool CLASS::initialize(Node *node) { \
return _impl->initialize(node); \
} \
\
void CLASS::onEnable() { \
_impl->onEnable(); \
} \
\
void CLASS::onDisable() { \
_impl->onDisable(); \
} \
\
void CLASS::onDestroy() { \
_impl->onDestroy(); \
} \
\
cc::Vec3 CLASS::getPosition() { \
return _impl->getPosition(); \
} \
\
void CLASS::setPosition(float x, float y, float z) { \
_impl->setPosition(x, y, z); \
} \
\
bool CLASS::onGround() { \
return _impl->onGround(); \
} \
\
void CLASS::move(float x, float y, float z, float minDist, float elapsedTime) { \
_impl->move(x, y, z, minDist, elapsedTime); \
} \
\
void CLASS::syncPhysicsToScene() { \
_impl->syncPhysicsToScene(); \
} \
\
void CLASS::setStepOffset(float v) { \
_impl->setStepOffset(v); \
} \
\
float CLASS::getStepOffset() { \
return _impl->getStepOffset(); \
} \
\
void CLASS::setSlopeLimit(float v) { \
_impl->setSlopeLimit(v); \
} \
\
float CLASS::getSlopeLimit() { \
return _impl->getSlopeLimit(); \
} \
\
void CLASS::setContactOffset(float v) { \
_impl->setContactOffset(v); \
} \
\
float CLASS::getContactOffset() { \
return _impl->getContactOffset(); \
} \
\
void CLASS::setDetectCollisions(bool v) { \
_impl->setDetectCollisions(v); \
} \
void CLASS::setOverlapRecovery(bool v) { \
_impl->setOverlapRecovery(v); \
} \
void CLASS::setCenter(float x, float y, float z) { \
_impl->setCenter(x, y, z); \
} \
uint32_t CLASS::getGroup() { \
return _impl->getGroup(); \
} \
\
void CLASS::setGroup(uint32_t g) { \
_impl->setGroup(g); \
} \
\
uint32_t CLASS::getMask() { \
return _impl->getMask(); \
} \
\
void CLASS::setMask(uint32_t m) { \
_impl->setMask(m); \
} \
void CLASS::updateEventListener(EShapeFilterFlag flag) { \
_impl->updateEventListener(flag); \
} \
uint32_t CLASS::getObjectID()const { \
return _impl->getObjectID(); \
} \
\
namespace cc {
namespace physics {
/// COMMON ///
CC_PHYSICS_CCT_DEFINITION(CapsuleCharacterController, WrappedCapsuleCharacterController)
CC_PHYSICS_CCT_DEFINITION(BoxCharacterController, WrappedBoxCharacterController)
/// EXTRAS ///
void CapsuleCharacterController::setRadius(float v) {
_impl->setRadius(v);
}
void CapsuleCharacterController::setHeight(float v) {
_impl->setHeight(v);
}
void BoxCharacterController::setHalfHeight(float v) {
_impl->setHalfHeight(v);
}
void BoxCharacterController::setHalfSideExtent(float v) {
_impl->setHalfSideExtent(v);
}
void BoxCharacterController::setHalfForwardExtent(float v) {
_impl->setHalfForwardExtent(v);
}
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,80 @@
/****************************************************************************
Copyright (c) 2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include <memory>
#include "base/Macros.h"
#include "core/scene-graph/Node.h"
#include "physics/spec/IShape.h"
#include "physics/spec/ICharacterController.h"
#define CC_PHYSICS_CCT_CLASS(CLASS) \
class CC_DLL CLASS final : public I##CLASS { \
protected: \
std::unique_ptr<I##CLASS> _impl; \
\
public: \
CLASS(); \
~CLASS() override; \
bool initialize(Node *node) override; \
void onEnable() override; \
void onDisable() override; \
void onDestroy() override; \
virtual cc::Vec3 getPosition() override; \
virtual void setPosition(float x, float y, float z) override; \
virtual bool onGround() override; \
virtual void move(float x, float y, float z, float minDist, \
float elapsedTime) override; \
void syncPhysicsToScene() override; \
virtual void setStepOffset(float v) override; \
virtual float getStepOffset() override; \
virtual void setSlopeLimit(float v) override; \
virtual float getSlopeLimit() override; \
virtual void setContactOffset(float v) override; \
virtual float getContactOffset() override; \
virtual void setDetectCollisions(bool v) override; \
virtual void setOverlapRecovery(bool v) override; \
virtual void setCenter(float x, float y, float z) override; \
uint32_t getGroup() override; \
void setGroup(uint32_t g) override; \
uint32_t getMask() override; \
void setMask(uint32_t m) override; \
void updateEventListener(EShapeFilterFlag flag) override; \
uint32_t getObjectID() const override;
namespace cc {
namespace physics {
CC_PHYSICS_CCT_CLASS(CapsuleCharacterController)
void setRadius(float v) override;
void setHeight(float v) override;
};
CC_PHYSICS_CCT_CLASS(BoxCharacterController)
void setHalfHeight(float v) override;
void setHalfSideExtent(float v) override;
void setHalfForwardExtent(float v) override;
};
}; // namespace physics
} // namespace cc

223
cocos/physics/sdk/Joint.cpp Normal file
View File

@@ -0,0 +1,223 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "physics/sdk/Joint.h"
#include "base/memory/Memory.h"
#include "physics/PhysicsSelector.h"
#define CC_PHYSICS_JOINT_DEFINITION(CLASS, WRAPPED) \
\
CLASS::CLASS() { \
_impl.reset(ccnew WRAPPED()); \
} \
\
CLASS::~CLASS() { \
_impl.reset(nullptr); \
} \
\
void CLASS::initialize(Node *node) { \
_impl->initialize(node); \
} \
\
void CLASS::onEnable() { \
_impl->onEnable(); \
} \
\
void CLASS::onDisable() { \
_impl->onDisable(); \
} \
\
void CLASS::onDestroy() { \
_impl->onDestroy(); \
} \
\
void CLASS::setConnectedBody(uint32_t rigidBodyID) { \
_impl->setConnectedBody(rigidBodyID); \
} \
\
void CLASS::setEnableCollision(bool v) { \
_impl->setEnableCollision(v); \
} \
uint32_t CLASS::getObjectID() const { \
return _impl->getObjectID(); \
}
namespace cc {
namespace physics {
/// COMMON ///
CC_PHYSICS_JOINT_DEFINITION(SphericalJoint, WrappedSphericalJoint)
CC_PHYSICS_JOINT_DEFINITION(RevoluteJoint, WrappedRevoluteJoint)
CC_PHYSICS_JOINT_DEFINITION(FixedJoint, WrappedFixedJoint)
CC_PHYSICS_JOINT_DEFINITION(GenericJoint, WrappedGenericJoint)
/// EXTRAS ///
void SphericalJoint::setPivotA(float x, float y, float z) {
_impl->setPivotA(x, y, z);
}
void SphericalJoint::setPivotB(float x, float y, float z) {
_impl->setPivotB(x, y, z);
}
void RevoluteJoint::setPivotA(float x, float y, float z) {
_impl->setPivotA(x, y, z);
}
void RevoluteJoint::setPivotB(float x, float y, float z) {
_impl->setPivotB(x, y, z);
}
void RevoluteJoint::setAxis(float x, float y, float z) {
_impl->setAxis(x, y, z);
}
void RevoluteJoint::setLimitEnabled(bool v) {
_impl->setLimitEnabled(v);
}
void RevoluteJoint::setLowerLimit(float v) {
_impl->setLowerLimit(v);
}
void RevoluteJoint::setUpperLimit(float v) {
_impl->setUpperLimit(v);
}
void RevoluteJoint::setMotorEnabled(bool v) {
_impl->setMotorEnabled(v);
}
void RevoluteJoint::setMotorVelocity(float v) {
_impl->setMotorVelocity(v);
}
void RevoluteJoint::setMotorForceLimit(float v) {
_impl->setMotorForceLimit(v);
}
void FixedJoint::setBreakForce(float force) {
_impl->setBreakForce(force);
}
void FixedJoint::setBreakTorque(float torque) {
_impl->setBreakTorque(torque);
}
void GenericJoint::setConstraintMode(uint32_t index, uint32_t mode) {
_impl->setConstraintMode(index, mode);
}
void GenericJoint::setLinearLimit(uint32_t index, float lower, float upper) {
_impl->setLinearLimit(index, lower, upper);
}
void GenericJoint::setAngularExtent(float twist, float swing1, float swing2) {
_impl->setAngularExtent(twist, swing1, swing2);
}
void GenericJoint::setLinearSoftConstraint(bool enable) {
_impl->setLinearSoftConstraint(enable);
}
void GenericJoint::setLinearStiffness(float stiffness) {
_impl->setLinearStiffness(stiffness);
}
void GenericJoint::setLinearDamping(float damping) {
_impl->setLinearDamping(damping);
}
void GenericJoint::setLinearRestitution(float restitution) {
_impl->setLinearRestitution(restitution);
}
void GenericJoint::setSwingSoftConstraint(bool enable) {
_impl->setSwingSoftConstraint(enable);
}
void GenericJoint::setTwistSoftConstraint(bool enable) {
_impl->setTwistSoftConstraint(enable);
}
void GenericJoint::setSwingStiffness(float stiffness) {
_impl->setSwingStiffness(stiffness);
}
void GenericJoint::setSwingDamping(float damping) {
_impl->setSwingDamping(damping);
}
void GenericJoint::setSwingRestitution(float restitution) {
_impl->setSwingRestitution(restitution);
}
void GenericJoint::setTwistStiffness(float stiffness) {
_impl->setTwistStiffness(stiffness);
}
void GenericJoint::setTwistDamping(float damping) {
_impl->setTwistDamping(damping);
}
void GenericJoint::setTwistRestitution(float restitution) {
_impl->setTwistRestitution(restitution);
}
void GenericJoint::setDriverMode(uint32_t index, uint32_t mode) {
_impl->setDriverMode(index, mode);
}
void GenericJoint::setLinearMotorTarget(float x, float y, float z) {
_impl->setLinearMotorTarget(x, y, z);
}
void GenericJoint::setLinearMotorVelocity(float x, float y, float z) {
_impl->setLinearMotorVelocity(x, y, z);
}
void GenericJoint::setLinearMotorForceLimit(float limit) {
_impl->setLinearMotorForceLimit(limit);
}
void GenericJoint::setAngularMotorTarget(float x, float y, float z) {
_impl->setAngularMotorTarget(x, y, z);
}
void GenericJoint::setAngularMotorVelocity(float x, float y, float z) {
_impl->setAngularMotorVelocity(x, y, z);
}
void GenericJoint::setAngularMotorForceLimit(float limit) {
_impl->setAngularMotorForceLimit(limit);
}
void GenericJoint::setPivotA(float x, float y, float z) {
_impl->setPivotA(x, y, z);
}
void GenericJoint::setPivotB(float x, float y, float z) {
_impl->setPivotB(x, y, z);
}
void GenericJoint::setAutoPivotB(bool enable) {
_impl->setAutoPivotB(enable);
}
void GenericJoint::setAxis(float x, float y, float z) {
_impl->setAxis(x, y, z);
}
void GenericJoint::setSecondaryAxis(float x, float y, float z) {
_impl->setSecondaryAxis(x, y, z);
}
void GenericJoint::setBreakForce(float force) {
_impl->setBreakForce(force);
}
void GenericJoint::setBreakTorque(float torque) {
_impl->setBreakTorque(torque);
}
} // namespace physics
} // namespace cc

114
cocos/physics/sdk/Joint.h Normal file
View File

@@ -0,0 +1,114 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include <cstdint>
#include <memory>
#include "base/Macros.h"
#include "core/scene-graph/Node.h"
#include "physics/spec/IJoint.h"
#define CC_PHYSICS_JOINT_CLASS(CLASS) \
class CC_DLL CLASS final : virtual public I##CLASS { \
protected: \
std::unique_ptr<I##CLASS> _impl; \
\
public: \
CLASS(); \
~CLASS() override; \
void initialize(Node *node) override; \
void onEnable() override; \
void onDisable() override; \
void onDestroy() override; \
void setEnableCollision(bool v) override; \
void setConnectedBody(uint32_t rigidBodyID) override; \
uint32_t getObjectID() const override;
namespace cc {
namespace physics {
CC_PHYSICS_JOINT_CLASS(RevoluteJoint)
void setPivotA(float x, float y, float z) override;
void setPivotB(float x, float y, float z) override;
void setAxis(float x, float y, float z) override;
void setLimitEnabled(bool v) override;
void setLowerLimit(float v) override;
void setUpperLimit(float v) override;
void setMotorEnabled(bool v) override;
void setMotorVelocity(float v) override;
void setMotorForceLimit(float v) override;
}; // RevoluteJoint
CC_PHYSICS_JOINT_CLASS(SphericalJoint)
void setPivotA(float x, float y, float z) override;
void setPivotB(float x, float y, float z) override;
}; // SphericalJoint
CC_PHYSICS_JOINT_CLASS(FixedJoint)
void setBreakForce(float force) override;
void setBreakTorque(float torque) override;
}
; // FixedJoint
CC_PHYSICS_JOINT_CLASS(GenericJoint)
void setConstraintMode(uint32_t index, uint32_t mode) override;
void setLinearLimit(uint32_t index, float lower, float upper) override;
void setAngularExtent(float twist, float swing1, float swing2) override;
void setLinearSoftConstraint(bool enable) override;
void setLinearStiffness(float stiffness) override;
void setLinearDamping(float damping) override;
void setLinearRestitution(float restitution) override;
void setSwingSoftConstraint(bool enable) override;
void setTwistSoftConstraint(bool enable) override;
void setSwingStiffness(float stiffness) override;
void setSwingDamping(float damping) override;
void setSwingRestitution(float restitution) override;
void setTwistStiffness(float stiffness) override;
void setTwistDamping(float damping) override;
void setTwistRestitution(float restitution) override;
virtual void setDriverMode(uint32_t index, uint32_t mode) override;
void setLinearMotorTarget(float x, float y, float z) override;
void setLinearMotorVelocity(float x, float y, float z) override;
void setLinearMotorForceLimit(float limit) override;
void setAngularMotorTarget(float x, float y, float z) override;
void setAngularMotorVelocity(float x, float y, float z) override;
void setAngularMotorForceLimit(float limit) override;
void setPivotA(float x, float y, float z) override;
void setPivotB(float x, float y, float z) override;
void setAutoPivotB(bool enable) override;
void setAxis(float x, float y, float z) override;
void setSecondaryAxis(float x, float y, float z) override;
void setBreakForce(float force) override;
void setBreakTorque(float torque) override;
}
;
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,193 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "physics/sdk/RigidBody.h"
#include <memory>
#include "physics/PhysicsSelector.h"
namespace cc {
namespace physics {
RigidBody::RigidBody() {
_impl = std::make_unique<WrappedRigidBody>();
}
RigidBody::~RigidBody() {
_impl.reset(nullptr);
}
void RigidBody::initialize(Node *node, const ERigidBodyType t, const uint32_t g) {
_impl->initialize(node, t, g);
}
void RigidBody::onEnable() {
_impl->onEnable();
}
void RigidBody::onDisable() {
_impl->onDisable();
}
void RigidBody::onDestroy() {
_impl->onDestroy();
}
bool RigidBody::isAwake() {
return _impl->isAwake();
}
bool RigidBody::isSleepy() {
return _impl->isSleepy();
}
bool RigidBody::isSleeping() {
return _impl->isSleeping();
}
void RigidBody::setType(ERigidBodyType v) {
_impl->setType(v);
}
void RigidBody::setMass(float v) {
_impl->setMass(v);
}
void RigidBody::setLinearDamping(float v) {
_impl->setLinearDamping(v);
}
void RigidBody::setAngularDamping(float v) {
_impl->setAngularDamping(v);
}
void RigidBody::useCCD(bool v) {
_impl->useCCD(v);
}
void RigidBody::useGravity(bool v) {
_impl->useGravity(v);
}
void RigidBody::setLinearFactor(float x, float y, float z) {
_impl->setLinearFactor(x, y, z);
}
void RigidBody::setAngularFactor(float x, float y, float z) {
_impl->setAngularFactor(x, y, z);
}
void RigidBody::setAllowSleep(bool v) {
_impl->setAllowSleep(v);
}
void RigidBody::wakeUp() {
_impl->wakeUp();
}
void RigidBody::sleep() {
_impl->sleep();
}
void RigidBody::clearState() {
_impl->clearState();
}
void RigidBody::clearForces() {
_impl->clearForces();
}
void RigidBody::clearVelocity() {
_impl->clearVelocity();
}
void RigidBody::setSleepThreshold(float v) {
_impl->setSleepThreshold(v);
}
float RigidBody::getSleepThreshold() {
return _impl->getSleepThreshold();
}
cc::Vec3 RigidBody::getLinearVelocity() {
return _impl->getLinearVelocity();
}
void RigidBody::setLinearVelocity(float x, float y, float z) {
_impl->setLinearVelocity(x, y, z);
}
cc::Vec3 RigidBody::getAngularVelocity() {
return _impl->getAngularVelocity();
}
void RigidBody::setAngularVelocity(float x, float y, float z) {
_impl->setAngularVelocity(x, y, z);
}
void RigidBody::applyForce(float x, float y, float z, float rx, float ry, float rz) {
_impl->applyForce(x, y, z, rx, ry, rz);
}
void RigidBody::applyLocalForce(float x, float y, float z, float rx, float ry, float rz) {
_impl->applyLocalForce(x, y, z, rx, ry, rz);
}
void RigidBody::applyImpulse(float x, float y, float z, float rx, float ry, float rz) {
_impl->applyImpulse(x, y, z, rx, ry, rz);
}
void RigidBody::applyLocalImpulse(float x, float y, float z, float rx, float ry, float rz) {
_impl->applyLocalImpulse(x, y, z, rx, ry, rz);
}
void RigidBody::applyTorque(float x, float y, float z) {
_impl->applyTorque(x, y, z);
}
void RigidBody::applyLocalTorque(float x, float y, float z) {
_impl->applyLocalTorque(x, y, z);
}
uint32_t RigidBody::getGroup() {
return _impl->getGroup();
}
void RigidBody::setGroup(uint32_t g) {
_impl->setGroup(g);
}
uint32_t RigidBody::getMask() {
return _impl->getMask();
}
void RigidBody::setMask(uint32_t m) {
_impl->setMask(m);
}
uint32_t RigidBody::getObjectID() const {
return _impl->getObjectID();
}
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,80 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include <memory>
#include "base/Macros.h"
#include "physics/spec/IBody.h"
namespace cc {
namespace physics {
class CC_DLL RigidBody final : public IRigidBody {
public:
RigidBody();
~RigidBody() override;
void initialize(Node *node, ERigidBodyType t, uint32_t g) override;
void onEnable() override;
void onDisable() override;
void onDestroy() override;
bool isAwake() override;
bool isSleepy() override;
bool isSleeping() override;
void setType(ERigidBodyType v) override;
void setMass(float v) override;
void setLinearDamping(float v) override;
void setAngularDamping(float v) override;
void useGravity(bool v) override;
void useCCD(bool v) override;
void setLinearFactor(float x, float y, float z) override;
void setAngularFactor(float x, float y, float z) override;
void setAllowSleep(bool v) override;
void wakeUp() override;
void sleep() override;
void clearState() override;
void clearForces() override;
void clearVelocity() override;
void setSleepThreshold(float v) override;
float getSleepThreshold() override;
cc::Vec3 getLinearVelocity() override;
void setLinearVelocity(float x, float y, float z) override;
cc::Vec3 getAngularVelocity() override;
void setAngularVelocity(float x, float y, float z) override;
void applyForce(float x, float y, float z, float rx, float ry, float rz) override;
void applyLocalForce(float x, float y, float z, float rx, float ry, float rz) override;
void applyImpulse(float x, float y, float z, float rx, float ry, float rz) override;
void applyLocalImpulse(float x, float y, float z, float rx, float ry, float rz) override;
void applyTorque(float x, float y, float z) override;
void applyLocalTorque(float x, float y, float z) override;
uint32_t getGroup() override;
void setGroup(uint32_t g) override;
uint32_t getMask() override;
void setMask(uint32_t m) override;
uint32_t getObjectID() const override;
private:
std::unique_ptr<IRigidBody> _impl;
};
} // namespace physics
} // namespace cc

173
cocos/physics/sdk/Shape.cpp Normal file
View File

@@ -0,0 +1,173 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "physics/sdk/Shape.h"
#include "base/memory/Memory.h"
#include "physics/PhysicsSelector.h"
#define CC_PHYSICS_SHAPE_DEFINITION(CLASS, WRAPPED) \
\
CLASS::CLASS() { \
_impl.reset(ccnew WRAPPED()); \
} \
\
CLASS::~CLASS() { \
_impl.reset(nullptr); \
} \
\
void CLASS::initialize(Node *node) { \
_impl->initialize(node); \
} \
\
void CLASS::onEnable() { \
_impl->onEnable(); \
} \
\
void CLASS::onDisable() { \
_impl->onDisable(); \
} \
\
void CLASS::onDestroy() { \
_impl->onDestroy(); \
} \
\
void CLASS::setMaterial(uint16_t ID, float f, float df, float r, \
uint8_t m0, uint8_t m1) { \
_impl->setMaterial(ID, f, df, r, m0, m1); \
} \
\
void CLASS::setAsTrigger(bool v) { \
_impl->setAsTrigger(v); \
} \
\
void CLASS::setCenter(float x, float y, float z) { \
_impl->setCenter(x, y, z); \
} \
\
void CLASS::setGroup(uint32_t g) { \
_impl->setGroup(g); \
} \
\
uint32_t CLASS::getGroup() { \
return _impl->getGroup(); \
} \
\
void CLASS::setMask(uint32_t m) { \
_impl->setMask(m); \
} \
\
uint32_t CLASS::getMask() { \
return _impl->getMask(); \
} \
\
void CLASS::updateEventListener(EShapeFilterFlag v) { \
_impl->updateEventListener(v); \
} \
\
geometry::AABB &CLASS::getAABB() { \
return _impl->getAABB(); \
} \
\
geometry::Sphere &CLASS::getBoundingSphere() { \
return _impl->getBoundingSphere(); \
} \
\
uint32_t CLASS::getObjectID() const { \
return _impl->getObjectID(); \
}
namespace cc {
namespace physics {
/// COMMON ///
CC_PHYSICS_SHAPE_DEFINITION(SphereShape, WrappedSphereShape)
CC_PHYSICS_SHAPE_DEFINITION(BoxShape, WrappedBoxShape)
CC_PHYSICS_SHAPE_DEFINITION(PlaneShape, WrappedPlaneShape)
CC_PHYSICS_SHAPE_DEFINITION(CapsuleShape, WrappedCapsuleShape)
CC_PHYSICS_SHAPE_DEFINITION(CylinderShape, WrappedCylinderShape)
CC_PHYSICS_SHAPE_DEFINITION(ConeShape, WrappedConeShape)
CC_PHYSICS_SHAPE_DEFINITION(TrimeshShape, WrappedTrimeshShape)
CC_PHYSICS_SHAPE_DEFINITION(TerrainShape, WrappedTerrainShape)
/// EXTRAS ///
void SphereShape::setRadius(float v) {
_impl->setRadius(v);
}
void BoxShape::setSize(float x, float y, float z) {
_impl->setSize(x, y, z);
}
void CapsuleShape::setRadius(float v) {
_impl->setRadius(v);
}
void CapsuleShape::setCylinderHeight(float v) {
_impl->setCylinderHeight(v);
}
void CapsuleShape::setDirection(EAxisDirection v) {
_impl->setDirection(v);
}
void PlaneShape::setConstant(float v) {
_impl->setConstant(v);
}
void PlaneShape::setNormal(float x, float y, float z) {
_impl->setNormal(x, y, z);
}
void TrimeshShape::setMesh(uint32_t objectID) {
_impl->setMesh(objectID);
}
void TrimeshShape::useConvex(bool v) {
_impl->useConvex(v);
}
void TerrainShape::setTerrain(uint32_t objectID, float rs, float cs, float hs) {
_impl->setTerrain(objectID, rs, cs, hs);
}
void CylinderShape::setConvex(uint32_t objectID) {
_impl->setConvex(objectID);
}
void CylinderShape::setCylinder(float r, float h, EAxisDirection d) {
_impl->setCylinder(r, h, d);
}
void ConeShape::setConvex(uint32_t objectID) {
_impl->setConvex(objectID);
}
void ConeShape::setCone(float r, float h, EAxisDirection d) {
_impl->setCone(r, h, d);
}
} // namespace physics
} // namespace cc

107
cocos/physics/sdk/Shape.h Normal file
View File

@@ -0,0 +1,107 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include <cstdint>
#include <memory>
#include "base/Macros.h"
#include "core/geometry/AABB.h"
#include "core/geometry/Sphere.h"
#include "physics/spec/IShape.h"
#define CC_PHYSICS_SHAPE_CLASS(CLASS) \
class CC_DLL CLASS final : public I##CLASS { \
protected: \
std::unique_ptr<I##CLASS> _impl; \
\
public: \
CLASS(); \
~CLASS() override; \
void initialize(Node *node) override; \
void onEnable() override; \
void onDisable() override; \
void onDestroy() override; \
void setMaterial(uint16_t ID, float f, float df, float r, \
uint8_t m0, uint8_t m1) override; \
void setAsTrigger(bool v) override; \
void setCenter(float x, float y, float z) override; \
void updateEventListener(EShapeFilterFlag v) override; \
geometry::AABB &getAABB() override; \
geometry::Sphere &getBoundingSphere() override; \
uint32_t getGroup() override; \
void setGroup(uint32_t g) override; \
uint32_t getMask() override; \
void setMask(uint32_t m) override; \
uint32_t getObjectID() const override;
namespace cc {
namespace physics {
CC_PHYSICS_SHAPE_CLASS(SphereShape)
void setRadius(float v) override;
}; // namespace physics
CC_PHYSICS_SHAPE_CLASS(BoxShape)
void setSize(float x, float y, float z) override;
}; // namespace cc
CC_PHYSICS_SHAPE_CLASS(CapsuleShape)
void setRadius(float v) override;
void setCylinderHeight(float v) override;
void setDirection(EAxisDirection v) override;
}
;
CC_PHYSICS_SHAPE_CLASS(PlaneShape)
void setConstant(float v) override;
void setNormal(float x, float y, float z) override;
}
;
CC_PHYSICS_SHAPE_CLASS(TrimeshShape)
void setMesh(uint32_t objectID) override;
void useConvex(bool v) override;
}
;
CC_PHYSICS_SHAPE_CLASS(CylinderShape)
void setConvex(uint32_t objectID) override;
void setCylinder(float r, float h, EAxisDirection d) override;
}
;
CC_PHYSICS_SHAPE_CLASS(ConeShape)
void setConvex(uint32_t objectID) override;
void setCone(float r, float h, EAxisDirection d) override;
}
;
CC_PHYSICS_SHAPE_CLASS(TerrainShape)
void setTerrain(uint32_t objectID, float rs, float cs, float hs) override;
}
;
} // namespace physics
} // namespace cc

182
cocos/physics/sdk/World.cpp Normal file
View File

@@ -0,0 +1,182 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "physics/sdk/World.h"
#include <memory>
#include "physics/PhysicsSelector.h"
namespace cc {
namespace physics {
World::World() {
_impl = std::make_unique<WrappedWorld>();
}
World::~World() {
_impl.reset(nullptr);
}
void World::emitEvents() {
_impl->emitEvents();
}
void World::step(float fixedTimeStep) {
_impl->step(fixedTimeStep);
}
void World::setAllowSleep(bool v) {
_impl->setAllowSleep(v);
}
void World::setGravity(float x, float y, float z) {
_impl->setGravity(x, y, z);
}
bool World::createMaterial(uint16_t id, float f, float df, float r,
uint8_t m0, uint8_t m1) {
return _impl->createMaterial(id, f, df, r, m0, m1);
}
void World::syncSceneToPhysics() {
_impl->syncSceneToPhysics();
}
void World::syncSceneWithCheck() {
_impl->syncSceneWithCheck();
}
void World::destroy() {
_impl->destroy();
}
ccstd::vector<std::shared_ptr<TriggerEventPair>> &World::getTriggerEventPairs() {
return _impl->getTriggerEventPairs();
}
ccstd::vector<std::shared_ptr<ContactEventPair>> &World::getContactEventPairs() {
return _impl->getContactEventPairs();
}
ccstd::vector<std::shared_ptr<CCTShapeEventPair>>& World::getCCTShapeEventPairs() {
return _impl->getCCTShapeEventPairs();
}
ccstd::vector<std::shared_ptr<CCTTriggerEventPair>> &World::getCCTTriggerEventPairs() {
return _impl->getCCTTriggerEventPairs();
}
void World::setDebugDrawFlags(EPhysicsDrawFlags flags) {
_impl->setDebugDrawFlags(flags);
}
EPhysicsDrawFlags World::getDebugDrawFlags() {
return _impl->getDebugDrawFlags();
}
void World::setDebugDrawConstraintSize(float size) {
_impl->setDebugDrawConstraintSize(size);
}
float World::getDebugDrawConstraintSize() {
return _impl->getDebugDrawConstraintSize();
}
void World::setCollisionMatrix(uint32_t i, uint32_t m) {
_impl->setCollisionMatrix(i, m);
}
uint32_t World::createConvex(ConvexDesc &desc) {
return _impl->createConvex(desc);
}
uint32_t World::createTrimesh(TrimeshDesc &desc) {
return _impl->createTrimesh(desc);
}
uint32_t World::createHeightField(HeightFieldDesc &desc) {
return _impl->createHeightField(desc);
}
bool World::raycast(RaycastOptions &opt) {
return _impl->raycast(opt);
}
ccstd::vector<RaycastResult> &World::raycastResult() {
return _impl->raycastResult();
}
bool World::raycastClosest(RaycastOptions &opt) {
return _impl->raycastClosest(opt);
}
RaycastResult &World::raycastClosestResult() {
return _impl->raycastClosestResult();
}
float World::getFixedTimeStep() const {
return _impl->getFixedTimeStep();
}
void World::setFixedTimeStep(float fixedTimeStep) {
_impl->setFixedTimeStep(fixedTimeStep);
}
bool World::sweepBox(RaycastOptions &opt, float halfExtentX, float halfExtentY, float halfExtentZ,
float orientationW, float orientationX, float orientationY, float orientationZ){
return _impl->sweepBox(opt, halfExtentX, halfExtentY, halfExtentZ, orientationW, orientationX, orientationY, orientationZ);
}
bool World::sweepBoxClosest(RaycastOptions &opt, float halfExtentX, float halfExtentY, float halfExtentZ,
float orientationW, float orientationX, float orientationY, float orientationZ){
return _impl->sweepBoxClosest(opt, halfExtentX, halfExtentY, halfExtentZ, orientationW, orientationX, orientationY, orientationZ);
}
bool World::sweepSphere(RaycastOptions &opt, float radius) {
return _impl->sweepSphere(opt, radius);
}
bool World::sweepSphereClosest(RaycastOptions &opt, float radius) {
return _impl->sweepSphereClosest(opt, radius);
}
bool World::sweepCapsule(RaycastOptions &opt, float radius, float height,
float orientationW, float orientationX, float orientationY, float orientationZ) {
return _impl->sweepCapsule(opt, radius, height, orientationW, orientationX, orientationY, orientationZ);
}
bool World::sweepCapsuleClosest(RaycastOptions &opt, float radius, float height,
float orientationW, float orientationX, float orientationY, float orientationZ) {
return _impl->sweepCapsuleClosest(opt, radius, height, orientationW, orientationX, orientationY, orientationZ);
}
RaycastResult &World::sweepClosestResult() {
return _impl->sweepClosestResult();
}
ccstd::vector<RaycastResult> &World::sweepResult() {
return _impl->sweepResult();
}
} // namespace physics
} // namespace cc

83
cocos/physics/sdk/World.h Normal file
View File

@@ -0,0 +1,83 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include <memory>
#include "base/Macros.h"
#include "physics/spec/IWorld.h"
namespace cc {
namespace physics {
class CC_DLL World final : public IPhysicsWorld {
public:
World();
~World() override;
void setGravity(float x, float y, float z) override;
void setAllowSleep(bool v) override;
void step(float fixedTimeStep) override;
void emitEvents() override;
void syncSceneToPhysics() override;
void syncSceneWithCheck() override;
void setDebugDrawFlags(EPhysicsDrawFlags flags) override;
EPhysicsDrawFlags getDebugDrawFlags() override;
void setDebugDrawConstraintSize(float size) override;
float getDebugDrawConstraintSize() override;
void setCollisionMatrix(uint32_t i, uint32_t m) override;
ccstd::vector<std::shared_ptr<TriggerEventPair>> &getTriggerEventPairs() override;
ccstd::vector<std::shared_ptr<ContactEventPair>>& getContactEventPairs() override;
ccstd::vector<std::shared_ptr<CCTShapeEventPair>>& getCCTShapeEventPairs() override;
ccstd::vector<std::shared_ptr<CCTTriggerEventPair>>& getCCTTriggerEventPairs() override;
bool raycast(RaycastOptions &opt) override;
bool raycastClosest(RaycastOptions &opt) override;
ccstd::vector<RaycastResult> &raycastResult() override;
RaycastResult &raycastClosestResult() override;
bool sweepBox(RaycastOptions &opt, float halfExtentX, float halfExtentY, float halfExtentZ,
float orientationW, float orientationX, float orientationY, float orientationZ) override;
bool sweepBoxClosest(RaycastOptions &opt, float halfExtentX, float halfExtentY, float halfExtentZ,
float orientationW, float orientationX, float orientationY, float orientationZ) override;
bool sweepSphere(RaycastOptions &opt, float radius) override;
bool sweepSphereClosest(RaycastOptions &opt, float radius) override;
bool sweepCapsule(RaycastOptions &opt, float radius, float height,
float orientationW, float orientationX, float orientationY, float orientationZ) override;
bool sweepCapsuleClosest(RaycastOptions &opt, float radius, float height,
float orientationW, float orientationX, float orientationY, float orientationZ) override;
RaycastResult &sweepClosestResult() override;
ccstd::vector<RaycastResult> &sweepResult() override;
uint32_t createConvex(ConvexDesc &desc) override;
uint32_t createTrimesh(TrimeshDesc &desc) override;
uint32_t createHeightField(HeightFieldDesc &desc) override;
bool createMaterial(uint16_t id, float f, float df, float r,
uint8_t m0, uint8_t m1) override;
float getFixedTimeStep() const override;
void setFixedTimeStep(float fixedTimeStep) override;
void destroy() override;
private:
std::unique_ptr<IPhysicsWorld> _impl;
};
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,81 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "core/scene-graph/Node.h"
#include "math/Vec3.h"
#include "physics/spec/ILifecycle.h"
namespace cc {
namespace physics {
enum class ERigidBodyType : uint8_t {
DYNAMIC = 1,
STATIC = 2,
KINEMATIC = 4,
};
class IRigidBody : public ILifecycle {
public:
~IRigidBody() override = default;
virtual void initialize(Node *node, ERigidBodyType t, uint32_t g) = 0;
virtual bool isAwake() = 0;
virtual bool isSleepy() = 0;
virtual bool isSleeping() = 0;
virtual void setType(ERigidBodyType v) = 0;
virtual void setMass(float v) = 0;
virtual void setLinearDamping(float v) = 0;
virtual void setAngularDamping(float v) = 0;
virtual void useGravity(bool v) = 0;
virtual void useCCD(bool v) = 0;
virtual void setLinearFactor(float x, float y, float z) = 0;
virtual void setAngularFactor(float x, float y, float z) = 0;
virtual void setAllowSleep(bool v) = 0;
virtual void wakeUp() = 0;
virtual void sleep() = 0;
virtual void clearState() = 0;
virtual void clearForces() = 0;
virtual void clearVelocity() = 0;
virtual void setSleepThreshold(float v) = 0;
virtual float getSleepThreshold() = 0;
virtual cc::Vec3 getLinearVelocity() = 0;
virtual void setLinearVelocity(float x, float y, float z) = 0;
virtual cc::Vec3 getAngularVelocity() = 0;
virtual void setAngularVelocity(float x, float y, float z) = 0;
virtual void applyForce(float x, float y, float z, float rx, float ry, float rz) = 0;
virtual void applyLocalForce(float x, float y, float z, float rx, float ry, float rz) = 0;
virtual void applyImpulse(float x, float y, float z, float rx, float ry, float rz) = 0;
virtual void applyLocalImpulse(float x, float y, float z, float rx, float ry, float rz) = 0;
virtual void applyTorque(float x, float y, float z) = 0;
virtual void applyLocalTorque(float x, float y, float z) = 0;
virtual uint32_t getGroup() = 0;
virtual void setGroup(uint32_t g) = 0;
virtual uint32_t getMask() = 0;
virtual void setMask(uint32_t m) = 0;
virtual uint32_t getObjectID() const = 0;
};
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,81 @@
/****************************************************************************
Copyright (c) 2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "core/scene-graph/Node.h"
#include "math/Vec3.h"
#include "physics/spec/ILifecycle.h"
#include "physics/spec/IShape.h"
namespace cc {
namespace physics {
class IBaseCharacterController : virtual public ILifecycle {
public:
~IBaseCharacterController() override = default;
virtual bool initialize(Node *node) = 0;
virtual void setStepOffset(float v) = 0;
virtual float getStepOffset() = 0;
virtual void setSlopeLimit(float v) = 0;
virtual float getSlopeLimit() = 0;
virtual void setContactOffset(float v) = 0;
virtual float getContactOffset() = 0;
virtual void setDetectCollisions(bool v) = 0;
virtual void setOverlapRecovery(bool v) = 0;
virtual void setCenter(float x, float y, float z) = 0;
virtual cc::Vec3 getPosition() = 0;
virtual void setPosition(float x, float y, float z) = 0;
virtual bool onGround() = 0;
virtual void move(float x, float y, float z, float minDist, float elapsedTime) = 0;
virtual void syncPhysicsToScene() = 0;
virtual uint32_t getGroup() = 0;
virtual void setGroup(uint32_t g) = 0;
virtual uint32_t getMask() = 0;
virtual void setMask(uint32_t m) = 0;
virtual void updateEventListener(EShapeFilterFlag flag) = 0;
virtual uint32_t getObjectID() const = 0;
};
class ICapsuleCharacterController : virtual public IBaseCharacterController {
public:
~ICapsuleCharacterController() override = default;
virtual void setRadius(float v) = 0;
virtual void setHeight(float v) = 0;
};
class IBoxCharacterController : virtual public IBaseCharacterController {
public:
~IBoxCharacterController() override = default;
virtual void setHalfHeight(float v) = 0;
virtual void setHalfSideExtent(float v) = 0;
virtual void setHalfForwardExtent(float v) = 0;
};
} // namespace physics
} // namespace cc

113
cocos/physics/spec/IJoint.h Normal file
View File

@@ -0,0 +1,113 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include <cstdint>
#include "core/scene-graph/Node.h"
#include "physics/spec/ILifecycle.h"
namespace cc {
namespace physics {
class IBaseJoint : virtual public ILifecycle {
public:
~IBaseJoint() override = default;
virtual void initialize(Node *node) = 0;
virtual void setEnableCollision(bool v) = 0;
virtual void setConnectedBody(uint32_t rigidBodyID) = 0;
virtual uint32_t getObjectID() const = 0;
};
class ISphericalJoint : virtual public IBaseJoint {
public:
~ISphericalJoint() override = default;
virtual void setPivotA(float x, float y, float z) = 0;
virtual void setPivotB(float x, float y, float z) = 0;
};
class IRevoluteJoint : virtual public IBaseJoint {
public:
~IRevoluteJoint() override = default;
virtual void setPivotA(float x, float y, float z) = 0;
virtual void setPivotB(float x, float y, float z) = 0;
virtual void setAxis(float x, float y, float z) = 0;
virtual void setLimitEnabled(bool v) = 0;
virtual void setLowerLimit(float v) = 0;
virtual void setUpperLimit(float v) = 0;
virtual void setMotorEnabled(bool v) = 0;
virtual void setMotorVelocity(float v) = 0;
virtual void setMotorForceLimit(float v) = 0;
};
class IFixedJoint : virtual public IBaseJoint {
public:
~IFixedJoint() override = default;
virtual void setBreakForce(float force) = 0;
virtual void setBreakTorque(float torque) = 0;
};
class IGenericJoint : virtual public IBaseJoint {
public:
~IGenericJoint() override = default;
virtual void setConstraintMode(uint32_t index, uint32_t mode) = 0;
virtual void setLinearLimit(uint32_t index, float lower, float upper) = 0;
virtual void setAngularExtent(float twist, float swing1, float swing2) = 0;
virtual void setLinearSoftConstraint(bool enable) = 0;
virtual void setLinearStiffness(float stiffness) = 0;
virtual void setLinearDamping(float damping) = 0;
virtual void setLinearRestitution(float restitution) = 0;
virtual void setSwingSoftConstraint(bool enable) = 0;
virtual void setTwistSoftConstraint(bool enable) = 0;
virtual void setSwingStiffness(float stiffness) = 0;
virtual void setSwingDamping(float damping) = 0;
virtual void setSwingRestitution(float restitution) = 0;
virtual void setTwistStiffness(float stiffness) = 0;
virtual void setTwistDamping(float damping) = 0;
virtual void setTwistRestitution(float restitution) = 0;
// motor
virtual void setDriverMode(uint32_t index, uint32_t mode) = 0;
virtual void setLinearMotorTarget(float x, float y, float z) = 0;
virtual void setLinearMotorVelocity(float x, float y, float z) = 0;
virtual void setLinearMotorForceLimit(float limit) = 0;
virtual void setAngularMotorTarget(float x, float y, float z) = 0;
virtual void setAngularMotorVelocity(float x, float y, float z) = 0;
virtual void setAngularMotorForceLimit(float limit) = 0;
virtual void setPivotA(float x, float y, float z) = 0;
virtual void setPivotB(float x, float y, float z) = 0;
virtual void setAutoPivotB(bool enable) = 0;
virtual void setAxis(float x, float y, float z) = 0;
virtual void setSecondaryAxis(float x, float y, float z) = 0;
virtual void setBreakForce(float force) = 0;
virtual void setBreakTorque(float torque) = 0;
};
} // namespace physics
} // namespace cc

View File

@@ -0,0 +1,40 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include <cstdint>
#include "base/TypeDef.h"
namespace cc {
namespace physics {
class ILifecycle {
public:
virtual ~ILifecycle() = default;
virtual void onEnable() = 0;
virtual void onDisable() = 0;
virtual void onDestroy() = 0;
};
} // namespace physics
} // namespace cc

130
cocos/physics/spec/IShape.h Normal file
View File

@@ -0,0 +1,130 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include <cstdint>
#include "core/geometry/AABB.h"
#include "core/geometry/Sphere.h"
#include "core/scene-graph/Node.h"
#include "physics/spec/ILifecycle.h"
namespace cc {
namespace physics {
enum class EAxisDirection : uint8_t {
X_AXIS,
Y_AXIS,
Z_AXIS,
};
enum class EShapeFilterFlag : uint8_t {
NONE = 0,
IS_TRIGGER = 1 << 0,
NEED_EVENT = 1 << 1,
NEED_CONTACT_DATA = 1 << 2,
DETECT_CONTACT_CCD = 1 << 3,
};
class IBaseShape : virtual public ILifecycle {
public:
~IBaseShape() override = default;
;
virtual void initialize(Node *node) = 0;
virtual void setMaterial(uint16_t id, float f, float df, float r,
uint8_t m0, uint8_t m1) = 0;
virtual void setAsTrigger(bool v) = 0;
virtual void setCenter(float x, float y, float z) = 0;
virtual geometry::AABB &getAABB() = 0;
virtual geometry::Sphere &getBoundingSphere() = 0;
virtual void updateEventListener(EShapeFilterFlag flag) = 0;
virtual uint32_t getGroup() = 0;
virtual void setGroup(uint32_t g) = 0;
virtual uint32_t getMask() = 0;
virtual void setMask(uint32_t m) = 0;
virtual uint32_t getObjectID() const = 0;
};
class ISphereShape : virtual public IBaseShape {
public:
~ISphereShape() override = default;
;
virtual void setRadius(float v) = 0;
};
class IBoxShape : virtual public IBaseShape {
public:
~IBoxShape() override = default;
;
virtual void setSize(float x, float y, float z) = 0;
};
class ICapsuleShape : virtual public IBaseShape {
public:
~ICapsuleShape() override = default;
;
virtual void setRadius(float v) = 0;
virtual void setCylinderHeight(float v) = 0;
virtual void setDirection(EAxisDirection v) = 0;
};
class ICylinderShape : virtual public IBaseShape {
public:
~ICylinderShape() override = default;
;
virtual void setConvex(uint32_t ObjectID) = 0;
virtual void setCylinder(float r, float h, EAxisDirection d) = 0;
};
class IConeShape : virtual public IBaseShape {
public:
~IConeShape() override = default;
;
virtual void setConvex(uint32_t ObjectID) = 0;
virtual void setCone(float r, float h, EAxisDirection d) = 0;
};
class IPlaneShape : virtual public IBaseShape {
public:
~IPlaneShape() override = default;
;
virtual void setConstant(float v) = 0;
virtual void setNormal(float x, float y, float z) = 0;
};
class ITrimeshShape : virtual public IBaseShape {
public:
~ITrimeshShape() override = default;
;
virtual void setMesh(uint32_t ObjectID) = 0;
virtual void useConvex(bool v) = 0;
};
class ITerrainShape : virtual public IBaseShape {
public:
virtual void setTerrain(uint32_t ObjectID, float rs, float cs, float hs) = 0;
};
} // namespace physics
} // namespace cc

190
cocos/physics/spec/IWorld.h Normal file
View File

@@ -0,0 +1,190 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include <cstdint>
#include <memory>
#include "base/TypeDef.h"
#include "base/std/container/vector.h"
#include "math/Vec3.h"
namespace cc {
namespace physics {
enum class ETouchState : uint8_t {
ENTER = 0,
STAY = 1,
EXIT = 2,
};
enum class EPhysicsDrawFlags : uint32_t {
NONE = 0,
WIRE_FRAME = 0x0001,
CONSTRAINT = 0x0002,
AABB = 0x0004
};
struct TriggerEventPair {
uint32_t shapeA; //wrapper object ID
uint32_t shapeB; //wrapper object ID
ETouchState state;
static constexpr uint8_t COUNT = 3;
TriggerEventPair(const uint32_t a, const uint32_t b)
: shapeA(a),
shapeB(b),
state(ETouchState::ENTER) {}
};
struct ContactPoint {
Vec3 position;
float separation;
Vec3 normal;
uint32_t internalFaceIndex0;
Vec3 impulse;
uint32_t internalFaceIndex1;
static constexpr uint8_t COUNT = 12;
};
struct ContactEventPair {
uint32_t shapeA; //wrapper object ID
uint32_t shapeB; //wrapper object ID
ETouchState state;
ccstd::vector<ContactPoint> contacts;
static constexpr uint8_t COUNT = 4;
ContactEventPair(const uint32_t a, const uint32_t b)
: shapeA(a),
shapeB(b),
state(ETouchState::ENTER) {}
};
struct CharacterControllerContact {
Vec3 worldPosition;
Vec3 worldNormal;
Vec3 motionDirection;
float motionLength;
static constexpr uint8_t COUNT = 10;
};
struct CCTShapeEventPair {
uint32_t cct; //wrapper object ID
uint32_t shape; //wrapper object ID
//ETouchState state;
ccstd::vector<CharacterControllerContact> contacts;
static constexpr uint8_t COUNT = 3;
CCTShapeEventPair(const uint32_t cct, const uint32_t shape)
: cct(cct), shape(shape) {
}
};
struct CCTTriggerEventPair {
uint32_t cct; //wrapper object ID
uint32_t shape; //wrapper object ID
ETouchState state;
static constexpr uint8_t COUNT = 3;
CCTTriggerEventPair(const uint32_t cct, const uint32_t shape)
: cct(cct),
shape(shape),
state(ETouchState::ENTER) {}
};
struct ConvexDesc {
void *positions;
uint32_t positionLength;
};
struct TrimeshDesc : ConvexDesc {
void *triangles;
uint32_t triangleLength;
bool isU16;
};
struct HeightFieldDesc {
uint32_t rows;
uint32_t columns;
void *samples;
};
struct RaycastOptions {
Vec3 origin;
float distance;
Vec3 unitDir;
uint32_t mask;
bool queryTrigger;
};
struct RaycastResult {
uint32_t shape{0};
Vec3 hitPoint;
float distance;
Vec3 hitNormal;
RaycastResult() = default;
};
class IPhysicsWorld {
public:
virtual ~IPhysicsWorld() = default;
;
virtual void setGravity(float x, float y, float z) = 0;
virtual void setAllowSleep(bool v) = 0;
virtual void step(float s) = 0;
virtual void emitEvents() = 0;
virtual void syncSceneToPhysics() = 0;
virtual void syncSceneWithCheck() = 0;
virtual void destroy() = 0;
virtual void setDebugDrawFlags(EPhysicsDrawFlags f) = 0;
virtual EPhysicsDrawFlags getDebugDrawFlags() = 0;
virtual void setDebugDrawConstraintSize(float s) = 0;
virtual float getDebugDrawConstraintSize() = 0;
virtual void setCollisionMatrix(uint32_t i, uint32_t m) = 0;
virtual ccstd::vector<std::shared_ptr<TriggerEventPair>> &getTriggerEventPairs() = 0;
virtual ccstd::vector<std::shared_ptr<ContactEventPair>>& getContactEventPairs() = 0;
virtual ccstd::vector<std::shared_ptr<CCTShapeEventPair>>& getCCTShapeEventPairs() = 0;
virtual ccstd::vector<std::shared_ptr<CCTTriggerEventPair>> &getCCTTriggerEventPairs() = 0;
virtual bool raycast(RaycastOptions &opt) = 0;
virtual bool raycastClosest(RaycastOptions &opt) = 0;
virtual ccstd::vector<RaycastResult> &raycastResult() = 0;
virtual RaycastResult &raycastClosestResult() = 0;
virtual bool sweepBox(RaycastOptions &opt, float halfExtentX, float halfExtentY, float halfExtentZ,
float orientationW, float orientationX, float orientationY, float orientationZ) = 0;
virtual bool sweepBoxClosest(RaycastOptions &opt, float halfExtentX, float halfExtentY, float halfExtentZ,
float orientationW, float orientationX, float orientationY, float orientationZ) = 0;
virtual bool sweepSphere(RaycastOptions &opt, float radius) = 0;
virtual bool sweepSphereClosest(RaycastOptions &opt, float radius) = 0;
virtual bool sweepCapsule(RaycastOptions &opt, float radius, float height,
float orientationW, float orientationX, float orientationY, float orientationZ) = 0;
virtual bool sweepCapsuleClosest(RaycastOptions &opt, float radius, float height,
float orientationW, float orientationX, float orientationY, float orientationZ) = 0;
virtual RaycastResult &sweepClosestResult() = 0;
virtual ccstd::vector<RaycastResult> &sweepResult() = 0;
virtual uint32_t createConvex(ConvexDesc &desc) = 0;
virtual uint32_t createTrimesh(TrimeshDesc &desc) = 0;
virtual uint32_t createHeightField(HeightFieldDesc &desc) = 0;
virtual bool createMaterial(uint16_t id, float f, float df, float r,
uint8_t m0, uint8_t m1) = 0;
virtual void setFixedTimeStep(float v) = 0;
virtual float getFixedTimeStep() const = 0;
};
} // namespace physics
} // namespace cc