2021-12-25 10:04:45 +08:00
|
|
|
/****************************************************************************
|
|
|
|
Copyright (c) 2015-2016 Chukong Technologies Inc.
|
|
|
|
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
2024-03-30 08:56:32 +08:00
|
|
|
Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md).
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2022-10-01 16:24:52 +08:00
|
|
|
https://axmolengine.github.io/
|
2021-12-25 10:04:45 +08:00
|
|
|
|
|
|
|
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.
|
|
|
|
****************************************************************************/
|
2019-11-23 20:27:39 +08:00
|
|
|
|
2023-06-11 13:08:08 +08:00
|
|
|
#include "physics3d/Physics3D.h"
|
|
|
|
#include "2d/Node.h"
|
|
|
|
#include "2d/Scene.h"
|
2019-11-23 20:27:39 +08:00
|
|
|
|
2024-03-30 08:56:32 +08:00
|
|
|
#if defined(AX_ENABLE_3D_PHYSICS)
|
2019-11-23 20:27:39 +08:00
|
|
|
|
2022-07-16 10:43:05 +08:00
|
|
|
# if (AX_ENABLE_BULLET_INTEGRATION)
|
2019-11-23 20:27:39 +08:00
|
|
|
|
2022-07-11 17:50:21 +08:00
|
|
|
NS_AX_BEGIN
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
Physics3DComponent::~Physics3DComponent()
|
|
|
|
{
|
2022-07-16 10:43:05 +08:00
|
|
|
AX_SAFE_RELEASE(_physics3DObj);
|
2019-11-23 20:27:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
std::string& Physics3DComponent::getPhysics3DComponentName()
|
|
|
|
{
|
|
|
|
static std::string comName = "___Physics3DComponent___";
|
|
|
|
return comName;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Physics3DComponent::init()
|
|
|
|
{
|
|
|
|
setName(getPhysics3DComponentName());
|
|
|
|
return Component::init();
|
|
|
|
}
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
Physics3DComponent* Physics3DComponent::create(Physics3DObject* physicsObj,
|
2022-08-08 18:02:17 +08:00
|
|
|
const ax::Vec3& translateInPhysics,
|
|
|
|
const ax::Quaternion& rotInPhsyics)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
2021-12-08 00:11:53 +08:00
|
|
|
auto ret = new Physics3DComponent();
|
|
|
|
if (ret->init())
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
ret->setPhysics3DObject(physicsObj);
|
|
|
|
ret->setTransformInPhysics(translateInPhysics, rotInPhsyics);
|
|
|
|
ret->autorelease();
|
|
|
|
return ret;
|
|
|
|
}
|
2022-07-16 10:43:05 +08:00
|
|
|
AX_SAFE_DELETE(ret);
|
2019-11-23 20:27:39 +08:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Physics3DComponent::setPhysics3DObject(Physics3DObject* physicsObj)
|
|
|
|
{
|
2022-07-16 10:43:05 +08:00
|
|
|
AX_SAFE_RETAIN(physicsObj);
|
|
|
|
AX_SAFE_RELEASE(_physics3DObj);
|
2019-11-23 20:27:39 +08:00
|
|
|
_physics3DObj = physicsObj;
|
|
|
|
}
|
|
|
|
|
|
|
|
Physics3DComponent::Physics3DComponent()
|
2021-12-25 10:04:45 +08:00
|
|
|
: _physics3DObj(nullptr), _syncFlag(Physics3DComponent::PhysicsSyncFlag::NODE_AND_NODE)
|
|
|
|
{}
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
void Physics3DComponent::setEnabled(bool b)
|
|
|
|
{
|
|
|
|
bool oldBool = _enabled;
|
|
|
|
Component::setEnabled(b);
|
|
|
|
if (_physics3DObj && oldBool != _enabled)
|
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
_enabled ? _physics3DObj->getPhysicsWorld()->addPhysics3DObject(_physics3DObj)
|
|
|
|
: _physics3DObj->getPhysicsWorld()->removePhysics3DObject(_physics3DObj);
|
2019-11-23 20:27:39 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Physics3DComponent::addToPhysicsWorld(Physics3DWorld* world)
|
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
// add component to physics world
|
2019-11-23 20:27:39 +08:00
|
|
|
if (_physics3DObj)
|
|
|
|
{
|
|
|
|
_physics3DObj->setPhysicsWorld(world);
|
|
|
|
world->addPhysics3DObject(_physics3DObj);
|
|
|
|
auto& components = world->_physicsComponents;
|
2021-12-25 10:04:45 +08:00
|
|
|
auto it = std::find(components.begin(), components.end(), this);
|
2019-11-23 20:27:39 +08:00
|
|
|
if (it == components.end())
|
|
|
|
{
|
|
|
|
auto parent = _owner->getParent();
|
2021-12-25 10:04:45 +08:00
|
|
|
while (parent)
|
|
|
|
{
|
|
|
|
for (size_t i = 0; i < components.size(); i++)
|
|
|
|
{
|
2019-11-23 20:27:39 +08:00
|
|
|
if (parent == components[i]->getOwner())
|
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
// insert it here
|
2019-11-23 20:27:39 +08:00
|
|
|
components.insert(components.begin() + i, this);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
parent = parent->getParent();
|
|
|
|
}
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
components.insert(components.begin(), this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Physics3DComponent::onEnter()
|
|
|
|
{
|
|
|
|
Component::onEnter();
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
if (_physics3DObj->getPhysicsWorld() == nullptr && _owner)
|
|
|
|
{
|
|
|
|
auto scene = _owner->getScene();
|
|
|
|
if (scene)
|
|
|
|
addToPhysicsWorld(scene->getPhysics3DWorld());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Physics3DComponent::onExit()
|
|
|
|
{
|
|
|
|
Component::onExit();
|
|
|
|
setEnabled(false);
|
2021-12-25 10:04:45 +08:00
|
|
|
|
|
|
|
// remove component from physics world
|
2019-11-23 20:27:39 +08:00
|
|
|
if (_physics3DObj)
|
|
|
|
{
|
|
|
|
auto& components = _physics3DObj->getPhysicsWorld()->_physicsComponents;
|
2021-12-25 10:04:45 +08:00
|
|
|
auto it = std::find(components.begin(), components.end(), this);
|
2019-11-23 20:27:39 +08:00
|
|
|
if (it != components.end())
|
|
|
|
components.erase(it);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Physics3DComponent::preSimulate()
|
|
|
|
{
|
|
|
|
if (((int)_syncFlag & (int)Physics3DComponent::PhysicsSyncFlag::NODE_TO_PHYSICS) && _physics3DObj && _owner)
|
|
|
|
{
|
|
|
|
syncNodeToPhysics();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Physics3DComponent::postSimulate()
|
|
|
|
{
|
|
|
|
if (((int)_syncFlag & (int)Physics3DComponent::PhysicsSyncFlag::PHYSICS_TO_NODE) && _physics3DObj && _owner)
|
|
|
|
{
|
|
|
|
syncPhysicsToNode();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-08 18:02:17 +08:00
|
|
|
void Physics3DComponent::setTransformInPhysics(const ax::Vec3& translateInPhysics,
|
|
|
|
const ax::Quaternion& rotInPhsyics)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
Mat4::createRotation(rotInPhsyics, &_transformInPhysics);
|
|
|
|
_transformInPhysics.m[12] = translateInPhysics.x;
|
|
|
|
_transformInPhysics.m[13] = translateInPhysics.y;
|
|
|
|
_transformInPhysics.m[14] = translateInPhysics.z;
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
_invTransformInPhysics = _transformInPhysics.getInversed();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Physics3DComponent::setSyncFlag(PhysicsSyncFlag syncFlag)
|
|
|
|
{
|
|
|
|
_syncFlag = syncFlag;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Physics3DComponent::syncPhysicsToNode()
|
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
if (_physics3DObj->getObjType() == Physics3DObject::PhysicsObjType::RIGID_BODY ||
|
|
|
|
_physics3DObj->getObjType() == Physics3DObject::PhysicsObjType::COLLIDER)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
Mat4 parentMat;
|
|
|
|
if (_owner->getParent())
|
|
|
|
parentMat = _owner->getParent()->getNodeToWorldTransform();
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
auto mat = parentMat.getInversed() * _physics3DObj->getWorldTransform();
|
2021-12-25 10:04:45 +08:00
|
|
|
// remove scale, no scale support for physics
|
2019-11-23 20:27:39 +08:00
|
|
|
float oneOverLen = 1.f / sqrtf(mat.m[0] * mat.m[0] + mat.m[1] * mat.m[1] + mat.m[2] * mat.m[2]);
|
|
|
|
mat.m[0] *= oneOverLen;
|
|
|
|
mat.m[1] *= oneOverLen;
|
|
|
|
mat.m[2] *= oneOverLen;
|
|
|
|
oneOverLen = 1.f / sqrtf(mat.m[4] * mat.m[4] + mat.m[5] * mat.m[5] + mat.m[6] * mat.m[6]);
|
|
|
|
mat.m[4] *= oneOverLen;
|
|
|
|
mat.m[5] *= oneOverLen;
|
|
|
|
mat.m[6] *= oneOverLen;
|
|
|
|
oneOverLen = 1.f / sqrtf(mat.m[8] * mat.m[8] + mat.m[9] * mat.m[9] + mat.m[10] * mat.m[10]);
|
|
|
|
mat.m[8] *= oneOverLen;
|
|
|
|
mat.m[9] *= oneOverLen;
|
|
|
|
mat.m[10] *= oneOverLen;
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2019-11-23 20:27:39 +08:00
|
|
|
mat *= _transformInPhysics;
|
|
|
|
static Vec3 scale, translation;
|
|
|
|
static Quaternion quat;
|
|
|
|
mat.decompose(&scale, &quat, &translation);
|
|
|
|
_owner->setPosition3D(translation);
|
|
|
|
quat.normalize();
|
|
|
|
_owner->setRotationQuat(quat);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Physics3DComponent::syncNodeToPhysics()
|
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
if (_physics3DObj->getObjType() == Physics3DObject::PhysicsObjType::RIGID_BODY ||
|
|
|
|
_physics3DObj->getObjType() == Physics3DObject::PhysicsObjType::COLLIDER)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
auto mat = _owner->getNodeToWorldTransform();
|
2021-12-25 10:04:45 +08:00
|
|
|
// remove scale, no scale support for physics
|
2019-11-23 20:27:39 +08:00
|
|
|
float oneOverLen = 1.f / sqrtf(mat.m[0] * mat.m[0] + mat.m[1] * mat.m[1] + mat.m[2] * mat.m[2]);
|
|
|
|
mat.m[0] *= oneOverLen;
|
|
|
|
mat.m[1] *= oneOverLen;
|
|
|
|
mat.m[2] *= oneOverLen;
|
|
|
|
oneOverLen = 1.f / sqrtf(mat.m[4] * mat.m[4] + mat.m[5] * mat.m[5] + mat.m[6] * mat.m[6]);
|
|
|
|
mat.m[4] *= oneOverLen;
|
|
|
|
mat.m[5] *= oneOverLen;
|
|
|
|
mat.m[6] *= oneOverLen;
|
|
|
|
oneOverLen = 1.f / sqrtf(mat.m[8] * mat.m[8] + mat.m[9] * mat.m[9] + mat.m[10] * mat.m[10]);
|
|
|
|
mat.m[8] *= oneOverLen;
|
|
|
|
mat.m[9] *= oneOverLen;
|
|
|
|
mat.m[10] *= oneOverLen;
|
2021-12-25 10:04:45 +08:00
|
|
|
|
|
|
|
mat *= _invTransformInPhysics;
|
2019-11-23 20:27:39 +08:00
|
|
|
if (_physics3DObj->getObjType() == Physics3DObject::PhysicsObjType::RIGID_BODY)
|
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
auto body = static_cast<Physics3DRigidBody*>(_physics3DObj)->getRigidBody();
|
2019-11-23 20:27:39 +08:00
|
|
|
auto motionState = body->getMotionState();
|
|
|
|
motionState->setWorldTransform(convertMat4TobtTransform(mat));
|
|
|
|
body->setMotionState(motionState);
|
|
|
|
}
|
|
|
|
else if (_physics3DObj->getObjType() == Physics3DObject::PhysicsObjType::COLLIDER)
|
|
|
|
{
|
|
|
|
auto object = static_cast<Physics3DCollider*>(_physics3DObj)->getGhostObject();
|
|
|
|
object->setWorldTransform(convertMat4TobtTransform(mat));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-11 17:50:21 +08:00
|
|
|
NS_AX_END
|
2019-11-23 20:27:39 +08:00
|
|
|
|
2022-07-16 10:43:05 +08:00
|
|
|
# endif // AX_ENABLE_BULLET_INTEGRATION
|
2019-11-23 20:27:39 +08:00
|
|
|
|
2024-03-30 08:56:32 +08:00
|
|
|
#endif // defined(AX_ENABLE_3D_PHYSICS)
|