From 7fb3aa7570aeee3c04e51841dbedaaaee6ab1fa7 Mon Sep 17 00:00:00 2001 From: Benau Date: Wed, 27 Feb 2019 11:06:18 +0800 Subject: [PATCH] Combine static physical objects with irrlicht GeometryCreator --- src/physics/physical_object.cpp | 133 ++++++++++++++++++++++++++++ src/physics/physical_object.hpp | 2 + src/tracks/track.cpp | 12 ++- src/tracks/track.hpp | 3 +- src/tracks/track_object.cpp | 31 +++++++ src/tracks/track_object.hpp | 2 + src/tracks/track_object_manager.hpp | 2 +- 7 files changed, 181 insertions(+), 4 deletions(-) diff --git a/src/physics/physical_object.cpp b/src/physics/physical_object.cpp index 98f029775..b3ba362a0 100644 --- a/src/physics/physical_object.cpp +++ b/src/physics/physical_object.cpp @@ -873,3 +873,136 @@ std::function PhysicalObject::getLocalStateRestoreFunction() } }; } // getLocalStateRestoreFunction + +// ---------------------------------------------------------------------------- +void PhysicalObject::joinToMainTrack() +{ + auto sm = irr_driver->getSceneManager(); + auto gc = sm->getGeometryCreator(); + scene::IMeshManipulator* mani = + irr_driver->getVideoDriver()->getMeshManipulator(); + + if (m_body_type == MP_EXACT) + { + TrackObjectPresentationSceneNode* presentation = + m_object->getPresentation(); + assert(presentation); + Track::getCurrentTrack()->convertTrackToBullet(presentation->getNode()); + } + else if (m_body_type == MP_CYLINDER_X || m_body_type == MP_CYLINDER_Y || + m_body_type == MP_CYLINDER_Z) + { + btCylinderShape* cylinder = dynamic_cast(m_shape); + assert(cylinder); + btTransform t; + m_motion_state->getWorldTransform(t); + + int up_axis = cylinder->getUpAxis(); + scene::IMesh* mesh = + gc->createCylinderMesh(cylinder->getRadius(), + cylinder->getHalfExtentsWithMargin()[up_axis] * 2.0f, + std::max((int)(cylinder->getRadius() / 2.0f), 4)); + scene::ISceneNode* node = sm->addMeshSceneNode(mesh); + mesh->drop(); + + core::matrix4 translate(core::matrix4::EM4CONST_IDENTITY); + Vec3 offset; + offset.setY(-cylinder->getHalfExtentsWithMargin()[up_axis]); + translate.setTranslation(offset.toIrrVector()); + mani->transform(mesh, translate); + + core::matrix4 adjust_axis(core::matrix4::EM4CONST_IDENTITY); + if (m_body_type == MP_CYLINDER_X) + adjust_axis.setRotationDegrees(core::vector3df(0, 0, -90)); + else if (m_body_type == MP_CYLINDER_Z) + adjust_axis.setRotationDegrees(core::vector3df(90, 0, 0)); + mani->transform(mesh, adjust_axis); + + node->setPosition(Vec3(t.getOrigin()).toIrrVector()); + Vec3 hpr; + hpr.setHPR(t.getRotation()); + node->setRotation(hpr.toIrrHPR()); + + Track::getCurrentTrack()->convertTrackToBullet(node); + node->remove(); + } + else if (m_body_type == MP_CONE_X || m_body_type == MP_CONE_Y || + m_body_type == MP_CONE_Z) + { + btConeShape* cone = dynamic_cast(m_shape); + assert(cone); + btTransform t; + m_motion_state->getWorldTransform(t); + + scene::IMesh* mesh = + gc->createConeMesh(cone->getRadius(), + cone->getHeight(), + std::max((int)(cone->getRadius() / 2.0f), 4)); + scene::ISceneNode* node = sm->addMeshSceneNode(mesh); + mesh->drop(); + + core::matrix4 translate(core::matrix4::EM4CONST_IDENTITY); + Vec3 offset; + offset.setY(cone->getHeight() * -0.5f); + translate.setTranslation(offset.toIrrVector()); + mani->transform(mesh, translate); + + core::matrix4 adjust_axis(core::matrix4::EM4CONST_IDENTITY); + if (m_body_type == MP_CONE_X) + adjust_axis.setRotationDegrees(core::vector3df(0, 0, -90)); + else if (m_body_type == MP_CONE_Z) + adjust_axis.setRotationDegrees(core::vector3df(90, 0, 0)); + mani->transform(mesh, adjust_axis); + + node->setPosition(Vec3(t.getOrigin()).toIrrVector()); + Vec3 hpr; + hpr.setHPR(t.getRotation()); + node->setRotation(hpr.toIrrHPR()); + + Track::getCurrentTrack()->convertTrackToBullet(node); + node->remove(); + } + else if (m_body_type == MP_SPHERE) + { + btSphereShape* sphere = dynamic_cast(m_shape); + assert(sphere); + btTransform t; + m_motion_state->getWorldTransform(t); + + scene::IMesh* mesh = + gc->createSphereMesh(sphere->getRadius(), + std::max((int)(sphere->getRadius() / 2.0f), 4), + std::max((int)(sphere->getRadius() / 2.0f), 4)); + scene::ISceneNode* node = sm->addMeshSceneNode(mesh); + mesh->drop(); + + node->setPosition(Vec3(t.getOrigin()).toIrrVector()); + Vec3 hpr; + hpr.setHPR(t.getRotation()); + node->setRotation(hpr.toIrrHPR()); + + Track::getCurrentTrack()->convertTrackToBullet(node); + node->remove(); + } + else if (m_body_type == MP_BOX) + { + btBoxShape* box = dynamic_cast(m_shape); + assert(box); + scene::IMesh* mesh = + gc->createCubeMesh( + Vec3(box->getHalfExtentsWithMargin() * 2.0f).toIrrVector()); + scene::ISceneNode* node = sm->addMeshSceneNode(mesh); + mesh->drop(); + + btTransform t; + m_motion_state->getWorldTransform(t); + node->setPosition(Vec3(t.getOrigin()).toIrrVector()); + Vec3 hpr; + hpr.setHPR(t.getRotation()); + node->setRotation(hpr.toIrrHPR()); + + Track::getCurrentTrack()->convertTrackToBullet(node); + node->remove(); + } + +} // joinToMainTrack diff --git a/src/physics/physical_object.hpp b/src/physics/physical_object.hpp index 480e5ca5f..5116bd5e1 100644 --- a/src/physics/physical_object.hpp +++ b/src/physics/physical_object.hpp @@ -286,6 +286,8 @@ public: virtual void restoreState(BareNetworkString *buffer, int count); virtual void undoState(BareNetworkString *buffer) {} virtual std::function getLocalStateRestoreFunction(); + bool hasTriangleMesh() const { return m_triangle_mesh != NULL; } + void joinToMainTrack(); LEAK_CHECK() }; // PhysicalObject diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp index 41bd29b35..6e5210df2 100644 --- a/src/tracks/track.cpp +++ b/src/tracks/track.cpp @@ -997,9 +997,9 @@ void Track::convertTrackToBullet(scene::ISceneNode *node) Vec3 normals[3]; #ifndef SERVER_ONLY - if (CVS->isGLSL()) + SP::SPMeshBuffer* spmb = dynamic_cast(mb); + if (spmb) { - SP::SPMeshBuffer* spmb = static_cast(mb); video::S3DVertexSkinnedMesh* mbVertices = (video::S3DVertexSkinnedMesh*)mb->getVertices(); for (unsigned int matrix_index = 0; matrix_index < matrices.size(); matrix_index++) { @@ -2144,6 +2144,14 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id) #endif main_loop->renderGUI(5500); + // Join all static physics only object to main track if possible + // Take the visibility condition by scripting into account + for (auto* to : m_track_object_manager->getObjects().m_contents_vector) + { + if (to->joinToMainTrack()) + m_track_object_manager->removeDriveableObject(to); + } + createPhysicsModel(main_track_count); main_loop->renderGUI(5600); diff --git a/src/tracks/track.hpp b/src/tracks/track.hpp index d5ce4d9f1..05a12f42e 100644 --- a/src/tracks/track.hpp +++ b/src/tracks/track.hpp @@ -394,7 +394,6 @@ private: void loadDriveGraph(unsigned int mode_id, const bool reverse); void loadArenaGraph(const XMLNode &node); btQuaternion getArenaStartRotation(const Vec3& xyz, float heading); - void convertTrackToBullet(scene::ISceneNode *node); bool loadMainTrack(const XMLNode &node); void loadMinimap(); void createWater(const XMLNode &node); @@ -695,6 +694,8 @@ public: const btTransform& getBlueFlag() const { return m_blue_flag; } // ------------------------------------------------------------------------ bool isAddon() const { return m_is_addon; } + // ------------------------------------------------------------------------ + void convertTrackToBullet(scene::ISceneNode *node); }; // class Track #endif diff --git a/src/tracks/track_object.cpp b/src/tracks/track_object.cpp index 2aa26613c..54de73d27 100644 --- a/src/tracks/track_object.cpp +++ b/src/tracks/track_object.cpp @@ -31,6 +31,7 @@ #include "io/xml_node.hpp" #include "input/device_manager.hpp" #include "items/item_manager.hpp" +#include "network/network_config.hpp" #include "physics/physical_object.hpp" #include "race/race_manager.hpp" #include "scriptengine/script_engine.hpp" @@ -740,3 +741,33 @@ scene::IAnimatedMeshSceneNode* TrackObject::getMesh() Log::debug("TrackObject", "No animated mesh"); return NULL; } // getMesh + +// ---------------------------------------------------------------------------- +bool TrackObject::joinToMainTrack() +{ + // If no physical object or there is animator, skip it + // Also no joining if will affect kart (like moveable, flatten...) + if (!isEnabled() || !m_physical_object || m_animator || + m_physical_object->isDynamic() || m_physical_object->isCrashReset() || + m_physical_object->isExplodeKartObject() || + m_physical_object->isFlattenKartObject()) + return false; + + // Scripting exploding barrel is assumed to be joinable in networking + // as it doesn't support it + if (!NetworkConfig::get()->isNetworking() && + (!m_physical_object->getOnKartCollisionFunction().empty() || + !m_physical_object->getOnItemCollisionFunction().empty())) + return false; + + // Skip driveable non-exact shape object + // Notice driveable object should always has exact shape specified in + // blender + if (m_is_driveable && !m_physical_object->hasTriangleMesh()) + return false; + + m_physical_object->joinToMainTrack(); + // This will remove the separated body + m_physical_object.reset(); + return true; +} // joinToMainTrack diff --git a/src/tracks/track_object.hpp b/src/tracks/track_object.hpp index 2ed661d01..50f46425c 100644 --- a/src/tracks/track_object.hpp +++ b/src/tracks/track_object.hpp @@ -249,6 +249,8 @@ public: std::vector& getChildren() { return m_children; } // ------------------------------------------------------------------------ void movePhysicalBodyToGraphicalNode(const core::vector3df& xyz, const core::vector3df& hpr); + // ------------------------------------------------------------------------ + bool joinToMainTrack(); LEAK_CHECK() }; // TrackObject diff --git a/src/tracks/track_object_manager.hpp b/src/tracks/track_object_manager.hpp index 2aff16d42..b75ca3e09 100644 --- a/src/tracks/track_object_manager.hpp +++ b/src/tracks/track_object_manager.hpp @@ -71,7 +71,7 @@ public: void insertObject(TrackObject* object); void removeObject(TrackObject* who); - + void removeDriveableObject(TrackObject* obj) { m_driveable_objects.remove(obj); } TrackObject* getTrackObject(const std::string& libraryInstance, const std::string& name); PtrVector& getObjects() { return m_all_objects; }