-
Notifications
You must be signed in to change notification settings - Fork 566
/
Copy pathworker.js
170 lines (137 loc) · 4.98 KB
/
worker.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
var Module = { TOTAL_MEMORY: 512*1024*1024 };
importScripts('../../builds/ammo.js');
Ammo().then(function(Ammo) {
var NUM = 0, NUMRANGE = [];
// Bullet-interfacing code
var collisionConfiguration = new Ammo.btDefaultCollisionConfiguration();
var dispatcher = new Ammo.btCollisionDispatcher(collisionConfiguration);
var overlappingPairCache = new Ammo.btDbvtBroadphase();
var solver = new Ammo.btSequentialImpulseConstraintSolver();
var dynamicsWorld = new Ammo.btDiscreteDynamicsWorld(dispatcher, overlappingPairCache, solver, collisionConfiguration);
dynamicsWorld.setGravity(new Ammo.btVector3(0, -10, 0));
var groundShape = new Ammo.btBoxShape(new Ammo.btVector3(50, 50, 50));
var bodies = [];
var groundTransform = new Ammo.btTransform();
groundTransform.setIdentity();
groundTransform.setOrigin(new Ammo.btVector3(0, -56, 0));
(function() {
var mass = 0;
var localInertia = new Ammo.btVector3(0, 0, 0);
var myMotionState = new Ammo.btDefaultMotionState(groundTransform);
var rbInfo = new Ammo.btRigidBodyConstructionInfo(0, myMotionState, groundShape, localInertia);
var body = new Ammo.btRigidBody(rbInfo);
dynamicsWorld.addRigidBody(body);
bodies.push(body);
})();
var boxShape = new Ammo.btBoxShape(new Ammo.btVector3(1, 1, 1));
function resetPositions() {
var side = Math.ceil(Math.pow(NUM, 1/3));
var i = 1;
for (var x = 0; x < side; x++) {
for (var y = 0; y < side; y++) {
for (var z = 0; z < side; z++) {
if (i == bodies.length) break;
var body = bodies[i++];
var origin = body.getWorldTransform().getOrigin();
origin.setX((x - side/2)*(2.2 + Math.random()));
origin.setY(y * (3 + Math.random()));
origin.setZ((z - side/2)*(2.2 + Math.random()) - side - 3);
body.activate();
var rotation = body.getWorldTransform().getRotation();
rotation.setX(1);
rotation.setY(0);
rotation.setZ(0);
rotation.setW(1);
}
}
}
}
function startUp() {
NUMRANGE.forEach(function(i) {
var startTransform = new Ammo.btTransform();
startTransform.setIdentity();
var mass = 1;
var localInertia = new Ammo.btVector3(0, 0, 0);
boxShape.calculateLocalInertia(mass, localInertia);
var myMotionState = new Ammo.btDefaultMotionState(startTransform);
var rbInfo = new Ammo.btRigidBodyConstructionInfo(mass, myMotionState, boxShape, localInertia);
var body = new Ammo.btRigidBody(rbInfo);
dynamicsWorld.addRigidBody(body);
bodies.push(body);
});
resetPositions();
}
var transform = new Ammo.btTransform(); // taking this out of readBulletObject reduces the leaking
function readBulletObject(i, object) {
var body = bodies[i];
body.getMotionState().getWorldTransform(transform);
var origin = transform.getOrigin();
object[0] = origin.x();
object[1] = origin.y();
object[2] = origin.z();
var rotation = transform.getRotation();
object[3] = rotation.x();
object[4] = rotation.y();
object[5] = rotation.z();
object[6] = rotation.w();
}
var nextTimeToRestart = 0;
function timeToRestart() { // restart if at least one is inactive - the scene is starting to get boring
if (nextTimeToRestart) {
if (Date.now() >= nextTimeToRestart) {
nextTimeToRestart = 0;
return true;
}
return false;
}
for (var i = 1; i <= NUM; i++) {
var body = bodies[i];
if (!body.isActive()) {
nextTimeToRestart = Date.now() + 1000; // add another second after first is inactive
break;
}
}
return false;
}
var meanDt = 0, meanDt2 = 0, frame = 1;
function simulate(dt) {
dt = dt || 1;
dynamicsWorld.stepSimulation(dt, 2);
var alpha;
if (meanDt > 0) {
alpha = Math.min(0.1, dt/1000);
} else {
alpha = 0.1; // first run
}
meanDt = alpha*dt + (1-alpha)*meanDt;
var alpha2 = 1/frame++;
meanDt2 = alpha2*dt + (1-alpha2)*meanDt2;
var data = { objects: [], currFPS: Math.round(1000/meanDt), allFPS: Math.round(1000/meanDt2) };
// Read bullet data into JS objects
for (var i = 0; i < NUM; i++) {
var object = [];
readBulletObject(i+1, object);
data.objects[i] = object;
}
postMessage(data);
if (timeToRestart()) resetPositions();
}
var interval = null;
onmessage = function(event) {
NUM = event.data;
NUMRANGE.length = 0;
while (NUMRANGE.length < NUM) NUMRANGE.push(NUMRANGE.length+1);
frame = 1;
meanDt = meanDt2 = 0;
startUp();
var last = Date.now();
function mainLoop() {
var now = Date.now();
simulate(now - last);
last = now;
}
if (interval) clearInterval(interval);
interval = setInterval(mainLoop, 1000/60);
}
postMessage({isReady: true});
});