Skip to content

Commit 76ac9b9

Browse files
author
Tiffany Bennett
committed
Make bouncing lights stop crashing
1 parent b8eb35f commit 76ac9b9

File tree

2 files changed

+156
-109
lines changed

2 files changed

+156
-109
lines changed

src/bouncing-lights/bouncinglights.cpp

Lines changed: 155 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
#include <ctime>
1111
#include <math.h>
1212

13+
#include <experimental/optional>
14+
1315
#include "tgl/tgl.h"
1416
#include "debugdraw.hpp"
1517
#include "bulletspace.hpp"
@@ -42,47 +44,159 @@ float rand_float(unsigned *seedp)
4244
return (float)rand_r(seedp) / RAND_MAX;
4345
}
4446

45-
struct Spheres {
47+
struct Scene : public Drawable {
48+
Scene(BulletSpace &space)
49+
: space(space) {}
50+
51+
BulletSpace &space;
4652
vector<BulletSpace::BodyID> bodies;
4753
vector<il_vec3> colors;
4854
vector<ilG_light> lights;
49-
};
55+
experimental::optional<BulletSpace::BodyID> heightmap_body;
56+
ilG_heightmap heightmap;
57+
BallRenderer ball;
58+
btSphereShape sphere_shape = btSphereShape(1);
59+
btStaticPlaneShape ground_shape[4] = {
60+
btStaticPlaneShape(btVector3( 1, 0, 0), 1),
61+
btStaticPlaneShape(btVector3(-1, 0, 0), 1),
62+
btStaticPlaneShape(btVector3( 0, 0, 1), 1),
63+
btStaticPlaneShape(btVector3( 0, 0, -1), 1)
64+
};
65+
btDefaultMotionState ground_motion_state[4], heightmap_motion_state;
66+
experimental::optional<btHeightfieldTerrainShape> heightmap_shape;
5067

51-
Spheres add_objects(BulletSpace &bs, btCollisionShape *shape, size_t count, unsigned *seedp)
52-
{
53-
Spheres spheres;
54-
for (size_t i = 0; i < count; i++) {
55-
// Physics body
56-
btVector3 position
57-
(rand_r(seedp) % 128,
58-
rand_r(seedp) % 32 + 50,
59-
rand_r(seedp) % 128);
60-
auto state = new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1), position));
61-
float mass = 1.f;
62-
btVector3 inertia(0,0,0);
63-
shape->calculateLocalInertia(mass, inertia);
64-
btRigidBody::btRigidBodyConstructionInfo ballRigidBodyCI(mass, state, shape, inertia);
65-
auto id = bs.add(ballRigidBodyCI);
66-
bs.getBody(id).setRestitution(1.0);
67-
68-
// Color
69-
float brightness = rand_float(seedp) + 1;
70-
auto col = il_vec3_new(
71-
rand_float(seedp) * brightness,
72-
rand_float(seedp) * brightness,
73-
rand_float(seedp) * brightness);
74-
75-
// Light
76-
ilG_light light;
77-
light.color = col;
78-
light.radius = brightness * 10;
79-
80-
spheres.bodies.push_back(id);
81-
spheres.colors.push_back(col);
82-
spheres.lights.push_back(light);
68+
void draw(Graphics &graphics) override {
69+
(void)graphics;
70+
il_mat hmvp, himt;
71+
space.objmats(&hmvp, &*heightmap_body, ILG_MVP, 1);
72+
space.objmats(&himt, &*heightmap_body, ILG_IMT, 1);
73+
ilG_heightmap_draw(&heightmap, hmvp, himt);
74+
75+
vector<il_mat> mvp, imt;
76+
mvp.resize(bodies.size());
77+
imt.resize(bodies.size());
78+
space.objmats(mvp.data(), bodies.data(), ILG_MVP, bodies.size());
79+
space.objmats(imt.data(), bodies.data(), ILG_IMT, bodies.size());
80+
ball.draw(mvp.data(), imt.data(), colors.data(), bodies.size());
8381
}
84-
return spheres;
85-
}
82+
83+
bool build(ilG_renderman *rm) {
84+
// Arena walls
85+
///////////////
86+
vector<btRigidBody> ground_body;
87+
ground_body.reserve(4);
88+
btVector3 positions[4] = {
89+
btVector3(0, 0, 0),
90+
btVector3(arenaWidth, 0, 0),
91+
btVector3(0, 0, 0),
92+
btVector3(0, 0, arenaWidth)
93+
};
94+
for (unsigned i = 0; i < 4; i++) {
95+
ground_motion_state[i] = btDefaultMotionState(btTransform(btQuaternion(0,0,0,1),positions[i]));
96+
btRigidBody::btRigidBodyConstructionInfo groundRigidBodyCI
97+
(0,
98+
&ground_motion_state[i],
99+
&ground_shape[i],
100+
btVector3(0,0,0) );
101+
auto id = space.add(groundRigidBodyCI);
102+
space.getBody(id).setRestitution(0.5);
103+
}
104+
105+
// Image
106+
///////////////////////
107+
ilA_img hm;
108+
ilA_imgerr res = ilA_img_loadfile(&hm, &demo_fs, "arena-heightmap.png");
109+
if (res) {
110+
il_error("Failed to load heightmap: %s", ilA_img_strerror(res));
111+
return false;
112+
}
113+
// Physics
114+
/////////////////////
115+
const unsigned height = 50;
116+
heightmap_shape = btHeightfieldTerrainShape(hm.width, hm.height, hm.data, height/255.f, 0,
117+
height, 1, PHY_UCHAR, false);
118+
heightmap_shape->setLocalScaling(btVector3(arenaWidth/hm.width, 1, arenaWidth/hm.height));
119+
btTransform trans = btTransform(btQuaternion(0,0,0,1),
120+
btVector3(arenaWidth/2, height/2, arenaWidth/2));
121+
heightmap_motion_state = trans;
122+
btRigidBody::btRigidBodyConstructionInfo groundRigidBodyCI
123+
(0, &heightmap_motion_state, &*heightmap_shape, btVector3(0,0,0));
124+
heightmap_body = space.add(groundRigidBodyCI);
125+
space.getBody(*heightmap_body).setRestitution(1.0);
126+
space.setBodyScale(*heightmap_body, il_vec3_new(128, 50, 128));
127+
// Rendering
128+
///////////////////////
129+
ilA_img norm;
130+
res = ilA_img_height_to_normal(&norm, &hm);
131+
if (res) {
132+
il_error("Failed to create normal map: %s", ilA_img_strerror(res));
133+
return false;
134+
}
135+
ilG_tex colortex, heighttex, normaltex;
136+
res = ilG_tex_loadfile(&colortex, &demo_fs, "terrain.png");
137+
if (res) {
138+
il_error("Failed to load heightmap texture: %s", ilA_img_strerror(res));
139+
return false;
140+
}
141+
ilA_img hmc;
142+
res = ilA_img_copy(&hmc, &hm);
143+
if (res) {
144+
il_error("Failed to copy image: %s", ilA_img_strerror(res));
145+
return false;
146+
}
147+
ilG_tex_loadimage(&heighttex, hmc);
148+
ilG_tex_loadimage(&normaltex, norm);
149+
char *error;
150+
if (!ilG_heightmap_build(&this->heightmap, rm, hm.width, hm.height,
151+
heighttex, normaltex, colortex, &error)) {
152+
il_error("heightmap: %s", error);
153+
free(error);
154+
return false;
155+
}
156+
157+
if (!ball.build(rm, &error)) {
158+
il_error("ball: %s", error);
159+
free(error);
160+
return false;
161+
}
162+
163+
return true;
164+
}
165+
166+
void populate(size_t count) {
167+
unsigned seed;
168+
for (size_t i = 0; i < count; i++) {
169+
// Physics body
170+
btVector3 position
171+
(rand_r(&seed) % 128,
172+
rand_r(&seed) % 32 + 50,
173+
rand_r(&seed) % 128);
174+
auto state = new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1), position));
175+
float mass = 1.f;
176+
btVector3 inertia(0,0,0);
177+
sphere_shape.calculateLocalInertia(mass, inertia);
178+
btRigidBody::btRigidBodyConstructionInfo ballRigidBodyCI(mass, state, &sphere_shape, inertia);
179+
auto id = space.add(ballRigidBodyCI);
180+
space.getBody(id).setRestitution(1.0);
181+
182+
// Color
183+
float brightness = rand_float(&seed) + 1;
184+
auto col = il_vec3_new(
185+
rand_float(&seed) * brightness,
186+
rand_float(&seed) * brightness,
187+
rand_float(&seed) * brightness);
188+
189+
// Light
190+
ilG_light light;
191+
light.color = col;
192+
light.radius = brightness * 10;
193+
194+
bodies.push_back(id);
195+
colors.push_back(col);
196+
lights.push_back(light);
197+
}
198+
}
199+
};
86200

87201
int main(int argc, char **argv)
88202
{
@@ -123,80 +237,13 @@ int main(int argc, char **argv)
123237

124238
// Setup invisible arena walls
125239
///////////////////////////////
126-
btStaticPlaneShape groundShape[4] = {
127-
btStaticPlaneShape(btVector3( 1, 0, 0), 1),
128-
btStaticPlaneShape(btVector3(-1, 0, 0), 1),
129-
btStaticPlaneShape(btVector3( 0, 0, 1), 1),
130-
btStaticPlaneShape(btVector3( 0, 0, -1), 1)
131-
};
132-
btDefaultMotionState groundMotionState[4];
133-
vector<btRigidBody> groundBody;
134-
btVector3 positions[4] = {
135-
btVector3(0, 0, 0),
136-
btVector3(arenaWidth, 0, 0),
137-
btVector3(0, 0, 0),
138-
btVector3(0, 0, arenaWidth)
139-
};
140-
for (unsigned i = 0; i < 4; i++) {
141-
groundMotionState[i] = btDefaultMotionState(btTransform(btQuaternion(0,0,0,1),positions[i]));
142-
btRigidBody::btRigidBodyConstructionInfo groundRigidBodyCI
143-
(0,
144-
&groundMotionState[i],
145-
&groundShape[i],
146-
btVector3(0,0,0) );
147-
groundBody.emplace_back(groundRigidBodyCI);
148-
btRigidBody &groundRigidBody = groundBody.back();
149-
groundRigidBody.setRestitution(0.5);
150-
world.world.addRigidBody(&groundRigidBody);
151-
}
152240

153-
// Create heightmap physics and render stuff
154-
/////////////////////////////////////////////
155-
ilA_img hm;
156-
ilA_imgerr res = ilA_img_loadfile(&hm, &demo_fs, "arena-heightmap.png");
157-
if (res) {
158-
il_error("Failed to load heightmap: %s", ilA_img_strerror(res));
159-
return 1;
160-
}
161-
const unsigned height = 50;
162-
btHeightfieldTerrainShape heightmap_shape
163-
(hm.width, hm.height, hm.data, height/255.f, 0, height, 1, PHY_UCHAR, false);
164-
heightmap_shape.setLocalScaling(btVector3(arenaWidth/hm.width, 1, arenaWidth/hm.height));
165-
btTransform trans = btTransform(btQuaternion(0,0,0,1),
166-
btVector3(arenaWidth/2, height/2, arenaWidth/2));
167-
btDefaultMotionState heightmap_state(trans);
168-
btRigidBody::btRigidBodyConstructionInfo groundRigidBodyCI
169-
(0, &heightmap_state, &heightmap_shape, btVector3(0,0,0));
170-
auto ground_id = world.add(groundRigidBodyCI);
171-
world.getBody(ground_id).setRestitution(1.0);
172-
world.setBodyScale(ground_id, il_vec3_new(128, 50, 128));
173-
ilA_img norm;
174-
res = ilA_img_height_to_normal(&norm, &hm);
175-
if (res) {
176-
il_error("Failed to create normal map: %s", ilA_img_strerror(res));
241+
Scene scene(world);
242+
if (!scene.build(graphics.rm)) {
177243
return 1;
178244
}
179-
ilG_tex colortex, heighttex, normaltex;
180-
res = ilG_tex_loadfile(&colortex, &demo_fs, "terrain.png");
181-
if (res) {
182-
il_error("Failed to load heightmap texture: %s", ilA_img_strerror(res));
183-
return 1;
184-
}
185-
ilA_img hmc;
186-
res = ilA_img_copy(&hmc, &hm);
187-
if (res) {
188-
il_error("Failed to copy image: %s", ilA_img_strerror(res));
189-
return 1;
190-
}
191-
ilG_tex_loadimage(&heighttex, hmc);
192-
ilG_tex_loadimage(&normaltex, norm);
193-
194-
// Create ball renderer and common bullet stuff
195-
////////////////////////////////////////////////
196-
btSphereShape ball_shape(1);
197-
BallRenderer ball;
198-
unsigned seed = time(NULL);
199-
add_objects(world, &ball_shape, 100, &seed);
245+
scene.populate(100);
246+
graphics.drawables.push_back(&scene);
200247

201248
float yaw = 0, pitch = 0;
202249
il_quat rot = il_quat_new(0,0,0,1);
@@ -235,7 +282,7 @@ int main(int argc, char **argv)
235282
playerwalk = il_vec3_rotate(playerwalk, rot);
236283
player.setWalkDirection(btVector3(playerwalk.x, playerwalk.y, playerwalk.z));
237284
}
238-
//world.step(1/60.f);
285+
world.step(1/60.f);
239286
graphics.draw(state);
240287
}
241288
}

0 commit comments

Comments
 (0)