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,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