├── .gitignore
├── CMakeLists.txt
├── Makefile
├── README.md
├── build
└── .gitkeep
├── raylib-cpp-bullet3.gif
├── resources
└── raylib-cpp.png
└── src
├── CMakeLists.txt
└── main.cpp
/.gitignore:
--------------------------------------------------------------------------------
1 | # Build directory.
2 | build/*
3 |
4 | # Prerequisites
5 | *.d
6 |
7 | # Object files
8 | *.o
9 | *.ko
10 | *.obj
11 | *.elf
12 |
13 | # Linker output
14 | *.ilk
15 | *.map
16 | *.exp
17 |
18 | # Precompiled Headers
19 | *.gch
20 | *.pch
21 |
22 | # Libraries
23 | *.lib
24 | *.a
25 | *.la
26 | *.lo
27 |
28 | # Shared objects (inc. Windows DLLs)
29 | *.dll
30 | *.so
31 | *.so.*
32 | *.dylib
33 |
34 | # Executables
35 | *.exe
36 | *.out
37 | *.app
38 | *.i*86
39 | *.x86_64
40 | *.hex
41 |
42 | # Debug files
43 | *.dSYM/
44 | *.su
45 | *.idb
46 | *.pdb
47 |
48 | # Kernel Module Compile Results
49 | *.mod*
50 | *.cmd
51 | .tmp_versions/
52 | modules.order
53 | Module.symvers
54 | Mkfile.old
55 | dkms.conf
56 |
57 | # IDE and editor private config/settings
58 | .vscode
59 | .cache
60 |
61 | # Ignores
62 | !build/.gitkeep
63 | !resources/*.obj
64 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Setup
2 | cmake_minimum_required(VERSION 3.20)
3 | set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
4 | include(FetchContent)
5 | set(FETCHCONTENT_QUIET 0)
6 |
7 | project (raylib-cpp-bullet3
8 | VERSION 0.0.1
9 | DESCRIPTION "raylib-cpp C++ & bullet3"
10 | HOMEPAGE_URL "https://github.com/rafaeldelboni/raylib-cpp-bullet3"
11 | LANGUAGES C CXX)
12 |
13 | # Fetch Raylib
14 | FetchContent_Declare(
15 | raylib
16 | GIT_REPOSITORY https://github.com/raysan5/raylib.git
17 | GIT_SHALLOW TRUE
18 | GIT_PROGRESS TRUE
19 | GIT_TAG master)
20 | set(BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) # don't build the supplied examples
21 | set(BUILD_GAMES OFF CACHE BOOL "" FORCE) # or games
22 |
23 | FetchContent_MakeAvailable(raylib)
24 |
25 | # Fetch Raylib-cpp
26 | FetchContent_Declare(
27 | raylib_cpp
28 | GIT_REPOSITORY https://github.com/robloach/raylib-cpp
29 | GIT_SHALLOW TRUE
30 | GIT_PROGRESS TRUE
31 | GIT_TAG master)
32 | set(BUILD_RAYLIB_CPP_EXAMPLES OFF CACHE BOOL "" FORCE)
33 |
34 | FetchContent_GetProperties(raylib_cpp)
35 | if(NOT raylib_cpp_POPULATED)
36 | FetchContent_Populate(raylib_cpp)
37 |
38 | file(COPY ${raylib_cpp_SOURCE_DIR}/vendor/raylib/src/raylib.h DESTINATION ${raylib_cpp_SOURCE_DIR}/include)
39 | file(COPY ${raylib_cpp_SOURCE_DIR}/vendor/raylib/src/raymath.h DESTINATION ${raylib_cpp_SOURCE_DIR}/include)
40 |
41 | add_subdirectory(${raylib_cpp_SOURCE_DIR} ${raylib_cpp_BINARY_DIR})
42 | endif()
43 |
44 | # Fetch Bullet3
45 | FetchContent_Declare(
46 | bullet
47 | GIT_REPOSITORY https://github.com/bulletphysics/bullet3
48 | GIT_SHALLOW TRUE
49 | GIT_PROGRESS TRUE
50 | GIT_TAG master)
51 | set(BUILD_EXTRAS OFF CACHE BOOL "" FORCE)
52 | set(BUILD_PYBULLET OFF CACHE BOOL "" FORCE)
53 | set(BUILD_BULLET2_DEMOS OFF CACHE BOOL "" FORCE)
54 | set(BUILD_UNIT_TESTS OFF CACHE BOOL "" FORCE)
55 | set(BUILD_CPU_DEMOS OFF CACHE BOOL "" FORCE)
56 | set(BUILD_OPENGL3_DEMOS OFF CACHE BOOL "" FORCE)
57 |
58 | FetchContent_GetProperties(bullet)
59 | if(NOT bullet_POPULATED)
60 | FetchContent_Populate(bullet)
61 | add_subdirectory(${bullet_SOURCE_DIR} ${bullet_BINARY_DIR})
62 | target_include_directories(Bullet3Collision PUBLIC ${BULLET_PHYSICS_SOURCE_DIR}/src)
63 | target_include_directories(Bullet3Common PUBLIC ${BULLET_PHYSICS_SOURCE_DIR}/src)
64 | target_include_directories(Bullet3Dynamics PUBLIC ${BULLET_PHYSICS_SOURCE_DIR}/src)
65 | target_include_directories(Bullet3Geometry PUBLIC ${BULLET_PHYSICS_SOURCE_DIR}/src)
66 | target_include_directories(Bullet3OpenCL_clew PUBLIC ${BULLET_PHYSICS_SOURCE_DIR}/src)
67 | target_include_directories(Bullet2FileLoader PUBLIC ${BULLET_PHYSICS_SOURCE_DIR}/src)
68 | target_include_directories(BulletCollision PUBLIC ${BULLET_PHYSICS_SOURCE_DIR}/src)
69 | target_include_directories(BulletDynamics PUBLIC ${BULLET_PHYSICS_SOURCE_DIR}/src)
70 | target_include_directories(BulletInverseDynamics PUBLIC ${BULLET_PHYSICS_SOURCE_DIR}/src)
71 | target_include_directories(BulletSoftBody PUBLIC ${BULLET_PHYSICS_SOURCE_DIR}/src)
72 | target_include_directories(LinearMath PUBLIC ${BULLET_PHYSICS_SOURCE_DIR}/src)
73 | endif()
74 |
75 | # Add symbolic link to resources folder in build
76 | add_custom_target(resources)
77 | FILE(TO_NATIVE_PATH "${PROJECT_SOURCE_DIR}/resources" source)
78 | FILE(TO_NATIVE_PATH "${PROJECT_BINARY_DIR}/resources" destination)
79 | IF (WIN32)
80 | add_custom_command(
81 | TARGET resources POST_BUILD
82 | COMMAND mklink /D ${destination} ${source}
83 | DEPENDS ${destination}
84 | COMMENT "symbolic link resources folder from ${source} => ${destination}"
85 | )
86 | ELSE()
87 | add_custom_command(
88 | TARGET resources POST_BUILD
89 | COMMAND ${CMAKE_COMMAND} -E create_symlink ${source} ${destination}
90 | DEPENDS ${destination}
91 | COMMENT "symbolic link resources folder from ${source} => ${destination}"
92 | )
93 | ENDIF()
94 |
95 | # C++
96 | set(CMAKE_CXX_STANDARD 11)
97 | set(CMAKE_CXX_STANDARD_REQUIRED ON)
98 | set(CMAKE_CXX_EXTENSIONS OFF)
99 |
100 | # Generates a compile_commands.json file containing the exact compiler calls
101 | set(CMAKE_EXPORT_COMPILE_COMMANDS 1)
102 |
103 | # Include Directory
104 | add_subdirectory(src)
105 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | # Lists phony targets for Makefile
2 | .PHONY: setup build
3 |
4 | setup:
5 | cmake -B build
6 |
7 | build:
8 | make --no-print-directory -C build
9 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # raylib-cpp-bullet3
2 | C, Cpp, Cmake, Raylib, Raylib-cpp and Bullet3 Boilerplate
3 |
4 | 
5 |
6 | ## Usage
7 |
8 | ```bash
9 | make setup
10 | make build
11 | ./build/src/main
12 | ```
13 |
14 | ## Features
15 | This is a Cpp project template with the following features:
16 |
17 | - CMake build scripts for building libraries, applications, and tests.
18 | - Integrated with [Raylib](https://www.raylib.com/).
19 | - Integrated with [Bullet3](https://bulletphysics.org).
20 | - Resource folder to include assets
21 |
22 | ## License
23 | This is free and unencumbered software released into the public domain.
24 | For more information, please refer to
25 |
--------------------------------------------------------------------------------
/build/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rafaeldelboni/raylib-cpp-bullet3/52811a524072f07004280c285c39eb9194b3e001/build/.gitkeep
--------------------------------------------------------------------------------
/raylib-cpp-bullet3.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rafaeldelboni/raylib-cpp-bullet3/52811a524072f07004280c285c39eb9194b3e001/raylib-cpp-bullet3.gif
--------------------------------------------------------------------------------
/resources/raylib-cpp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rafaeldelboni/raylib-cpp-bullet3/52811a524072f07004280c285c39eb9194b3e001/resources/raylib-cpp.png
--------------------------------------------------------------------------------
/src/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_executable(
2 | main
3 | main.cpp)
4 |
5 | add_dependencies(
6 | main
7 | resources)
8 |
9 | target_link_libraries(
10 | main
11 | raylib
12 | raylib-cpp
13 | BulletDynamics
14 | BulletCollision
15 | LinearMath)
16 |
--------------------------------------------------------------------------------
/src/main.cpp:
--------------------------------------------------------------------------------
1 | #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
2 |
3 | #include "BulletCollision/CollisionShapes/btCollisionShape.h"
4 | #include "BulletCollision/CollisionShapes/btConvexPolyhedron.h"
5 | #include "BulletCollision/CollisionShapes/btShapeHull.h"
6 |
7 | #include "LinearMath/btVector3.h"
8 | #include "btBulletDynamicsCommon.h"
9 | #include "raylib-cpp.hpp"
10 | #include "raylib.h"
11 |
12 | void setTransform(btScalar m[16], Matrix *matrix) {
13 | matrix->m0 = m[0];
14 | matrix->m1 = m[1];
15 | matrix->m2 = m[2];
16 | matrix->m3 = m[3];
17 | matrix->m4 = m[4];
18 | matrix->m5 = m[5];
19 | matrix->m6 = m[6];
20 | matrix->m7 = m[7];
21 | matrix->m8 = m[8];
22 | matrix->m9 = m[9];
23 | matrix->m10 = m[10];
24 | matrix->m11 = m[11];
25 | matrix->m12 = m[12];
26 | matrix->m13 = m[13];
27 | matrix->m14 = m[14];
28 | matrix->m15 = m[15];
29 | }
30 |
31 | void AllocateMeshData(Mesh *mesh, int triangleCount) {
32 | mesh->vertexCount = triangleCount * 3;
33 | mesh->triangleCount = triangleCount;
34 |
35 | mesh->vertices = (float *)MemAlloc(mesh->vertexCount * 3 * sizeof(float));
36 | mesh->texcoords = (float *)MemAlloc(mesh->vertexCount * 2 * sizeof(float));
37 | mesh->normals = (float *)MemAlloc(mesh->vertexCount * 3 * sizeof(float));
38 | }
39 |
40 | Mesh ShapeToMesh(btCollisionShape *shape) {
41 | Mesh mesh = {0};
42 |
43 | if (shape->isConvex()) {
44 |
45 | const btConvexPolyhedron *poly =
46 | shape->isPolyhedral()
47 | ? ((btPolyhedralConvexShape *)shape)->getConvexPolyhedron()
48 | : 0;
49 |
50 | if (poly) {
51 | int i;
52 | AllocateMeshData(&mesh, poly->m_faces.size());
53 | int currentVertice = 0;
54 | for (i = 0; i < poly->m_faces.size(); i++) {
55 | btVector3 centroid(0, 0, 0);
56 | int numVerts = poly->m_faces[i].m_indices.size();
57 | if (numVerts > 2) {
58 | btVector3 v1 = poly->m_vertices[poly->m_faces[i].m_indices[0]];
59 | for (int v = 0; v < poly->m_faces[i].m_indices.size() - 2; v++) {
60 | btVector3 v2 = poly->m_vertices[poly->m_faces[i].m_indices[v + 1]];
61 | btVector3 v3 = poly->m_vertices[poly->m_faces[i].m_indices[v + 2]];
62 | btVector3 normal = (v3 - v1).cross(v2 - v1);
63 | normal.normalize();
64 |
65 | mesh.vertices[currentVertice] = v1.x();
66 | mesh.vertices[currentVertice + 1] = v1.y();
67 | mesh.vertices[currentVertice + 2] = v1.z();
68 | mesh.normals[currentVertice] = normal.getX();
69 | mesh.normals[currentVertice + 1] = normal.getY();
70 | mesh.normals[currentVertice + 2] = normal.getZ();
71 |
72 | mesh.vertices[currentVertice + 3] = v2.x();
73 | mesh.vertices[currentVertice + 4] = v2.y();
74 | mesh.vertices[currentVertice + 5] = v2.z();
75 | mesh.normals[currentVertice + 3] = normal.getX();
76 | mesh.normals[currentVertice + 4] = normal.getY();
77 | mesh.normals[currentVertice + 5] = normal.getZ();
78 |
79 | mesh.vertices[currentVertice + 6] = v3.x();
80 | mesh.vertices[currentVertice + 7] = v3.y();
81 | mesh.vertices[currentVertice + 8] = v3.z();
82 | mesh.normals[currentVertice + 6] = normal.getX();
83 | mesh.normals[currentVertice + 7] = normal.getY();
84 | mesh.normals[currentVertice + 8] = normal.getZ();
85 |
86 | currentVertice += 9;
87 | }
88 | }
89 | }
90 | } else {
91 | btConvexShape *convexShape = (btConvexShape *)shape;
92 | btShapeHull *hull = new btShapeHull(convexShape);
93 | hull->buildHull(shape->getMargin());
94 |
95 | AllocateMeshData(&mesh, hull->numTriangles());
96 | int currentVertice = 0;
97 | if (hull->numTriangles() > 0) {
98 |
99 | int index = 0;
100 | const unsigned int *idx = hull->getIndexPointer();
101 | const btVector3 *vtx = hull->getVertexPointer();
102 |
103 | for (int i = 0; i < hull->numTriangles(); i++) {
104 | int i1 = index++;
105 | int i2 = index++;
106 | int i3 = index++;
107 | btAssert(i1 < hull->numIndices() && i2 < hull->numIndices() &&
108 | i3 < hull->numIndices());
109 |
110 | int index1 = idx[i1];
111 | int index2 = idx[i2];
112 | int index3 = idx[i3];
113 | btAssert(index1 < hull->numVertices() &&
114 | index2 < hull->numVertices() &&
115 | index3 < hull->numVertices());
116 |
117 | btVector3 v1 = vtx[index1];
118 | btVector3 v2 = vtx[index2];
119 | btVector3 v3 = vtx[index3];
120 | btVector3 normal = (v3 - v1).cross(v2 - v1);
121 | normal.normalize();
122 |
123 | mesh.vertices[currentVertice] = v1.x();
124 | mesh.vertices[currentVertice + 1] = v1.y();
125 | mesh.vertices[currentVertice + 2] = v1.z();
126 | mesh.normals[currentVertice] = normal.getX();
127 | mesh.normals[currentVertice + 1] = normal.getY();
128 | mesh.normals[currentVertice + 2] = normal.getZ();
129 |
130 | mesh.vertices[currentVertice + 3] = v2.x();
131 | mesh.vertices[currentVertice + 4] = v2.y();
132 | mesh.vertices[currentVertice + 5] = v2.z();
133 | mesh.normals[currentVertice + 3] = normal.getX();
134 | mesh.normals[currentVertice + 4] = normal.getY();
135 | mesh.normals[currentVertice + 5] = normal.getZ();
136 |
137 | mesh.vertices[currentVertice + 6] = v3.x();
138 | mesh.vertices[currentVertice + 7] = v3.y();
139 | mesh.vertices[currentVertice + 8] = v3.z();
140 | mesh.normals[currentVertice + 6] = normal.getX();
141 | mesh.normals[currentVertice + 7] = normal.getY();
142 | mesh.normals[currentVertice + 8] = normal.getZ();
143 |
144 | currentVertice += 9;
145 | }
146 | }
147 | }
148 | UploadMesh(&mesh, false);
149 | }
150 | return mesh;
151 | }
152 |
153 | struct PhysicsWorld {
154 | // keep the collision shapes, for deletion/cleanup
155 | btAlignedObjectArray m_collisionShapes;
156 | btAlignedObjectArray m_models;
157 | btBroadphaseInterface *m_broadphase;
158 | btCollisionDispatcher *m_dispatcher;
159 | btConstraintSolver *m_solver;
160 | btDefaultCollisionConfiguration *m_collisionConfiguration;
161 | btDiscreteDynamicsWorld *m_dynamicsWorld;
162 |
163 | PhysicsWorld()
164 | : m_broadphase(0), m_dispatcher(0), m_solver(0),
165 | m_collisionConfiguration(0), m_dynamicsWorld(0) {}
166 |
167 | virtual ~PhysicsWorld() {}
168 |
169 | btDiscreteDynamicsWorld *getDynamicsWorld() { return m_dynamicsWorld; }
170 |
171 | virtual void initPhysics() {
172 | /// collision configuration contains default setup for memory, collision
173 | /// setup
174 | m_collisionConfiguration = new btDefaultCollisionConfiguration();
175 |
176 | /// use the default collision dispatcher. For parallel processing you can
177 | /// use a diffent dispatcher (see Extras/BulletMultiThreaded)
178 | m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
179 | m_broadphase = new btDbvtBroadphase();
180 |
181 | /// the default constraint solver. For parallel processing you can use a
182 | /// different solver (see Extras/BulletMultiThreaded)
183 | btSequentialImpulseConstraintSolver *sol =
184 | new btSequentialImpulseConstraintSolver;
185 | m_solver = sol;
186 |
187 | m_dynamicsWorld = new btDiscreteDynamicsWorld(
188 | m_dispatcher, m_broadphase, m_solver, m_collisionConfiguration);
189 |
190 | m_dynamicsWorld->setGravity(btVector3(0, -10, 0));
191 | }
192 |
193 | virtual void exitPhysics() {
194 | // cleanup in the reverse order of creation/initialization
195 | // remove the rigidbodies from the dynamics world and delete them
196 |
197 | if (m_dynamicsWorld) {
198 | int i;
199 | for (i = m_dynamicsWorld->getNumConstraints() - 1; i >= 0; i--) {
200 | m_dynamicsWorld->removeConstraint(m_dynamicsWorld->getConstraint(i));
201 | }
202 | for (i = m_dynamicsWorld->getNumCollisionObjects() - 1; i >= 0; i--) {
203 | btCollisionObject *obj = m_dynamicsWorld->getCollisionObjectArray()[i];
204 | btRigidBody *body = btRigidBody::upcast(obj);
205 | if (body && body->getMotionState()) {
206 | delete body->getMotionState();
207 | }
208 | m_dynamicsWorld->removeCollisionObject(obj);
209 | delete obj;
210 | }
211 | }
212 | // delete collision shapes
213 | for (int j = 0; j < m_collisionShapes.size(); j++) {
214 | btCollisionShape *shape = m_collisionShapes[j];
215 | delete shape;
216 | }
217 | m_collisionShapes.clear();
218 |
219 | // delete raylib's models
220 | for (int j = 0; j < m_models.size(); j++) {
221 | UnloadModel(m_models[j]);
222 | }
223 | m_models.clear();
224 |
225 | delete m_dynamicsWorld;
226 | m_dynamicsWorld = 0;
227 |
228 | delete m_solver;
229 | m_solver = 0;
230 |
231 | delete m_broadphase;
232 | m_broadphase = 0;
233 |
234 | delete m_dispatcher;
235 | m_dispatcher = 0;
236 |
237 | delete m_collisionConfiguration;
238 | m_collisionConfiguration = 0;
239 | }
240 |
241 | btRigidBody *createRigidBody(float mass, const btTransform &startTransform,
242 | btCollisionShape *shape, int modelIndex,
243 | btVector3 colorRGB = btVector3(130, 130, 130)) {
244 |
245 | btAssert((!shape || shape->getShapeType() != INVALID_SHAPE_PROXYTYPE));
246 |
247 | // rigidbody is dynamic if and only if mass is non zero, otherwise static
248 | bool isDynamic = (mass != 0.f);
249 |
250 | btVector3 localInertia(0, 0, 0);
251 | if (isDynamic)
252 | shape->calculateLocalInertia(mass, localInertia);
253 |
254 | // using motionstate is recommended, it provides interpolation
255 | // capabilities, and only synchronizes 'active' objects
256 | btDefaultMotionState *myMotionState =
257 | new btDefaultMotionState(startTransform);
258 |
259 | btRigidBody::btRigidBodyConstructionInfo cInfo(mass, myMotionState, shape,
260 | localInertia);
261 |
262 | btRigidBody *body = new btRigidBody(cInfo);
263 |
264 | body->setUserIndex(-1);
265 | body->setUserIndex3(modelIndex);
266 |
267 | body->setCustomDebugColor(colorRGB);
268 |
269 | m_dynamicsWorld->addRigidBody(body);
270 | return body;
271 | }
272 |
273 | void deleteRigidBody(btRigidBody *body) {
274 | int graphicsUid = body->getUserIndex();
275 | m_dynamicsWorld->removeRigidBody(body);
276 | btMotionState *ms = body->getMotionState();
277 | delete body;
278 | delete ms;
279 | }
280 |
281 | void drawDebug() {
282 | for (int j = m_dynamicsWorld->getNumCollisionObjects() - 1; j >= 0; j--) {
283 | btCollisionObject *obj = m_dynamicsWorld->getCollisionObjectArray()[j];
284 | btRigidBody *body = btRigidBody::upcast(obj);
285 | btTransform trans;
286 | if (body && body->getMotionState()) {
287 | body->getMotionState()->getWorldTransform(trans);
288 | } else {
289 | trans = obj->getWorldTransform();
290 | }
291 |
292 | btScalar m[16];
293 | trans.getOpenGLMatrix(m);
294 | Vector3 position = (Vector3){0, 0, 0};
295 | Model model = this->m_models[body->getUserIndex3()];
296 | setTransform(m, &model.transform);
297 |
298 | btVector3 vecColor = btVector3(230, 41, 55);
299 | body->getCustomDebugColor(vecColor);
300 | Color color = raylib::Color((int)vecColor.getX(), (int)vecColor.getY(),
301 | (int)vecColor.getZ(), 255);
302 |
303 | DrawModelWires(model, position, 1.0f, color);
304 | }
305 | }
306 | };
307 |
308 | int main() {
309 | const int screenWidth = 1024;
310 | const int screenHeight = 720;
311 | raylib::Window window(screenWidth, screenHeight, "raylib");
312 | raylib::Camera3D camera(
313 | raylib::Vector3(0.0f, 10.0f, 10.0f), raylib::Vector3(0.0f, -5.0f, 0.0f),
314 | raylib::Vector3(0.0f, 10.0f, 0.0f), 45.0f, CAMERA_PERSPECTIVE);
315 | camera.SetMode(CAMERA_ORBITAL); // Set an orbital camera mode
316 |
317 | SetTargetFPS(60); // Set our game to run at 60 frames-per-second
318 |
319 | // physics
320 | //--------------------------------------------------------------------------------------
321 | PhysicsWorld world = *new PhysicsWorld();
322 | world.initPhysics();
323 |
324 | {
325 | btCollisionShape *groundShape =
326 | new btBoxShape(btVector3(btScalar(50.), btScalar(50.), btScalar(50.)));
327 | world.m_collisionShapes.push_back(groundShape);
328 |
329 | Model model = LoadModelFromMesh(ShapeToMesh(groundShape));
330 | world.m_models.push_back(model);
331 |
332 | btTransform groundTransform;
333 | groundTransform.setIdentity();
334 | groundTransform.setOrigin(btVector3(0, -56, 0));
335 |
336 | btRigidBody *ground = world.createRigidBody(
337 | 0., groundTransform, groundShape, world.m_models.size() - 1);
338 | }
339 |
340 | {
341 | btCollisionShape *colShape = new btSphereShape(btScalar(1.));
342 | world.m_collisionShapes.push_back(colShape);
343 | world.m_collisionShapes.push_back(colShape);
344 |
345 | Model model = LoadModelFromMesh(ShapeToMesh(colShape));
346 | world.m_models.push_back(model);
347 |
348 | btTransform startTransform;
349 | startTransform.setIdentity();
350 | startTransform.setOrigin(btVector3(2, 10, 0));
351 |
352 | btRigidBody *sphere = world.createRigidBody(1.f, startTransform, colShape,
353 | world.m_models.size() - 1,
354 | btVector3(255, 161, 0));
355 | }
356 |
357 | {
358 | // create a few dynamic rigidbodies
359 | // Re-using the same collision is better for memory usage and performance
360 |
361 | btBoxShape *colShape =
362 | new btBoxShape(btVector3(btScalar(.1), btScalar(.1), btScalar(.1)));
363 |
364 | // btCollisionShape* colShape = new btSphereShape(btScalar(1.));
365 | world.m_collisionShapes.push_back(colShape);
366 |
367 | Model model = LoadModelFromMesh(ShapeToMesh(colShape));
368 | world.m_models.push_back(model);
369 |
370 | /// Create Dynamic Objects
371 | btTransform startTransform;
372 | startTransform.setIdentity();
373 |
374 | btScalar mass(1.f);
375 |
376 | // rigidbody is dynamic if and only if mass is non zero, otherwise static
377 | bool isDynamic = (mass != 0.f);
378 |
379 | btVector3 localInertia(0, 0, 0);
380 | if (isDynamic)
381 | colShape->calculateLocalInertia(mass, localInertia);
382 |
383 | int arraySizeY = 5;
384 | int arraySizeX = 5;
385 | int arraySizeZ = 5;
386 |
387 | for (int k = 0; k < arraySizeY; k++) {
388 | for (int i = 0; i < arraySizeX; i++) {
389 | for (int j = 0; j < arraySizeZ; j++) {
390 | startTransform.setOrigin(btVector3(
391 | btScalar(0.2 * i), btScalar(2 + .2 * k), btScalar(0.2 * j)));
392 |
393 | world.createRigidBody(mass, startTransform, colShape,
394 | world.m_models.size() - 1,
395 | btVector3(0, 121, 241));
396 | }
397 | }
398 | }
399 | }
400 |
401 | //--------------------------------------------------------------------------------------
402 |
403 | // Main game loop
404 | while (!window.ShouldClose()) { // Detect window close button or ESC key
405 | // Update
406 | //----------------------------------------------------------------------------------
407 | world.m_dynamicsWorld->stepSimulation(GetFrameTime(), 10);
408 | camera.Update(); // Update camera
409 | //----------------------------------------------------------------------------------
410 |
411 | // Draw
412 | //----------------------------------------------------------------------------------
413 | BeginDrawing();
414 | {
415 | window.ClearBackground(RAYWHITE);
416 |
417 | camera.BeginMode();
418 | { world.drawDebug(); }
419 | camera.EndMode();
420 |
421 | DrawFPS(10, 10);
422 | }
423 | EndDrawing();
424 | //----------------------------------------------------------------------------------
425 | }
426 |
427 | world.exitPhysics();
428 | return 0;
429 | }
430 |
--------------------------------------------------------------------------------