├── plugins └── bullet │ ├── bullet.json │ ├── bodies │ ├── rigidspherebody.h │ ├── rigidboxbody.h │ ├── rigidconvexhullbody.h │ ├── rigidspherebody.cpp │ ├── rigidstaticplanebody.h │ ├── rigidboxbody.cpp │ ├── motionstate.h │ ├── rigidstaticplanebody.cpp │ ├── rigidconvexhullbody.cpp │ ├── abstractrigidbody.h │ ├── motionstate.cpp │ └── abstractrigidbody.cpp │ ├── dependencies.pri │ ├── bulletfactory.h │ ├── bullet.pro │ ├── worlds │ ├── dynamicsworld.h │ └── dynamicsworld.cpp │ └── bulletfactory.cpp ├── imports ├── qmldir ├── physics-qml_plugin.h ├── physics-qml_plugin.cpp └── imports.pro ├── examples ├── examples.pro └── aspect-test │ ├── qml.qrc │ ├── deployment.pri │ ├── main.cpp │ ├── main.qml │ ├── aspect-test.pro │ └── AnimatedEntity.qml ├── src ├── backend │ ├── physics_entities │ │ ├── physicsabstractsoftbody.cpp │ │ ├── physicsabstractrigidbody.cpp │ │ ├── physicsabstractdynamicsworld.cpp │ │ ├── physicsabstractsoftrigiddynamicsworld.cpp │ │ ├── physicsabstractsoftrigiddynamicsworld.h │ │ ├── physicsfactoryinterface.h │ │ ├── physicsabstractsoftbody.h │ │ ├── physicsabstractrigidbody.h │ │ └── physicsabstractdynamicsworld.h │ ├── jobs │ │ ├── simulatestepjob.cpp │ │ ├── simulatestepjob.h │ │ ├── debugjob.h │ │ ├── updatetransformsjob.h │ │ ├── notifycollisionsjob.h │ │ ├── insertphysicstransformjob.h │ │ ├── insertphysicstransformjob.cpp │ │ ├── debugjob.cpp │ │ ├── updatephysicsentitiesjob.h │ │ ├── notifycollisionsjob.cpp │ │ ├── updatetransformsjob.cpp │ │ └── updatephysicsentitiesjob.cpp │ ├── physicsmanager.h │ ├── physicscollision.h │ ├── backendtypes │ │ ├── physicssoftbodyinfobackendnode.h │ │ ├── physicsgeometry.h │ │ ├── physicstransform.h │ │ ├── physicsbuffer.h │ │ ├── physicsgeometryrenderer.h │ │ ├── physicsworldinfobackendnode.h │ │ ├── physicsentity.h │ │ ├── physicsattribute.h │ │ ├── physicssoftbodyinfobackendnode.cpp │ │ ├── physicsgeometry.cpp │ │ ├── physicstransform.cpp │ │ ├── physicsbuffer.cpp │ │ ├── physicsbodyinfobackendnode.h │ │ ├── physicsworldinfobackendnode.cpp │ │ ├── physicsgeometryrenderer.cpp │ │ ├── physicsentity.cpp │ │ ├── physicsattribute.cpp │ │ └── physicsbodyinfobackendnode.cpp │ ├── physicsmanager.cpp │ └── backend.pri ├── frontend │ ├── physicsquickbodyinfo.cpp │ ├── physicsquickbodyinfo.h │ ├── physicssoftbodyinfo.cpp │ ├── physicsaspect.h │ ├── frontend.pri │ ├── physicssoftbodyinfo.h │ ├── physicscollisionevent.cpp │ ├── physicsworldinfo.cpp │ ├── physicsworldinfo.h │ ├── physicscollisionevent.h │ ├── physicsbodyinfo.h │ ├── physicsaspect.cpp │ └── physicsbodyinfo.cpp ├── qtphysicsunofficial_global.h └── src.pro ├── config.tests └── bullet │ ├── bullet.pro │ └── main.cpp ├── qtphysics-unofficial.pro └── Readme.md /plugins/bullet/bullet.json: -------------------------------------------------------------------------------- 1 | { 2 | "Keys" : [ ] 3 | } 4 | -------------------------------------------------------------------------------- /imports/qmldir: -------------------------------------------------------------------------------- 1 | module QtPhysics.unofficial 2 | plugin physics 3 | -------------------------------------------------------------------------------- /examples/examples.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = subdirs 2 | 3 | SUBDIRS += \ 4 | aspect-test 5 | 6 | -------------------------------------------------------------------------------- /examples/aspect-test/qml.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | main.qml 4 | AnimatedEntity.qml 5 | Model1.dae 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/backend/physics_entities/physicsabstractsoftbody.cpp: -------------------------------------------------------------------------------- 1 | #include "physicsabstractsoftbody.h" 2 | 3 | namespace Physics { 4 | 5 | PhysicsAbstractSoftBody::PhysicsAbstractSoftBody(QObject *parent): 6 | QObject(parent) 7 | { 8 | 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/backend/physics_entities/physicsabstractrigidbody.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | namespace Physics { 3 | 4 | 5 | PhysicsAbstractRigidBody::PhysicsAbstractRigidBody(QObject *parent) : QObject(parent) 6 | { 7 | 8 | } 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/backend/physics_entities/physicsabstractdynamicsworld.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace Physics { 4 | 5 | PhysicsAbstractDynamicsWorld::PhysicsAbstractDynamicsWorld(QObject *parent) : QObject(parent) 6 | { 7 | 8 | } 9 | 10 | } 11 | -------------------------------------------------------------------------------- /config.tests/bullet/bullet.pro: -------------------------------------------------------------------------------- 1 | include("../../plugins/bullet/dependencies.pri") 2 | 3 | SOURCES += main.cpp 4 | 5 | INCLUDEPATH += $${BULLET_INCLUDE_PATH} 6 | LIBS += $${BULLET_LIBS_PATH} 7 | 8 | message("Bullet Include:"$${INCLUDEPATH}) 9 | message("Bullet Include:"$${LIBS}) 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/backend/physics_entities/physicsabstractsoftrigiddynamicsworld.cpp: -------------------------------------------------------------------------------- 1 | #include "physicsabstractsoftrigiddynamicsworld.h" 2 | 3 | namespace Physics { 4 | 5 | 6 | PhysicsAbstractSoftRigidDynamicsWorld::PhysicsAbstractSoftRigidDynamicsWorld(): 7 | PhysicsAbstractDynamicsWorld() 8 | { 9 | 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/frontend/physicsquickbodyinfo.cpp: -------------------------------------------------------------------------------- 1 | #include "physicsquickbodyinfo.h" 2 | #include "physicsbodyinfo.h" 3 | namespace Physics { 4 | 5 | PhysicsQuickBodyInfo::PhysicsQuickBodyInfo(QObject* parent) 6 | : QObject(parent) 7 | { 8 | Q_ASSERT(qobject_cast(parent) != Q_NULLPTR); 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /examples/aspect-test/deployment.pri: -------------------------------------------------------------------------------- 1 | 2 | #unix:!android { 3 | # isEmpty(target.path) { 4 | # qnx { 5 | # target.path = /tmp/$${TARGET}/bin 6 | # } else { 7 | # target.path = /opt/$${TARGET}/bin 8 | # } 9 | # export(target.path) 10 | # } 11 | # INSTALLS += target 12 | #} 13 | 14 | #export(INSTALLS) 15 | 16 | -------------------------------------------------------------------------------- /src/backend/jobs/simulatestepjob.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace Physics { 5 | 6 | SimulateStepJob::SimulateStepJob(PhysicsManager* manager): 7 | QAspectJob() 8 | { 9 | m_manager=manager; 10 | } 11 | void SimulateStepJob::run(){ 12 | m_manager->m_physics_world->stepSimulation(); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /imports/physics-qml_plugin.h: -------------------------------------------------------------------------------- 1 | #ifndef PHYSICS_QML_PLUGIN_H 2 | #define PHYSICS_QML_PLUGIN_H 3 | 4 | #include 5 | 6 | class Qml_PhysicsPlugin : public QQmlExtensionPlugin 7 | { 8 | Q_OBJECT 9 | Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") 10 | 11 | public: 12 | void registerTypes(const char *uri); 13 | }; 14 | 15 | #endif // PHYSICS_QML_PLUGIN_H 16 | 17 | -------------------------------------------------------------------------------- /src/frontend/physicsquickbodyinfo.h: -------------------------------------------------------------------------------- 1 | #ifndef PHYSICSQUICKBODYINFO_H 2 | #define PHYSICSQUICKBODYINFO_H 3 | #include 4 | #include "frontend_global.h" 5 | 6 | namespace Physics { 7 | 8 | class PhysicsBodyInfo; 9 | 10 | class FRONTENDSHARED_EXPORT PhysicsQuickBodyInfo : public QObject 11 | { 12 | Q_OBJECT 13 | public: 14 | explicit PhysicsQuickBodyInfo(QObject* parent=0); 15 | }; 16 | 17 | } 18 | 19 | #endif // PHYSICSQUICKBODYINFO_H 20 | -------------------------------------------------------------------------------- /src/qtphysicsunofficial_global.h: -------------------------------------------------------------------------------- 1 | #ifndef QTPHYSICSUNOFFICIAL_GLOBAL 2 | #define QTPHYSICSUNOFFICIAL_GLOBAL 3 | 4 | #if defined(QTPHYSICSUNOFFICIAL_LIBRARY) 5 | # define QTPHYSICSUNOFFICIAL_EXPORT Q_DECL_EXPORT 6 | #else 7 | # define QTPHYSICSUNOFFICIAL_EXPORT Q_DECL_IMPORT 8 | #endif 9 | 10 | #include 11 | #if (QT_VERSION > QT_VERSION_CHECK(5, 5, 0)) 12 | #include 13 | #else 14 | #include 15 | #endif 16 | 17 | #endif // QTPHYSICSUNOFFICIAL_GLOBAL 18 | -------------------------------------------------------------------------------- /src/backend/jobs/simulatestepjob.h: -------------------------------------------------------------------------------- 1 | #ifndef SimulateStepJob_H 2 | #define SimulateStepJob_H 3 | #include 4 | 5 | 6 | namespace Physics { 7 | 8 | class PhysicsManager; 9 | 10 | class QTPHYSICSUNOFFICIAL_EXPORT SimulateStepJob:public Qt3DCore::QAspectJob 11 | { 12 | public: 13 | explicit SimulateStepJob(PhysicsManager* manager); 14 | protected: 15 | void run() Q_DECL_OVERRIDE; 16 | private: 17 | PhysicsManager* m_manager; 18 | 19 | }; 20 | } 21 | #endif // SimulateStepJob_H 22 | -------------------------------------------------------------------------------- /src/backend/jobs/debugjob.h: -------------------------------------------------------------------------------- 1 | #ifndef DEBUGJOB_H 2 | #define DEBUGJOB_H 3 | #include 4 | 5 | namespace Physics { 6 | 7 | class PhysicsManager; 8 | 9 | class QTPHYSICSUNOFFICIAL_EXPORT DebugJob: public Qt3DCore::QAspectJob 10 | { 11 | 12 | public: 13 | DebugJob(PhysicsManager* manager); 14 | protected: 15 | void run() Q_DECL_OVERRIDE; 16 | private: 17 | void print(Qt3DCore::QNodeId id); 18 | PhysicsManager* m_manager; 19 | }; 20 | 21 | 22 | } 23 | 24 | #endif // DEBUGJOB_H 25 | -------------------------------------------------------------------------------- /src/backend/jobs/updatetransformsjob.h: -------------------------------------------------------------------------------- 1 | #ifndef UPDATETRANSFORMSJOB_H 2 | #define UPDATETRANSFORMSJOB_H 3 | #include 4 | 5 | 6 | namespace Physics { 7 | 8 | class PhysicsManager; 9 | 10 | class QTPHYSICSUNOFFICIAL_EXPORT UpdateTransformsJob: public Qt3DCore::QAspectJob 11 | { 12 | public: 13 | explicit UpdateTransformsJob(PhysicsManager* manager); 14 | protected: 15 | void run() Q_DECL_OVERRIDE; 16 | private: 17 | PhysicsManager* m_manager; 18 | }; 19 | } 20 | 21 | #endif // UPDATETRANSFORMSJOB_H 22 | -------------------------------------------------------------------------------- /qtphysics-unofficial.pro: -------------------------------------------------------------------------------- 1 | load(configure) 2 | qtCompileTest(bullet) 3 | 4 | TEMPLATE = subdirs 5 | CONFIG += ordered c++11 6 | CONFIG -= android_install 7 | 8 | qtHaveModule(3dcore){ 9 | SUBDIRS += \ 10 | src \ 11 | imports 12 | 13 | if(config_bullet){ 14 | message("Bullet found") 15 | SUBDIRS += \ 16 | plugins/bullet 17 | } 18 | else{ 19 | message("Bullet not found") 20 | } 21 | # SUBDIRS += examples 22 | }else{ 23 | message("Physics needs Qt3d 2.0") 24 | } 25 | #Add step make install INSTALL_ROOT=$BUILD_TARGET 26 | -------------------------------------------------------------------------------- /src/backend/jobs/notifycollisionsjob.h: -------------------------------------------------------------------------------- 1 | #ifndef NOTIFYCOLLISIONSJOB_H 2 | #define NOTIFYCOLLISIONSJOB_H 3 | #include 4 | 5 | 6 | namespace Physics { 7 | 8 | class PhysicsManager; 9 | class PhysicsBodyInfoBackendNode; 10 | class QTPHYSICSUNOFFICIAL_EXPORT NotifyCollisionsJob: public Qt3DCore::QAspectJob 11 | { 12 | public: 13 | explicit NotifyCollisionsJob(PhysicsManager* manager); 14 | protected: 15 | void run() Q_DECL_OVERRIDE; 16 | private: 17 | PhysicsManager* m_manager; 18 | }; 19 | } 20 | 21 | #endif // NOTIFYCOLLISIONSJOB_H 22 | -------------------------------------------------------------------------------- /plugins/bullet/bodies/rigidspherebody.h: -------------------------------------------------------------------------------- 1 | #ifndef RigidSphereBody_H 2 | #define RigidSphereBody_H 3 | 4 | #include 5 | 6 | namespace Physics { 7 | 8 | 9 | namespace Bullet { 10 | 11 | class RigidSphereBody: public AbstractRigidBody 12 | { 13 | Q_OBJECT 14 | 15 | public: 16 | explicit RigidSphereBody(QObject* parent=0); 17 | ~RigidSphereBody(); 18 | qreal radius(){return m_radius;} 19 | void setRadius(qreal radius); 20 | protected: 21 | virtual void initShape(); 22 | 23 | private: 24 | 25 | qreal m_radius; 26 | }; 27 | 28 | }} 29 | #endif // RigidSphereBody_H 30 | -------------------------------------------------------------------------------- /plugins/bullet/bodies/rigidboxbody.h: -------------------------------------------------------------------------------- 1 | #ifndef RigidBoxBody_H 2 | #define RigidBoxBody_H 3 | 4 | #include 5 | #include 6 | 7 | namespace Physics { 8 | 9 | namespace Bullet { 10 | 11 | class RigidBoxBody: public AbstractRigidBody 12 | { 13 | Q_OBJECT 14 | public: 15 | explicit RigidBoxBody(QObject* parent=0); 16 | ~RigidBoxBody(); 17 | 18 | QVector3D dimension(){return m_dimension;} 19 | void setDimension(QVector3D dimention); 20 | protected: 21 | virtual void initShape(); 22 | private: 23 | QVector3D m_dimension; 24 | 25 | }; 26 | 27 | } 28 | 29 | } 30 | #endif // RigidBoxBody_H 31 | -------------------------------------------------------------------------------- /src/src.pro: -------------------------------------------------------------------------------- 1 | TARGET = QtPhysicsUnofficial 2 | TEMPLATE = lib 3 | PROJECT_NAME=QtPhysicsUnofficial 4 | 5 | QT+= 3dcore 3dquick 3drender 6 | 7 | DESTDIR+= ./lib 8 | 9 | CONFIG += c++11 10 | CONFIG -= android_install 11 | 12 | DEFINES += QTPHYSICSUNOFFICIAL_LIBRARY 13 | 14 | HEADERS += \ 15 | qtphysicsunofficial_global.h 16 | 17 | include(frontend/frontend.pri) 18 | include(backend/backend.pri) 19 | 20 | INCLUDEPATH += $$PWD 21 | 22 | headersDataFiles.path = $$[QT_INSTALL_HEADERS]/$$PROJECT_NAME 23 | headersDataFiles.files = $$PWD/*.h 24 | 25 | 26 | INSTALLS += headersDataFiles 27 | 28 | target.path = $$[QT_INSTALL_LIBS] 29 | INSTALLS +=target 30 | -------------------------------------------------------------------------------- /imports/physics-qml_plugin.cpp: -------------------------------------------------------------------------------- 1 | #include "physics-qml_plugin.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | void Qml_PhysicsPlugin::registerTypes(const char *uri) 8 | { 9 | // @uri com.mycompany.qmlcomponents 10 | Q_ASSERT(uri == QLatin1String("QtPhysics.unofficial")); 11 | qmlRegisterType(uri, 1, 0, "PhysicsBodyInfo"); 12 | qmlRegisterType(uri, 1, 0, "PhysicsWorldInfo"); 13 | qmlRegisterUncreatableType(uri, 1, 0, "PhysicsCollisionEvent", QStringLiteral("Events cannot be created")); 14 | } 15 | -------------------------------------------------------------------------------- /plugins/bullet/dependencies.pri: -------------------------------------------------------------------------------- 1 | android{ 2 | BULLET_INCLUDE_PATH += /home/chili/bullet3-2.83.5/build_android/install/include/ 3 | BULLET_INCLUDE_PATH += /home/chili/bullet3-2.83.5/build_android/install/include/bullet/ 4 | BULLET_LIBS_PATH += -L/home/chili/bullet3-2.83.5/build_android/install/lib/ 5 | } 6 | 7 | !android{ 8 | BULLET_INCLUDE_PATH += /home/chili/bullet3-2.83.5/build_linux/install/include/ 9 | BULLET_INCLUDE_PATH += /home/chili/bullet3-2.83.5/build_linux/install/include/bullet 10 | BULLET_LIBS_PATH += -L/home/chili/bullet3-2.83.5/build_linux/install/lib 11 | } 12 | 13 | BULLET_LIBS_PATH += -lLinearMath -lBulletDynamics -lBulletCollision 14 | 15 | -------------------------------------------------------------------------------- /examples/aspect-test/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | //#include "physicssetter.h" 7 | 8 | #include 9 | int main(int argc, char **argv) 10 | { 11 | 12 | QGuiApplication app(argc, argv); 13 | QQmlApplicationEngine engine; 14 | //qmlRegisterType("PhysicsSetter", 1, 0, "PhysicsSetter"); 15 | 16 | QQuickView view; 17 | 18 | view.resize(500, 500); 19 | view.setResizeMode(QQuickView::SizeRootObjectToView); 20 | view.setSource(QUrl("qrc:/main.qml")); 21 | view.show(); 22 | 23 | return app.exec(); 24 | } 25 | -------------------------------------------------------------------------------- /src/backend/jobs/insertphysicstransformjob.h: -------------------------------------------------------------------------------- 1 | #ifndef INSERTPHYSICSTRANSFORMJOB_H 2 | #define INSERTPHYSICSTRANSFORMJOB_H 3 | #include "backend_global.h" 4 | #include 5 | #include 6 | 7 | namespace Physics { 8 | 9 | class PhysicsManager; 10 | 11 | class BACKENDSHARED_EXPORT InsertPhysicsTransformJob: public Qt3DCore::QAspectJob 12 | { 13 | 14 | public: 15 | explicit InsertPhysicsTransformJob(PhysicsManager* manager); 16 | protected: 17 | void run() Q_DECL_OVERRIDE; 18 | private: 19 | void recursive_step(Qt3DCore::QNodeId id); 20 | 21 | PhysicsManager* m_manager; 22 | }; 23 | 24 | 25 | } 26 | 27 | #endif // INSERTPHYSICSTRANSFORMJOB_H 28 | -------------------------------------------------------------------------------- /plugins/bullet/bulletfactory.h: -------------------------------------------------------------------------------- 1 | #ifndef BulletFactory_H 2 | #define BulletFactory_H 3 | 4 | #include 5 | #include 6 | namespace Physics { 7 | 8 | namespace Bullet { 9 | 10 | class BulletFactory :public QObject, 11 | PhysicsFactoryInterface 12 | { 13 | Q_OBJECT 14 | Q_PLUGIN_METADATA(IID "org.qt-project.Qt.Physics.Unofficial.PhysicsFactoryInterface" FILE "bullet.json") 15 | Q_INTERFACES(Physics::PhysicsFactoryInterface) 16 | public: 17 | BulletFactory(QObject *parent = 0); 18 | PhysicsAbstractRigidBody* create_rigid_body(QVariantMap geometric_info); 19 | PhysicsAbstractDynamicsWorld* create_dynamics_world(); 20 | }; 21 | 22 | 23 | } 24 | } 25 | #endif // BulletFactory_H 26 | -------------------------------------------------------------------------------- /src/backend/physics_entities/physicsabstractsoftrigiddynamicsworld.h: -------------------------------------------------------------------------------- 1 | #ifndef PHYSICSABSTRACTSOFTRIGIDDYNAMICSWORLD_H 2 | #define PHYSICSABSTRACTSOFTRIGIDDYNAMICSWORLD_H 3 | 4 | #include "physicsabstractdynamicsworld.h" 5 | #include "physicsabstractsoftbody.h" 6 | 7 | namespace Physics { 8 | 9 | 10 | class PhysicsAbstractSoftRigidDynamicsWorld: public PhysicsAbstractDynamicsWorld 11 | { 12 | Q_OBJECT 13 | public: 14 | explicit PhysicsAbstractSoftRigidDynamicsWorld(); 15 | 16 | virtual WorldType type(){return SOFTRIGIDDYNAMICSWORLD;} 17 | 18 | virtual void addSoftBody(PhysicsAbstractSoftBody* body)=0; 19 | virtual void removeSoftBody(PhysicsAbstractSoftBody* body)=0; 20 | 21 | 22 | 23 | }; 24 | 25 | } 26 | #endif // PHYSICSABSTRACTSOFTRIGIDDYNAMICSWORLD_H 27 | -------------------------------------------------------------------------------- /plugins/bullet/bodies/rigidconvexhullbody.h: -------------------------------------------------------------------------------- 1 | #ifndef RigidConvexHullBody_H 2 | #define RigidConvexHullBody_H 3 | #include 4 | namespace Physics { 5 | 6 | namespace Bullet { 7 | 8 | class RigidConvexHullBody : public AbstractRigidBody 9 | { 10 | Q_OBJECT 11 | public: 12 | explicit RigidConvexHullBody(QObject* parent=0); 13 | explicit RigidConvexHullBody(qreal* points,int n_points,QObject* parent=0); 14 | ~RigidConvexHullBody(); 15 | void addPoint(QVector3D p); 16 | void updatePoints(qreal* points,int n_points); 17 | void setCollisionMargin(qreal margin); 18 | protected: 19 | void initShape(qreal* points,int n_points); 20 | void initShape()Q_DECL_OVERRIDE; 21 | private: 22 | }; 23 | 24 | }} 25 | #endif // RigidConvexHullBody_H 26 | -------------------------------------------------------------------------------- /examples/aspect-test/main.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import QtQuick.Scene3D 2.0 3 | import QtPhysics.unofficial 1.0 4 | Item { 5 | Text { 6 | text: "Click me!" 7 | anchors.top: parent.top 8 | anchors.topMargin: 10 9 | anchors.horizontalCenter: parent.horizontalCenter 10 | 11 | } 12 | Rectangle { 13 | id: scene 14 | width: Math.min(parent.width, parent.height) - 100 15 | height: width 16 | anchors.centerIn: parent 17 | color: "darkRed" 18 | 19 | Scene3D { 20 | anchors.fill: parent 21 | anchors.margins: 10 22 | focus: true 23 | aspects: ["input","physics"] 24 | 25 | AnimatedEntity { 26 | id:sceneroot 27 | } 28 | } 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/backend/physics_entities/physicsfactoryinterface.h: -------------------------------------------------------------------------------- 1 | #ifndef PHYSICSFACTORYINTERFACE_H 2 | #define PHYSICSFACTORYINTERFACE_H 3 | #include 4 | #include 5 | #include 6 | 7 | namespace Physics { 8 | 9 | 10 | class QTPHYSICSUNOFFICIAL_EXPORT PhysicsFactoryInterface 11 | { 12 | public: 13 | virtual PhysicsAbstractRigidBody* create_rigid_body(QVariantMap geometric_info)=0; 14 | 15 | virtual PhysicsAbstractDynamicsWorld* create_dynamics_world()=0; 16 | 17 | 18 | }; 19 | } 20 | 21 | #define PhysicsFactoryInterface_iid "org.qt-project.Qt.Physics.Unofficial.PhysicsFactoryInterface" 22 | Q_DECLARE_INTERFACE(Physics::PhysicsFactoryInterface, PhysicsFactoryInterface_iid) 23 | 24 | #endif // PHYSICSFACTORYINTERFACE_H 25 | -------------------------------------------------------------------------------- /plugins/bullet/bodies/rigidspherebody.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | namespace Physics { 6 | 7 | 8 | namespace Bullet { 9 | 10 | 11 | RigidSphereBody::RigidSphereBody(QObject* parent): 12 | AbstractRigidBody(parent), 13 | m_radius(1) 14 | { 15 | initShape(); 16 | initBody(); 17 | } 18 | RigidSphereBody::~RigidSphereBody() 19 | { 20 | 21 | } 22 | 23 | void RigidSphereBody::initShape(){ 24 | m_shape = new btSphereShape(m_radius); 25 | } 26 | 27 | 28 | 29 | void RigidSphereBody::setRadius(qreal radius){ 30 | if(m_radius!=radius){ 31 | m_radius=radius; 32 | delete m_shape; 33 | m_shape = new btSphereShape(m_radius); 34 | m_rigidBody->setCollisionShape(m_shape); 35 | setMassProps(); 36 | } 37 | } 38 | 39 | 40 | }} 41 | -------------------------------------------------------------------------------- /plugins/bullet/bodies/rigidstaticplanebody.h: -------------------------------------------------------------------------------- 1 | #ifndef RigidStaticPlaneBody_H 2 | #define RigidStaticPlaneBody_H 3 | 4 | #include 5 | #include 6 | 7 | namespace Physics { 8 | 9 | namespace Bullet { 10 | 11 | class RigidStaticPlaneBody : public AbstractRigidBody 12 | { 13 | Q_OBJECT 14 | public: 15 | explicit RigidStaticPlaneBody(QObject* parent=0); 16 | ~RigidStaticPlaneBody(); 17 | QVector3D normal(){return m_normal;} 18 | void setNormal(QVector3D normal); 19 | qreal planeConstant(){return m_planeConstant;} 20 | void setPlaneConstant(qreal d); 21 | virtual void setMass(qreal m) Q_DECL_OVERRIDE; 22 | 23 | public slots: 24 | 25 | protected: 26 | void initShape(); 27 | private: 28 | 29 | QVector3D m_normal; 30 | qreal m_planeConstant; 31 | }; 32 | 33 | } 34 | } 35 | #endif // RigidStaticPlaneBody_H 36 | -------------------------------------------------------------------------------- /src/frontend/physicssoftbodyinfo.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace Physics { 4 | 5 | 6 | 7 | PhysicsSoftBodyInfo::PhysicsSoftBodyInfo(Qt3DCore::QNode* parent): 8 | PhysicsBodyInfo(parent), 9 | m_inputMesh(Q_NULLPTR), 10 | m_outputMesh(Q_NULLPTR) 11 | { 12 | 13 | } 14 | 15 | PhysicsSoftBodyInfo::~PhysicsSoftBodyInfo(){ 16 | 17 | } 18 | 19 | void PhysicsSoftBodyInfo::copy(const Qt3DCore::QNode *ref){ 20 | Qt3DCore::QComponent::copy(ref); 21 | PhysicsBodyInfo::copy(ref); 22 | const PhysicsSoftBodyInfo * body_info = static_cast(ref); 23 | 24 | m_inputMesh=body_info->m_inputMesh; 25 | m_outputMesh=body_info->m_outputMesh; 26 | 27 | } 28 | 29 | void PhysicsSoftBodyInfo::setInputMesh(Qt3DRender::QGeometryRenderer* mesh){ 30 | if(m_inputMesh!=mesh){ 31 | m_inputMesh=mesh; 32 | emit inputMeshChanged(); 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /plugins/bullet/bodies/rigidboxbody.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace Physics { 5 | 6 | namespace Bullet { 7 | 8 | RigidBoxBody::RigidBoxBody(QObject* parent): 9 | AbstractRigidBody(parent), 10 | m_dimension(1,1,1) 11 | 12 | { 13 | initShape(); 14 | initBody(); 15 | 16 | } 17 | RigidBoxBody::~RigidBoxBody() 18 | { 19 | 20 | } 21 | 22 | void RigidBoxBody::setDimension(QVector3D dimension){ 23 | if(m_dimension!=dimension){ 24 | m_dimension=dimension; 25 | delete m_shape; 26 | m_shape=new btBoxShape(btVector3(m_dimension.x()/2,m_dimension.y()/2,m_dimension.z()/2)); 27 | m_rigidBody->setCollisionShape(m_shape); 28 | setMassProps(); 29 | } 30 | } 31 | void RigidBoxBody::initShape(){ 32 | m_shape = new btBoxShape(btVector3(m_dimension.x()/2,m_dimension.y()/2,m_dimension.z()/2)); 33 | } 34 | 35 | }} 36 | 37 | 38 | -------------------------------------------------------------------------------- /imports/imports.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = lib 2 | TARGET = physics 3 | 4 | QT += 3dcore 3drender 3dquick qml quick 5 | 6 | CONFIG += qt plugin c++11 7 | CONFIG -= android_install 8 | 9 | uri = QtPhysics.unofficial 10 | 11 | INCLUDEPATH += $$PWD/../src/ 12 | 13 | SOURCES += \ 14 | physics-qml_plugin.cpp 15 | 16 | HEADERS += \ 17 | physics-qml_plugin.h 18 | 19 | 20 | DISTFILES = qmldir 21 | 22 | !equals(_PRO_FILE_PWD_, $$OUT_PWD) { 23 | copy_qmldir.target = $$OUT_PWD/qmldir 24 | copy_qmldir.depends = $$_PRO_FILE_PWD_/qmldir 25 | copy_qmldir.commands = $(COPY_FILE) \"$$replace(copy_qmldir.depends, /, $$QMAKE_DIR_SEP)\" \"$$replace(copy_qmldir.target, /, $$QMAKE_DIR_SEP)\" 26 | QMAKE_EXTRA_TARGETS += copy_qmldir 27 | PRE_TARGETDEPS += $$copy_qmldir.target 28 | } 29 | 30 | qmldir.files = qmldir 31 | installPath = $$[QT_INSTALL_QML]/$$replace(uri, \\., /) 32 | qmldir.path = $$installPath 33 | target.path = $$installPath 34 | INSTALLS += target qmldir 35 | 36 | LIBS += -lQtPhysicsUnofficial 37 | LIBS += -L../src/lib 38 | -------------------------------------------------------------------------------- /plugins/bullet/bodies/motionstate.h: -------------------------------------------------------------------------------- 1 | #ifndef MOTIONSTATE_H 2 | #define MOTIONSTATE_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace Physics { 9 | 10 | 11 | namespace Bullet{ 12 | 13 | class MotionState : public QObject, public btDefaultMotionState 14 | { 15 | Q_OBJECT 16 | public: 17 | explicit MotionState(QObject *parent = 0); 18 | explicit MotionState(const btTransform &startTrans=btTransform::getIdentity(), const btTransform ¢erOfMassOffset=btTransform::getIdentity(),QObject* parent=0); 19 | explicit MotionState(const QMatrix4x4 startTrans, const QMatrix4x4 centerOfMassOffset,QObject* parent=0); 20 | virtual void getWorldTransform(btTransform& centerOfMassWorldTrans ) const; 21 | virtual void setWorldTransform(const btTransform& centerOfMassWorldTrans); 22 | void setWorldTransform(QMatrix4x4 mat, qreal scaleFactor=1.0); 23 | QMatrix4x4 getWorldTransformAsQMatrix4x4(); 24 | public slots: 25 | }; 26 | } 27 | } 28 | #endif // MOTIONSTATE_H 29 | -------------------------------------------------------------------------------- /src/frontend/physicsaspect.h: -------------------------------------------------------------------------------- 1 | #ifndef PhysicsASPECT_H 2 | #define PhysicsASPECT_H 3 | 4 | #include 5 | 6 | 7 | QT_BEGIN_NAMESPACE 8 | 9 | namespace Physics { 10 | 11 | class PhysicsManager; 12 | 13 | class QTPHYSICSUNOFFICIAL_EXPORT PhysicsAspect: public Qt3DCore::QAbstractAspect 14 | { 15 | public: 16 | explicit PhysicsAspect(QObject* parent=0); 17 | 18 | QVector jobsToExecute(qint64 time) Q_DECL_OVERRIDE; 19 | // void sceneNodeAdded(Qt3DCore::QSceneChangePtr &e) Q_DECL_OVERRIDE; 20 | // void sceneNodeRemoved(Qt3DCore::QSceneChangePtr &e) Q_DECL_OVERRIDE; 21 | 22 | private: 23 | // void setRootEntity(Qt3DCore::QEntity *rootObject) Q_DECL_OVERRIDE; 24 | void onRootEntityChanged(Qt3DCore::QEntity *rootEntity) Q_DECL_OVERRIDE; 25 | void onInitialize(const QVariantMap &data) Q_DECL_OVERRIDE; 26 | void onCleanup() Q_DECL_OVERRIDE; 27 | void visitNode(Qt3DCore::QNode *node); 28 | 29 | PhysicsManager* m_manager; 30 | 31 | signals: 32 | 33 | public slots: 34 | }; 35 | } 36 | QT_END_NAMESPACE 37 | 38 | #endif // PhysicsASPECT_H 39 | -------------------------------------------------------------------------------- /src/frontend/frontend.pri: -------------------------------------------------------------------------------- 1 | #------------------------------------------------- 2 | # 3 | # Project created by QtCreator 2015-08-11T10:08:11 4 | # 5 | #------------------------------------------------- 6 | 7 | SOURCES += \ 8 | $$PWD/physicsbodyinfo.cpp \ 9 | $$PWD/physicsworldinfo.cpp \ 10 | $$PWD/physicscollisionevent.cpp \ 11 | # $$PWD/physicssoftbodyinfo.cpp \ 12 | $$PWD/physicsaspect.cpp 13 | 14 | HEADERS +=\ 15 | $$PWD/physicsbodyinfo.h \ 16 | $$PWD/physicsworldinfo.h \ 17 | $$PWD/physicscollisionevent.h \ 18 | # $$PWD/physicssoftbodyinfo.h \ 19 | $$PWD/physicsaspect.h 20 | 21 | 22 | 23 | frontHeadersDataFiles.path = $$[QT_INSTALL_HEADERS]/$$PROJECT_NAME/frontend 24 | frontHeadersDataFiles.files = $$PWD/*.h 25 | 26 | INSTALLS += frontHeadersDataFiles 27 | 28 | #libraryFiles.path = $$[QT_INSTALL_LIBS] 29 | #Debug:libraryFiles.files = $$OUT_PWD/debug/*.a $$OUT_PWD/debug/*.prl $$OUT_PWD/debug/*.so 30 | #Release:libraryFiles.files = $$OUT_PWD/release/*.a $$OUT_PWD/release/*.prl $$OUT_PWD/release/*.so 31 | #INSTALLS += libraryFiles 32 | 33 | #frontendTarget.path = $$[QT_INSTALL_LIBS] 34 | #INSTALLS +=frontendTarget 35 | -------------------------------------------------------------------------------- /src/frontend/physicssoftbodyinfo.h: -------------------------------------------------------------------------------- 1 | #ifndef PHYSICSSOFTBODYINFO_H 2 | #define PHYSICSSOFTBODYINFO_H 3 | 4 | #include 5 | 6 | namespace Physics { 7 | 8 | 9 | 10 | class QTPHYSICSUNOFFICIAL_EXPORT PhysicsSoftBodyInfo: public PhysicsBodyInfo 11 | { 12 | Q_OBJECT 13 | Q_PROPERTY(Qt3DRender::QGeometryRenderer* inputMesh READ inputMesh WRITE setInputMesh NOTIFY inputMeshChanged) 14 | Q_PROPERTY(Qt3DRender::QGeometryRenderer* outputMesh READ outputMesh NOTIFY outputMeshChanged) 15 | public: 16 | explicit PhysicsSoftBodyInfo(Qt3DCore::QNode* parent=0); 17 | ~PhysicsSoftBodyInfo(); 18 | Qt3DRender::QGeometryRenderer* inputMesh(){return m_inputMesh;} 19 | Qt3DRender::QGeometryRenderer* outputMesh(){return m_outputMesh;} 20 | 21 | void setInputMesh(Qt3DRender::QGeometryRenderer* mesh); 22 | 23 | signals: 24 | void inputMeshChanged(); 25 | void outputMeshChanged(); 26 | 27 | protected: 28 | void copy(const Qt3DCore::QNode *ref) Q_DECL_OVERRIDE; 29 | QT3D_CLONEABLE(PhysicsSoftBodyInfo) 30 | 31 | Qt3DRender::QGeometryRenderer* m_inputMesh; 32 | Qt3DRender::QGeometryRenderer* m_outputMesh; 33 | 34 | }; 35 | 36 | } 37 | #endif // PHYSICSSOFTBODYINFO_H 38 | -------------------------------------------------------------------------------- /config.tests/bullet/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | /*From http://bulletphysics.org/mediawiki-1.5.8/index.php/Hello_World*/ 3 | int main(int , char **) 4 | { 5 | // Build the broadphase 6 | btBroadphaseInterface* broadphase = new btDbvtBroadphase(); 7 | 8 | // Set up the collision configuration and dispatcher 9 | btDefaultCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration(); 10 | btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfiguration); 11 | 12 | // The actual physics solver 13 | btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver; 14 | 15 | // The world. 16 | btDiscreteDynamicsWorld* dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher, broadphase, solver, collisionConfiguration); 17 | dynamicsWorld->setGravity(btVector3(0, -10, 0)); 18 | 19 | // Do_everything_else_here 20 | 21 | 22 | // Clean up behind ourselves like good little programmers 23 | delete dynamicsWorld; 24 | delete solver; 25 | delete dispatcher; 26 | delete collisionConfiguration; 27 | delete broadphase; 28 | 29 | return 0; 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/frontend/physicscollisionevent.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | namespace Physics { 5 | 6 | PhysicsCollisionEvent::PhysicsCollisionEvent(QObject* parent): 7 | QObject(parent), 8 | m_target(), 9 | m_contactPointOnBody(0,0,0), 10 | m_contactPointOnTarget(0,0,0), 11 | m_contactPointOnBodyLocal(0,0,0), 12 | m_contactPointOnTargetLocal(0,0,0), 13 | m_normalOnTarget(0,0,0), 14 | m_isNew(true) 15 | { 16 | 17 | } 18 | void PhysicsCollisionEvent::setTarget(Qt3DCore::QNodeId target){ 19 | m_target=target; 20 | } 21 | void PhysicsCollisionEvent::setContactPointOnBody(QVector3D point){ 22 | m_contactPointOnBody=point; 23 | } 24 | void PhysicsCollisionEvent::setContactPointOnTarget(QVector3D point){ 25 | m_contactPointOnTarget=point; 26 | } 27 | void PhysicsCollisionEvent::setContactPointOnBodyLocal(QVector3D point){ 28 | m_contactPointOnBodyLocal=point; 29 | } 30 | void PhysicsCollisionEvent::setContactPointOnTargetLocal(QVector3D point){ 31 | m_contactPointOnTargetLocal=point; 32 | } 33 | void PhysicsCollisionEvent::setNormalOnTarget(QVector3D normal){ 34 | m_normalOnTarget=normal; 35 | } 36 | void PhysicsCollisionEvent::setIsNew(bool val){ 37 | m_isNew=val; 38 | } 39 | 40 | 41 | 42 | 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/frontend/physicsworldinfo.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace Physics { 5 | 6 | 7 | PhysicsWorldInfo::PhysicsWorldInfo(QNode* parent): 8 | Qt3DCore::QComponent(parent), 9 | m_gravity(0, -10, 0), 10 | m_scaleFactor(1) 11 | { 12 | 13 | } 14 | 15 | PhysicsWorldInfo::~PhysicsWorldInfo(){ 16 | Qt3DCore::QNode::cleanup(); 17 | } 18 | 19 | void PhysicsWorldInfo::setGravity(QVector3D gravity){ 20 | if(m_gravity!=gravity){ 21 | m_gravity=gravity; 22 | emit gravityChanged(); 23 | } 24 | } 25 | 26 | void PhysicsWorldInfo::setScaleFactor(qreal val) 27 | { 28 | if(val!=m_scaleFactor){ 29 | m_scaleFactor=val; 30 | emit scaleFactorChanged(); 31 | } 32 | } 33 | 34 | void PhysicsWorldInfo::copy(const Qt3DCore::QNode *ref){ 35 | Qt3DCore::QComponent::copy(ref); 36 | const PhysicsWorldInfo* world_info = static_cast(ref); 37 | m_gravity=world_info->gravity(); 38 | 39 | } 40 | 41 | void PhysicsWorldInfo::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) 42 | { 43 | Qt3DCore::QScenePropertyChangePtr e = qSharedPointerCast< Qt3DCore::QScenePropertyChange>(change); 44 | if (e->type() == Qt3DCore::NodeUpdated) { 45 | 46 | } 47 | } 48 | } 49 | 50 | 51 | -------------------------------------------------------------------------------- /src/backend/jobs/insertphysicstransformjob.cpp: -------------------------------------------------------------------------------- 1 | #include "insertphysicstransformjob.h" 2 | 3 | #include "../physicsmanager.h" 4 | #include "../backendtypes/physicsentity.h" 5 | #include "../backendtypes/physicsbodyinfobackendnode.h" 6 | #include 7 | 8 | namespace Physics { 9 | 10 | InsertPhysicsTransformJob::InsertPhysicsTransformJob(PhysicsManager* manager): 11 | QAspectJob() 12 | { 13 | m_manager=manager; 14 | } 15 | 16 | void InsertPhysicsTransformJob::run(){ 17 | recursive_step(m_manager->rootEntityId()); 18 | } 19 | 20 | void InsertPhysicsTransformJob::recursive_step(Qt3D::QNodeId id){ 21 | if(id.isNull()) return; 22 | PhysicsEntity* entity= static_cast(m_manager->m_resources.operator [](id)); 23 | if(!entity->physicsBodyInfo().isNull() && 24 | !entity->default_transform().isNull() && 25 | entity->physics_transform().isNull()){ 26 | /*Make the backend node notify the front end that a matrix should be added*/ 27 | PhysicsBodyInfoBackendNode* b_info=static_cast(m_manager->m_resources.operator [](entity->physicsBodyInfo())); 28 | b_info->notifyFrontEnd("attachPhysicsTransfrom",QVariantMap()); 29 | } 30 | for(Qt3D::QNodeId childId : entity->childrenIds()) 31 | recursive_step(childId); 32 | } 33 | 34 | } 35 | 36 | -------------------------------------------------------------------------------- /src/backend/physics_entities/physicsabstractsoftbody.h: -------------------------------------------------------------------------------- 1 | #ifndef PHYSICSABSTRACTSOFTBODY_H 2 | #define PHYSICSABSTRACTSOFTBODY_H 3 | #include "qtphysicsunofficial_global.h" 4 | 5 | #include 6 | 7 | namespace Physics { 8 | 9 | class QTPHYSICSUNOFFICIAL_EXPORT PhysicsAbstractSoftBody : public QObject 10 | { 11 | Q_OBJECT 12 | public: 13 | explicit PhysicsAbstractSoftBody(QObject *parent = 0); 14 | 15 | virtual int mask()=0; 16 | virtual int group()=0; 17 | virtual void setMask(int mask)=0; 18 | virtual void setGroup(int group)=0; 19 | virtual bool kinematic()=0; 20 | virtual void setKinematic(bool kinematic)=0; 21 | 22 | 23 | virtual qreal mass()=0; 24 | virtual QVector3D fallInertia()=0; 25 | virtual qreal restitution()=0; 26 | virtual qreal rollingFriction()=0; 27 | virtual qreal friction()=0; 28 | virtual QMatrix4x4 worldTransformation()=0; 29 | 30 | virtual void setMass(qreal mass)=0; 31 | virtual void setFallInertia(QVector3D fallInertia)=0; 32 | virtual void setRestitution(qreal restitution)=0; 33 | virtual void setRollingFriction(qreal rollingFriction)=0; 34 | virtual void setFriction(qreal friction)=0; 35 | virtual void setWorldTransformation(QMatrix4x4 m)=0; 36 | 37 | 38 | protected: 39 | 40 | signals: 41 | 42 | public slots: 43 | }; 44 | 45 | } 46 | 47 | 48 | #endif // PHYSICSABSTRACTSOFTBODY_H 49 | -------------------------------------------------------------------------------- /plugins/bullet/bullet.pro: -------------------------------------------------------------------------------- 1 | #------------------------------------------------- 2 | # 3 | # Project created by QtCreator 2015-08-11T15:01:48 4 | # 5 | #------------------------------------------------- 6 | 7 | QT += core gui 3dcore 3drender 8 | 9 | TARGET = bullet 10 | TEMPLATE = lib 11 | CONFIG += plugin 12 | CONFIG -= android_install 13 | 14 | include("dependencies.pri") 15 | 16 | DESTDIR = $$[QT_INSTALL_PLUGINS]/physicsfactories 17 | 18 | SOURCES += \ 19 | bulletfactory.cpp \ 20 | #bodies/compoundshape.cpp \ 21 | bodies/motionstate.cpp \ 22 | worlds/dynamicsworld.cpp \ 23 | bodies/abstractrigidbody.cpp \ 24 | bodies/rigidboxbody.cpp \ 25 | bodies/rigidstaticplanebody.cpp \ 26 | bodies/rigidconvexhullbody.cpp \ 27 | bodies/rigidspherebody.cpp 28 | 29 | HEADERS += \ 30 | bulletfactory.h \ 31 | #bodies/compoundshape.h \ 32 | bodies/motionstate.h \ 33 | worlds/dynamicsworld.h \ 34 | bodies/abstractrigidbody.h \ 35 | bodies/rigidboxbody.h \ 36 | bodies/rigidconvexhullbody.h \ 37 | bodies/rigidspherebody.h \ 38 | bodies/rigidstaticplanebody.h 39 | 40 | INCLUDEPATH += $$PWD/../../src/backend 41 | INCLUDEPATH += $$PWD/../../src/ 42 | INCLUDEPATH += $$PWD 43 | 44 | DISTFILES += bullet.json \ 45 | 46 | INCLUDEPATH += $${BULLET_INCLUDE_PATH} 47 | LIBS += $${BULLET_LIBS_PATH} 48 | 49 | LIBS += -lQtPhysicsUnofficial 50 | LIBS += -L../../src/lib 51 | -------------------------------------------------------------------------------- /src/backend/physicsmanager.h: -------------------------------------------------------------------------------- 1 | #ifndef PHYSICSMANAGER_H 2 | #define PHYSICSMANAGER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | namespace Physics { 14 | 15 | const QString PHYSICS_FACTORIES_PATH = QStringLiteral("/physicsfactories"); 16 | 17 | class QTPHYSICSUNOFFICIAL_EXPORT PhysicsManager 18 | { 19 | 20 | public: 21 | 22 | PhysicsManager(); 23 | ~PhysicsManager(); 24 | 25 | void setRootEntityId(Qt3DCore::QNodeId rootId){m_rootId=rootId;} 26 | Qt3DCore::QNodeId rootEntityId(){return m_rootId;} 27 | 28 | QHash m_resources; 29 | 30 | QHash m_Id2RigidBodies; 31 | QHash m_RigidBodies2Id; 32 | 33 | PhysicsAbstractDynamicsWorld* m_physics_world; 34 | 35 | PhysicsFactoryInterface* m_physics_factory; 36 | 37 | QVector getCollisions(); 38 | 39 | signals: 40 | 41 | public slots: 42 | 43 | private: 44 | void loadPhysicsFactories(); 45 | Qt3DCore::QNodeId m_rootId; 46 | 47 | 48 | 49 | }; 50 | 51 | 52 | } 53 | #endif // PHYSICSMANAGER_H 54 | -------------------------------------------------------------------------------- /src/backend/physics_entities/physicsabstractrigidbody.h: -------------------------------------------------------------------------------- 1 | #ifndef PHYSICSABSTRACTRIGIDBODY_H 2 | #define PHYSICSABSTRACTRIGIDBODY_H 3 | #include 4 | 5 | namespace Physics { 6 | 7 | class QTPHYSICSUNOFFICIAL_EXPORT PhysicsAbstractRigidBody : public QObject 8 | { 9 | Q_OBJECT 10 | public: 11 | explicit PhysicsAbstractRigidBody(QObject *parent = 0); 12 | 13 | virtual int mask()=0; 14 | virtual int group()=0; 15 | virtual void setMask(int mask)=0; 16 | virtual void setGroup(int group)=0; 17 | virtual bool kinematic()=0; 18 | virtual void setKinematic(bool kinematic)=0; 19 | 20 | 21 | virtual qreal mass()=0; 22 | virtual QVector3D fallInertia()=0; 23 | virtual qreal restitution()=0; 24 | virtual qreal rollingFriction()=0; 25 | virtual qreal friction()=0; 26 | virtual QMatrix4x4 worldTransformation()=0; 27 | virtual qreal collisionMargin()=0; 28 | 29 | virtual void setMass(qreal mass)=0; 30 | virtual void setFallInertia(QVector3D fallInertia)=0; 31 | virtual void setRestitution(qreal restitution)=0; 32 | virtual void setRollingFriction(qreal rollingFriction)=0; 33 | virtual void setFriction(qreal friction)=0; 34 | virtual void setWorldTransformation(QMatrix4x4 m,qreal scaleFactor=1.0)=0; 35 | virtual void setCollisionMargin(qreal margin)=0; 36 | 37 | 38 | protected: 39 | 40 | signals: 41 | 42 | public slots: 43 | }; 44 | 45 | } 46 | #endif // PHYSICSABSTRACTRIGIDBODY_H 47 | -------------------------------------------------------------------------------- /src/frontend/physicsworldinfo.h: -------------------------------------------------------------------------------- 1 | #ifndef PhysicsWorldInfo_H 2 | #define PhysicsWorldInfo_H 3 | #include 4 | 5 | 6 | #include 7 | 8 | namespace Physics { 9 | 10 | 11 | class QTPHYSICSUNOFFICIAL_EXPORT PhysicsWorldInfo: 12 | public Qt3DCore::QComponent 13 | { 14 | Q_OBJECT 15 | Q_PROPERTY(QVector3D gravity READ gravity WRITE setGravity NOTIFY gravityChanged) 16 | Q_PROPERTY(qreal scaleFactor READ scaleFactor WRITE setScaleFactor NOTIFY scaleFactorChanged) 17 | Q_PROPERTY(bool debug READ debug WRITE setDebug NOTIFY debugChanged) 18 | public: 19 | explicit PhysicsWorldInfo(QNode* parent=0); 20 | ~PhysicsWorldInfo(); 21 | void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) Q_DECL_OVERRIDE; 22 | void copy(const QNode *ref) Q_DECL_OVERRIDE; 23 | 24 | QVector3D gravity() const {return m_gravity;} 25 | void setGravity(QVector3D gravity); 26 | 27 | qreal scaleFactor() const{return m_scaleFactor;} 28 | void setScaleFactor(qreal val); 29 | 30 | 31 | bool debug(){return m_debug;} 32 | void setDebug(bool debug){if(debug!=m_debug){m_debug=debug;emit debugChanged(m_debug);}} 33 | signals: 34 | void gravityChanged(); 35 | void debugChanged(bool debug); 36 | void scaleFactorChanged(); 37 | private: 38 | QVector3D m_gravity; 39 | bool m_debug; 40 | qreal m_scaleFactor; 41 | QT3D_CLONEABLE(PhysicsWorldInfo) 42 | 43 | }; 44 | 45 | } 46 | #endif // PhysicsWorldInfo_H 47 | -------------------------------------------------------------------------------- /plugins/bullet/bodies/rigidstaticplanebody.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace Physics { 4 | 5 | namespace Bullet { 6 | 7 | RigidStaticPlaneBody::RigidStaticPlaneBody(QObject* parent): 8 | AbstractRigidBody(parent), 9 | m_normal(0,1,0), 10 | m_planeConstant(0.0f) 11 | { 12 | setMass(0.0f); 13 | initShape(); 14 | initBody(); 15 | } 16 | 17 | RigidStaticPlaneBody::~RigidStaticPlaneBody() 18 | { 19 | 20 | } 21 | 22 | void RigidStaticPlaneBody::setPlaneConstant(qreal d){ 23 | if(m_planeConstant!=d){ 24 | m_planeConstant=d; 25 | delete m_shape; 26 | m_shape = new btStaticPlaneShape(btVector3(m_normal.x(),m_normal.y(),m_normal.z()), m_planeConstant); 27 | m_rigidBody->setCollisionShape(m_shape); 28 | setMassProps(); 29 | } 30 | } 31 | 32 | void RigidStaticPlaneBody::setNormal(QVector3D normal){ 33 | if(m_normal!=normal){ 34 | m_normal=normal; 35 | delete m_shape; 36 | m_shape = new btStaticPlaneShape(btVector3(m_normal.x(),m_normal.y(),m_normal.z()), m_planeConstant); 37 | m_rigidBody->setCollisionShape(m_shape); 38 | setMassProps(); 39 | } 40 | } 41 | void RigidStaticPlaneBody::setMass(qreal mass){ 42 | if(m_mass!=mass){ 43 | qWarning()<<"RigidStaticPlaneBody does not support mass"; 44 | } 45 | } 46 | 47 | void RigidStaticPlaneBody::initShape(){ 48 | m_shape = new btStaticPlaneShape(btVector3(m_normal.x(),m_normal.y(),m_normal.z()), m_planeConstant); 49 | } 50 | 51 | }} 52 | -------------------------------------------------------------------------------- /src/backend/physicscollision.h: -------------------------------------------------------------------------------- 1 | #ifndef PHYSICSCOLLISION 2 | #define PHYSICSCOLLISION 3 | #include 4 | #include 5 | 6 | namespace Physics { 7 | 8 | class QTPHYSICSUNOFFICIAL_EXPORT Collision{ 9 | 10 | public: 11 | 12 | Qt3DCore::QNodeId body1; 13 | Qt3DCore::QNodeId body2; 14 | QVector3D pointOnBody1; 15 | QVector3D pointOnBody2; 16 | QVector3D pointOnBody1Local; 17 | QVector3D pointOnBody2Local; 18 | QVector3D normalBody2; 19 | bool isNew; 20 | 21 | void swapBodies(){ 22 | /**TODO: Swapping the normal???*/ 23 | Qt3DCore::QNodeId tmp=this->body1; 24 | QVector3D tmp_v1=this->pointOnBody1; 25 | this->body1=this->body2; 26 | this->pointOnBody1=this->pointOnBody2; 27 | this->body2=tmp; 28 | this->pointOnBody2=tmp_v1; 29 | } 30 | 31 | }; 32 | 33 | inline bool operator==(const Collision& c1,const Collision& c2) 34 | { 35 | return ( 36 | ( 37 | (c1.body1 == c2.body1 && c1.body2 == c2.body2 && c1.pointOnBody1 == c2.pointOnBody1 && c1.pointOnBody2 == c2.pointOnBody2) 38 | || 39 | (c1.body1 == c2.body2 && c1.body2 == c2.body1 && c1.pointOnBody1 == c2.pointOnBody2 && c1.pointOnBody2 == c2.pointOnBody1) 40 | ) 41 | && c1.normalBody2 == c2.normalBody2); 42 | } 43 | inline uint qHash(const Collision &key, uint seed) 44 | { 45 | return Qt3DCore::qHash(key.body1, seed) ^ Qt3DCore::qHash(key.body2, seed); 46 | } 47 | 48 | 49 | } 50 | #endif // PHYSICSCOLLISION 51 | 52 | -------------------------------------------------------------------------------- /examples/aspect-test/aspect-test.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = app 2 | 3 | QT += 3dcore 3drender 3dinput 3dquick qml quick 4 | CONFIG += c++11 5 | #CONFIG -= android_install 6 | 7 | SOURCES += main.cpp 8 | # physicssetter.cpp 9 | 10 | RESOURCES += qml.qrc 11 | 12 | # Additional import path used to resolve QML modules in Qt Creator's code model 13 | QML_IMPORT_PATH = 14 | 15 | # Default rules for deployment. 16 | include(deployment.pri) 17 | 18 | 19 | android{ 20 | LIBS += -L/home/chili/bullet3-2.83.5/build_android/install/lib/ 21 | } 22 | 23 | !android{ 24 | LIBS += -L/home/chili/Downloads/bullet3-2.83.5/build-linux/install/lib 25 | } 26 | 27 | LIBS += -lLinearMath -lBulletDynamics -lBulletCollision 28 | 29 | #HEADERS += \ 30 | # physicssetter.h 31 | 32 | LIBS += -lQtPhysicsUnofficial 33 | LIBS += -L../../src/lib 34 | 35 | contains(ANDROID_TARGET_ARCH,armeabi-v7a) { 36 | ANDROID_EXTRA_LIBS = \ 37 | /home/chili/QTProjects/qtphysics-unofficial/examples/aspect-test/../../../../bullet3-2.83.5/build_android/install/lib/libLinearMath.so \ 38 | /home/chili/QTProjects/qtphysics-unofficial/examples/aspect-test/../../../../bullet3-2.83.5/build_android/install/lib/libBulletDynamics.so \ 39 | /home/chili/QTProjects/qtphysics-unofficial/examples/aspect-test/../../../../bullet3-2.83.5/build_android/install/lib/libBulletCollision.so \ 40 | /home/chili/QTProjects/qtphysics-unofficial/examples/aspect-test/../../../../bullet3-2.83.5/build_android/install/lib/libBulletSoftBody.so \ 41 | $$PWD/../../../../Qt/5.6/android_armv7/plugins/physicsfactories/libbullet.so 42 | } 43 | -------------------------------------------------------------------------------- /src/backend/physics_entities/physicsabstractdynamicsworld.h: -------------------------------------------------------------------------------- 1 | #ifndef PHYSICSABSTRACTDYNAMICSWORLD_H 2 | #define PHYSICSABSTRACTDYNAMICSWORLD_H 3 | #include 4 | 5 | #include 6 | namespace Physics { 7 | 8 | class PhysicsAbstractDynamicsWorld : public QObject 9 | { 10 | Q_OBJECT 11 | public: 12 | 13 | struct Collision{ 14 | PhysicsAbstractRigidBody* body1; 15 | PhysicsAbstractRigidBody* body2; 16 | QVector3D pointOnBody1; 17 | QVector3D pointOnBody2; 18 | QVector3D pointOnBody1Local; 19 | QVector3D pointOnBody2Local; 20 | QVector3D normalBody2; 21 | 22 | }; 23 | 24 | explicit PhysicsAbstractDynamicsWorld(QObject *parent = 0); 25 | 26 | enum WorldType{DISCRETEDYNAMICSWORLD,SOFTRIGIDDYNAMICSWORLD}; 27 | 28 | virtual WorldType type(){return DISCRETEDYNAMICSWORLD;} 29 | 30 | virtual qreal simulationRate()=0; 31 | virtual void setSimulationRate(qreal rate)=0; 32 | virtual void stepSimulation()=0; 33 | virtual QVector3D gravity()=0; 34 | virtual void setGravity(QVector3D gravity)=0; 35 | 36 | virtual qreal scaleFactor()=0; 37 | virtual void setScaleFactor(qreal val)=0; 38 | 39 | virtual void setDebug(bool debug)=0; 40 | virtual bool debug()=0; 41 | 42 | virtual void addRigidBody(PhysicsAbstractRigidBody* body)=0; 43 | virtual void removeRigidBody(PhysicsAbstractRigidBody* body)=0; 44 | 45 | virtual QVector getCollisions()=0; 46 | 47 | }; 48 | 49 | } 50 | #endif // PHYSICSABSTRACTDYNAMICSWORLD_H 51 | -------------------------------------------------------------------------------- /src/backend/backendtypes/physicssoftbodyinfobackendnode.h: -------------------------------------------------------------------------------- 1 | #ifndef PHYSICSSOFTBODYINFOBACKENDNODE_H 2 | #define PHYSICSSOFTBODYINFOBACKENDNODE_H 3 | 4 | #include "physicsbodyinfobackendnode.h" 5 | #include "physicssoftbodyinfo.h" 6 | 7 | namespace Physics { 8 | 9 | 10 | class QTPHYSICSUNOFFICIAL_EXPORT PhysicsSoftBodyInfoBackendNode: public PhysicsBodyInfoBackendNode 11 | { 12 | public: 13 | 14 | explicit PhysicsSoftBodyInfoBackendNode(); 15 | ~PhysicsSoftBodyInfoBackendNode(); 16 | virtual void updateFromPeer(Qt3DCore::QNode *peer) Q_DECL_OVERRIDE; 17 | 18 | Qt3DCore::QNodeId inputMesh(){return m_inputMesh;} 19 | void setInputMesh(Qt3DCore::QNodeId inputMesh); 20 | 21 | bool isDirtyMesh(){return m_dirtyMesh;} 22 | void setDirtyMesh(bool val){m_dirtyMesh=val;} 23 | 24 | protected: 25 | virtual void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &) Q_DECL_OVERRIDE; 26 | 27 | bool m_dirtyMesh; 28 | bool m_enabled; 29 | 30 | Qt3DCore::QNodeId m_inputMesh; 31 | 32 | 33 | 34 | }; 35 | 36 | class QTPHYSICSUNOFFICIAL_EXPORT PhysicsSoftBodyInfoBackendNodeFunctor : public Qt3DCore::QBackendNodeFunctor 37 | { 38 | public: 39 | explicit PhysicsSoftBodyInfoBackendNodeFunctor(PhysicsManager* manager); 40 | Qt3DCore::QBackendNode *create(Qt3DCore::QNode *frontend, const Qt3DCore::QBackendNodeFactory *factory) const Q_DECL_OVERRIDE; 41 | Qt3DCore::QBackendNode *get(const Qt3DCore::QNodeId &id) const Q_DECL_OVERRIDE; 42 | void destroy(const Qt3DCore::QNodeId &id) const Q_DECL_OVERRIDE; 43 | private: 44 | PhysicsManager* m_manager; 45 | }; 46 | 47 | 48 | 49 | } 50 | #endif // PHYSICSSOFTBODYINFOBACKENDNODE_H 51 | -------------------------------------------------------------------------------- /src/backend/jobs/debugjob.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | namespace Physics { 11 | 12 | 13 | DebugJob::DebugJob(PhysicsManager* manager): 14 | QAspectJob() 15 | { 16 | m_manager=manager; 17 | } 18 | 19 | void DebugJob::run(){ 20 | print(m_manager->rootEntityId()); 21 | //qDebug()<<"End"; 22 | } 23 | 24 | void DebugJob::print(Qt3DCore::QNodeId id){ 25 | if(id.isNull()) return; 26 | PhysicsEntity* e= static_cast(m_manager->m_resources.operator [](id)); 27 | qDebug()<< e->objectName(); 28 | if(!e->geometry_renderer().isNull()){ 29 | PhysicsGeometryRenderer* gr= static_cast(m_manager->m_resources.operator [](e->geometry_renderer())); 30 | if(!gr->m_geometry.isNull()){ 31 | PhysicsGeometry* g=static_cast(m_manager->m_resources.operator [](gr->m_geometry)); 32 | Q_FOREACH(Qt3DCore::QNodeId att, g->attributes()){ 33 | PhysicsAttribute* a=static_cast(m_manager->m_resources.operator [](att)); 34 | if(a->objectName()=="vertexPosition"){ 35 | qDebug()<asVector3D(); 36 | } 37 | } 38 | } 39 | } 40 | for(Qt3DCore::QNodeId childId : e->childrenIds()) 41 | print(childId); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/backend/backendtypes/physicsgeometry.h: -------------------------------------------------------------------------------- 1 | #ifndef PHYSICSGEOMETRY_H 2 | #define PHYSICSGEOMETRY_H 3 | #include 4 | 5 | namespace Physics { 6 | 7 | class PhysicsManager; 8 | class QTPHYSICSUNOFFICIAL_EXPORT PhysicsGeometry : public Qt3DCore::QBackendNode 9 | { 10 | public: 11 | 12 | explicit PhysicsGeometry(); 13 | ~PhysicsGeometry(); 14 | 15 | void updateFromPeer(Qt3DCore::QNode *peer) Q_DECL_OVERRIDE; 16 | 17 | QString objectName(){return m_objectName;} 18 | 19 | bool isEnabled(){return m_enabled;} 20 | void setManager(PhysicsManager *manager); 21 | inline int verticesPerPatch() const { return m_verticesPerPatch; } 22 | inline QVector attributes() const { return m_attributes; } 23 | protected: 24 | void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &) Q_DECL_OVERRIDE; 25 | private: 26 | QString m_objectName; 27 | 28 | bool m_enabled; 29 | 30 | QVector m_attributes; 31 | int m_verticesPerPatch; 32 | 33 | PhysicsManager* m_manager; 34 | 35 | }; 36 | 37 | 38 | class QTPHYSICSUNOFFICIAL_EXPORT PhysicsGeometryFunctor : public Qt3DCore::QBackendNodeFunctor 39 | { 40 | public: 41 | explicit PhysicsGeometryFunctor(PhysicsManager* manager); 42 | Qt3DCore::QBackendNode *create(Qt3DCore::QNode *frontend, const Qt3DCore::QBackendNodeFactory *factory) const Q_DECL_OVERRIDE; 43 | Qt3DCore::QBackendNode *get(const Qt3DCore::QNodeId &id) const Q_DECL_OVERRIDE; 44 | void destroy(const Qt3DCore::QNodeId &id) const Q_DECL_OVERRIDE; 45 | private: 46 | PhysicsManager* m_manager; 47 | 48 | 49 | }; 50 | 51 | } 52 | 53 | #endif // PHYSICSGEOMETRY_H 54 | -------------------------------------------------------------------------------- /src/backend/jobs/updatephysicsentitiesjob.h: -------------------------------------------------------------------------------- 1 | #ifndef UpdatePhysicsEntitiesJob_H 2 | #define UpdatePhysicsEntitiesJob_H 3 | #include 4 | #include 5 | 6 | namespace Physics { 7 | 8 | class PhysicsManager; 9 | class PhysicsAbstractRigidBody; 10 | class PhysicsGeometryRenderer; 11 | class PhysicsBodyInfoBackendNode; 12 | class PhysicsEntity; 13 | 14 | /*This job simply create or update the rigid bodies in the simulation and the world set up. 15 | * No simulation is performed, no update of the objects positions in the frontend*/ 16 | class QTPHYSICSUNOFFICIAL_EXPORT UpdatePhysicsEntitiesJob : public Qt3DCore::QAspectJob 17 | { 18 | public: 19 | explicit UpdatePhysicsEntitiesJob(PhysicsManager* manager); 20 | protected: 21 | void run() Q_DECL_OVERRIDE; 22 | private: 23 | void iterative_step(Qt3DCore::QNodeId node_id, QMatrix4x4 parent_matrix,bool forceUpdateMS); 24 | bool isDefiningBody(PhysicsEntity* entity); 25 | bool isRequiringShapeUpdate(PhysicsGeometryRenderer* entity_geometry_renderer); 26 | void removeNotEnabledSubtrees(Qt3DCore::QNodeId rootId); 27 | 28 | PhysicsAbstractRigidBody* createRigidBodyFromMesh(PhysicsGeometryRenderer* entity_mesh); 29 | 30 | PhysicsManager* m_manager; 31 | 32 | struct Visit_Data{ 33 | Qt3DCore::QNodeId node_id; 34 | QMatrix4x4 parent_matrix; 35 | bool forceUpdateMS; 36 | void set(Qt3DCore::QNodeId id,QMatrix4x4 mat,bool fU){ 37 | node_id=id; 38 | parent_matrix=mat; 39 | forceUpdateMS=fU; 40 | } 41 | }; 42 | 43 | QQueue m_visit_queue; 44 | }; 45 | 46 | } 47 | #endif // UpdatePhysicsEntitiesJob_H 48 | -------------------------------------------------------------------------------- /src/backend/backendtypes/physicstransform.h: -------------------------------------------------------------------------------- 1 | #ifndef PHYSICSTRANSFORM_H 2 | #define PHYSICSTRANSFORM_H 3 | #include 4 | 5 | namespace Physics { 6 | 7 | class PhysicsManager; 8 | 9 | class QTPHYSICSUNOFFICIAL_EXPORT PhysicsTransform : public Qt3DCore::QBackendNode 10 | { 11 | public: 12 | explicit PhysicsTransform(); 13 | ~PhysicsTransform(); 14 | void updateFromPeer(Qt3DCore::QNode *peer) Q_DECL_OVERRIDE; 15 | 16 | QString objectName(){return m_objectName;} 17 | 18 | bool isDirty(){return m_dirty;} 19 | void setDirty(bool dirty){ m_dirty=dirty;} 20 | bool isEnabled(){return m_enabled;} 21 | 22 | void setManager(PhysicsManager *manager); 23 | 24 | const QMatrix4x4& transformMatrix(){return m_transformMatrix;} 25 | 26 | protected: 27 | void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &) Q_DECL_OVERRIDE; 28 | private: 29 | QString m_objectName; 30 | 31 | bool m_dirty; 32 | bool m_enabled; 33 | QMatrix4x4 m_transformMatrix; 34 | QQuaternion m_rotation; 35 | QVector3D m_scale; 36 | QVector3D m_translation; 37 | PhysicsManager* m_manager; 38 | 39 | void updateMatrix(); 40 | }; 41 | 42 | 43 | class QTPHYSICSUNOFFICIAL_EXPORT PhysicsTransformFunctor : public Qt3DCore::QBackendNodeFunctor 44 | { 45 | public: 46 | explicit PhysicsTransformFunctor(PhysicsManager* manager); 47 | Qt3DCore::QBackendNode *create(Qt3DCore::QNode *frontend, const Qt3DCore::QBackendNodeFactory *factory) const Q_DECL_OVERRIDE; 48 | Qt3DCore::QBackendNode *get(const Qt3DCore::QNodeId &id) const Q_DECL_OVERRIDE; 49 | void destroy(const Qt3DCore::QNodeId &id) const Q_DECL_OVERRIDE; 50 | private: 51 | PhysicsManager* m_manager; 52 | 53 | }; 54 | 55 | } 56 | 57 | #endif // PHYSICSTRANSFORM_H 58 | -------------------------------------------------------------------------------- /plugins/bullet/worlds/dynamicsworld.h: -------------------------------------------------------------------------------- 1 | #ifndef DYNAMICSWORLD_H 2 | #define DYNAMICSWORLD_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | namespace Physics { 12 | 13 | namespace Bullet{ 14 | 15 | 16 | class DynamicsWorld : public PhysicsAbstractDynamicsWorld 17 | { 18 | Q_OBJECT 19 | 20 | public: 21 | DynamicsWorld(QObject *parent=0); 22 | ~DynamicsWorld(); 23 | 24 | qreal simulationRate(){return m_simulationRate;} 25 | void setSimulationRate(qreal rate); 26 | 27 | void stepSimulation(); 28 | 29 | QVector3D gravity(){return m_gravity;} 30 | void setGravity(QVector3D gravity); 31 | 32 | qreal scaleFactor(){return m_scaleFactor;} 33 | void setScaleFactor(qreal val); 34 | 35 | void removeRigidBody(PhysicsAbstractRigidBody* b); 36 | void addRigidBody(PhysicsAbstractRigidBody*b); 37 | 38 | void setDebug(bool debug); 39 | bool debug(){return m_debug;} 40 | 41 | QVector getCollisions(); 42 | 43 | 44 | private slots: 45 | void onBodyDestroyed(QObject* obj); 46 | private: 47 | void removebtRigidBody(btRigidBody* b); 48 | void addbtRigidBody(btRigidBody* b,int group,int mask); 49 | 50 | void init(); 51 | 52 | qreal m_simulationRate; 53 | qreal m_scaleFactor; 54 | QVector3D m_gravity; 55 | 56 | QHash m_PhysicsBodies2BulletBodies; 57 | QHash m_BulletBodies2PhysicsBodies; 58 | 59 | btBroadphaseInterface* m_broadphase; 60 | btDefaultCollisionConfiguration* m_collisionConfiguration; 61 | btCollisionDispatcher* m_dispatcher; 62 | btSequentialImpulseConstraintSolver* m_solver; 63 | btDynamicsWorld* m_dynamicsWorld; 64 | 65 | bool m_debug; 66 | 67 | }; 68 | 69 | }} 70 | 71 | #endif // DYNAMICSWORLD_H 72 | 73 | -------------------------------------------------------------------------------- /src/backend/backendtypes/physicsbuffer.h: -------------------------------------------------------------------------------- 1 | #ifndef PHYSICSBUFFER_H 2 | #define PHYSICSBUFFER_H 3 | 4 | #include 5 | namespace Physics { 6 | 7 | class PhysicsManager; 8 | class QTPHYSICSUNOFFICIAL_EXPORT PhysicsBuffer : public Qt3DCore::QBackendNode 9 | { 10 | public: 11 | 12 | explicit PhysicsBuffer(); 13 | ~PhysicsBuffer(); 14 | 15 | void updateFromPeer(Qt3DCore::QNode *peer) Q_DECL_OVERRIDE; 16 | 17 | QString objectName(){return m_objectName;} 18 | 19 | bool isDirty(){return m_dirty;} 20 | void setDirty(bool dirty){m_dirty=dirty;} 21 | void setManager(PhysicsManager *manager); 22 | bool isEnabled(){return m_enabled;} 23 | 24 | inline Qt3DRender::QBuffer::BufferType type() const { return m_type; } 25 | inline Qt3DRender::QBuffer::UsageType usage() const { return m_usage; } 26 | inline QByteArray data() const { return m_data; } 27 | inline Qt3DRender::QBufferFunctorPtr bufferFunctor() const { return m_functor; } 28 | 29 | protected: 30 | void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &) Q_DECL_OVERRIDE; 31 | private: 32 | QString m_objectName; 33 | bool m_enabled; 34 | 35 | bool m_dirty; 36 | 37 | Qt3DRender::QBuffer::BufferType m_type; 38 | Qt3DRender::QBuffer::UsageType m_usage; 39 | QByteArray m_data; 40 | Qt3DRender::QBufferFunctorPtr m_functor; 41 | 42 | PhysicsManager* m_manager; 43 | 44 | 45 | }; 46 | 47 | 48 | class QTPHYSICSUNOFFICIAL_EXPORT PhysicsBufferFunctor : public Qt3DCore::QBackendNodeFunctor 49 | { 50 | public: 51 | explicit PhysicsBufferFunctor(PhysicsManager* manager); 52 | Qt3DCore::QBackendNode *create(Qt3DCore::QNode *frontend, const Qt3DCore::QBackendNodeFactory *factory) const Q_DECL_OVERRIDE; 53 | Qt3DCore::QBackendNode *get(const Qt3DCore::QNodeId &id) const Q_DECL_OVERRIDE; 54 | void destroy(const Qt3DCore::QNodeId &id) const Q_DECL_OVERRIDE; 55 | private: 56 | PhysicsManager* m_manager; 57 | 58 | 59 | }; 60 | 61 | } 62 | 63 | #endif // PHYSICSBUFFER_H 64 | -------------------------------------------------------------------------------- /src/backend/backendtypes/physicsgeometryrenderer.h: -------------------------------------------------------------------------------- 1 | #ifndef PhysicsGeometryRenderer_H 2 | #define PhysicsGeometryRenderer_H 3 | #include 4 | #include 5 | 6 | 7 | namespace Physics { 8 | 9 | class PhysicsManager; 10 | class QTPHYSICSUNOFFICIAL_EXPORT PhysicsGeometryRenderer : public Qt3DCore::QBackendNode 11 | { 12 | public: 13 | explicit PhysicsGeometryRenderer(); 14 | ~PhysicsGeometryRenderer(); 15 | 16 | void updateFromPeer(Qt3DCore::QNode *peer) Q_DECL_OVERRIDE; 17 | 18 | QString objectName(){return m_objectName;} 19 | 20 | bool isEnabled(){return m_enabled;} 21 | bool isDirty(){return m_dirty;} 22 | void setDirty(bool dirty){m_dirty=dirty;} 23 | void setManager(PhysicsManager *manager); 24 | 25 | protected: 26 | void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &) Q_DECL_OVERRIDE; 27 | private: 28 | void setGeometry(Qt3DCore::QNodeId geometry); 29 | 30 | QString m_objectName; 31 | 32 | bool m_dirty; 33 | bool m_enabled; 34 | 35 | Qt3DCore::QNodeId m_geometry; 36 | Qt3DRender::QGeometryFunctorPtr m_geometry_functor; 37 | 38 | PhysicsManager* m_manager; 39 | 40 | int m_instanceCount; 41 | int m_primitiveCount; 42 | int m_baseVertex; 43 | int m_baseInstance; 44 | int m_restartIndex; 45 | bool m_primitiveRestart; 46 | 47 | Qt3DRender::QGeometryRenderer::PrimitiveType m_primitiveType; 48 | 49 | friend class UpdatePhysicsEntitiesJob; 50 | 51 | }; 52 | 53 | 54 | class QTPHYSICSUNOFFICIAL_EXPORT PhysicsGeometryRendererFunctor : public Qt3DCore::QBackendNodeFunctor 55 | { 56 | public: 57 | explicit PhysicsGeometryRendererFunctor(PhysicsManager* manager); 58 | Qt3DCore::QBackendNode *create(Qt3DCore::QNode *frontend, const Qt3DCore::QBackendNodeFactory *factory) const Q_DECL_OVERRIDE; 59 | Qt3DCore::QBackendNode *get(const Qt3DCore::QNodeId &id) const Q_DECL_OVERRIDE; 60 | void destroy(const Qt3DCore::QNodeId &id) const Q_DECL_OVERRIDE; 61 | private: 62 | PhysicsManager* m_manager; 63 | 64 | 65 | }; 66 | 67 | } 68 | 69 | 70 | #endif // PhysicsGeometryRenderer_H 71 | -------------------------------------------------------------------------------- /src/frontend/physicscollisionevent.h: -------------------------------------------------------------------------------- 1 | #ifndef PHYSICSCOLLISIONEVENT_H 2 | #define PHYSICSCOLLISIONEVENT_H 3 | #include 4 | 5 | namespace Physics { 6 | 7 | 8 | class QTPHYSICSUNOFFICIAL_EXPORT PhysicsCollisionEvent: public QObject 9 | { 10 | Q_OBJECT 11 | Q_PROPERTY(Qt3DCore::QNodeId target READ target) 12 | Q_PROPERTY(QVector3D contactPointOnBody READ contactPointOnBody) 13 | Q_PROPERTY(QVector3D contactPointOnTarget READ contactPointOnTarget) 14 | Q_PROPERTY(QVector3D normalOnTarget READ normalOnTarget) 15 | Q_PROPERTY(QVector3D contactPointOnBodyLocal READ contactPointOnBodyLocal) 16 | Q_PROPERTY(QVector3D contactPointOnTargetLocal READ contactPointOnTargetLocal) 17 | 18 | public: 19 | explicit PhysicsCollisionEvent(QObject* parent=0); 20 | Qt3DCore::QNodeId target(){ return m_target;} 21 | QVector3D contactPointOnBody(){return m_contactPointOnBody;} 22 | QVector3D contactPointOnTarget(){return m_contactPointOnTarget;} 23 | QVector3D contactPointOnBodyLocal(){return m_contactPointOnBodyLocal;} 24 | QVector3D contactPointOnTargetLocal(){return m_contactPointOnTargetLocal;} 25 | QVector3D normalOnTarget(){return m_normalOnTarget;} 26 | 27 | bool isNew(){return m_isNew;} 28 | 29 | void setTarget(Qt3DCore::QNodeId target); 30 | void setContactPointOnBody(QVector3D point); 31 | void setContactPointOnTarget(QVector3D point); 32 | void setContactPointOnBodyLocal(QVector3D point); 33 | void setContactPointOnTargetLocal(QVector3D point); 34 | void setNormalOnTarget(QVector3D normal); 35 | void setIsNew(bool val); 36 | private: 37 | Qt3DCore::QNodeId m_target; 38 | QVector3D m_contactPointOnBody; 39 | QVector3D m_contactPointOnTarget; 40 | QVector3D m_contactPointOnBodyLocal; 41 | QVector3D m_contactPointOnTargetLocal; 42 | QVector3D m_normalOnTarget; 43 | bool m_isNew; 44 | }; 45 | 46 | typedef QSharedPointer PhysicsCollisionEventPtr; 47 | typedef QList PhysicsCollisionEventPtrList; 48 | typedef QList PhysicsCollisionEventList; 49 | 50 | } 51 | 52 | 53 | #endif // PHYSICSCOLLISIONEVENT_H 54 | -------------------------------------------------------------------------------- /src/backend/backendtypes/physicsworldinfobackendnode.h: -------------------------------------------------------------------------------- 1 | #ifndef PHYSICSWORLDINFOBACKENDNODE_H 2 | #define PHYSICSWORLDINFOBACKENDNODE_H 3 | #include 4 | 5 | 6 | namespace Physics { 7 | 8 | class PhysicsManager; 9 | class QTPHYSICSUNOFFICIAL_EXPORT PhysicsWorldInfoBackendNode : public Qt3DCore::QBackendNode 10 | { 11 | public: 12 | enum DirtyFlag { 13 | Clean = 0 , 14 | GravityChanged = 1, 15 | ScaleFactorChanged=2 16 | }; 17 | Q_DECLARE_FLAGS(DirtyFlags, DirtyFlag) 18 | 19 | explicit PhysicsWorldInfoBackendNode(); 20 | ~PhysicsWorldInfoBackendNode(); 21 | 22 | void updateFromPeer(Qt3DCore::QNode *peer) Q_DECL_OVERRIDE; 23 | 24 | DirtyFlags& dirtyFlags(){return m_dirtyFlags;} 25 | 26 | QString objectName(){return m_objectName;} 27 | 28 | void setManager(PhysicsManager *manager); 29 | 30 | void setGravity(QVector3D gravity); 31 | 32 | void setScaleFactor(qreal val); 33 | 34 | QVector3D gravity(){return m_gravity;} 35 | bool debug(){return m_debug;} 36 | qreal scaleFactor(){return m_scaleFactor;} 37 | 38 | void notifyFrontEnd(QString operation, QVariantList args); 39 | 40 | bool isEnabled(){return m_enabled;} 41 | void setEnabled(bool val); 42 | 43 | protected: 44 | void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &) Q_DECL_OVERRIDE; 45 | private: 46 | DirtyFlags m_dirtyFlags; 47 | 48 | QString m_objectName; 49 | 50 | bool m_enabled; 51 | 52 | QVector3D m_gravity; 53 | qreal m_scaleFactor; 54 | bool m_debug; 55 | 56 | PhysicsManager* m_manager; 57 | 58 | 59 | }; 60 | Q_DECLARE_OPERATORS_FOR_FLAGS(PhysicsWorldInfoBackendNode::DirtyFlags) 61 | 62 | class QTPHYSICSUNOFFICIAL_EXPORT PhysicsWorldInfoBackendNodeFunctor : public Qt3DCore::QBackendNodeFunctor 63 | { 64 | public: 65 | explicit PhysicsWorldInfoBackendNodeFunctor(PhysicsManager* manager); 66 | Qt3DCore::QBackendNode *create(Qt3DCore::QNode *frontend, const Qt3DCore::QBackendNodeFactory *factory) const Q_DECL_OVERRIDE; 67 | Qt3DCore::QBackendNode *get(const Qt3DCore::QNodeId &id) const Q_DECL_OVERRIDE; 68 | void destroy(const Qt3DCore::QNodeId &id) const Q_DECL_OVERRIDE; 69 | private: 70 | PhysicsManager* m_manager; 71 | }; 72 | 73 | } 74 | 75 | 76 | #endif // PHYSICSWORLDINFOBACKENDNODE_H 77 | -------------------------------------------------------------------------------- /src/backend/backendtypes/physicsentity.h: -------------------------------------------------------------------------------- 1 | #ifndef PhysicsENTITY_H 2 | #define PhysicsENTITY_H 3 | #include 4 | 5 | 6 | namespace Physics { 7 | 8 | class PhysicsManager; 9 | class QTPHYSICSUNOFFICIAL_EXPORT PhysicsEntity : public Qt3DCore::QBackendNode 10 | { 11 | public: 12 | explicit PhysicsEntity(); 13 | ~PhysicsEntity(); 14 | 15 | void updateFromPeer(Qt3DCore::QNode *peer) Q_DECL_OVERRIDE; 16 | 17 | QString objectName(){return m_objectName;} 18 | 19 | PhysicsEntity* parent(); 20 | Qt3DCore::QNodeId parentId() { return m_parentId; } 21 | 22 | void addChildId(Qt3DCore::QNodeId childId); 23 | void removeChildId(Qt3DCore::QNodeId childId); 24 | 25 | const QSet& childrenIds() { return m_childrenId; } 26 | 27 | void setParentEntity(Qt3DCore::QEntity* parent); 28 | 29 | void addComponent(Qt3DCore::QComponent* comp); 30 | void removeComponent(Qt3DCore::QNodeId componentId); 31 | 32 | void setManager(PhysicsManager *manager); 33 | 34 | Qt3DCore::QNodeId geometry_renderer(){return m_geometry_renderer;} 35 | Qt3DCore::QNodeId transform(){return m_transform;} 36 | Qt3DCore::QNodeId physicsBodyInfo(){return m_physicsBodyInfo;} 37 | Qt3DCore::QNodeId physicsWorldInfo(){return m_physicsWorldInfo;} 38 | 39 | bool isEnabled(){return m_enabled;} 40 | 41 | protected: 42 | void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &) Q_DECL_OVERRIDE; 43 | private: 44 | 45 | Qt3DCore::QNodeId m_parentId; 46 | QSet m_childrenId; 47 | bool m_enabled; 48 | QString m_objectName; 49 | 50 | Qt3DCore::QNodeId m_transform; 51 | Qt3DCore::QNodeId m_geometry_renderer; 52 | Qt3DCore::QNodeId m_physicsBodyInfo; 53 | 54 | Qt3DCore::QNodeId m_physicsWorldInfo; 55 | 56 | PhysicsManager* m_manager; 57 | 58 | }; 59 | 60 | 61 | class QTPHYSICSUNOFFICIAL_EXPORT PhysicsEntityFunctor : public Qt3DCore::QBackendNodeFunctor 62 | { 63 | public: 64 | explicit PhysicsEntityFunctor(PhysicsManager* manager); 65 | Qt3DCore::QBackendNode *create(Qt3DCore::QNode *frontend, const Qt3DCore::QBackendNodeFactory *factory) const Q_DECL_OVERRIDE; 66 | Qt3DCore::QBackendNode *get(const Qt3DCore::QNodeId &id) const Q_DECL_OVERRIDE; 67 | void destroy(const Qt3DCore::QNodeId &id) const Q_DECL_OVERRIDE; 68 | private: 69 | PhysicsManager* m_manager; 70 | }; 71 | 72 | } 73 | 74 | 75 | 76 | #endif // PhysicsENTITYFUNCTOR_H 77 | -------------------------------------------------------------------------------- /src/backend/jobs/notifycollisionsjob.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace Physics { 11 | 12 | NotifyCollisionsJob::NotifyCollisionsJob(PhysicsManager* manager): 13 | QAspectJob() 14 | 15 | { 16 | m_manager=manager; 17 | } 18 | void NotifyCollisionsJob::run(){ 19 | 20 | /*Reset Collition*/ 21 | PhysicsEntity* entity; 22 | PhysicsBodyInfoBackendNode* body_info; 23 | Q_FOREACH(Qt3DCore::QNodeId nodeId, m_manager->m_Id2RigidBodies.keys()){ 24 | entity= static_cast(m_manager->m_resources.operator [](nodeId)); 25 | body_info=static_cast(m_manager->m_resources.operator [](entity->physicsBodyInfo())); 26 | body_info->resetCollisions(); 27 | } 28 | /*Set collitions*/ 29 | PhysicsEntity *entity1, *entity2; 30 | Q_FOREACH(Physics::Collision c, m_manager->getCollisions()){ 31 | entity1=static_cast(m_manager->m_resources[c.body1]); 32 | entity2=static_cast(m_manager->m_resources[c.body2]); 33 | body_info=static_cast(m_manager->m_resources[entity1->physicsBodyInfo()]); 34 | if(body_info->collisions().contains(c)){ 35 | body_info->collisions().operator [](c)=1; 36 | } 37 | else { 38 | body_info->collisions().operator [](c)=2; 39 | } 40 | /*Swap the collision bodies*/ 41 | c.swapBodies(); 42 | body_info=static_cast(m_manager->m_resources[entity2->physicsBodyInfo()]); 43 | if(body_info->collisions().contains(c)){ 44 | body_info->collisions().operator [](c)=1; 45 | } 46 | else { 47 | body_info->collisions().operator [](c)=2; 48 | } 49 | } 50 | 51 | Q_FOREACH(Qt3DCore::QNodeId nodeId, m_manager->m_Id2RigidBodies.keys()){ 52 | entity= static_cast(m_manager->m_resources.operator [](nodeId)); 53 | body_info=static_cast(m_manager->m_resources.operator [](entity->physicsBodyInfo())); 54 | body_info->notifyFrontEnd("notifyCollision"); 55 | } 56 | } 57 | 58 | } 59 | 60 | 61 | -------------------------------------------------------------------------------- /src/backend/backendtypes/physicsattribute.h: -------------------------------------------------------------------------------- 1 | #ifndef PHYSICSATTRIBUTE_H 2 | #define PHYSICSATTRIBUTE_H 3 | 4 | #include 5 | 6 | namespace Physics { 7 | 8 | class PhysicsManager; 9 | class QTPHYSICSUNOFFICIAL_EXPORT PhysicsAttribute : public Qt3DCore::QBackendNode 10 | { 11 | public: 12 | 13 | explicit PhysicsAttribute(); 14 | ~PhysicsAttribute(); 15 | 16 | void updateFromPeer(Qt3DCore::QNode *peer) Q_DECL_OVERRIDE; 17 | 18 | QString objectName(){return m_objectName;} 19 | 20 | bool isDirty(){return m_dirty;} 21 | void setDirty(bool dirty){m_dirty=dirty;} 22 | void setManager(PhysicsManager *manager); 23 | 24 | inline Qt3DCore::QNodeId bufferId() const { return m_bufferId; } 25 | inline Qt3DRender::QAbstractAttribute::DataType dataType() const { return m_dataType; } 26 | inline uint dataSize() const { return m_dataSize; } 27 | inline uint count() const { return m_count; } 28 | inline uint byteStride() const { return m_byteStride; } 29 | inline uint byteOffset() const { return m_byteOffset; } 30 | inline uint divisor() const { return m_divisor; } 31 | bool isEnabled(){return m_enabled;} 32 | inline Qt3DRender::QAbstractAttribute::AttributeType attributeType() const { return m_attributeType; } 33 | QVector asVector3D() const; 34 | protected: 35 | void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &) Q_DECL_OVERRIDE; 36 | private: 37 | Qt3DCore::QNodeId m_bufferId; 38 | Qt3DRender::QAbstractAttribute::DataType m_dataType; 39 | /*These can make dirty true*/ 40 | uint m_dataSize; 41 | uint m_count; 42 | uint m_byteStride; 43 | uint m_byteOffset; 44 | uint m_divisor; 45 | QString m_objectName; 46 | bool m_dirty; 47 | 48 | 49 | bool m_enabled; 50 | Qt3DRender::QAbstractAttribute::AttributeType m_attributeType; 51 | 52 | PhysicsManager* m_manager; 53 | 54 | 55 | }; 56 | 57 | 58 | class QTPHYSICSUNOFFICIAL_EXPORT PhysicsAttributeFunctor : public Qt3DCore::QBackendNodeFunctor 59 | { 60 | public: 61 | explicit PhysicsAttributeFunctor(PhysicsManager* manager); 62 | Qt3DCore::QBackendNode *create(Qt3DCore::QNode *frontend, const Qt3DCore::QBackendNodeFactory *factory) const Q_DECL_OVERRIDE; 63 | Qt3DCore::QBackendNode *get(const Qt3DCore::QNodeId &id) const Q_DECL_OVERRIDE; 64 | void destroy(const Qt3DCore::QNodeId &id) const Q_DECL_OVERRIDE; 65 | private: 66 | PhysicsManager* m_manager; 67 | 68 | 69 | }; 70 | 71 | } 72 | 73 | #endif // PHYSICSATTRIBUTE_H 74 | -------------------------------------------------------------------------------- /src/backend/physicsmanager.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace Physics { 5 | 6 | 7 | PhysicsManager::PhysicsManager(): 8 | m_rootId() 9 | { 10 | m_physics_world=Q_NULLPTR; 11 | m_physics_factory=Q_NULLPTR; 12 | loadPhysicsFactories(); 13 | if(m_physics_factory){ 14 | m_physics_world=m_physics_factory->create_dynamics_world(); 15 | } 16 | } 17 | 18 | PhysicsManager::~PhysicsManager() 19 | { 20 | 21 | Q_FOREACH(Qt3DCore::QBackendNode* node, m_resources.values()) 22 | delete node; 23 | 24 | m_Id2RigidBodies.clear(); 25 | m_RigidBodies2Id.clear(); 26 | delete m_physics_world; 27 | } 28 | 29 | 30 | void PhysicsManager::loadPhysicsFactories(){ 31 | #ifdef ANDROID 32 | QString pluginsPath="../lib"; 33 | #else 34 | QString pluginsPath = QLibraryInfo::location(QLibraryInfo::PluginsPath) + PHYSICS_FACTORIES_PATH; 35 | #endif 36 | QDir physicsFactoryPluginDir(pluginsPath); 37 | //TODO: handle more than 1 38 | Q_FOREACH (QString plugin, physicsFactoryPluginDir.entryList(QDir::Files)) { 39 | QPluginLoader loader(physicsFactoryPluginDir.absoluteFilePath(plugin)); 40 | loader.load(); 41 | PhysicsFactoryInterface* factory_interface = qobject_cast(loader.instance()); 42 | if (factory_interface != Q_NULLPTR) 43 | m_physics_factory=factory_interface; 44 | } 45 | if(m_physics_factory==Q_NULLPTR) 46 | qWarning("No PhysicsFactoryInterface found"); 47 | } 48 | /*Simply convert the collisions from the world to the format of the Physics manager.*/ 49 | QVector PhysicsManager::getCollisions(){ 50 | QVector collisions; 51 | QVector collisions_from_world=m_physics_world->getCollisions(); 52 | qreal inv_scaleFactor=1.0/m_physics_world->scaleFactor(); 53 | Q_FOREACH(PhysicsAbstractDynamicsWorld::Collision c,collisions_from_world){ 54 | Collision collision; 55 | collision.body1=m_RigidBodies2Id[c.body1]; 56 | collision.body2=m_RigidBodies2Id[c.body2]; 57 | collision.normalBody2=c.normalBody2; 58 | collision.pointOnBody1=c.pointOnBody1*inv_scaleFactor; 59 | collision.pointOnBody2=c.pointOnBody2*inv_scaleFactor; 60 | collision.pointOnBody1Local=c.pointOnBody1Local*inv_scaleFactor; 61 | collision.pointOnBody2Local=c.pointOnBody2Local*inv_scaleFactor; 62 | collisions.append(collision); 63 | } 64 | return collisions; 65 | } 66 | 67 | 68 | } 69 | -------------------------------------------------------------------------------- /plugins/bullet/bulletfactory.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace Physics { 10 | 11 | namespace Bullet { 12 | BulletFactory::BulletFactory(QObject *parent) : 13 | QObject(parent) 14 | { 15 | } 16 | 17 | PhysicsAbstractRigidBody* BulletFactory::create_rigid_body(QVariantMap geometric_info){ 18 | if(geometric_info.contains("Type")){ 19 | QString type=geometric_info["Type"].toString(); 20 | if(type=="Cuboid"){ 21 | RigidBoxBody* b=new RigidBoxBody(); 22 | b->setDimension(QVector3D(geometric_info["X_Dim"].toFloat(), 23 | geometric_info["Y_Dim"].toFloat(), 24 | geometric_info["Z_Dim"].toFloat())); 25 | return b; 26 | } 27 | else if(type=="Sphere"){ 28 | RigidSphereBody* b=new RigidSphereBody(); 29 | b->setRadius(geometric_info["Radius"].toFloat()); 30 | return b; 31 | } 32 | else if(type=="StaticPlane"){ 33 | RigidStaticPlaneBody* b=new RigidStaticPlaneBody(); 34 | b->setPlaneConstant(geometric_info["PlaneConstant"].toFloat()); 35 | b->setNormal(geometric_info["PlaneNormal"].value()); 36 | return b; 37 | } 38 | else if(type=="Generic" ){ 39 | QVector points=geometric_info["Points"].value >(); 40 | qreal* _points=new qreal[points.size()*3]; 41 | int i=0; 42 | Q_FOREACH(QVector3D p, points){ 43 | //QVector3D _p=p.value(); 44 | _points[i]=p.x(); 45 | _points[i+1]=p.y(); 46 | _points[i+2]=p.z(); 47 | i+=3; 48 | } 49 | RigidConvexHullBody* b=new RigidConvexHullBody(_points,points.size(),0); 50 | delete _points; 51 | return b; 52 | } 53 | else{ 54 | qFatal("Invalid geometric info"); 55 | return Q_NULLPTR; 56 | } 57 | } 58 | else{ 59 | qFatal("Invalid geometric info"); 60 | return Q_NULLPTR; 61 | } 62 | 63 | } 64 | 65 | PhysicsAbstractDynamicsWorld* BulletFactory::create_dynamics_world(){ 66 | return new DynamicsWorld(); 67 | } 68 | 69 | } 70 | 71 | } 72 | #if QT_VERSION < 0x050000 73 | Q_EXPORT_PLUGIN2(bullet, BulletFactory) 74 | #endif // QT_VERSION < 0x050000 75 | -------------------------------------------------------------------------------- /plugins/bullet/bodies/rigidconvexhullbody.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | namespace Physics { 6 | 7 | namespace Bullet { 8 | 9 | 10 | RigidConvexHullBody::RigidConvexHullBody(QObject* parent): 11 | AbstractRigidBody(parent) 12 | { 13 | initShape(); 14 | initBody(); 15 | } 16 | RigidConvexHullBody::RigidConvexHullBody(qreal* points,int n_points,QObject* parent): 17 | AbstractRigidBody(parent) 18 | { 19 | initShape(points,n_points); 20 | initBody(); 21 | 22 | } 23 | 24 | RigidConvexHullBody::~RigidConvexHullBody(){ 25 | 26 | } 27 | void RigidConvexHullBody::initShape(){ 28 | initShape(Q_NULLPTR,0); 29 | } 30 | 31 | void RigidConvexHullBody::initShape(qreal* points,int n_points){ 32 | m_shape = new btConvexHullShape(); 33 | for(int i=0;i<3*n_points;i=i+3){ 34 | btVector3 point(points[i],points[i+1],points[i+2]); 35 | ((btConvexHullShape*)m_shape)->addPoint(point); 36 | } 37 | 38 | btShapeHull* hull = new btShapeHull((btConvexHullShape*)m_shape); 39 | btScalar margin = m_shape->getMargin(); 40 | hull->buildHull(margin); 41 | 42 | btAlignedObjectArray planes,vertices; 43 | for(int i=0;inumVertices();i++){ 44 | vertices.push_back(hull->getVertexPointer()[i]); 45 | } 46 | btGeometryUtil::getPlaneEquationsFromVertices(vertices, planes); 47 | 48 | int sz = planes.size(); 49 | bool tooSmall = false; 50 | for (int i=0 ; igetMargin()) >= 0) { 52 | tooSmall = true; 53 | break; 54 | } 55 | } 56 | 57 | if (!tooSmall) { 58 | qWarning("Convex hull too small to apply margin"); 59 | vertices.clear(); 60 | btGeometryUtil::getVerticesFromPlaneEquations(planes, vertices); 61 | } 62 | 63 | sz = vertices.size(); 64 | for (int i=0 ; iaddPoint(vertices[i]); 66 | } 67 | delete hull; 68 | } 69 | void RigidConvexHullBody::setCollisionMargin(qreal margin){ 70 | 71 | } 72 | 73 | void RigidConvexHullBody::addPoint(QVector3D p){ 74 | ((btConvexHullShape*)m_shape)->addPoint(btVector3(p.x(),p.y(),p.z())); 75 | } 76 | 77 | void RigidConvexHullBody::updatePoints(qreal* points,int n_points){ 78 | delete m_shape; 79 | btScalar* bt_points=new btScalar[3*n_points]; 80 | for(int i=0;i<3*n_points;i++) 81 | bt_points[i]=points[i]; 82 | m_shape = new btConvexHullShape(bt_points,n_points); 83 | m_rigidBody->setCollisionShape(m_shape); 84 | delete bt_points; 85 | setMassProps(); 86 | } 87 | 88 | 89 | 90 | }} 91 | -------------------------------------------------------------------------------- /plugins/bullet/bodies/abstractrigidbody.h: -------------------------------------------------------------------------------- 1 | #ifndef AbstractRigidBody_H 2 | #define AbstractRigidBody_H 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | namespace Physics { 12 | 13 | namespace Bullet { 14 | 15 | 16 | class AbstractRigidBody : public PhysicsAbstractRigidBody { 17 | Q_OBJECT 18 | 19 | public: 20 | enum ChangeFlag{ 21 | NoChange =0, 22 | MaskChanged=1, 23 | GroupChanged=2 24 | }; 25 | Q_DECLARE_FLAGS(ChangeFlags, ChangeFlag) 26 | explicit AbstractRigidBody(QObject* parent=0); 27 | ~AbstractRigidBody(); 28 | virtual int mask(){return m_mask;} 29 | virtual int group(){return m_group;} 30 | virtual bool kinematic(){return m_kinematic;} 31 | 32 | virtual void setMask(int mask); 33 | virtual void setGroup(int group); 34 | virtual void setKinematic(bool kinematic); 35 | 36 | virtual QMatrix4x4 worldTransformation(); 37 | virtual void setWorldTransformation(QMatrix4x4 m,qreal scaleFactor=1.0); 38 | 39 | virtual qreal restitution(){return m_restitution;} 40 | virtual qreal rollingFriction(){return m_rollingFriction;} 41 | virtual qreal friction(){return m_friction;} 42 | virtual qreal mass(){return m_mass;} 43 | virtual QVector3D fallInertia(){return m_fallInertia;} 44 | virtual qreal collisionMargin(){return m_collisionMargin;} 45 | 46 | virtual void setRestitution(qreal restitution); 47 | virtual void setRollingFriction(qreal rollingFriction); 48 | virtual void setFriction(qreal friction); 49 | virtual void setMass(qreal mass); 50 | virtual void setFallInertia(QVector3D fallInertia); 51 | virtual void setCollisionMargin(qreal margin); 52 | 53 | btRigidBody* bulletBody(){return m_rigidBody;} 54 | public slots: 55 | 56 | virtual void applyForce(QVector3D force,QVector3D relationPosition=QVector3D()); 57 | virtual void applyImpulse(QVector3D force,QVector3D relationPosition=QVector3D()); 58 | virtual void clearForces(); 59 | 60 | protected: 61 | virtual void initBody(); 62 | virtual void initShape()=0; 63 | virtual void setMassProps(); 64 | 65 | int m_mask; 66 | int m_group; 67 | bool m_kinematic; 68 | ChangeFlags m_changeFlags; 69 | qreal m_mass; 70 | QVector3D m_fallInertia; 71 | qreal m_restitution; 72 | qreal m_friction; 73 | qreal m_rollingFriction; 74 | qreal m_collisionMargin; 75 | btCollisionShape* m_shape ; 76 | btMotionState* m_motionState; 77 | 78 | btRigidBody* m_rigidBody; 79 | }; 80 | Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractRigidBody::ChangeFlags) 81 | }} 82 | #endif // AbstractRigidBody_H 83 | -------------------------------------------------------------------------------- /src/backend/backendtypes/physicssoftbodyinfobackendnode.cpp: -------------------------------------------------------------------------------- 1 | #include "physicssoftbodyinfobackendnode.h" 2 | #include "physicsmanager.h" 3 | 4 | namespace Physics { 5 | 6 | 7 | 8 | PhysicsSoftBodyInfoBackendNode::PhysicsSoftBodyInfoBackendNode(): 9 | PhysicsBodyInfoBackendNode(), 10 | m_dirtyFlags(false), 11 | m_enabled(false), 12 | m_inputMesh() 13 | { 14 | 15 | } 16 | PhysicsSoftBodyInfoBackendNode::~PhysicsSoftBodyInfoBackendNode(){ 17 | m_manager->m_resources.remove(peerUuid()); 18 | } 19 | 20 | void PhysicsSoftBodyInfoBackendNode::updateFromPeer(Qt3DCore::QNode *peer){ 21 | PhysicsBodyInfoBackendNode::updateFromPeer(peer); 22 | PhysicsSoftBodyInfo *soft_body_info = static_cast(peer); 23 | setInputMesh(soft_body_info->inputMesh()->id()); 24 | m_enabled=soft_body_info->isEnabled(); 25 | } 26 | 27 | void PhysicsSoftBodyInfoBackendNode::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e){ 28 | PhysicsBodyInfoBackendNode::sceneChangeEvent(e); 29 | switch (e->type()) { 30 | case Qt3DCore::NodeUpdated: { 31 | Qt3DCore::QScenePropertyChangePtr propertyChange = qSharedPointerCast(e); 32 | if (propertyName == QByteArrayLiteral("enabled")) 33 | m_enabled = propertyChange->value().value(); 34 | else if (propertyChange->propertyName() == QByteArrayLiteral("inputMesh")) 35 | setInputMesh(propertyChange->value().value()->id()); 36 | break; 37 | } 38 | default: 39 | break; 40 | } 41 | 42 | } 43 | 44 | void PhysicsSoftBodyInfoBackendNode::setInputMesh(Qt3DCore::QNodeId inputMesh){ 45 | if(m_inputMesh!=inputMesh){ 46 | m_inputMesh=inputMesh; 47 | m_dirtyMesh=true; 48 | } 49 | } 50 | 51 | 52 | 53 | PhysicsSoftBodyInfoBackendNodeFunctor::PhysicsSoftBodyInfoBackendNodeFunctor(PhysicsManager* manager) 54 | { 55 | m_manager=manager; 56 | } 57 | 58 | 59 | Qt3DCore::QBackendNode *PhysicsSoftBodyInfoBackendNodeFunctor::create(Qt3DCore::QNode *frontend, const Qt3DCore::QBackendNodeFactory *factory) 60 | const { 61 | PhysicsSoftBodyInfoBackendNode* body_info=new PhysicsSoftBodyInfoBackendNode(); 62 | m_manager->m_resources.insert(frontend->id(),body_info); 63 | body_info->setFactory(factory); 64 | body_info->setManager(m_manager); 65 | body_info->setPeer(frontend); 66 | return body_info; 67 | } 68 | Qt3DCore::QBackendNode *PhysicsSoftBodyInfoBackendNodeFunctor::get(const Qt3DCore::QNodeId &id) const 69 | { 70 | if(m_manager->m_resources.contains(id)) 71 | return m_manager->m_resources.operator [](id); 72 | else 73 | return Q_NULLPTR; 74 | } 75 | void PhysicsSoftBodyInfoBackendNodeFunctor::destroy(const Qt3DCore::QNodeId &id) const 76 | { 77 | if(m_manager->m_resources.contains(id)) 78 | delete m_manager->m_resources.operator [](id); 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /src/backend/jobs/updatetransformsjob.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | namespace Physics { 11 | 12 | UpdateTransformsJob::UpdateTransformsJob(PhysicsManager* manager): 13 | QAspectJob() 14 | 15 | { 16 | m_manager=manager; 17 | 18 | } 19 | void UpdateTransformsJob::run(){ 20 | QQueue > nodes_to_visit; 21 | QPair current_node(m_manager->rootEntityId(),QMatrix4x4()); 22 | nodes_to_visit.enqueue(current_node); 23 | PhysicsEntity* entity; 24 | QMatrix4x4 current_world_transform,global_transform; 25 | QVector4D translation; 26 | PhysicsTransform* transform; 27 | PhysicsBodyInfoBackendNode* body_info; 28 | PhysicsAbstractRigidBody* rigid_body; 29 | QPair childNode; 30 | qreal inv_scaleFactor=1.0/m_manager->m_physics_world->scaleFactor(); 31 | while(!nodes_to_visit.isEmpty()){ 32 | current_node=nodes_to_visit.dequeue(); 33 | current_world_transform=current_node.second; 34 | entity=static_cast(m_manager->m_resources[current_node.first]); 35 | if(!entity->transform().isNull() && m_manager->m_resources.contains(entity->transform())){ 36 | transform=static_cast(m_manager->m_resources[entity->transform()]); 37 | current_world_transform=current_world_transform*transform->transformMatrix(); 38 | } 39 | if(m_manager->m_Id2RigidBodies.contains(current_node.first)){ 40 | body_info=static_cast(m_manager->m_resources[entity->physicsBodyInfo()]); 41 | rigid_body=static_cast(m_manager->m_Id2RigidBodies[current_node.first]); 42 | 43 | global_transform=rigid_body->worldTransformation(); 44 | translation=global_transform.column(3); 45 | translation=translation*inv_scaleFactor; 46 | translation.setW(1); 47 | global_transform.setColumn(3,translation); 48 | 49 | current_world_transform=global_transform; 50 | /*If the object is not statics (or kinematic) then update the position*/ 51 | //if(rigid_body->mass()!=0){ 52 | body_info->setLocalTransform(current_node.second.inverted()*global_transform); 53 | body_info->notifyFrontEnd("updateTransform"); 54 | //} 55 | } 56 | Q_FOREACH(Qt3DCore::QNodeId id, entity->childrenIds()){ 57 | childNode=QPair(id,current_world_transform); 58 | nodes_to_visit.enqueue(childNode); 59 | } 60 | } 61 | } 62 | 63 | 64 | } 65 | -------------------------------------------------------------------------------- /plugins/bullet/bodies/motionstate.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | namespace Physics { 3 | 4 | 5 | namespace Bullet{ 6 | 7 | MotionState::MotionState(QObject *parent) : QObject(parent), 8 | btDefaultMotionState() 9 | { 10 | 11 | } 12 | 13 | MotionState::MotionState(const btTransform &startTrans, const btTransform ¢erOfMassOffset,QObject* parent) 14 | :QObject(parent),btDefaultMotionState(startTrans,centerOfMassOffset) 15 | { 16 | 17 | } 18 | MotionState::MotionState(const QMatrix4x4 startTrans, const QMatrix4x4 centerOfMassOffset,QObject* parent) 19 | :QObject(parent) 20 | { 21 | btMatrix3x3 w_rotation(startTrans.operator ()(0,0),startTrans.operator ()(0,1),startTrans.operator ()(0,2), 22 | startTrans.operator ()(1,0),startTrans.operator ()(1,1),startTrans.operator ()(1,2), 23 | startTrans.operator ()(2,0),startTrans.operator ()(2,1),startTrans.operator ()(2,2)); 24 | 25 | btVector3 w_translation(startTrans.operator ()(0,3),startTrans.operator ()(1,3),startTrans.operator ()(2,3)); 26 | m_graphicsWorldTrans=btTransform(w_rotation,w_translation); 27 | btMatrix3x3 c_rotation(centerOfMassOffset.operator ()(0,0),centerOfMassOffset.operator ()(0,1),centerOfMassOffset.operator ()(0,2), 28 | centerOfMassOffset.operator ()(1,0),centerOfMassOffset.operator ()(1,1),centerOfMassOffset.operator ()(1,2), 29 | centerOfMassOffset.operator ()(2,0),centerOfMassOffset.operator ()(2,1),centerOfMassOffset.operator ()(2,2)); 30 | btVector3 c_translation(centerOfMassOffset.operator ()(0,3),centerOfMassOffset.operator ()(1,3),centerOfMassOffset.operator ()(2,3)); 31 | 32 | m_centerOfMassOffset=btTransform(c_rotation,c_translation); 33 | m_startWorldTrans=btTransform(m_graphicsWorldTrans); 34 | 35 | } 36 | void MotionState::setWorldTransform(const btTransform ¢erOfMassWorldTrans){ 37 | btDefaultMotionState::setWorldTransform(centerOfMassWorldTrans); 38 | } 39 | void MotionState::getWorldTransform(btTransform ¢erOfMassWorldTrans) const{ 40 | return btDefaultMotionState::getWorldTransform(centerOfMassWorldTrans); 41 | } 42 | 43 | 44 | void MotionState::setWorldTransform(QMatrix4x4 m,qreal scaleFactor){ 45 | btMatrix3x3 w_rotation(m.operator ()(0,0),m.operator ()(0,1),m.operator ()(0,2), 46 | m.operator ()(1,0),m.operator ()(1,1),m.operator ()(1,2), 47 | m.operator ()(2,0),m.operator ()(2,1),m.operator ()(2,2)); 48 | btVector3 w_translation(m.operator ()(0,3)*scaleFactor,m.operator ()(1,3)*scaleFactor,m.operator ()(2,3)*scaleFactor); 49 | btDefaultMotionState::setWorldTransform(btTransform(w_rotation,w_translation)); 50 | } 51 | 52 | QMatrix4x4 MotionState::getWorldTransformAsQMatrix4x4(){ 53 | btTransform matrix; 54 | getWorldTransform(matrix); 55 | btScalar* m=new btScalar[16]; 56 | matrix.getOpenGLMatrix(m); 57 | QMatrix4x4 worldTranform(m[0],m[4],m[8],m[12], 58 | m[1],m[5],m[9],m[13], 59 | m[2],m[6],m[10],m[14], 60 | m[3],m[7],m[11],m[15]); 61 | delete m; 62 | return worldTranform; 63 | } 64 | 65 | }} 66 | -------------------------------------------------------------------------------- /src/backend/backend.pri: -------------------------------------------------------------------------------- 1 | #------------------------------------------------- 2 | # 3 | # Project created by QtCreator 2015-08-11T09:58:05 4 | # 5 | #------------------------------------------------- 6 | 7 | SOURCES += \ 8 | $$PWD/backendtypes/physicsbodyinfobackendnode.cpp \ 9 | $$PWD/backendtypes/physicsentity.cpp \ 10 | $$PWD/backendtypes/physicstransform.cpp \ 11 | #$$PWD/jobs/debugjob.cpp \ 12 | #jobs/insertphysicstransformjob.cpp \ 13 | $$PWD/physicsmanager.cpp \ 14 | $$PWD/backendtypes/physicsworldinfobackendnode.cpp \ 15 | $$PWD/physics_entities/physicsabstractrigidbody.cpp \ 16 | $$PWD/physics_entities/physicsabstractdynamicsworld.cpp \ 17 | $$PWD/jobs/simulatestepjob.cpp \ 18 | $$PWD/jobs/updatephysicsentitiesjob.cpp \ 19 | $$PWD/jobs/updatetransformsjob.cpp \ 20 | $$PWD/backendtypes/physicsgeometryrenderer.cpp \ 21 | $$PWD/backendtypes/physicsgeometry.cpp \ 22 | $$PWD/backendtypes/physicsattribute.cpp \ 23 | $$PWD/backendtypes/physicsbuffer.cpp \ 24 | $$PWD/jobs/notifycollisionsjob.cpp 25 | # $$PWD/backendtypes/physicssoftbodyinfobackendnode.cpp \ 26 | # $$PWD/physics_entities/physicsabstractsoftbody.cpp \ 27 | # $$PWD/physics_entities/physicsabstractsoftrigiddynamicsworld.cpp 28 | 29 | HEADERS +=\ 30 | $$PWD/backendtypes/physicsbodyinfobackendnode.h \ 31 | $$PWD/backendtypes/physicsentity.h \ 32 | $$PWD/backendtypes/physicstransform.h \ 33 | #$$PWD/jobs/debugjob.h \ 34 | #jobs/insertphysicstransformjob.h \ 35 | $$PWD/physicsmanager.h \ 36 | $$PWD/physics_entities/physicsabstractrigidbody.h \ 37 | $$PWD/physics_entities/physicsabstractdynamicsworld.h \ 38 | $$PWD/backendtypes/physicsworldinfobackendnode.h \ 39 | $$PWD/jobs/simulatestepjob.h \ 40 | $$PWD/jobs/updatephysicsentitiesjob.h \ 41 | $$PWD/jobs/updatetransformsjob.h \ 42 | $$PWD/physics_entities/physicsfactoryinterface.h \ 43 | $$PWD/backendtypes/physicsgeometryrenderer.h \ 44 | $$PWD/backendtypes/physicsgeometry.h \ 45 | $$PWD/backendtypes/physicsattribute.h \ 46 | $$PWD/backendtypes/physicsbuffer.h \ 47 | $$PWD/jobs/notifycollisionsjob.h \ 48 | # $$PWD/backendtypes/physicssoftbodyinfobackendnode.h \ 49 | # $$PWD/physics_entities/physicsabstractsoftbody.h \ 50 | # $$PWD/physics_entities/physicsabstractsoftrigiddynamicsworld.h \ 51 | $$PWD/physicscollision.h 52 | 53 | backend1HeadersDataFiles.path = $$[QT_INSTALL_HEADERS]/$$PROJECT_NAME/backend 54 | backend1HeadersDataFiles.files = $$PWD/*.h 55 | backend2HeadersDataFiles.path = $$[QT_INSTALL_HEADERS]/$$PROJECT_NAME/backend/jobs 56 | backend2HeadersDataFiles.files += $$PWD/jobs/*.h 57 | backend3HeadersDataFiles.path = $$[QT_INSTALL_HEADERS]/$$PROJECT_NAME/backend/backendtypes 58 | backend3HeadersDataFiles.files += $$PWD/backendtypes/*.h 59 | backend4HeadersDataFiles.path = $$[QT_INSTALL_HEADERS]/$$PROJECT_NAME/backend/physics_entities 60 | backend4HeadersDataFiles.files += $$PWD/physics_entities/*.h 61 | INSTALLS += backend1HeadersDataFiles backend2HeadersDataFiles backend3HeadersDataFiles backend4HeadersDataFiles 62 | 63 | #libraryFiles.path = $$[QT_INSTALL_LIBS] 64 | #Debug:libraryFiles.files = $$OUT_PWD/debug/*.so $$OUT_PWD/debug/*.prl $$OUT_PWD/debug/*.so 65 | #Release:libraryFiles.files = $$OUT_PWD/release/*.a $$OUT_PWD/release/*.prl 66 | #INSTALLS += libraryFiles 67 | #backendTarget.path = $$[QT_INSTALL_LIBS] 68 | #INSTALLS +=backendTarget 69 | -------------------------------------------------------------------------------- /src/backend/backendtypes/physicsgeometry.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | #include 5 | 6 | namespace Physics { 7 | 8 | PhysicsGeometry::PhysicsGeometry(): 9 | Qt3DCore::QBackendNode(), 10 | m_objectName(), 11 | m_enabled(false), 12 | m_attributes() 13 | { 14 | m_verticesPerPatch=0; 15 | m_manager=Q_NULLPTR; 16 | } 17 | 18 | void PhysicsGeometry::setManager(PhysicsManager *manager){ 19 | m_manager=manager; 20 | } 21 | 22 | 23 | PhysicsGeometry::~PhysicsGeometry(){ 24 | m_manager->m_resources.remove(peerUuid()); 25 | } 26 | 27 | void PhysicsGeometry::updateFromPeer(Qt3DCore::QNode *peer){ 28 | Qt3DRender::QGeometry *geometry = static_cast(peer); 29 | if (geometry != Q_NULLPTR) { 30 | m_enabled=geometry->isEnabled(); 31 | m_attributes.reserve(geometry->attributes().size()); 32 | Q_FOREACH (Qt3DRender::QAbstractAttribute *attribute, geometry->attributes()) 33 | m_attributes.push_back(attribute->id()); 34 | m_verticesPerPatch = geometry->verticesPerPatch(); 35 | } 36 | } 37 | 38 | 39 | void PhysicsGeometry::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e){ 40 | Qt3DCore::QScenePropertyChangePtr propertyChange = qSharedPointerCast(e); 41 | QByteArray propertyName = propertyChange->propertyName(); 42 | switch (e->type()) { 43 | case Qt3DCore::NodeAdded: { 44 | if (propertyName == QByteArrayLiteral("attribute")) { 45 | m_attributes.push_back(propertyChange->value().value()); 46 | } 47 | break; 48 | } 49 | case Qt3DCore::NodeRemoved: { 50 | if (propertyName == QByteArrayLiteral("attribute")) { 51 | m_attributes.removeOne(propertyChange->value().value()); 52 | } 53 | break; 54 | } 55 | case Qt3DCore::NodeUpdated: 56 | if (propertyName == QByteArrayLiteral("enabled")){ 57 | m_enabled = propertyChange->value().value(); 58 | } 59 | else if (propertyName == QByteArrayLiteral("verticesPerPatch")) { 60 | m_verticesPerPatch = propertyChange->value().value(); 61 | break; 62 | } 63 | default: 64 | break; 65 | } 66 | } 67 | 68 | 69 | PhysicsGeometryFunctor::PhysicsGeometryFunctor(PhysicsManager* manager) 70 | { 71 | m_manager=manager; 72 | } 73 | 74 | 75 | Qt3DCore::QBackendNode *PhysicsGeometryFunctor::create(Qt3DCore::QNode *frontend, const Qt3DCore::QBackendNodeFactory *factory) 76 | const { 77 | PhysicsGeometry* geometry=new PhysicsGeometry(); 78 | m_manager->m_resources.insert(frontend->id(),geometry); 79 | geometry->setFactory(factory); 80 | geometry->setManager(m_manager); 81 | geometry->setPeer(frontend); 82 | return geometry; 83 | } 84 | Qt3DCore::QBackendNode *PhysicsGeometryFunctor::get(const Qt3DCore::QNodeId &id) const 85 | { 86 | if(m_manager->m_resources.contains(id)) 87 | return m_manager->m_resources.operator [](id); 88 | else 89 | return Q_NULLPTR; 90 | } 91 | void PhysicsGeometryFunctor::destroy(const Qt3DCore::QNodeId &id) const 92 | { 93 | if(m_manager->m_resources.contains(id)) 94 | delete m_manager->m_resources.operator [](id); 95 | } 96 | 97 | 98 | 99 | } 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /src/backend/backendtypes/physicstransform.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace Physics { 5 | 6 | PhysicsTransform::PhysicsTransform(): 7 | Qt3DCore::QBackendNode(), 8 | m_objectName(), 9 | m_dirty(false), 10 | m_enabled(false), 11 | m_transformMatrix(), 12 | m_rotation() 13 | , m_scale(1.0f, 1.0f, 1.0f) 14 | , m_translation() 15 | { 16 | m_manager=Q_NULLPTR; 17 | } 18 | 19 | void PhysicsTransform::setManager(PhysicsManager *manager){ 20 | m_manager=manager; 21 | } 22 | 23 | 24 | PhysicsTransform::~PhysicsTransform(){ 25 | m_manager->m_resources.remove(peerUuid()); 26 | } 27 | 28 | void PhysicsTransform::updateFromPeer(Qt3DCore::QNode *peer){ 29 | Qt3DCore::QTransform *transform = static_cast(peer); 30 | m_rotation = transform->rotation(); 31 | m_scale = transform->scale3D(); 32 | m_translation = transform->translation(); 33 | updateMatrix(); 34 | m_enabled = transform->isEnabled(); 35 | m_dirty=true; 36 | } 37 | 38 | void PhysicsTransform::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e){ 39 | if (e->type() == Qt3DCore::NodeUpdated) { 40 | const Qt3DCore::QScenePropertyChangePtr &propertyChange = qSharedPointerCast(e); 41 | if (propertyChange->propertyName() == QByteArrayLiteral("scale3D")) { 42 | m_scale = propertyChange->value().value(); 43 | updateMatrix(); 44 | } else if (propertyChange->propertyName() == QByteArrayLiteral("rotation")) { 45 | m_rotation = propertyChange->value().value(); 46 | updateMatrix(); 47 | } else if (propertyChange->propertyName() == QByteArrayLiteral("translation")) { 48 | m_translation = propertyChange->value().value(); 49 | updateMatrix(); 50 | } 51 | else if (propertyChange->propertyName() == QByteArrayLiteral("enabled")){ 52 | m_enabled = propertyChange->value().value(); 53 | m_dirty = true; 54 | } 55 | } 56 | } 57 | 58 | void PhysicsTransform::updateMatrix(){ 59 | QMatrix4x4 m; 60 | m.translate(m_translation); 61 | m.rotate(m_rotation); 62 | m.scale(m_scale); 63 | m_transformMatrix = m; 64 | m_dirty=true; 65 | } 66 | 67 | PhysicsTransformFunctor::PhysicsTransformFunctor(PhysicsManager* manager) 68 | { 69 | m_manager=manager; 70 | } 71 | 72 | 73 | Qt3DCore::QBackendNode *PhysicsTransformFunctor::create(Qt3DCore::QNode *frontend, const Qt3DCore::QBackendNodeFactory *factory) 74 | const { 75 | PhysicsTransform* transform=new PhysicsTransform(); 76 | m_manager->m_resources.insert(frontend->id(),transform); 77 | transform->setFactory(factory); 78 | transform->setManager(m_manager); 79 | transform->setPeer(frontend); 80 | return transform; 81 | } 82 | Qt3DCore::QBackendNode *PhysicsTransformFunctor::get(const Qt3DCore::QNodeId &id) const 83 | { 84 | if(m_manager->m_resources.contains(id)) 85 | return m_manager->m_resources.operator [](id); 86 | else 87 | return Q_NULLPTR; 88 | } 89 | void PhysicsTransformFunctor::destroy(const Qt3DCore::QNodeId &id) const 90 | { 91 | if(m_manager->m_resources.contains(id)) 92 | delete m_manager->m_resources.operator [](id); 93 | } 94 | 95 | 96 | 97 | } 98 | 99 | 100 | -------------------------------------------------------------------------------- /src/backend/backendtypes/physicsbuffer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | namespace Physics { 6 | 7 | PhysicsBuffer::PhysicsBuffer(): 8 | Qt3DCore::QBackendNode(), 9 | m_objectName(), 10 | m_enabled(false), 11 | m_dirty(false), 12 | m_type(), 13 | m_usage() 14 | { 15 | m_manager=Q_NULLPTR; 16 | } 17 | 18 | void PhysicsBuffer::setManager(PhysicsManager *manager){ 19 | m_manager=manager; 20 | } 21 | 22 | 23 | PhysicsBuffer::~PhysicsBuffer(){ 24 | m_manager->m_resources.remove(peerUuid()); 25 | } 26 | 27 | void PhysicsBuffer::updateFromPeer(Qt3DCore::QNode *peer){ 28 | Qt3DRender::QBuffer *buffer = static_cast(peer); 29 | if (buffer != Q_NULLPTR) { 30 | m_type = buffer->type(); 31 | m_usage = buffer->usage(); 32 | m_data = buffer->data(); 33 | m_functor = buffer->bufferFunctor(); 34 | m_dirty = true; 35 | m_enabled=buffer->isEnabled(); 36 | } 37 | } 38 | 39 | void PhysicsBuffer::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e){ 40 | if (e->type() == Qt3DCore::NodeUpdated) { 41 | Qt3DCore::QScenePropertyChangePtr propertyChange = qSharedPointerCast(e); 42 | QByteArray propertyName = propertyChange->propertyName(); 43 | if (propertyName == QByteArrayLiteral("enabled")){ 44 | m_enabled = propertyChange->value().value(); 45 | } 46 | else if (propertyName == QByteArrayLiteral("data")) { 47 | QByteArray newData = propertyChange->value().value(); 48 | m_dirty |= m_data != newData; 49 | m_data = newData; 50 | } else if (propertyName == QByteArrayLiteral("type")) { 51 | m_type = static_cast(propertyChange->value().value()); 52 | m_dirty = true; 53 | } else if (propertyName == QByteArrayLiteral("usage")) { 54 | m_usage = static_cast(propertyChange->value().value()); 55 | m_dirty = true; 56 | } else if (propertyName == QByteArrayLiteral("bufferFunctor")) { 57 | Qt3DRender::QBufferFunctorPtr newFunctor = propertyChange->value().value(); 58 | m_dirty |= !(newFunctor && m_functor && *newFunctor == *m_functor); 59 | m_functor = newFunctor; 60 | } 61 | } 62 | 63 | } 64 | 65 | 66 | PhysicsBufferFunctor::PhysicsBufferFunctor(PhysicsManager* manager) 67 | { 68 | m_manager=manager; 69 | } 70 | 71 | 72 | Qt3DCore::QBackendNode *PhysicsBufferFunctor::create(Qt3DCore::QNode *frontend, const Qt3DCore::QBackendNodeFactory *factory) 73 | const { 74 | PhysicsBuffer* attribute=new PhysicsBuffer(); 75 | m_manager->m_resources.insert(frontend->id(),attribute); 76 | attribute->setFactory(factory); 77 | attribute->setManager(m_manager); 78 | attribute->setPeer(frontend); 79 | return attribute; 80 | } 81 | Qt3DCore::QBackendNode *PhysicsBufferFunctor::get(const Qt3DCore::QNodeId &id) const 82 | { 83 | if(m_manager->m_resources.contains(id)) 84 | return m_manager->m_resources.operator [](id); 85 | else 86 | return Q_NULLPTR; 87 | } 88 | void PhysicsBufferFunctor::destroy(const Qt3DCore::QNodeId &id) const 89 | { 90 | if(m_manager->m_resources.contains(id)) 91 | delete m_manager->m_resources.operator [](id); 92 | } 93 | 94 | 95 | 96 | } 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /src/backend/backendtypes/physicsbodyinfobackendnode.h: -------------------------------------------------------------------------------- 1 | #ifndef PHYSICSBODYINFOBACKENDNODE_H 2 | #define PHYSICSBODYINFOBACKENDNODE_H 3 | 4 | #include 5 | #include 6 | 7 | namespace Physics { 8 | 9 | class PhysicsManager; 10 | 11 | /*PhysicsBodyInfoBackendNode: the representation of the node PhysicsBodyInfo in the backend. 12 | PhysicsSoftBodyInfo is handled as a special case*/ 13 | class QTPHYSICSUNOFFICIAL_EXPORT PhysicsBodyInfoBackendNode : public Qt3DCore::QBackendNode 14 | { 15 | public: 16 | enum DirtyFlag { 17 | Clean = 0, 18 | MaskChanged = 1 , 19 | GroupChanged = 2, 20 | MassChanged = 4, 21 | FallInertiaChanged = 8, 22 | RestistutionChanged = 16, 23 | FrictionChanged = 32, 24 | RollingFrictionChanged = 64, 25 | InputTransformChanged = 128, 26 | KinematicChanged = 256 27 | }; 28 | Q_DECLARE_FLAGS(DirtyFlags, DirtyFlag) 29 | 30 | explicit PhysicsBodyInfoBackendNode(); 31 | ~PhysicsBodyInfoBackendNode(); 32 | 33 | virtual void updateFromPeer(Qt3DCore::QNode *peer) Q_DECL_OVERRIDE; 34 | 35 | virtual DirtyFlags& dirtyFlags(){return m_dirtyFlags;} 36 | 37 | virtual QString objectName(){return m_objectName;} 38 | 39 | virtual void setManager(PhysicsManager *manager); 40 | 41 | virtual int mask(){return m_mask;} 42 | virtual void setMask(int mask); 43 | 44 | virtual int group(){return m_group;} 45 | virtual void setGroup(int group); 46 | 47 | virtual bool kinematic(){return m_kinematic;} 48 | virtual void setKinematic(bool kinematic); 49 | 50 | virtual qreal restitution(){return m_restitution;} 51 | virtual void setRestitution(qreal restitution); 52 | 53 | virtual qreal rollingFriction(){return m_rollingFriction;} 54 | virtual void setRollingFriction(qreal rollingFriction); 55 | 56 | virtual qreal friction(){return m_friction;} 57 | virtual void setFriction(qreal friction); 58 | 59 | virtual qreal mass(){return m_mass;} 60 | virtual void setMass(qreal mass); 61 | 62 | virtual QVector3D fallInertia(){return m_fallInertia;} 63 | virtual void setFallInertia(QVector3D fallInertia); 64 | 65 | virtual Qt3DCore::QNodeId inputTransform(){return m_inputTransform;} 66 | virtual void setInputTransform(Qt3DCore::QNodeId inputTranform); 67 | 68 | virtual QMatrix4x4 localTransform() {return m_local_transform;} 69 | virtual void setLocalTransform(QMatrix4x4 m){m_local_transform=m;} 70 | 71 | virtual void notifyFrontEnd(QString operation); 72 | 73 | virtual QHash& collisions(){return m_collisions;} 74 | virtual void resetCollisions(); 75 | 76 | bool isEnabled(){return m_enabled;} 77 | void setEnabled(bool val); 78 | 79 | protected: 80 | virtual void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &) Q_DECL_OVERRIDE; 81 | 82 | DirtyFlags m_dirtyFlags; 83 | 84 | QString m_objectName; 85 | bool m_enabled; 86 | 87 | int m_mask; 88 | int m_group; 89 | bool m_kinematic; 90 | qreal m_mass; 91 | QVector3D m_fallInertia; 92 | qreal m_restitution; 93 | qreal m_friction; 94 | qreal m_rollingFriction; 95 | 96 | Qt3DCore::QNodeId m_inputTransform; 97 | 98 | PhysicsManager* m_manager; 99 | 100 | QHash m_collisions; 101 | 102 | QMatrix4x4 m_local_transform; 103 | 104 | }; 105 | Q_DECLARE_OPERATORS_FOR_FLAGS(PhysicsBodyInfoBackendNode::DirtyFlags) 106 | 107 | 108 | class QTPHYSICSUNOFFICIAL_EXPORT PhysicsBodyInfoBackendNodeFunctor : public Qt3DCore::QBackendNodeFunctor 109 | { 110 | public: 111 | explicit PhysicsBodyInfoBackendNodeFunctor(PhysicsManager* manager); 112 | Qt3DCore::QBackendNode *create(Qt3DCore::QNode *frontend, const Qt3DCore::QBackendNodeFactory *factory) const Q_DECL_OVERRIDE; 113 | Qt3DCore::QBackendNode *get(const Qt3DCore::QNodeId &id) const Q_DECL_OVERRIDE; 114 | void destroy(const Qt3DCore::QNodeId &id) const Q_DECL_OVERRIDE; 115 | private: 116 | PhysicsManager* m_manager; 117 | }; 118 | 119 | } 120 | 121 | #endif // PHYSICSBODYINFOBACKENDNODE_H 122 | -------------------------------------------------------------------------------- /src/backend/backendtypes/physicsworldinfobackendnode.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | #include 5 | #include 6 | 7 | namespace Physics { 8 | 9 | PhysicsWorldInfoBackendNode::PhysicsWorldInfoBackendNode(): 10 | Qt3DCore::QBackendNode(Qt3DCore::QBackendNode::ReadWrite), 11 | m_dirtyFlags(Clean), 12 | m_objectName(), 13 | m_enabled(false), 14 | m_debug(false) 15 | { 16 | m_scaleFactor=1.0; 17 | m_manager=Q_NULLPTR; 18 | } 19 | 20 | void PhysicsWorldInfoBackendNode::setManager(PhysicsManager *manager){ 21 | m_manager=manager; 22 | } 23 | 24 | 25 | PhysicsWorldInfoBackendNode::~PhysicsWorldInfoBackendNode(){ 26 | m_manager->m_resources.remove(peerUuid()); 27 | } 28 | 29 | void PhysicsWorldInfoBackendNode::updateFromPeer(Qt3DCore::QNode *peer){ 30 | PhysicsWorldInfo *world_info = static_cast(peer); 31 | m_objectName = peer->objectName(); 32 | setEnabled(world_info->isEnabled()); 33 | setGravity(world_info->gravity()); 34 | setScaleFactor(world_info->scaleFactor()); 35 | m_debug=world_info->debug(); 36 | } 37 | 38 | void PhysicsWorldInfoBackendNode::setGravity(QVector3D gravity){ 39 | if(m_gravity!=gravity){ 40 | m_gravity=gravity; 41 | m_dirtyFlags.operator |=(GravityChanged); 42 | } 43 | } 44 | 45 | void PhysicsWorldInfoBackendNode::setScaleFactor(qreal val) 46 | { 47 | if(m_scaleFactor!=val){ 48 | m_scaleFactor=val; 49 | m_dirtyFlags.operator |=(ScaleFactorChanged); 50 | } 51 | } 52 | 53 | 54 | void PhysicsWorldInfoBackendNode::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e){ 55 | switch (e->type()) { 56 | case Qt3DCore::NodeUpdated: { 57 | Qt3DCore::QScenePropertyChangePtr propertyChange = qSharedPointerCast(e); 58 | if (propertyChange->propertyName() == QByteArrayLiteral("gravity")) 59 | setGravity(propertyChange->value().value()); 60 | else if (propertyChange->propertyName() == QByteArrayLiteral("enabled")) 61 | setEnabled(propertyChange->value().toBool()); 62 | else if (propertyChange->propertyName() == QByteArrayLiteral("debug")) 63 | m_debug = propertyChange->value().toBool(); 64 | else if (propertyChange->propertyName() == QByteArrayLiteral("scaleFactor")) 65 | setScaleFactor( propertyChange->value().toReal()); 66 | break; 67 | } 68 | default: 69 | break; 70 | } 71 | } 72 | 73 | void PhysicsWorldInfoBackendNode::notifyFrontEnd(QString operation, QVariantList args){ 74 | Qt3DCore::QBackendScenePropertyChangePtr e(new Qt3DCore::QBackendScenePropertyChange(Qt3DCore::NodeUpdated, peerUuid())); 75 | /*if(operation=="attachPhysicsTransfrom"){ 76 | e->setPropertyName("attachPhysicsTransfrom"); 77 | e->setValue(true); 78 | } 79 | else */ 80 | if(operation=="debugdraw"){ 81 | e->setPropertyName("debugdraw"); 82 | e->setValue(args); 83 | } 84 | else{ 85 | return; 86 | } 87 | e->setTargetNode(peerUuid()); 88 | notifyObservers(e); 89 | } 90 | 91 | void PhysicsWorldInfoBackendNode::setEnabled(bool val) 92 | { 93 | if(m_enabled!=val){ 94 | m_enabled=val; 95 | } 96 | } 97 | 98 | 99 | 100 | PhysicsWorldInfoBackendNodeFunctor::PhysicsWorldInfoBackendNodeFunctor(PhysicsManager* manager) 101 | { 102 | m_manager=manager; 103 | } 104 | 105 | 106 | Qt3DCore::QBackendNode *PhysicsWorldInfoBackendNodeFunctor::create(Qt3DCore::QNode *frontend, const Qt3DCore::QBackendNodeFactory *factory) 107 | const { 108 | PhysicsWorldInfoBackendNode* world_info=new PhysicsWorldInfoBackendNode(); 109 | m_manager->m_resources.insert(frontend->id(),world_info); 110 | world_info->setFactory(factory); 111 | world_info->setManager(m_manager); 112 | world_info->setPeer(frontend); 113 | return world_info; 114 | } 115 | Qt3DCore::QBackendNode *PhysicsWorldInfoBackendNodeFunctor::get(const Qt3DCore::QNodeId &id) const 116 | { 117 | if(m_manager->m_resources.contains(id)) 118 | return m_manager->m_resources.operator [](id); 119 | else 120 | return Q_NULLPTR; 121 | } 122 | void PhysicsWorldInfoBackendNodeFunctor::destroy(const Qt3DCore::QNodeId &id) const 123 | { 124 | if(m_manager->m_resources.contains(id)) 125 | delete m_manager->m_resources.operator [](id); 126 | } 127 | 128 | 129 | 130 | } 131 | 132 | 133 | 134 | -------------------------------------------------------------------------------- /src/frontend/physicsbodyinfo.h: -------------------------------------------------------------------------------- 1 | #ifndef PHYSICSBODYINFO_H 2 | #define PHYSICSBODYINFO_H 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | namespace Physics { 9 | 10 | class QTPHYSICSUNOFFICIAL_EXPORT PhysicsBodyInfo: 11 | public Qt3DCore::QComponent 12 | { 13 | Q_OBJECT 14 | Q_PROPERTY(bool shareable READ shareable) 15 | Q_PROPERTY(int mask READ mask WRITE setMask NOTIFY maskChanged) 16 | Q_PROPERTY(int group READ group WRITE setGroup NOTIFY groupChanged) 17 | Q_PROPERTY(bool kinematic READ kinematic WRITE setKinematic NOTIFY kinematicChanged) 18 | 19 | Q_PROPERTY(qreal restitution READ restitution WRITE setRestitution NOTIFY restitutionChanged) 20 | Q_PROPERTY(qreal friction READ friction WRITE setFriction NOTIFY frictionChanged) 21 | Q_PROPERTY(qreal rollingFriction READ rollingFriction WRITE setRollingFriction NOTIFY rollingFrictionChanged) 22 | Q_PROPERTY(qreal mass READ mass WRITE setMass NOTIFY massChanged) 23 | Q_PROPERTY(QVector3D fallInertia READ fallInertia WRITE setFallInertia NOTIFY fallInertiaChanged) 24 | 25 | Q_PROPERTY(bool hasCollided READ hasCollided NOTIFY hasCollidedChanged) 26 | Q_PROPERTY(QQmlListProperty collisionsList READ collisionsList NOTIFY collisionsListChanged) 27 | 28 | Q_PROPERTY(Qt3DCore::QTransform* inputTransform READ inputTransform WRITE setInputTransform NOTIFY inputTransformChanged) 29 | Q_PROPERTY(Qt3DCore::QTransform* outputTransform READ outputTransform NOTIFY outputTransformChanged) 30 | 31 | public: 32 | explicit PhysicsBodyInfo(Qt3DCore::QNode* parent=0); 33 | ~PhysicsBodyInfo(); 34 | void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) Q_DECL_OVERRIDE; 35 | 36 | virtual int mask(){return m_mask;} 37 | virtual int group(){return m_group;} 38 | virtual bool kinematic(){return m_kinematic;} 39 | 40 | virtual void setMask(int mask); 41 | virtual void setGroup(int group); 42 | virtual void setKinematic(bool kinematic); 43 | 44 | virtual qreal restitution(){return m_restitution;} 45 | virtual qreal rollingFriction(){return m_rollingFriction;} 46 | virtual qreal friction(){return m_friction;} 47 | virtual qreal mass(){return m_mass;} 48 | virtual QVector3D fallInertia(){return m_fallInertia;} 49 | virtual Qt3DCore::QTransform* inputTransform(){return m_inputTransform;} 50 | virtual Qt3DCore::QTransform* outputTransform(){return m_outputTransform;} 51 | 52 | 53 | virtual void setRestitution(qreal restitution); 54 | virtual void setRollingFriction(qreal rollingFriction); 55 | virtual void setFriction(qreal friction); 56 | virtual void setMass(qreal mass); 57 | virtual void setFallInertia(QVector3D fallInertia); 58 | virtual void setInputTransform(Qt3DCore::QTransform* inputTransform); 59 | 60 | QQmlListProperty collisionsList(); 61 | bool hasCollided(){return m_hasCollided;} 62 | 63 | bool collisionTest(Qt3DCore::QNodeId); 64 | 65 | signals: 66 | void maskChanged(int mask); 67 | void groupChanged(int group); 68 | void kinematicChanged(bool kinematic); 69 | 70 | void fallInertiaChanged(QVector3D fallInertia); 71 | void massChanged(qreal mass); 72 | void rollingFrictionChanged(qreal rollingFriction); 73 | void frictionChanged(qreal friction); 74 | void restitutionChanged(qreal restitution); 75 | void inputTransformChanged(); 76 | void outputTransformChanged(); 77 | 78 | void collided(Physics::PhysicsCollisionEventPtr event); 79 | void hasCollidedChanged(bool val); 80 | void collisionsListChanged(); 81 | protected: 82 | void copy(const Qt3DCore::QNode *ref) Q_DECL_OVERRIDE; 83 | 84 | QT3D_CLONEABLE(PhysicsBodyInfo) 85 | 86 | int m_mask; 87 | int m_group; 88 | bool m_kinematic; 89 | 90 | qreal m_mass; 91 | QVector3D m_fallInertia; 92 | qreal m_restitution; 93 | qreal m_friction; 94 | qreal m_rollingFriction; 95 | 96 | Qt3DCore::QTransform* m_inputTransform; 97 | Qt3DCore::QTransform* m_outputTransform; 98 | 99 | 100 | 101 | PhysicsCollisionEventPtrList m_collisionsList; 102 | QSet m_collisionsCache; 103 | bool m_hasCollided; 104 | 105 | static PhysicsCollisionEvent *qmlComponentAt(QQmlListProperty *list, int index); 106 | static int qmlComponentsCount(QQmlListProperty *list); 107 | 108 | }; 109 | 110 | } 111 | #endif // PHYSICSBODYINFO_H 112 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # QtPhysics-Unofficial: A wrapper around BulletPhysics for Qt # 2 | 3 | QtPhysics-Unofficial is an unofficial module that aims at intergrating Bullet physics engine into Qt (>5.5). 4 | Based on the Qt3D 2.x, the module offers: 5 | 6 | * QML components to add physics properties to Qt3D Entities; 7 | * An aspect that implements the physic simulation; 8 | * A Qt plugin that works as wrapper around Bullet Physics; 9 | 10 | Video at 11 | 12 | ## QML Components ## 13 | 14 | Two Qml componets are provided: 15 | 16 | * PhysicsBodyInfo 17 | * PhysicsWorldInfo 18 | 19 | Both components inherit from Qt3D:QComponent. The first one, PhysicsBodyInfo, allows to specify for an entity properties such as mass, restituition, friction etc; 20 | The entities belonging to the physic world are: 21 | * Object with an abstract mesh and a PhysicsBodyInfo 22 | 23 | PhysicsBodyInfo has two property: 24 | * InputTransform. This matrix is used to set the original position of the object or to force the motion state. When the matrix changes the motion state of the object is updated. NB. By "matrix changes" I mean that a change is notified. For example, if you create button that set a traslation to dz:100, the matrix changes only if the prevoius value of dz was different. 25 | * OutputTransorm: the matrix coming from the physics simulation 26 | 27 | A body can be declered as kinematic using the kinematic flag. 28 | PhysicsBodyInfo emit a signal collided(CollitionEvent*) when a collition happens. 29 | 30 | 31 | PhysicsWorldInfo defines general setting for the physic world, such as gravity. 32 | 33 | ##Physic aspect ## 34 | 35 | On the backend, the module implements a Qt3D aspect. In the Bullet world, nested entities are actually single bodies with a compound shape. The relation parent-child is completly absent in the bullet world. 36 | 37 | The aspect executes sequentially those jobs: 38 | 39 | * Visit the scenegraph and update the physic world. For each entry, create a rigid body and/or update its properties; 40 | * Run a simulation step 41 | * Update the transformation of the entities. 42 | * Update the collitions 43 | 44 | ##Bullet Plugin## 45 | The wrapper around Bullet is implemented as a plugin. It implements the interface PhysicsFactoryInterface, which defines the methods to create 46 | bodies and worlds (PhysicsAbstractRigidBody and PhysicsAbstractDynamicsWorld). 47 | 48 | ##What is missing## 49 | ;) 50 | 51 | #Build it# 52 | 53 | In order to build the module, you need to have Qt >5.6 with Qt3D and Bullet >2.73. 54 | Modify the dependency in the file dependecy.pri in /bullet in order to instruct the compiler about the position of the bullet folder. 55 | 56 | Remember to add the step install to your make chain. This will put headers and libs in the default Qt directory. 57 | Since this is not an official qt module, you have to add the includepath in your project .pro file. 58 | 59 | Bullet should be available otherwise the plugin cannot be built. 60 | 61 | ##Build and install Bullet for Desktop## 62 | 63 | Follow the procedure at 64 | https://github.com/bulletphysics/bullet3/releases 65 | 66 | ##Build and install Bullet for Android## 67 | 68 | It is required : 69 | 70 | * Android NDK 10d 71 | * Android SDK 72 | * android.toolchain.cmake file from Opencv project 73 | 74 | Before you compile it, you have to be sure that the shared libraries of Bullet will not have any version number. In fact, Android doesn't support library versioning. 75 | What I suggest is to modify the CMakeList.txt and add the option: 76 | 77 | OPTION(NO_VERSION "remove the version form shared libraries" OFF) 78 | 79 | Then for each CMakeList.txt in the subdirs of src/ add a IF: 80 | Example: In BulletSoftBody/CMakeList.txt 81 | 82 | IF(NOT NO_VERSION) 83 | SET_TARGET_PROPERTIES(BulletSoftBody PROPERTIES VERSION ${BULLET_VERSION}) 84 | SET_TARGET_PROPERTIES(BulletSoftBody PROPERTIES SOVERSION ${BULLET_VERSION}) 85 | ENDIF(NOT NO_VERSION) 86 | 87 | 88 | Then in bullet directory: 89 | * mkdir build-android and cd build-android 90 | * ccmake .. -DANDROID_NDK=[NDK dir] -DCMAKE_TOOLCHAIN_FILE=[android.toolchain.cmake] -DANDROID_TOOLCHAIN_NAME=[TOOLChain name] -DANDROID_NDK_LAYOUT=RELEASE -DANDROID_ABI=[Your ABI] 91 | example: 92 | ccmake .. -DCMAKE_TOOLCHAIN_FILE=/home/chili/android-ndk-r13b/build/cmake/android.toolchain.cmake -DANDROID_PLATFORM=android-19 -DANDROID_ARM_MODE=arm -DANDROID_ABI=armeabi-v7a\ with\ NEON 93 | 94 | * Disable everything except BUILD_SHARED_LIBS ,INSTALL_LIBS and NO_VERSION=true. Check also your install directory. 95 | * make and make install 96 | 97 | Do not forget to add your include dirs and libs enviroment if they are not in the default position. 98 | 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /plugins/bullet/bodies/abstractrigidbody.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace Physics { 5 | 6 | namespace Bullet { 7 | 8 | AbstractRigidBody::AbstractRigidBody(QObject* parent): 9 | PhysicsAbstractRigidBody(parent), 10 | m_mask(1), 11 | m_group(1), 12 | m_kinematic(false), 13 | m_changeFlags(NoChange), 14 | m_mass(0), 15 | m_fallInertia(), 16 | m_restitution(0.0f), 17 | m_friction(0.0f), 18 | m_rollingFriction(0.0f) 19 | { 20 | m_shape=Q_NULLPTR; 21 | m_motionState=Q_NULLPTR; 22 | m_rigidBody=Q_NULLPTR; 23 | m_collisionMargin=-1.0; 24 | } 25 | 26 | AbstractRigidBody::~AbstractRigidBody() 27 | { 28 | delete m_rigidBody; 29 | delete m_motionState; 30 | delete m_shape; 31 | } 32 | 33 | void AbstractRigidBody::initBody(){ 34 | 35 | btVector3 inertia(m_fallInertia.x(),m_fallInertia.y(),m_fallInertia.z()); 36 | if(m_fallInertia.x()==0 && m_fallInertia.y()==0 && m_fallInertia.z()==0) 37 | m_shape->calculateLocalInertia(m_mass,inertia); 38 | 39 | m_motionState = new MotionState(QMatrix4x4(),QMatrix4x4()); 40 | btRigidBody::btRigidBodyConstructionInfo* m_rigidBodyCI= 41 | new btRigidBody::btRigidBodyConstructionInfo(m_mass,m_motionState, m_shape, 42 | btVector3(m_fallInertia.x(),m_fallInertia.y(),m_fallInertia.z())); 43 | m_rigidBody= new btRigidBody(*m_rigidBodyCI); 44 | 45 | m_rigidBody->setRestitution(m_restitution); 46 | 47 | m_rigidBody->setFriction(m_friction); 48 | 49 | m_rigidBody->setRollingFriction(m_rollingFriction); 50 | 51 | //setKinematic(m_kinematic); 52 | 53 | m_collisionMargin=m_shape->getMargin(); 54 | 55 | delete m_rigidBodyCI; 56 | } 57 | 58 | void AbstractRigidBody::setMass(qreal mass){ 59 | if(mass!=m_mass){ 60 | m_mass=mass; 61 | setMassProps(); 62 | } 63 | } 64 | void AbstractRigidBody::setFallInertia(QVector3D fallInertia){ 65 | if(m_fallInertia!=fallInertia){ 66 | m_fallInertia=fallInertia; 67 | setMassProps(); 68 | } 69 | } 70 | 71 | void AbstractRigidBody::setCollisionMargin(qreal margin) 72 | { 73 | if(m_collisionMargin!=margin && margin>0){ 74 | m_collisionMargin=margin; 75 | m_shape->setMargin(m_collisionMargin); 76 | } 77 | 78 | } 79 | 80 | void AbstractRigidBody::setMassProps(){ 81 | btVector3 inertia(m_fallInertia.x(),m_fallInertia.y(),m_fallInertia.z()); 82 | if(m_fallInertia.x()==0 && m_fallInertia.y()==0 && m_fallInertia.z()==0) 83 | m_shape->calculateLocalInertia(m_mass,inertia); 84 | m_rigidBody->setMassProps(m_mass,inertia); 85 | m_rigidBody->activate(); 86 | } 87 | 88 | void AbstractRigidBody::setMask(int mask){ 89 | if(mask >0 && m_mask!=mask){ 90 | m_mask=mask; 91 | m_changeFlags|=MaskChanged; 92 | } 93 | } 94 | 95 | void AbstractRigidBody::setGroup(int group){ 96 | if(group >0 && m_group!=group){ 97 | m_group=group; 98 | m_changeFlags|=GroupChanged; 99 | } 100 | } 101 | 102 | void AbstractRigidBody::setKinematic(bool kinematic){ 103 | if(m_kinematic!=kinematic){ 104 | m_kinematic=kinematic; 105 | if(m_kinematic){ 106 | m_rigidBody->setCollisionFlags(m_rigidBody->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); 107 | m_rigidBody->setActivationState(DISABLE_DEACTIVATION); 108 | } 109 | else{ 110 | m_rigidBody->setCollisionFlags(m_rigidBody->getCollisionFlags() & ~btCollisionObject::CF_KINEMATIC_OBJECT); 111 | m_rigidBody->setActivationState(ACTIVE_TAG); 112 | 113 | } 114 | } 115 | } 116 | 117 | QMatrix4x4 AbstractRigidBody::worldTransformation(){ 118 | return static_cast(m_motionState)->getWorldTransformAsQMatrix4x4(); 119 | } 120 | 121 | void AbstractRigidBody::setWorldTransformation(QMatrix4x4 m, qreal scaleFactor){ 122 | static_cast(m_motionState)->setWorldTransform(m,scaleFactor); 123 | m_rigidBody->setMotionState(m_motionState); 124 | } 125 | 126 | 127 | void AbstractRigidBody::setRestitution(qreal restitution){ 128 | if(restitution!=m_restitution){ 129 | m_restitution=restitution; 130 | m_rigidBody->setRestitution(m_restitution); 131 | } 132 | } 133 | void AbstractRigidBody::setRollingFriction(qreal rollingFriction){ 134 | if(rollingFriction!=m_rollingFriction){ 135 | m_rollingFriction=rollingFriction; 136 | m_rigidBody->setRollingFriction(m_rollingFriction); 137 | } 138 | } 139 | void AbstractRigidBody::setFriction(qreal friction){ 140 | if(friction!=m_friction){ 141 | m_friction=friction; 142 | m_rigidBody->setFriction(m_friction); 143 | } 144 | } 145 | 146 | void AbstractRigidBody::applyForce(QVector3D force,QVector3D relationPosition){ 147 | m_rigidBody->applyForce(btVector3(force.x(),force.y(),force.z()), 148 | btVector3(relationPosition.x(),relationPosition.y(),relationPosition.z())); 149 | } 150 | 151 | void AbstractRigidBody::applyImpulse(QVector3D force,QVector3D relationPosition){ 152 | m_rigidBody->applyImpulse(btVector3(force.x(),force.y(),force.z()), 153 | btVector3(relationPosition.x(),relationPosition.y(),relationPosition.z())); 154 | } 155 | void AbstractRigidBody::clearForces(){ 156 | m_rigidBody->clearForces(); 157 | 158 | } 159 | 160 | 161 | }} 162 | -------------------------------------------------------------------------------- /src/frontend/physicsaspect.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | 23 | using namespace Qt3DCore; 24 | QT_BEGIN_NAMESPACE 25 | namespace Physics { 26 | 27 | PhysicsAspect::PhysicsAspect(QObject* parent): 28 | Qt3DCore::QAbstractAspect(parent) 29 | { 30 | m_manager=new PhysicsManager(); 31 | registerBackendType(Qt3DCore::QBackendNodeFunctorPtr(new Physics::PhysicsEntityFunctor(m_manager))); 32 | registerBackendType(Qt3DCore::QBackendNodeFunctorPtr(new Physics::PhysicsGeometryRendererFunctor(m_manager))); 33 | registerBackendType(Qt3DCore::QBackendNodeFunctorPtr(new Physics::PhysicsGeometryFunctor(m_manager))); 34 | registerBackendType(Qt3DCore::QBackendNodeFunctorPtr(new Physics::PhysicsAttributeFunctor(m_manager))); 35 | registerBackendType(Qt3DCore::QBackendNodeFunctorPtr(new Physics::PhysicsBufferFunctor(m_manager))); 36 | registerBackendType(Qt3DCore::QBackendNodeFunctorPtr(new Physics::PhysicsTransformFunctor(m_manager))); 37 | registerBackendType(Qt3DCore::QBackendNodeFunctorPtr(new Physics::PhysicsBodyInfoBackendNodeFunctor(m_manager))); 38 | registerBackendType(Qt3DCore::QBackendNodeFunctorPtr(new Physics::PhysicsWorldInfoBackendNodeFunctor(m_manager))); 39 | //registerBackendType(Qt3DCore::QBackendNodeFunctorPtr(new Physics::PhysicsSoftBodyInfoBackendNodeFunctor(m_manager))); 40 | 41 | } 42 | 43 | QVector PhysicsAspect::jobsToExecute(qint64 time){ 44 | Q_UNUSED(time); 45 | QVector jobs; 46 | if(m_manager->m_physics_factory!=Q_NULLPTR && m_manager->m_physics_world!=Q_NULLPTR){ 47 | Qt3DCore::QAspectJobPtr insert_physics_transform, update_physics_entities, simulate_step,update_transform,notify_collisions; 48 | //insert_physics_transform.reset(new InsertPhysicsTransformJob(m_manager)); 49 | 50 | update_physics_entities.reset(new UpdatePhysicsEntitiesJob(m_manager)); 51 | simulate_step.reset(new SimulateStepJob(m_manager)); 52 | update_transform.reset(new UpdateTransformsJob(m_manager)); 53 | notify_collisions.reset(new NotifyCollisionsJob(m_manager)); 54 | 55 | update_physics_entities->addDependency(insert_physics_transform); 56 | simulate_step->addDependency(update_physics_entities); 57 | update_transform->addDependency(simulate_step); 58 | notify_collisions->addDependency(simulate_step); 59 | 60 | 61 | //jobs.append(insert_physics_transform); 62 | jobs.append(update_physics_entities); 63 | jobs.append(simulate_step); 64 | jobs.append(update_transform); 65 | jobs.append(notify_collisions); 66 | 67 | if(m_manager->m_physics_world->debug()){ 68 | 69 | } 70 | 71 | /*Qt3DCore::QAspectJobPtr debug_job; 72 | debug_job.reset(new DebugJob(m_manager)); 73 | jobs.append(debug_job);*/ 74 | 75 | } 76 | return jobs; 77 | 78 | } 79 | 80 | void PhysicsAspect::onRootEntityChanged(QEntity *rootEntity) 81 | { 82 | m_manager->setRootEntityId(rootEntity->id()); 83 | } 84 | 85 | 86 | 87 | //void PhysicsAspect::sceneNodeAdded(Qt3DCore::QSceneChangePtr &e) { 88 | // Qt3DCore::QScenePropertyChangePtr propertyChange = e.staticCast(); 89 | // Qt3DCore::QNodePtr nodePtr = propertyChange->value().value(); 90 | // Qt3DCore::QNode *n = nodePtr.data(); 91 | // Qt3D::QNodeVisitor visitor; 92 | // visitor.traverse(n, this, &PhysicsAspect::visitNode, &PhysicsAspect::visitNode); 93 | //} 94 | //void PhysicsAspect::sceneNodeRemoved(Qt3DCore::QSceneChangePtr &e) { 95 | // Qt3DCore::QScenePropertyChangePtr propertyChange = e.staticCast(); 96 | // Qt3DCore::QNodePtr nodePtr = propertyChange->value().value(); 97 | // Qt3DCore::QNode *n = nodePtr.data(); 98 | // Qt3DCore::QAbstractAspect::clearBackendNode(n); 99 | //} 100 | 101 | //void PhysicsAspect::setRootEntity(Qt3DCore::QEntity *rootObject) { 102 | //// Qt3DCore::QAbstractAspect::setRootEntity(rootObject); 103 | //// Qt3DCore::QNodeVisitor visitor; 104 | //// visitor.traverse(rootObject, this, &PhysicsAspect::visitNode, &PhysicsAspect::visitNode); 105 | // m_manager->setRootEntityId(rootObject->id()); 106 | //} 107 | void PhysicsAspect::onInitialize(const QVariantMap &data) { 108 | Q_UNUSED(data); 109 | } 110 | void PhysicsAspect::onCleanup() { 111 | delete m_manager; 112 | } 113 | 114 | void PhysicsAspect::visitNode(Qt3DCore::QNode *node){ 115 | // Qt3DCore::QAbstractAspect::createBackendNode(node); 116 | } 117 | 118 | } 119 | 120 | QT_END_NAMESPACE 121 | 122 | QT3D_REGISTER_NAMESPACED_ASPECT("physics", QT_PREPEND_NAMESPACE(Physics), PhysicsAspect); 123 | -------------------------------------------------------------------------------- /examples/aspect-test/AnimatedEntity.qml: -------------------------------------------------------------------------------- 1 | import Qt3D.Core 2.0 2 | import Qt3D.Render 2.0 3 | import QtPhysics.unofficial 1.0 4 | import QtQuick 2.0 as QQ2 5 | import Qt3D.Input 2.0 6 | 7 | 8 | 9 | Entity { 10 | id: sceneRoot 11 | objectName: "Root" 12 | Camera { 13 | id: camera 14 | projectionType: CameraLens.PerspectiveProjection 15 | fieldOfView: 45 16 | aspectRatio: 16/9 17 | nearPlane : 0.1 18 | farPlane : 1000.0 19 | position: Qt.vector3d( 0.0, 0.0, -10.0 ) 20 | upVector: Qt.vector3d( 0.0, 1.0, 0.0 ) 21 | viewCenter: Qt.vector3d( 0.0, 0.0, 0.0 ) 22 | } 23 | 24 | Configuration { 25 | controlledCamera: camera 26 | } 27 | 28 | MouseController { 29 | id: mouseController 30 | } 31 | components: [ 32 | FrameGraph { 33 | activeFrameGraph: Viewport { 34 | id: viewport 35 | rect: Qt.rect(0, 0.0, 1.0, 1.0) // From Top Left 36 | clearColor: Qt.rgba(0, 0.5, 1, 1) 37 | 38 | CameraSelector { 39 | id : cameraSelector 40 | camera: camera 41 | 42 | ClearBuffer { 43 | buffers : ClearBuffer.ColorDepthBuffer 44 | } 45 | } 46 | } 47 | }, 48 | PhysicsWorldInfo{ 49 | gravity: Qt.vector3d(0,-10,0) 50 | debug:true 51 | scaleFactor: 0.1 52 | } 53 | ] 54 | 55 | 56 | 57 | SphereMesh { 58 | id: torusMesh 59 | radius: 2 60 | //minorRadius: 1 61 | //rings: 50 62 | //slices: 50 63 | //radius:4 64 | //length: 10 65 | } 66 | 67 | Transform { 68 | id: torusTransform 69 | translation:Qt.vector3d(0,-5,0) 70 | 71 | /*Rotate{ 72 | axis: Qt.vector3d(1,0,0) 73 | angle: 2 74 | }*/ 75 | // Translate{ 76 | // id:torusTranslate 77 | // } 78 | } 79 | 80 | PhysicsBodyInfo{ 81 | id:torusBodyinfo 82 | mass:1000 83 | kinematic: true 84 | restitution: 1 85 | inputTransform: torusTransform 86 | 87 | } 88 | Transform{ 89 | 90 | 91 | 92 | 93 | } 94 | 95 | Entity { 96 | id: torusEntity 97 | objectName: "torus" 98 | 99 | 100 | // property MouseInput mouseInput : MouseInput { 101 | // controller: mouseController 102 | 103 | // onReleased: { 104 | // switch (mouse.button) { 105 | // case Qt.LeftButton: 106 | // torusTranslate.setDy(10+Math.random()); 107 | // break; 108 | // } 109 | // } 110 | // } 111 | 112 | 113 | components: [ torusMesh, torusBodyinfo, torusBodyinfo.outputTransform ] 114 | } 115 | 116 | Transform { 117 | id: torusTransform2 118 | translation:Qt.vector3d(0,10,0) 119 | } 120 | 121 | TorusMesh { 122 | id: torusMesh2 123 | radius: 1 124 | minorRadius: 1 125 | rings: 100 126 | slices: 25 127 | } 128 | 129 | PhysicsBodyInfo{ 130 | id:torusBodyinfo2 131 | mass:1 132 | restitution: 1 133 | inputTransform: torusTransform2 134 | 135 | } 136 | 137 | // SphereMesh { 138 | // id: sphereMesh 139 | // radius: 30 140 | // } 141 | 142 | // Transform { 143 | // id: sphereTransform 144 | // } 145 | // PhysicsBodyInfo{ 146 | // id:sphereBody 147 | // restitution: 1 148 | // kinematic:true 149 | // mass:1 150 | // onCollided: console.log(parent.objectName) 151 | // } 152 | //// SceneLoader{ 153 | //// id:sceneloader 154 | //// source: "qrc:/Model1.dae" 155 | //// onStatusChanged: {if(status==SceneLoader.Loaded) physicssetter.onAnyChange();} 156 | //// } 157 | 158 | //// PhysicsSetter{ 159 | //// id:physicssetter 160 | //// bodyInfo: sphereBody 161 | //// entityName: "Sphere" 162 | //// sceneroot: sphereEntity 163 | //// } 164 | 165 | //// Entity { 166 | //// objectName: "Sphere" 167 | //// id: sphereEntity 168 | //// components: [ sceneloader, sphereTransform ] 169 | //// } 170 | Entity{ 171 | id: torusEntity2 172 | objectName: "torus2" 173 | components: [ torusMesh2, torusBodyinfo2, torusBodyinfo2.outputTransform ] 174 | } 175 | 176 | /*Floor is an entity non renderable 177 | but defined by the shape details*/ 178 | Entity{ 179 | objectName: "Floor" 180 | PlaneMesh{ 181 | id: planeMesh 182 | height: 10 183 | width: 10 184 | } 185 | Transform{ 186 | id:transformFloor 187 | matrix: { 188 | var m = Qt.matrix4x4(); 189 | //m.rotate(25, Qt.vector3d(0, 0, 1)) 190 | m.translate(Qt.vector3d(0, -10, 0)); 191 | return m; 192 | } 193 | onMatrixChanged:console.log(matrix) 194 | } 195 | PhysicsBodyInfo{ 196 | id:floorBodyInfo 197 | restitution: 1 198 | inputTransform: transformFloor 199 | //shapeDetails:{"Type":"StaticPlane","PlaneConstant":0,"PlaneNormal": Qt.vector3d(0, 1, 0) } 200 | } 201 | components: [planeMesh,transformFloor,floorBodyInfo] 202 | } 203 | 204 | 205 | 206 | } 207 | -------------------------------------------------------------------------------- /src/backend/backendtypes/physicsgeometryrenderer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | namespace Physics { 6 | 7 | PhysicsGeometryRenderer::PhysicsGeometryRenderer(): 8 | Qt3DCore::QBackendNode(), 9 | m_objectName(), 10 | m_dirty(false), 11 | m_enabled(false), 12 | m_geometry(), 13 | m_geometry_functor(), 14 | m_manager(Q_NULLPTR), 15 | m_instanceCount(0) 16 | , m_primitiveCount(0) 17 | , m_baseVertex(0) 18 | , m_baseInstance(0) 19 | , m_restartIndex(-1) 20 | , m_primitiveRestart(false) 21 | , m_primitiveType(Qt3DRender::QGeometryRenderer::Triangles) 22 | { 23 | 24 | } 25 | 26 | void PhysicsGeometryRenderer::setManager(PhysicsManager *manager){ 27 | m_manager=manager; 28 | } 29 | 30 | 31 | PhysicsGeometryRenderer::~PhysicsGeometryRenderer(){ 32 | m_manager->m_resources.remove(peerUuid()); 33 | } 34 | 35 | void PhysicsGeometryRenderer::updateFromPeer(Qt3DCore::QNode *peer){ 36 | Qt3DRender::QGeometryRenderer *geometry_renderer = static_cast(peer); 37 | m_instanceCount = geometry_renderer->instanceCount(); 38 | m_primitiveCount = geometry_renderer->primitiveCount(); 39 | m_baseVertex = geometry_renderer->baseVertex(); 40 | m_baseInstance = geometry_renderer->baseInstance(); 41 | m_restartIndex = geometry_renderer->restartIndex(); 42 | m_primitiveRestart = geometry_renderer->primitiveRestart(); 43 | m_primitiveType = geometry_renderer->primitiveType(); 44 | 45 | m_objectName = peer->objectName(); 46 | m_dirty=true; 47 | m_enabled=geometry_renderer->isEnabled(); 48 | if (geometry_renderer->geometry() != Q_NULLPTR) 49 | setGeometry(geometry_renderer->geometry()->id()); 50 | m_geometry_functor = geometry_renderer->geometryFunctor(); 51 | } 52 | 53 | void PhysicsGeometryRenderer::setGeometry(Qt3DCore::QNodeId geometry) 54 | { 55 | if (m_geometry != geometry) { 56 | m_geometry = geometry; 57 | } 58 | } 59 | 60 | void PhysicsGeometryRenderer::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e){ 61 | switch (e->type()) { 62 | case Qt3DCore::NodeUpdated: { 63 | Qt3DCore::QScenePropertyChangePtr propertyChange = qSharedPointerCast(e); 64 | QByteArray propertyName = propertyChange->propertyName(); 65 | if (propertyName == QByteArrayLiteral("geometryFunctor")){ // Mesh with source 66 | m_geometry_functor= propertyChange->value().value(); 67 | m_dirty=true; 68 | } 69 | else if (propertyName == QByteArrayLiteral("enabled")){ 70 | m_enabled = propertyChange->value().value(); 71 | }else if (propertyChange->propertyName() == QByteArrayLiteral("instanceCount")) { 72 | m_instanceCount = propertyChange->value().value(); 73 | m_dirty = true; 74 | } else if (propertyName == QByteArrayLiteral("primitiveCount")) { 75 | m_primitiveCount = propertyChange->value().value(); 76 | m_dirty = true; 77 | } else if (propertyName == QByteArrayLiteral("baseVertex")) { 78 | m_baseVertex = propertyChange->value().value(); 79 | m_dirty = true; 80 | } else if (propertyName == QByteArrayLiteral("baseInstance")) { 81 | m_baseInstance = propertyChange->value().value(); 82 | m_dirty = true; 83 | } else if (propertyName == QByteArrayLiteral("restartIndex")) { 84 | m_restartIndex = propertyChange->value().value(); 85 | m_dirty = true; 86 | } else if (propertyName == QByteArrayLiteral("primitiveRestart")) { 87 | m_primitiveRestart = propertyChange->value().value(); 88 | m_dirty = true; 89 | } 90 | break; 91 | } 92 | case Qt3DCore::NodeAdded: { 93 | Qt3DCore::QScenePropertyChangePtr propertyChange = qSharedPointerCast(e); 94 | if (propertyChange->propertyName() == QByteArrayLiteral("geometry")) { 95 | m_geometry = propertyChange->value().value(); 96 | } 97 | break; 98 | } 99 | case Qt3DCore::NodeRemoved: { 100 | Qt3DCore::QScenePropertyChangePtr propertyChange = qSharedPointerCast(e); 101 | if (propertyChange->propertyName() == QByteArrayLiteral("geometry")) { 102 | m_geometry = Qt3DCore::QNodeId(); 103 | } 104 | break; 105 | } 106 | default: 107 | break; 108 | } 109 | } 110 | 111 | 112 | PhysicsGeometryRendererFunctor::PhysicsGeometryRendererFunctor(PhysicsManager* manager) 113 | { 114 | m_manager=manager; 115 | } 116 | 117 | 118 | Qt3DCore::QBackendNode *PhysicsGeometryRendererFunctor::create(Qt3DCore::QNode *frontend, const Qt3DCore::QBackendNodeFactory *factory) 119 | const { 120 | PhysicsGeometryRenderer* geometry_renderer=new PhysicsGeometryRenderer(); 121 | m_manager->m_resources.insert(frontend->id(),geometry_renderer); 122 | geometry_renderer->setFactory(factory); 123 | geometry_renderer->setManager(m_manager); 124 | geometry_renderer->setPeer(frontend); 125 | return geometry_renderer; 126 | } 127 | Qt3DCore::QBackendNode *PhysicsGeometryRendererFunctor::get(const Qt3DCore::QNodeId &id) const 128 | { 129 | if(m_manager->m_resources.contains(id)) 130 | return m_manager->m_resources.operator [](id); 131 | else 132 | return Q_NULLPTR; 133 | } 134 | void PhysicsGeometryRendererFunctor::destroy(const Qt3DCore::QNodeId &id) const 135 | { 136 | if(m_manager->m_resources.contains(id)) 137 | delete m_manager->m_resources.operator [](id); 138 | } 139 | 140 | 141 | 142 | } 143 | 144 | 145 | -------------------------------------------------------------------------------- /plugins/bullet/worlds/dynamicsworld.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | namespace Physics { 3 | 4 | namespace Bullet{ 5 | 6 | DynamicsWorld::DynamicsWorld(QObject *parent): 7 | PhysicsAbstractDynamicsWorld(parent) 8 | { 9 | m_simulationRate=60.0; 10 | m_scaleFactor=1.0; 11 | m_gravity=QVector3D(0,0,0); 12 | init(); 13 | } 14 | 15 | DynamicsWorld::~DynamicsWorld() 16 | { 17 | 18 | for(AbstractRigidBody* c: m_PhysicsBodies2BulletBodies.keys()){ 19 | removeRigidBody(c); 20 | delete c; 21 | } 22 | delete m_dynamicsWorld; 23 | delete m_solver; 24 | delete m_collisionConfiguration; 25 | delete m_dispatcher; 26 | delete m_broadphase; 27 | 28 | } 29 | 30 | void DynamicsWorld::init(){ 31 | 32 | m_broadphase = new btDbvtBroadphase(); 33 | m_collisionConfiguration = new btDefaultCollisionConfiguration(); 34 | m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); 35 | m_solver = new btSequentialImpulseConstraintSolver; 36 | 37 | m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher, m_broadphase, m_solver, m_collisionConfiguration); 38 | 39 | m_dynamicsWorld->setGravity(btVector3(m_gravity.x(),m_gravity.y(),m_gravity.z())); 40 | 41 | } 42 | 43 | void DynamicsWorld::setSimulationRate(qreal rate){ 44 | if(m_simulationRate!=rate){ 45 | m_simulationRate=rate; 46 | } 47 | } 48 | 49 | void DynamicsWorld::stepSimulation(){ 50 | m_dynamicsWorld->stepSimulation(1.0f/m_simulationRate); 51 | if(m_debug){ 52 | //m_debugDraw->debug_entities.clear(); 53 | //m_dynamicsWorld->debugDrawWorld(); 54 | } 55 | 56 | } 57 | 58 | void DynamicsWorld::setGravity(QVector3D gravity){ 59 | if(m_gravity!=gravity){ 60 | m_gravity=gravity; 61 | m_dynamicsWorld->setGravity(btVector3(m_gravity.x(),m_gravity.y(),m_gravity.z())); 62 | } 63 | } 64 | 65 | void DynamicsWorld::setScaleFactor(qreal val) 66 | { 67 | if(m_scaleFactor!=val){ 68 | m_scaleFactor=val; 69 | //remove all the objects. Next iteration will create them back 70 | for(AbstractRigidBody* c: m_PhysicsBodies2BulletBodies.keys()){ 71 | removeRigidBody(c); 72 | delete c; 73 | } 74 | } 75 | } 76 | void DynamicsWorld::setDebug(bool debug){ 77 | if(m_debug!=debug){ 78 | m_debug=debug; 79 | } 80 | } 81 | 82 | 83 | void DynamicsWorld::removeRigidBody(PhysicsAbstractRigidBody* c){ 84 | if(!c->inherits("Physics::Bullet::AbstractRigidBody")) 85 | qWarning("The body was defined with a plugin different from Bullet"); 86 | else{ 87 | Physics::Bullet::AbstractRigidBody* c_cast=static_cast(c); 88 | m_PhysicsBodies2BulletBodies.remove(c_cast); 89 | m_BulletBodies2PhysicsBodies.remove(c_cast->bulletBody()); 90 | removebtRigidBody(c_cast->bulletBody()); 91 | } 92 | } 93 | void DynamicsWorld::addRigidBody(PhysicsAbstractRigidBody* c){ 94 | if(!c->inherits("Physics::Bullet::AbstractRigidBody")) 95 | qWarning("The body was defined with a plugin different from Bullet"); 96 | else{ 97 | Physics::Bullet::AbstractRigidBody* c_cast=static_cast(c); 98 | m_PhysicsBodies2BulletBodies[c_cast]=c_cast->bulletBody(); 99 | m_BulletBodies2PhysicsBodies[c_cast->bulletBody()]=c_cast; 100 | addbtRigidBody(c_cast->bulletBody(),c_cast->group(),c_cast->mask()); 101 | connect(c,SIGNAL(destroyed(QObject*)),this,SLOT(onBodyDestroyed(QObject*))); 102 | } 103 | } 104 | 105 | 106 | void DynamicsWorld::onBodyDestroyed(QObject* obj){ 107 | // btRigidBody* btBody= (btRigidBody*)m_PhysicsBodies2BulletBodies[(AbstractRigidBody*)obj]; 108 | // m_PhysicsBodies2BulletBodies.remove((AbstractRigidBody*)obj); 109 | // m_BulletBodies2PhysicsBodies.remove(btBody); 110 | // removebtRigidBody(btBody); 111 | } 112 | 113 | void DynamicsWorld::removebtRigidBody(btRigidBody* b){ 114 | m_dynamicsWorld->removeRigidBody(b); 115 | } 116 | void DynamicsWorld::addbtRigidBody(btRigidBody* b,int group,int mask){ 117 | m_dynamicsWorld->addRigidBody(b,group,mask); 118 | } 119 | 120 | 121 | QVector DynamicsWorld::getCollisions(){ 122 | QVector collisions; 123 | int numManifolds = m_dynamicsWorld->getDispatcher()->getNumManifolds(); 124 | for (int i=0;igetDispatcher()->getManifoldByIndexInternal(i); 127 | btCollisionObject* obA = const_cast(contactManifold->getBody0()); 128 | btCollisionObject* obB = const_cast(contactManifold->getBody1()); 129 | 130 | Collision collision; 131 | collision.body1=m_BulletBodies2PhysicsBodies[obA]; 132 | collision.body2=m_BulletBodies2PhysicsBodies[obB]; 133 | 134 | int numContacts = contactManifold->getNumContacts(); 135 | for (int j=0;jgetContactPoint(j); 138 | if (pt.getDistance()<0.5f) 139 | { 140 | collision.pointOnBody1= QVector3D(pt.getPositionWorldOnA().x(),pt.getPositionWorldOnA().y(),pt.getPositionWorldOnA().z()); 141 | collision.pointOnBody2=QVector3D(pt.getPositionWorldOnB().x(),pt.getPositionWorldOnB().y(),pt.getPositionWorldOnB().z()); 142 | collision.pointOnBody1Local= QVector3D(pt.m_localPointA.x(),pt.m_localPointA.y(),pt.m_localPointA.z()); 143 | collision.pointOnBody2Local=QVector3D(pt.m_localPointB.x(),pt.m_localPointB.y(),pt.m_localPointB.z()); 144 | collisions.append(collision); 145 | break; 146 | //const btVector3& ptA = pt.getPositionWorldOnA(); 147 | //const btVector3& ptB = pt.getPositionWorldOnB(); 148 | //const btVector3& normalOnB = pt.m_normalWorldOnB; 149 | } 150 | } 151 | } 152 | return collisions; 153 | } 154 | 155 | 156 | } 157 | 158 | } 159 | -------------------------------------------------------------------------------- /src/backend/backendtypes/physicsentity.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | namespace Physics { 8 | 9 | PhysicsEntity::PhysicsEntity(): 10 | Qt3DCore::QBackendNode(), 11 | m_parentId(), 12 | m_enabled(false), 13 | m_objectName(), 14 | m_transform(), 15 | m_geometry_renderer(), 16 | m_physicsBodyInfo(), 17 | m_physicsWorldInfo() 18 | { 19 | m_manager=Q_NULLPTR; 20 | } 21 | 22 | void PhysicsEntity::setManager(PhysicsManager *manager){ 23 | m_manager=manager; 24 | } 25 | 26 | 27 | 28 | PhysicsEntity::~PhysicsEntity(){ 29 | m_manager->m_resources.remove(peerUuid()); 30 | for (Qt3DCore::QNodeId id : m_childrenId){ 31 | if(m_manager->m_resources.contains(id)){ 32 | Physics::PhysicsEntity* child=static_cast(m_manager->m_resources.operator [](id)); 33 | child->setParentEntity(Q_NULLPTR); 34 | } 35 | } 36 | if(this->parent()){ 37 | this->parent()->removeChildId(peerUuid()); 38 | } 39 | if(m_manager->m_Id2RigidBodies.contains(peerUuid())){ 40 | PhysicsAbstractRigidBody* body =m_manager->m_Id2RigidBodies[peerUuid()]; 41 | m_manager->m_Id2RigidBodies.remove(peerUuid()); 42 | m_manager->m_RigidBodies2Id.remove(body); 43 | m_manager->m_physics_world->removeRigidBody(body); 44 | delete body; 45 | } 46 | } 47 | 48 | void PhysicsEntity::updateFromPeer(Qt3DCore::QNode *peer){ 49 | Qt3DCore::QEntity *entity = static_cast(peer); 50 | Qt3DCore::QEntity *parentEntity = entity->parentEntity(); 51 | m_objectName = peer->objectName(); 52 | m_geometry_renderer=Qt3DCore::QNodeId(); 53 | m_physicsBodyInfo=Qt3DCore::QNodeId(); 54 | m_transform=Qt3DCore::QNodeId(); 55 | m_physicsWorldInfo=Qt3DCore::QNodeId(); 56 | m_enabled=entity->isEnabled(); 57 | for(Qt3DCore::QComponent* comp : entity->components()){ 58 | addComponent(comp); 59 | } 60 | if (parentEntity != Q_NULLPTR) 61 | setParentEntity(parentEntity); 62 | } 63 | 64 | void PhysicsEntity::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e){ 65 | Qt3DCore::QScenePropertyChangePtr propertyChange = qSharedPointerCast(e); 66 | switch (e->type()) { 67 | case Qt3DCore::ComponentAdded: { 68 | Qt3DCore::QNodePtr nodePtr = propertyChange->value().value(); 69 | Qt3DCore::QComponent *component = qobject_cast(nodePtr.data()); 70 | addComponent(component); 71 | break; 72 | } 73 | case Qt3DCore::NodeUpdated: { 74 | if (propertyChange->propertyName() == QByteArrayLiteral("enabled")){ 75 | m_enabled = propertyChange->value().value(); 76 | } 77 | else if (propertyChange->propertyName() == QByteArrayLiteral("objectName")){ 78 | m_objectName = propertyChange->value().value(); 79 | } 80 | break; 81 | } 82 | case Qt3DCore::ComponentRemoved: { 83 | Qt3DCore::QNodeId nodeId = propertyChange->value().value(); 84 | removeComponent(nodeId); 85 | break; 86 | } 87 | default: 88 | break; 89 | } 90 | } 91 | 92 | void PhysicsEntity::setParentEntity(Qt3DCore::QEntity *parent){ 93 | if(!m_parentId.isNull() && m_manager->m_resources.contains(m_parentId)){ 94 | PhysicsEntity* parent_entity = static_cast(m_manager->m_resources.operator [](m_parentId)); 95 | parent_entity->removeChildId(peerUuid()); 96 | } 97 | if(parent==Q_NULLPTR){ 98 | m_parentId=Qt3DCore::QNodeId(); 99 | } 100 | else{ 101 | m_parentId=parent->id(); 102 | if(m_manager->m_resources.contains(m_parentId)){ 103 | PhysicsEntity* parent_entity = static_cast(m_manager->m_resources.operator [](m_parentId)); 104 | parent_entity->addChildId(peerUuid()); 105 | } 106 | } 107 | } 108 | 109 | void PhysicsEntity::addComponent(Qt3DCore::QComponent *component){ 110 | if (qobject_cast(component) != Q_NULLPTR){ 111 | m_transform = component->id(); 112 | } 113 | else if (qobject_cast(component) != Q_NULLPTR){ 114 | m_geometry_renderer = component->id(); 115 | } 116 | else if (qobject_cast(component) != Q_NULLPTR){ 117 | m_physicsBodyInfo = component->id(); 118 | } 119 | else if (qobject_cast(component) != Q_NULLPTR){ 120 | m_physicsWorldInfo = component->id(); 121 | } 122 | } 123 | 124 | void PhysicsEntity::removeComponent(Qt3DCore::QNodeId componentId){ 125 | if (m_transform==componentId){ 126 | m_transform = Qt3DCore::QNodeId(); 127 | } 128 | else if (m_geometry_renderer==componentId){ 129 | m_geometry_renderer = Qt3DCore::QNodeId(); 130 | } 131 | else if (m_physicsBodyInfo==componentId){ 132 | m_physicsBodyInfo = Qt3DCore::QNodeId(); 133 | } 134 | else if(m_physicsWorldInfo==componentId){ 135 | m_physicsWorldInfo=Qt3DCore::QNodeId(); 136 | } 137 | } 138 | 139 | PhysicsEntity* PhysicsEntity::parent(){ 140 | if(m_manager->m_resources.contains(m_parentId)) 141 | return static_cast(m_manager->m_resources.operator [](m_parentId)); 142 | return Q_NULLPTR; 143 | } 144 | 145 | void PhysicsEntity::addChildId(Qt3DCore::QNodeId childId){ 146 | m_childrenId.insert(childId); 147 | } 148 | 149 | void PhysicsEntity::removeChildId(Qt3DCore::QNodeId childId){ 150 | if(m_childrenId.contains(childId)) 151 | m_childrenId.remove(childId); 152 | } 153 | 154 | PhysicsEntityFunctor::PhysicsEntityFunctor(PhysicsManager* manager) 155 | { 156 | m_manager=manager; 157 | } 158 | 159 | 160 | Qt3DCore::QBackendNode *PhysicsEntityFunctor::create(Qt3DCore::QNode *frontend, const Qt3DCore::QBackendNodeFactory *factory) 161 | const { 162 | PhysicsEntity* entity=new PhysicsEntity(); 163 | m_manager->m_resources.insert(frontend->id(),entity); 164 | entity->setFactory(factory); 165 | entity->setManager(m_manager); 166 | entity->setPeer(frontend); 167 | return entity; 168 | } 169 | Qt3DCore::QBackendNode *PhysicsEntityFunctor::get(const Qt3DCore::QNodeId &id) const 170 | { 171 | if(m_manager->m_resources.contains(id)) 172 | return m_manager->m_resources.operator [](id); 173 | else 174 | return Q_NULLPTR; 175 | } 176 | void PhysicsEntityFunctor::destroy(const Qt3DCore::QNodeId &id) const 177 | { 178 | if(m_manager->m_resources.contains(id)) 179 | delete m_manager->m_resources.operator [](id); 180 | } 181 | 182 | 183 | 184 | } 185 | -------------------------------------------------------------------------------- /src/backend/backendtypes/physicsattribute.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | namespace Physics { 7 | 8 | PhysicsAttribute::PhysicsAttribute(): 9 | Qt3DCore::QBackendNode(), 10 | m_bufferId(), 11 | m_dataType(Qt3DRender::QAbstractAttribute::Float), 12 | m_dataSize(1), 13 | m_count(0), 14 | m_byteStride(0), 15 | m_byteOffset(0), 16 | m_divisor(0), 17 | m_objectName(), 18 | m_dirty(false), 19 | m_enabled(false), 20 | m_attributeType(Qt3DRender::QAbstractAttribute::VertexAttribute) 21 | { 22 | m_manager=Q_NULLPTR; 23 | } 24 | 25 | void PhysicsAttribute::setManager(PhysicsManager *manager){ 26 | m_manager=manager; 27 | } 28 | 29 | 30 | PhysicsAttribute::~PhysicsAttribute(){ 31 | m_manager->m_resources.remove(peerUuid()); 32 | } 33 | 34 | void PhysicsAttribute::updateFromPeer(Qt3DCore::QNode *peer){ 35 | Qt3DRender::QAttribute *attribute = static_cast(peer); 36 | if (attribute) { 37 | m_dataType = attribute->dataType(); 38 | m_dataSize = attribute->dataSize(); 39 | m_count = attribute->count(); 40 | m_byteOffset = attribute->byteOffset(); 41 | m_byteStride = attribute->byteStride(); 42 | m_divisor = attribute->divisor(); 43 | m_attributeType = attribute->attributeType(); 44 | m_objectName = attribute->name(); 45 | if (attribute->buffer()) 46 | m_bufferId = attribute->buffer()->id(); 47 | m_enabled=attribute->isEnabled(); 48 | m_dirty = true; 49 | } 50 | } 51 | void PhysicsAttribute::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e){ 52 | Qt3DCore::QScenePropertyChangePtr propertyChange = qSharedPointerCast(e); 53 | QByteArray propertyName = propertyChange->propertyName(); 54 | switch (e->type()) { 55 | case Qt3DCore::NodeUpdated: { 56 | if (propertyName == QByteArrayLiteral("enabled")){ 57 | m_enabled = propertyChange->value().value(); 58 | } 59 | else if (propertyName == QByteArrayLiteral("name")) { 60 | m_objectName = propertyChange->value().value(); 61 | m_dirty = true; 62 | } else if (propertyName == QByteArrayLiteral("dataType")) { 63 | m_dataType = static_cast(propertyChange->value().value()); 64 | m_dirty = true; 65 | } else if (propertyName == QByteArrayLiteral("dataSize")) { 66 | m_dataSize = propertyChange->value().value(); 67 | m_dirty = true; 68 | } else if (propertyName == QByteArrayLiteral("count")) { 69 | m_count = propertyChange->value().value(); 70 | m_dirty = true; 71 | } else if (propertyName == QByteArrayLiteral("byteStride")) { 72 | m_byteStride = propertyChange->value().value(); 73 | m_dirty = true; 74 | } else if (propertyName == QByteArrayLiteral("byteOffset")) { 75 | m_byteOffset = propertyChange->value().value(); 76 | m_dirty = true; 77 | } else if (propertyName == QByteArrayLiteral("divisor")) { 78 | m_divisor = propertyChange->value().value(); 79 | m_dirty = true; 80 | } else if (propertyName == QByteArrayLiteral("attributeType")) { 81 | m_attributeType = static_cast(propertyChange->value().value()); 82 | } 83 | break; 84 | } 85 | case Qt3DCore::NodeAdded: { 86 | if (propertyName == QByteArrayLiteral("buffer")) { 87 | m_bufferId = propertyChange->value().value(); 88 | } 89 | break; 90 | } 91 | case Qt3DCore::NodeRemoved: { 92 | if (propertyName == QByteArrayLiteral("buffer")) { 93 | m_bufferId = Qt3DCore::QNodeId(); 94 | } 95 | break; 96 | } 97 | default: 98 | break; 99 | } 100 | 101 | } 102 | 103 | /*A copy of what is in the frontend*/ 104 | QVector PhysicsAttribute::asVector3D() const{ 105 | QVector result; 106 | if(m_bufferId.isNull() || !m_manager->m_resources.contains(m_bufferId)){ 107 | qDebug()<<"BufferId is null"; 108 | return result; 109 | } 110 | QByteArray buffer; 111 | PhysicsBuffer* buffer_node=static_cast(m_manager->m_resources.operator [](m_bufferId)); 112 | if(buffer_node->bufferFunctor().isNull()){ 113 | buffer=buffer_node->data(); 114 | } 115 | else{ 116 | buffer=buffer_node->bufferFunctor().data()->operator ()(); 117 | } 118 | 119 | const char *rawBuffer = buffer.constData(); 120 | rawBuffer += m_byteOffset; 121 | const float* fptr; 122 | int stride; 123 | switch (m_dataType) { 124 | case Qt3DRender::QAttribute::Float: 125 | stride = sizeof(float) * m_dataSize; 126 | break; 127 | default: 128 | qDebug()<< "can't convert" << m_dataType << "x" << m_dataSize << "to QVector3D"; 129 | return result; 130 | } 131 | if (m_byteStride != 0) 132 | stride = m_byteStride; 133 | 134 | result.resize(m_count); 135 | for (uint c = 0; c < m_count; ++c) { 136 | QVector3D v; 137 | fptr = reinterpret_cast(rawBuffer); 138 | for (uint i = 0, m = qMin(m_dataSize, 3U); i < m; ++i) 139 | v[i] = fptr[i]; 140 | result[c] = v; 141 | rawBuffer += stride; 142 | } 143 | return result; 144 | } 145 | 146 | 147 | 148 | PhysicsAttributeFunctor::PhysicsAttributeFunctor(PhysicsManager* manager) 149 | { 150 | m_manager=manager; 151 | } 152 | 153 | 154 | Qt3DCore::QBackendNode *PhysicsAttributeFunctor::create(Qt3DCore::QNode *frontend, const Qt3DCore::QBackendNodeFactory *factory) 155 | const { 156 | PhysicsAttribute* attribute=new PhysicsAttribute(); 157 | m_manager->m_resources.insert(frontend->id(),attribute); 158 | attribute->setFactory(factory); 159 | attribute->setManager(m_manager); 160 | attribute->setPeer(frontend); 161 | return attribute; 162 | } 163 | Qt3DCore::QBackendNode *PhysicsAttributeFunctor::get(const Qt3DCore::QNodeId &id) const 164 | { 165 | if(m_manager->m_resources.contains(id)) 166 | return m_manager->m_resources.operator [](id); 167 | else 168 | return Q_NULLPTR; 169 | } 170 | void PhysicsAttributeFunctor::destroy(const Qt3DCore::QNodeId &id) const 171 | { 172 | if(m_manager->m_resources.contains(id)) 173 | delete m_manager->m_resources.operator [](id); 174 | } 175 | 176 | 177 | 178 | } 179 | 180 | 181 | 182 | 183 | 184 | -------------------------------------------------------------------------------- /src/frontend/physicsbodyinfo.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | namespace Physics { 4 | 5 | PhysicsBodyInfo::PhysicsBodyInfo(Qt3DCore::QNode* parent): 6 | Qt3DCore::QComponent(parent), 7 | m_mask(1), 8 | m_group(1), 9 | m_kinematic(false), 10 | m_mass(0), 11 | m_fallInertia(), 12 | m_restitution(0.0f), 13 | m_friction(0.0f), 14 | m_rollingFriction(0.0f) 15 | { 16 | m_inputTransform=Q_NULLPTR; 17 | m_outputTransform=new Qt3DCore::QTransform(this); 18 | setShareable(false); 19 | } 20 | void PhysicsBodyInfo::copy(const Qt3DCore::QNode *ref){ 21 | Qt3DCore::QComponent::copy(ref); 22 | const PhysicsBodyInfo * body_info = static_cast(ref); 23 | 24 | m_fallInertia=body_info->m_fallInertia; 25 | m_restitution=body_info->m_restitution; 26 | m_friction=body_info->m_restitution; 27 | m_rollingFriction=body_info->m_rollingFriction; 28 | m_mass=body_info->m_mass; 29 | m_mask=body_info->m_mask; 30 | m_group=body_info->m_group; 31 | m_kinematic=body_info->m_kinematic; 32 | 33 | m_inputTransform=body_info->m_inputTransform; 34 | m_outputTransform=body_info->m_outputTransform; 35 | } 36 | 37 | PhysicsBodyInfo::~PhysicsBodyInfo(){ 38 | Qt3DCore::QNode::cleanup(); 39 | } 40 | 41 | void PhysicsBodyInfo::setMass(qreal mass){ 42 | if(mass >=0 && m_mass!=mass){ 43 | m_mass=mass; 44 | emit massChanged(m_mass); 45 | } 46 | } 47 | 48 | void PhysicsBodyInfo::setFallInertia(QVector3D fallInertia){ 49 | if( m_fallInertia!=fallInertia){ 50 | m_fallInertia=fallInertia; 51 | emit fallInertiaChanged(m_fallInertia); 52 | } 53 | } 54 | 55 | void PhysicsBodyInfo::setMask(int mask){ 56 | if(mask >0 && m_mask!=mask){ 57 | m_mask=mask; 58 | emit maskChanged(m_mask); 59 | } 60 | } 61 | 62 | void PhysicsBodyInfo::setGroup(int group){ 63 | if(group >0 && m_group!=group){ 64 | m_group=group; 65 | emit groupChanged(m_group); 66 | } 67 | } 68 | void PhysicsBodyInfo::setKinematic(bool kinematic){ 69 | if(m_kinematic!=kinematic){ 70 | m_kinematic=kinematic; 71 | emit kinematicChanged(m_kinematic); 72 | } 73 | } 74 | 75 | void PhysicsBodyInfo::setRestitution(qreal restitution){ 76 | if(restitution!=m_restitution){ 77 | m_restitution=restitution; 78 | emit restitutionChanged(m_restitution); 79 | } 80 | } 81 | 82 | void PhysicsBodyInfo::setRollingFriction(qreal rollingFriction){ 83 | if(rollingFriction!=m_rollingFriction){ 84 | m_rollingFriction=rollingFriction; 85 | emit rollingFrictionChanged(m_rollingFriction); 86 | } 87 | } 88 | void PhysicsBodyInfo::setFriction(qreal friction){ 89 | if(friction!=m_friction){ 90 | m_friction=friction; 91 | emit frictionChanged(m_friction); 92 | } 93 | } 94 | 95 | void PhysicsBodyInfo::setInputTransform(Qt3DCore::QTransform* inputTransform){ 96 | m_inputTransform=inputTransform; 97 | emit inputTransformChanged(); 98 | } 99 | 100 | 101 | QQmlListProperty PhysicsBodyInfo::collisionsList(){ 102 | return QQmlListProperty(this, 0, 103 | PhysicsBodyInfo::qmlComponentsCount, 104 | PhysicsBodyInfo::qmlComponentAt); 105 | 106 | } 107 | 108 | PhysicsCollisionEvent* PhysicsBodyInfo::qmlComponentAt(QQmlListProperty *list, int index){ 109 | PhysicsBodyInfo *self = static_cast(list->object); 110 | return self->m_collisionsList.at(index).data(); 111 | } 112 | 113 | int PhysicsBodyInfo::qmlComponentsCount(QQmlListProperty *list){ 114 | PhysicsBodyInfo *self = static_cast(list->object); 115 | return self->m_collisionsList.size(); 116 | } 117 | 118 | bool PhysicsBodyInfo::collisionTest(Qt3DCore::QNodeId id){ 119 | return m_collisionsCache.contains(id); 120 | } 121 | 122 | 123 | void PhysicsBodyInfo::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) 124 | { 125 | Qt3DCore::QScenePropertyChangePtr e = qSharedPointerCast< Qt3DCore::QScenePropertyChange>(change); 126 | if (e->type() == Qt3DCore::NodeUpdated) { 127 | /*if (e->propertyName() == QByteArrayLiteral("attachPhysicsTransfrom")) { 128 | bool val = e->value().toBool(); 129 | if(val){ 130 | QVector entities = this->entities(); 131 | if (entities.size() > 1) 132 | qWarning()<< "It is strongly discouraged to share PhysicsBodyInfo component between entities"; 133 | Q_FOREACH(Qt3D::QEntity* e, entities){ 134 | bool hasPhysicsTransform=false; 135 | QMatrix4x4 m; 136 | Q_FOREACH(Qt3D::QComponent* c, e->components()){ 137 | if(c->inherits("Qt3D::QTransform") && c->objectName().compare("@MaDeByPhYsIcS@")!=0){ 138 | c->setEnabled(false); 139 | m=qobject_cast(c)->matrix(); 140 | } 141 | else if(c->inherits("Qt3D::QTransform") && c->objectName().compare("@MaDeByPhYsIcS@")==0){ 142 | hasPhysicsTransform=true; 143 | } 144 | } 145 | if(!hasPhysicsTransform){ 146 | Qt3D::QTransform* physics_transform=new Qt3D::QTransform(this->parentNode()); 147 | physics_transform->setObjectName("@MaDeByPhYsIcS@"); 148 | Qt3D::QMatrixTransform* matrix= new Qt3D::QMatrixTransform(m,physics_transform); 149 | physics_transform->addTransform(matrix); 150 | e->addComponent(physics_transform); 151 | m_attached_matrix=matrix; 152 | } 153 | } 154 | } 155 | }*/ 156 | if(e->propertyName() == QByteArrayLiteral("updateTransform")){ 157 | QMatrix4x4 mat= e->value().value(); 158 | m_outputTransform->setMatrix(mat); 159 | emit outputTransformChanged(); 160 | } 161 | if(e->propertyName() == QByteArrayLiteral("notifyCollision")){ 162 | PhysicsCollisionEventPtrList collisions_list=e->value().value(); 163 | if(collisions_list.size()==0){ 164 | if(m_hasCollided){ 165 | m_hasCollided=false; 166 | emit hasCollidedChanged(m_hasCollided); 167 | } 168 | m_collisionsList.clear(); 169 | m_collisionsCache.clear(); 170 | emit collisionsListChanged(); 171 | } 172 | else{ 173 | m_collisionsList.clear(); 174 | m_collisionsCache.clear(); 175 | Q_FOREACH(PhysicsCollisionEventPtr event_ptr,collisions_list){ 176 | m_collisionsList.append(event_ptr); 177 | m_collisionsCache.insert(event_ptr->target()); 178 | if(m_collisionsList.last()->isNew()){ 179 | emit collided(m_collisionsList.last()); 180 | } 181 | } 182 | if(!m_hasCollided){ 183 | m_hasCollided=true; 184 | emit hasCollidedChanged(m_hasCollided); 185 | } 186 | emit collisionsListChanged(); 187 | } 188 | } 189 | } 190 | } 191 | 192 | 193 | 194 | } 195 | 196 | 197 | 198 | -------------------------------------------------------------------------------- /src/backend/backendtypes/physicsbodyinfobackendnode.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | #include 5 | 6 | #include 7 | 8 | namespace Physics { 9 | 10 | PhysicsBodyInfoBackendNode::PhysicsBodyInfoBackendNode(): 11 | Qt3DCore::QBackendNode(Qt3DCore::QBackendNode::ReadWrite), 12 | m_dirtyFlags(Clean), 13 | m_objectName(), 14 | m_enabled(false) 15 | { 16 | m_manager=Q_NULLPTR; 17 | } 18 | 19 | void PhysicsBodyInfoBackendNode::setManager(PhysicsManager *manager){ 20 | m_manager=manager; 21 | } 22 | 23 | PhysicsBodyInfoBackendNode::~PhysicsBodyInfoBackendNode(){ 24 | m_manager->m_resources.remove(peerUuid()); 25 | } 26 | 27 | void PhysicsBodyInfoBackendNode::updateFromPeer(Qt3DCore::QNode *peer){ 28 | PhysicsBodyInfo *body_info = static_cast(peer); 29 | m_objectName = peer->objectName(); 30 | setEnabled(body_info->isEnabled()); 31 | setFallInertia(body_info->fallInertia()); 32 | setFriction(body_info->friction()); 33 | setGroup(body_info->group()); 34 | setMask(body_info->mask()); 35 | setKinematic(body_info->kinematic()); 36 | setMass(body_info->mass()); 37 | setRestitution(body_info->restitution()); 38 | setRollingFriction(body_info->rollingFriction()); 39 | if(body_info->inputTransform()) 40 | setInputTransform(body_info->inputTransform()->id()); 41 | 42 | } 43 | 44 | void PhysicsBodyInfoBackendNode::setMass(qreal mass){ 45 | if(mass >=0 && m_mass!=mass){ 46 | m_mass=mass; 47 | m_dirtyFlags.operator |=(MassChanged); 48 | } 49 | } 50 | void PhysicsBodyInfoBackendNode::setFallInertia(QVector3D fallInertia){ 51 | if( m_fallInertia!=fallInertia){ 52 | m_fallInertia=fallInertia; 53 | m_dirtyFlags.operator |=(FallInertiaChanged); 54 | } 55 | } 56 | 57 | 58 | void PhysicsBodyInfoBackendNode::setMask(int mask){ 59 | if(mask >0 && m_mask!=mask){ 60 | m_mask=mask; 61 | m_dirtyFlags.operator |=(MaskChanged); 62 | } 63 | } 64 | 65 | void PhysicsBodyInfoBackendNode::setGroup(int group){ 66 | if(group >0 && m_group!=group){ 67 | m_group=group; 68 | m_dirtyFlags.operator |=(GroupChanged); 69 | } 70 | } 71 | void PhysicsBodyInfoBackendNode::setKinematic(bool kinematic){ 72 | if(m_kinematic!=kinematic){ 73 | m_kinematic=kinematic; 74 | m_dirtyFlags.operator |=(KinematicChanged); 75 | } 76 | } 77 | 78 | void PhysicsBodyInfoBackendNode::setRestitution(qreal restitution){ 79 | if(restitution!=m_restitution){ 80 | m_restitution=restitution; 81 | m_dirtyFlags.operator |=(RestistutionChanged); 82 | } 83 | } 84 | 85 | void PhysicsBodyInfoBackendNode::setRollingFriction(qreal rollingFriction){ 86 | if(rollingFriction!=m_rollingFriction){ 87 | m_rollingFriction=rollingFriction; 88 | m_dirtyFlags.operator |=(RollingFrictionChanged); 89 | } 90 | } 91 | void PhysicsBodyInfoBackendNode::setFriction(qreal friction){ 92 | if(friction!=m_friction){ 93 | m_friction=friction; 94 | m_dirtyFlags.operator |=(FrictionChanged); 95 | } 96 | 97 | } 98 | 99 | void PhysicsBodyInfoBackendNode::setInputTransform(Qt3DCore::QNodeId inputTranform){ 100 | if(inputTranform!=m_inputTransform){ 101 | m_inputTransform=inputTranform; 102 | m_dirtyFlags.operator |=(InputTransformChanged); 103 | } 104 | } 105 | 106 | 107 | 108 | void PhysicsBodyInfoBackendNode::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e){ 109 | switch (e->type()) { 110 | case Qt3DCore::NodeUpdated: { 111 | Qt3DCore::QScenePropertyChangePtr propertyChange = qSharedPointerCast(e); 112 | if (propertyChange->propertyName() == QByteArrayLiteral("fallInertia")) 113 | setFallInertia(propertyChange->value().value()); 114 | else if (propertyChange->propertyName() == QByteArrayLiteral("friction")) 115 | setFriction(propertyChange->value().toReal()); 116 | else if (propertyChange->propertyName() == QByteArrayLiteral("group")) 117 | setGroup(propertyChange->value().toInt()); 118 | else if (propertyChange->propertyName() == QByteArrayLiteral("mask")) 119 | setMask(propertyChange->value().toInt()); 120 | else if (propertyChange->propertyName() == QByteArrayLiteral("kinematic")) 121 | setKinematic(propertyChange->value().toBool()); 122 | else if (propertyChange->propertyName() == QByteArrayLiteral("mass")) 123 | setMass(propertyChange->value().toReal()); 124 | else if (propertyChange->propertyName() == QByteArrayLiteral("restitution")) 125 | setRestitution(propertyChange->value().toReal()); 126 | else if (propertyChange->propertyName() == QByteArrayLiteral("rollingFriction")) 127 | setRollingFriction(propertyChange->value().toReal()); 128 | else if (propertyChange->propertyName() == QByteArrayLiteral("enabled")) 129 | setEnabled(propertyChange->value().toBool()); 130 | else if (propertyChange->propertyName() == QByteArrayLiteral("inputMatrix")) 131 | setInputTransform(propertyChange->value().value()->id()); 132 | break; 133 | } 134 | default: 135 | break; 136 | } 137 | } 138 | 139 | void PhysicsBodyInfoBackendNode::resetCollisions(){ 140 | Q_FOREACH(Collision c, m_collisions.keys()){ 141 | m_collisions[c]=0; 142 | } 143 | } 144 | 145 | void PhysicsBodyInfoBackendNode::setEnabled(bool val) 146 | { 147 | if(m_enabled!=val){ 148 | m_enabled=val; 149 | } 150 | } 151 | 152 | 153 | 154 | void PhysicsBodyInfoBackendNode::notifyFrontEnd(QString operation){ 155 | Qt3DCore::QBackendScenePropertyChangePtr e(new Qt3DCore::QBackendScenePropertyChange(Qt3DCore::NodeUpdated, peerUuid())); 156 | /*if(operation=="attachPhysicsTransfrom"){ 157 | e->setPropertyName("attachPhysicsTransfrom"); 158 | e->setValue(true); 159 | } 160 | else */ 161 | if(operation=="updateTransform"){ 162 | e->setPropertyName("updateTransform"); 163 | e->setValue(m_local_transform); 164 | } 165 | else if(operation=="notifyCollision"){ 166 | PhysicsCollisionEventPtrList collisions_list; 167 | 168 | if(m_collisions.values().contains(0) || m_collisions.values().contains(2)){ 169 | e->setPropertyName("notifyCollision"); 170 | Q_FOREACH(Collision c, m_collisions.keys()){ 171 | if(m_collisions[c]==0){ 172 | m_collisions.remove(c); 173 | continue; 174 | } 175 | PhysicsCollisionEvent* collision_event=new PhysicsCollisionEvent(); 176 | if(m_collisions[c]==1){ 177 | collision_event->setIsNew(false); 178 | } 179 | else{ 180 | collision_event->setIsNew(true); 181 | } 182 | 183 | //if(c.body1==peerUuid()){ 184 | collision_event->setTarget(c.body2); 185 | collision_event->setContactPointOnBody(c.pointOnBody1); 186 | collision_event->setContactPointOnTarget(c.pointOnBody2); 187 | collision_event->setContactPointOnBodyLocal(c.pointOnBody1Local); 188 | collision_event->setContactPointOnTargetLocal(c.pointOnBody2Local); 189 | collision_event->setNormalOnTarget(QVector3D()); 190 | /*} 191 | else{ 192 | collision_event->setTarget(c.body1); 193 | collision_event->setContactPointOnBody(c.pointOnBody2); 194 | collision_event->setContactPointOnTarget(c.pointOnBody1); 195 | collision_event->setNormalOnTarget(QVector3D()); 196 | }*/ 197 | PhysicsCollisionEventPtr event_ptr; 198 | event_ptr.reset(collision_event); 199 | collisions_list.append(event_ptr); 200 | 201 | } 202 | //qDebug()<<"end"; 203 | e->setValue(QVariant::fromValue(collisions_list)); 204 | } 205 | else return; 206 | } 207 | else{ 208 | return; 209 | } 210 | // The Frontend element has to perform the action (PhysicsBodyInfo) 211 | e->setTargetNode(peerUuid()); 212 | notifyObservers(e); 213 | } 214 | 215 | 216 | 217 | 218 | PhysicsBodyInfoBackendNodeFunctor::PhysicsBodyInfoBackendNodeFunctor(PhysicsManager* manager) 219 | { 220 | m_manager=manager; 221 | } 222 | 223 | 224 | Qt3DCore::QBackendNode *PhysicsBodyInfoBackendNodeFunctor::create(Qt3DCore::QNode *frontend, const Qt3DCore::QBackendNodeFactory *factory) 225 | const { 226 | PhysicsBodyInfoBackendNode* body_info=new PhysicsBodyInfoBackendNode(); 227 | m_manager->m_resources.insert(frontend->id(),body_info); 228 | body_info->setFactory(factory); 229 | body_info->setManager(m_manager); 230 | body_info->setPeer(frontend); 231 | return body_info; 232 | } 233 | Qt3DCore::QBackendNode *PhysicsBodyInfoBackendNodeFunctor::get(const Qt3DCore::QNodeId &id) const 234 | { 235 | if(m_manager->m_resources.contains(id)) 236 | return m_manager->m_resources.operator [](id); 237 | else 238 | return Q_NULLPTR; 239 | } 240 | void PhysicsBodyInfoBackendNodeFunctor::destroy(const Qt3DCore::QNodeId &id) const 241 | { 242 | if(m_manager->m_resources.contains(id)) 243 | delete m_manager->m_resources.operator [](id); 244 | } 245 | 246 | 247 | 248 | } 249 | 250 | 251 | -------------------------------------------------------------------------------- /src/backend/jobs/updatephysicsentitiesjob.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | namespace Physics { 13 | 14 | 15 | UpdatePhysicsEntitiesJob::UpdatePhysicsEntitiesJob(PhysicsManager* manager): 16 | Qt3DCore::QAspectJob() 17 | { 18 | m_manager=manager; 19 | } 20 | 21 | void UpdatePhysicsEntitiesJob::run(){ 22 | m_visit_queue.clear(); 23 | if(!m_manager->rootEntityId().isNull()){ 24 | /*Remove not enabled subtrees*/ 25 | removeNotEnabledSubtrees(m_manager->rootEntityId()); 26 | /*Start update*/ 27 | Visit_Data tmp_visit_data; 28 | tmp_visit_data.set(m_manager->rootEntityId(),QMatrix4x4(),false); 29 | m_visit_queue.enqueue(tmp_visit_data); 30 | while(!m_visit_queue.isEmpty()){ 31 | tmp_visit_data=m_visit_queue.dequeue(); 32 | iterative_step(tmp_visit_data.node_id, tmp_visit_data.parent_matrix,tmp_visit_data.forceUpdateMS); 33 | } 34 | } 35 | } 36 | 37 | void UpdatePhysicsEntitiesJob::removeNotEnabledSubtrees(Qt3DCore::QNodeId rootId){ 38 | QQueue nodesToVisit, nodesToRemove; 39 | nodesToVisit.enqueue(rootId); 40 | PhysicsEntity* entity; 41 | Qt3DCore::QNodeId current_node; 42 | while(!nodesToVisit.empty()){ 43 | current_node=nodesToVisit.dequeue(); 44 | if(!m_manager->m_resources.contains(current_node)) continue; 45 | entity= static_cast(m_manager->m_resources.operator [](current_node)); 46 | if(!entity) continue; 47 | if(!entity->isEnabled())//you need this info, even if the node is not dirty 48 | nodesToRemove.enqueue(current_node); 49 | else if(!entity->parentId().isNull() && nodesToRemove.contains(entity->parentId())) 50 | nodesToRemove.enqueue(current_node); 51 | for(Qt3DCore::QNodeId childId : entity->childrenIds()) 52 | nodesToVisit.enqueue(childId); 53 | } 54 | while(!nodesToRemove.empty()){ 55 | current_node=nodesToRemove.dequeue(); 56 | if(m_manager->m_Id2RigidBodies.contains(current_node)){ 57 | PhysicsAbstractRigidBody* body =m_manager->m_Id2RigidBodies[current_node]; 58 | m_manager->m_Id2RigidBodies.remove(current_node); 59 | m_manager->m_RigidBodies2Id.remove(body); 60 | m_manager->m_physics_world->removeRigidBody(body); 61 | delete body; 62 | } 63 | } 64 | 65 | } 66 | 67 | void UpdatePhysicsEntitiesJob::iterative_step(Qt3DCore::QNodeId node_id, QMatrix4x4 parent_matrix, bool forceUpdateMS) 68 | { 69 | if(node_id.isNull()) return; 70 | if(!m_manager->m_resources.contains(node_id)) return; 71 | PhysicsEntity* entity= static_cast(m_manager->m_resources.operator [](node_id)); 72 | if(!entity || !entity->isEnabled() ) return; 73 | QMatrix4x4 current_global_matrix=parent_matrix; 74 | if(isDefiningBody(entity)){ 75 | bool isBodyNew=false; 76 | PhysicsAbstractRigidBody* rigid_body; 77 | PhysicsGeometryRenderer* entity_geometry_renderer=static_cast(m_manager->m_resources.operator [](entity->geometry_renderer())); 78 | if(m_manager->m_Id2RigidBodies.contains(entity->peerUuid())) 79 | rigid_body=m_manager->m_Id2RigidBodies[entity->peerUuid()]; 80 | else{ 81 | rigid_body=createRigidBodyFromMesh(entity_geometry_renderer); 82 | rigid_body->setCollisionMargin(rigid_body->collisionMargin()*m_manager->m_physics_world->scaleFactor()); 83 | isBodyNew=true; 84 | } 85 | /*Update collision Shape*/ 86 | if(isRequiringShapeUpdate(entity_geometry_renderer)){ 87 | /*Destroy the rigid body and make a new one*/ 88 | m_manager->m_Id2RigidBodies.remove(node_id); 89 | m_manager->m_RigidBodies2Id.remove(rigid_body); 90 | m_manager->m_physics_world->removeRigidBody(rigid_body); 91 | delete rigid_body; 92 | rigid_body=createRigidBodyFromMesh(entity_geometry_renderer); 93 | rigid_body->setCollisionMargin(rigid_body->collisionMargin()*m_manager->m_physics_world->scaleFactor()); 94 | isBodyNew=true; 95 | } 96 | /*Update Body properties*/ 97 | bool bodyNeedsReadd=isBodyNew; 98 | PhysicsBodyInfoBackendNode* entity_body_info=static_cast(m_manager->m_resources.operator [](entity->physicsBodyInfo())); 99 | if(isBodyNew || entity_body_info->dirtyFlags().testFlag(PhysicsBodyInfoBackendNode::DirtyFlag::MaskChanged)){ 100 | rigid_body->setMask(entity_body_info->mask()); 101 | entity_body_info->dirtyFlags() &= ~PhysicsBodyInfoBackendNode::DirtyFlag::MaskChanged; 102 | bodyNeedsReadd=true; 103 | } 104 | if(isBodyNew || entity_body_info->dirtyFlags().testFlag(PhysicsBodyInfoBackendNode::DirtyFlag::GroupChanged)){ 105 | rigid_body->setGroup(entity_body_info->group()); 106 | entity_body_info->dirtyFlags() &= ~PhysicsBodyInfoBackendNode::DirtyFlag::GroupChanged; 107 | bodyNeedsReadd=true; 108 | } 109 | if(isBodyNew || entity_body_info->dirtyFlags().testFlag(PhysicsBodyInfoBackendNode::DirtyFlag::MassChanged)){ 110 | rigid_body->setMass(entity_body_info->mass()); 111 | entity_body_info->dirtyFlags() &= ~PhysicsBodyInfoBackendNode::DirtyFlag::MassChanged; 112 | bodyNeedsReadd=true; 113 | } 114 | if(isBodyNew || entity_body_info->dirtyFlags().testFlag(PhysicsBodyInfoBackendNode::DirtyFlag::KinematicChanged)){ 115 | rigid_body->setKinematic(entity_body_info->kinematic()); 116 | entity_body_info->dirtyFlags() &= ~PhysicsBodyInfoBackendNode::DirtyFlag::KinematicChanged; 117 | bodyNeedsReadd=true; 118 | } 119 | if(isBodyNew || entity_body_info->dirtyFlags().testFlag(PhysicsBodyInfoBackendNode::DirtyFlag::FallInertiaChanged)){ 120 | rigid_body->setFallInertia(entity_body_info->fallInertia()); 121 | entity_body_info->dirtyFlags() &= ~PhysicsBodyInfoBackendNode::DirtyFlag::FallInertiaChanged; 122 | bodyNeedsReadd=true; 123 | } 124 | if(isBodyNew || entity_body_info->dirtyFlags().testFlag(PhysicsBodyInfoBackendNode::DirtyFlag::RestistutionChanged)){ 125 | rigid_body->setRestitution(entity_body_info->restitution()); 126 | entity_body_info->dirtyFlags() &= ~PhysicsBodyInfoBackendNode::DirtyFlag::RestistutionChanged; 127 | bodyNeedsReadd=true; 128 | } 129 | if(isBodyNew || entity_body_info->dirtyFlags().testFlag(PhysicsBodyInfoBackendNode::DirtyFlag::FrictionChanged)){ 130 | rigid_body->setFriction(entity_body_info->friction()); 131 | entity_body_info->dirtyFlags() &= ~PhysicsBodyInfoBackendNode::DirtyFlag::FrictionChanged; 132 | bodyNeedsReadd=true; 133 | } 134 | if(isBodyNew || entity_body_info->dirtyFlags().testFlag(PhysicsBodyInfoBackendNode::DirtyFlag::RollingFrictionChanged)){ 135 | rigid_body->setRollingFriction(entity_body_info->rollingFriction()); 136 | entity_body_info->dirtyFlags() &= ~PhysicsBodyInfoBackendNode::DirtyFlag::RollingFrictionChanged; 137 | bodyNeedsReadd=true; 138 | } 139 | if(bodyNeedsReadd){ 140 | if(m_manager->m_Id2RigidBodies.contains(node_id)){ 141 | m_manager->m_physics_world->removeRigidBody(rigid_body); 142 | m_manager->m_physics_world->addRigidBody(rigid_body); 143 | 144 | } 145 | else{ 146 | //New body 147 | m_manager->m_Id2RigidBodies[node_id]=rigid_body; 148 | m_manager->m_RigidBodies2Id[rigid_body]=node_id; 149 | m_manager->m_physics_world->addRigidBody(rigid_body); 150 | } 151 | 152 | } 153 | /*Update Motion State*/ 154 | PhysicsTransform* inputTransform=Q_NULLPTR; 155 | if(!entity_body_info->inputTransform().isNull() && m_manager->m_resources.contains(entity_body_info->inputTransform())){ 156 | inputTransform=static_cast(m_manager->m_resources.operator [](entity_body_info->inputTransform())); 157 | } 158 | /*The input transform has changed; the new position is taken from that.*/ 159 | if(inputTransform!=Q_NULLPTR && (inputTransform->isDirty() || isBodyNew )){ 160 | current_global_matrix=current_global_matrix*inputTransform->transformMatrix(); 161 | forceUpdateMS=true; 162 | inputTransform->setDirty(false); 163 | } 164 | /*Otherwise use the matrix from the simulation*/ 165 | else{ 166 | current_global_matrix=current_global_matrix*entity_body_info->localTransform(); 167 | } 168 | if(forceUpdateMS){ 169 | rigid_body->setWorldTransformation(current_global_matrix,m_manager->m_physics_world->scaleFactor()); 170 | } 171 | } 172 | else { 173 | /*If the node doesn't define a valid body then remove a former associated body*/ 174 | if(m_manager->m_Id2RigidBodies.contains(node_id)){ 175 | PhysicsAbstractRigidBody* rigid_body= m_manager->m_Id2RigidBodies.operator [](node_id); 176 | m_manager->m_Id2RigidBodies.remove(node_id); 177 | m_manager->m_RigidBodies2Id.remove(rigid_body); 178 | m_manager->m_physics_world->removeRigidBody(rigid_body); 179 | delete rigid_body; 180 | } 181 | if(!entity->transform().isNull() && m_manager->m_resources.contains(entity->transform())){ 182 | /*Entity with only a transformation*/ 183 | PhysicsTransform* entity_transform=static_cast(m_manager->m_resources.operator [](entity->transform())); 184 | current_global_matrix=current_global_matrix*entity_transform->transformMatrix(); 185 | if(entity_transform->isDirty()){ 186 | forceUpdateMS=true; 187 | entity_transform->setDirty(false); 188 | } 189 | } 190 | } 191 | 192 | /*Update Physic World settings*/ 193 | if(!entity->physicsWorldInfo().isNull() && m_manager->m_resources.contains(entity->physicsWorldInfo())){ 194 | PhysicsWorldInfoBackendNode* entity_physics_world_info=static_cast(m_manager->m_resources.operator [](entity->physicsWorldInfo())); 195 | if(entity_physics_world_info->dirtyFlags().testFlag(PhysicsWorldInfoBackendNode::DirtyFlag::GravityChanged)){ 196 | m_manager->m_physics_world->setGravity(entity_physics_world_info->gravity()*m_manager->m_physics_world->scaleFactor()); 197 | entity_physics_world_info->dirtyFlags() &= ~PhysicsWorldInfoBackendNode::DirtyFlag::GravityChanged; 198 | m_manager->m_physics_world->setDebug(entity_physics_world_info->debug()); 199 | } 200 | if(entity_physics_world_info->dirtyFlags().testFlag(PhysicsWorldInfoBackendNode::DirtyFlag::ScaleFactorChanged)){ 201 | //This requires that all the objects are removed 202 | m_manager->m_physics_world->setScaleFactor(entity_physics_world_info->scaleFactor()); 203 | m_manager->m_physics_world->setGravity(entity_physics_world_info->gravity()*m_manager->m_physics_world->scaleFactor()); 204 | m_manager->m_Id2RigidBodies.clear(); 205 | m_manager->m_RigidBodies2Id.clear(); 206 | entity_physics_world_info->dirtyFlags() &= ~PhysicsWorldInfoBackendNode::DirtyFlag::ScaleFactorChanged; 207 | return; 208 | } 209 | } 210 | /*Next call*/ 211 | Visit_Data child_data; 212 | for(Qt3DCore::QNodeId childId : entity->childrenIds()){ 213 | child_data.set(childId, current_global_matrix,forceUpdateMS); 214 | m_visit_queue.enqueue(child_data); 215 | } 216 | } 217 | bool UpdatePhysicsEntitiesJob::isRequiringShapeUpdate(PhysicsGeometryRenderer* entity_geometry_renderer){ 218 | if(entity_geometry_renderer->isDirty()) return true; 219 | Qt3DCore::QNodeId geometryId; 220 | if(!entity_geometry_renderer->m_geometry.isNull()){ 221 | geometryId=entity_geometry_renderer->m_geometry; 222 | } 223 | else{ 224 | geometryId=entity_geometry_renderer->m_geometry_functor.data()->operator ()()->id(); 225 | } 226 | PhysicsGeometry* geometry=static_cast(m_manager->m_resources.operator [](geometryId)); 227 | Q_FOREACH(Qt3DCore::QNodeId attrId,geometry->attributes()){ 228 | if(!m_manager->m_resources.contains(attrId)) continue; 229 | PhysicsAttribute* attribute=static_cast(m_manager->m_resources.operator [](attrId)); 230 | if(attribute->objectName()==Qt3DRender::QAttribute::defaultPositionAttributeName()){ 231 | if(attribute->isDirty()) return true; 232 | PhysicsBuffer* buffer_node=static_cast(m_manager->m_resources.operator [](attribute->bufferId())); 233 | if(buffer_node->isDirty()) return true; 234 | } 235 | else if(attribute->attributeType()==Qt3DRender::QAttribute::IndexAttribute){ 236 | if(attribute->isDirty()) return true; 237 | if(m_manager->m_resources.contains(attribute->bufferId())){ 238 | PhysicsBuffer* buffer_node=static_cast(m_manager->m_resources.operator [](attribute->bufferId())); 239 | if(buffer_node->isDirty()) return true; 240 | } 241 | } 242 | } 243 | return false; 244 | } 245 | bool UpdatePhysicsEntitiesJob::isDefiningBody(PhysicsEntity* entity){ 246 | /*A body must have a body info which should be enabled*/ 247 | if(!entity->physicsBodyInfo().isNull() && m_manager->m_resources.contains(entity->physicsBodyInfo())){ 248 | PhysicsBodyInfoBackendNode* entity_body_info=static_cast(m_manager->m_resources.operator [](entity->physicsBodyInfo())); 249 | if(!entity_body_info->isEnabled()) return false; 250 | }else return false; 251 | 252 | /*A body must have a geometry suitable for defining a collition shape*/ 253 | if(entity->geometry_renderer().isNull() || !m_manager->m_resources.contains(entity->geometry_renderer())) return false; 254 | PhysicsGeometryRenderer* entity_geometry_renderer=static_cast(m_manager->m_resources.operator [](entity->geometry_renderer())); 255 | if(!entity_geometry_renderer->isEnabled()) return false; 256 | if(entity_geometry_renderer->m_primitiveType!=Qt3DRender::QGeometryRenderer::Triangles) return false; 257 | //if(entity_geometry_renderer->m_primitiveCount<=0) return false; 258 | if(entity_geometry_renderer->m_geometry.isNull() && entity_geometry_renderer->m_geometry_functor.isNull()) 259 | return false; 260 | Qt3DCore::QNodeId geometryId; 261 | if(!entity_geometry_renderer->m_geometry.isNull()){ 262 | geometryId=entity_geometry_renderer->m_geometry; 263 | } 264 | else{ 265 | geometryId=entity_geometry_renderer->m_geometry_functor.data()->operator ()()->id(); 266 | } 267 | if(geometryId.isNull() || !m_manager->m_resources.contains(geometryId)) return false; 268 | PhysicsGeometry* geometry=static_cast(m_manager->m_resources.operator [](geometryId)); 269 | if(!geometry->isEnabled()) return false; 270 | if(geometry->attributes().isEmpty()) return false; 271 | PhysicsAttribute* vertexPositionAttribute=Q_NULLPTR; 272 | Q_FOREACH(Qt3DCore::QNodeId attrId,geometry->attributes()){ 273 | if(attrId.isNull() || !m_manager->m_resources.contains(attrId)) continue; 274 | vertexPositionAttribute=static_cast(m_manager->m_resources.operator [](attrId)); 275 | if(!vertexPositionAttribute) continue; 276 | if(vertexPositionAttribute->objectName()==Qt3DRender::QAttribute::defaultPositionAttributeName()){ 277 | break; 278 | } 279 | else 280 | vertexPositionAttribute=Q_NULLPTR; 281 | } 282 | if(!vertexPositionAttribute) return false; 283 | if(vertexPositionAttribute->count()==0) return false; 284 | if(vertexPositionAttribute->bufferId().isNull() || !m_manager->m_resources.contains(vertexPositionAttribute->bufferId())) return false; 285 | PhysicsBuffer* buffer_node=static_cast(m_manager->m_resources.operator [](vertexPositionAttribute->bufferId())); 286 | if(!buffer_node) return false; 287 | if(!buffer_node->isEnabled()) return false; 288 | return true; 289 | } 290 | 291 | PhysicsAbstractRigidBody* UpdatePhysicsEntitiesJob::createRigidBodyFromMesh(PhysicsGeometryRenderer* entity_geometry_renderer){ 292 | QVariantMap geometric_info; 293 | entity_geometry_renderer->setDirty(false); 294 | geometric_info["Type"]="Generic"; 295 | Qt3DCore::QNodeId geometryId; 296 | if(!entity_geometry_renderer->m_geometry.isNull()){ 297 | geometryId=entity_geometry_renderer->m_geometry; 298 | } 299 | else{ 300 | geometryId=entity_geometry_renderer->m_geometry_functor.data()->operator ()()->id(); 301 | } 302 | PhysicsGeometry* geometry=static_cast(m_manager->m_resources.operator [](geometryId)); 303 | QVector vertexPosition; 304 | QSet index_Set; 305 | Q_FOREACH(Qt3DCore::QNodeId attrId,geometry->attributes()){ 306 | PhysicsAttribute* attribute=static_cast(m_manager->m_resources.operator [](attrId)); 307 | if(!attribute) continue; 308 | if(attribute->objectName()==Qt3DRender::QAttribute::defaultPositionAttributeName()){ 309 | vertexPosition=attribute->asVector3D(); 310 | attribute->setDirty(false); 311 | PhysicsBuffer* buffer_node=static_cast(m_manager->m_resources.operator [](attribute->bufferId())); 312 | buffer_node->setDirty(false); 313 | } 314 | else if(attribute->attributeType()==Qt3DRender::QAttribute::IndexAttribute){ 315 | if(!attribute->bufferId().isNull() && m_manager->m_resources.contains(attribute->bufferId())){ 316 | attribute->setDirty(false); 317 | QByteArray buffer; 318 | if(!m_manager->m_resources.contains(attribute->bufferId())) continue; 319 | PhysicsBuffer* buffer_node=static_cast(m_manager->m_resources.operator [](attribute->bufferId())); 320 | buffer_node->setDirty(false); 321 | if(buffer_node->bufferFunctor().isNull()){ 322 | buffer=buffer_node->data(); 323 | } 324 | else{ 325 | buffer=buffer_node->bufferFunctor().data()->operator ()(); 326 | } 327 | const char *rawBuffer = buffer.constData(); 328 | rawBuffer += attribute->byteOffset(); 329 | const quint16* fptr; 330 | int stride; 331 | switch (attribute->dataType()) { 332 | case Qt3DRender::QAttribute::UnsignedShort: 333 | stride = sizeof(quint16) * attribute->dataSize(); 334 | break; 335 | default: 336 | qDebug()<< "can't convert"; 337 | } 338 | if (attribute->byteStride() != 0) 339 | stride = attribute->byteStride(); 340 | index_Set.reserve(attribute->count()); 341 | for (uint c = 0; c < attribute->count(); ++c) { 342 | fptr = reinterpret_cast(rawBuffer); 343 | for (uint i = 0, m = qMin(attribute->dataSize(), 3U); i < m; ++i) 344 | index_Set.insert(fptr[i]); 345 | rawBuffer += stride; 346 | } 347 | } 348 | } 349 | } 350 | QVector v=vertexPosition; 351 | vertexPosition.clear(); 352 | vertexPosition.reserve(index_Set.size()); 353 | Q_FOREACH(quint16 index,index_Set.values()){ 354 | if(indexm_physics_world->scaleFactor()); 356 | } 357 | geometric_info["Points"]=QVariant::fromValue(vertexPosition); 358 | return m_manager->m_physics_factory->create_rigid_body(geometric_info); 359 | } 360 | 361 | 362 | } 363 | --------------------------------------------------------------------------------