简介
ReactPhysics3D is a C++ physics engine library that can be used in 3D simulations and games.
主要想尝试一下RL,想先弄个物理引擎,这样方便模拟场景。看了一圈,虽然也有不少Python的,但是好多都要自己写update函数,各种运动要自己算,想想还是算了吧,希望搞一个比较General的物理引擎,这样搭复杂模型会很简单,大不了做个interprocess communication (ipc) 接口,用Python搭RL模型控制下完事。
所以想要物理引擎尽可能light weight,库小一些,feature不那么多,能模拟就行,document好一些,方便自己修改。
最后看上了 ReactPhysics3D。
feature list,我比较看重的特性都粗体了:
- Rigid body dynamics
- Discrete collision detection
- Collision shapes (Sphere, Box, Capsule, Convex Mesh, Static Concave Mesh, Height Field)
- Multiple collision shapes per body
- Broadphase collision detection (Dynamic AABB tree)
- Narrowphase collision detection (SAT/GJK)
- Collision response and friction (Sequential Impulses Solver)
- Joints (Ball and Socket, Hinge, Slider, Fixed)
- Collision filtering with categories
- Ray casting
- Sleeping technique for inactive bodies
- Multi-platform (Windows, Linux, Mac OS X)
- No external libraries (do not use STL containers)
- Documentation (user manual and Doxygen API)
- Testbed application with demos
- Integrated Profiler
- Logs
- Unit tests
初步了解项目运行过程
看了下代码,不多,比较规整,有一个完整的看起来很方便改的Demo APP。看起来很完美的符合我的需求了。
CMakeLists.txt
构建方式cmake,直接搞到clion里面。root的cmakelist.txt就270行,包含了众多header文件和cpp文件,实际结构非常简单。构建目标主要就是 ADD_LIBRARY(reactphysics3d ${REACTPHYSICS3D_HEADERS} ${REACTPHYSICS3D_SOURCES})
。包含了两个子目录:
IF(RP3D_COMPILE_TESTS)
add_subdirectory(test/)
ENDIF()
IF(RP3D_COMPILE_TESTBED)
add_subdirectory(testbed/)
ENDIF()
显然一个测试一个是feature list 里面提及的 Demo。
去掉demo的 IF
,直接编译运行,demo 没问题。
Main函数
下面可以开始读代码理解他的逻辑了。
main 入口函数很简单:
// Libraries
#include "TestbedApplication.h"
#include "nanogui/nanogui.h"
using namespace nanogui;
// Main function
int main(int argc, char** argv) {
nanogui::init();
{
// Create and start the testbed application
bool isFullscreen = false;
nanogui::ref<TestbedApplication> application = new TestbedApplication(isFullscreen);
application->setVisible(true);
nanogui::mainloop();
}
nanogui::shutdown();
return 0;
}
实例化了一下TestbedApplication
,然后进 mainloop
。
GUI框架概览
class TestbedApplication : public Screen {
...
}
查看TestbedApplication
的定义,可以看到继承了Screen
,下面是精简的Screen
的定义,列出了主要的修改、初始化Screen
的函数,Screen
中protected以及OpenGL相关的函数都略去了。
class NANOGUI_EXPORT Screen : public Widget {
friend class Widget;
friend class Window;
public:
Screen(const Vector2i &size, const std::string &caption,
bool resizable = true, bool fullscreen = false, int colorBits = 8,
int alphaBits = 8, int depthBits = 24, int stencilBits = 8,
int nSamples = 0,
unsigned int glMajor = 3, unsigned int glMinor = 3);
const std::string &caption() const {
return mCaption; }
void setCaption(const std::string &caption);
const Color &background() const {
return mBackground; }
void setBackground(const Color &background) {
mBackground = background; }
void setVisible(bool visible);
void setSize(const Vector2i& size);
virtual void drawAll();
virtual void drawContents() {
/* To be overridden */ }
float pixelRatio() const {
return mPixelRatio; }
virtual bool dropEvent(const std::vector<std::string> & /* filenames */) {
return false; /* To be overridden */ }
virtual bool keyboardEvent(int key, int scancode, int action, int modifiers);
virtual bool keyboardCharacterEvent(unsigned int codepoint);
virtual bool resizeEvent(const Vector2i& size);
std::function<void(Vector2i)> resizeCallback() const {
return mResizeCallback; }
void setResizeCallback(const std::function<void(Vector2i)> &callback) {
mResizeCallback = callback; }
Vector2i mousePos() const {
return mMousePos; }
GLFWwindow *glfwWindow() {
return mGLFWWindow; }
NVGcontext