physics_body.ts 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. ///if arm_physics
  2. type physics_body_t = {
  3. _mass?: f32;
  4. object?: object_t;
  5. friction?: f32;
  6. restitution?: f32;
  7. collision_margin?: f32;
  8. linear_damping?: f32;
  9. angular_damping?: f32;
  10. linear_factors?: f32[];
  11. angular_factors?: f32[];
  12. linear_threshold?: f32;
  13. angular_threshold?: f32;
  14. ccd?: bool; // Continuous collision detection
  15. trigger?: bool;
  16. group?: i32;
  17. mask?: i32;
  18. shape?: shape_type_t;
  19. destroyed?: bool;
  20. body_scale_x?: f32; // Transform scale at creation time
  21. body_scale_y?: f32;
  22. body_scale_z?: f32;
  23. current_scale_x?: f32;
  24. current_scale_y?: f32;
  25. current_scale_z?: f32;
  26. body?: Ammo.btRigidBody;
  27. motion_state?: Ammo.btMotionState;
  28. btshape?: Ammo.btCollisionShape;
  29. ready?: bool;
  30. id?: i32;
  31. height_data?: u8_array_t;
  32. };
  33. let physics_body_next_id: i32 = 0;
  34. let physics_body_ammo_array: i32 = -1;
  35. let physics_body_gimpact_registered: bool = false;
  36. let physics_body_first: bool = true;
  37. let physics_body_vec1: Ammo.btVector3;
  38. let physics_body_vec2: Ammo.btVector3;
  39. let physics_body_vec3: Ammo.btVector3;
  40. let physics_body_quat1: Ammo.btQuaternion;
  41. let physics_body_trans1: Ammo.btTransform;
  42. let physics_body_trans2: Ammo.btTransform;
  43. let physics_body_quat: quat_t = quat_create();
  44. let physics_body_convex_hull_cache: map_t<mesh_data_t, Ammo.btConvexHullShape> = map_create();
  45. let physics_body_triangle_mesh_cache: map_t<mesh_data_t, Ammo.btTriangleMesh> = map_create();
  46. let physics_body_users_cache: map_t<mesh_data_t, i32> = map_create();
  47. let physics_body_object_map: map_t<object_t, physics_body_t> = map_create();
  48. function physics_body_create(): physics_body_t {
  49. if (physics_body_first) {
  50. physics_body_first = false;
  51. physics_body_vec1 = new Ammo.btVector3(0, 0, 0);
  52. physics_body_vec2 = new Ammo.btVector3(0, 0, 0);
  53. physics_body_vec3 = new Ammo.btVector3(0, 0, 0);
  54. physics_body_quat1 = new Ammo.btQuaternion(0, 0, 0, 0);
  55. physics_body_trans1 = new Ammo.btTransform();
  56. physics_body_trans2 = new Ammo.btTransform();
  57. }
  58. let pb: physics_body_t = {};
  59. pb._mass = 0.0;
  60. pb.friction = 0.5;
  61. pb.restitution = 0.0;
  62. pb.collision_margin = 0.0;
  63. pb.linear_damping = 0.04;
  64. pb.angular_damping = 0.1;
  65. pb.linear_factors = [1.0, 1.0, 1.0];
  66. pb.angular_factors = [1.0, 1.0, 1.0];
  67. pb.linear_threshold = 0.0;
  68. pb.angular_threshold = 0.0;
  69. pb.ccd = false;
  70. pb.trigger = false;
  71. pb.group = 1;
  72. pb.mask = 1;
  73. pb.shape = shape_type_t.BOX;
  74. pb.destroyed = false;
  75. pb.ready = false;
  76. pb.id = 0;
  77. return pb;
  78. }
  79. function physics_body_get_mass(pb: physics_body_t): f32 {
  80. return pb._mass;
  81. }
  82. function physics_body_set_mass(pb: physics_body_t, f: f32) {
  83. if (pb.ready) {
  84. // remove();
  85. let t: physics_body_t = physics_body_create();
  86. t._mass = f;
  87. physics_body_init(t, pb.object);
  88. map_set(physics_body_object_map, pb.object, t);
  89. }
  90. else {
  91. pb._mass = f;
  92. }
  93. }
  94. function physics_body_with_margin(pb: physics_body_t, f: f32) {
  95. return f - f * pb.collision_margin;
  96. }
  97. function physics_body_init(pb: physics_body_t, o: object_t) {
  98. pb.object = o;
  99. if (pb.ready) {
  100. return;
  101. }
  102. pb.ready = true;
  103. if (pb.object.ext_type != "mesh_object_t") {
  104. return; // No mesh data
  105. }
  106. let transform: transform_t = o.transform;
  107. let physics: physics_world_t = physics_world_active;
  108. if (pb.shape == shape_type_t.BOX) {
  109. physics_world_vec1.setX(physics_body_with_margin(pb, transform.dim.x / 2));
  110. physics_world_vec1.setY(physics_body_with_margin(pb, transform.dim.y / 2));
  111. physics_world_vec1.setZ(physics_body_with_margin(pb, transform.dim.z / 2));
  112. pb.btshape = new Ammo.btBoxShape(physics_world_vec1);
  113. }
  114. else if (pb.shape == shape_type_t.SPHERE) {
  115. pb.btshape = new Ammo.btSphereShape(physics_body_with_margin(pb, transform.dim.x / 2));
  116. }
  117. else if (pb.shape == shape_type_t.CONVEX_HULL) {
  118. let shape_convex: Ammo.btConvexHullShape = physics_body_fill_convex_hull(pb, transform.scale, pb.collision_margin);
  119. pb.btshape = shape_convex;
  120. }
  121. else if (pb.shape == shape_type_t.CONE) {
  122. let cone_z: Ammo.btConeShapeZ = new Ammo.btConeShapeZ(
  123. physics_body_with_margin(pb, transform.dim.x / 2), // Radius
  124. physics_body_with_margin(pb, transform.dim.z)); // Height
  125. let cone: Ammo.btConeShape = cone_z;
  126. pb.btshape = cone;
  127. }
  128. else if (pb.shape == shape_type_t.CYLINDER) {
  129. physics_world_vec1.setX(physics_body_with_margin(pb, transform.dim.x / 2));
  130. physics_world_vec1.setY(physics_body_with_margin(pb, transform.dim.y / 2));
  131. physics_world_vec1.setZ(physics_body_with_margin(pb, transform.dim.z / 2));
  132. let cyl_z: Ammo.btCylinderShapeZ = new Ammo.btCylinderShapeZ(physics_world_vec1);
  133. let cyl: Ammo.btCylinderShape = cyl_z;
  134. pb.btshape = cyl;
  135. }
  136. else if (pb.shape == shape_type_t.CAPSULE) {
  137. let r: f32 = transform.dim.x / 2;
  138. let caps_z: Ammo.btCapsuleShapeZ = new Ammo.btCapsuleShapeZ(
  139. physics_body_with_margin(pb, r), // Radius
  140. physics_body_with_margin(pb, transform.dim.z - r * 2)); // Distance between 2 sphere centers
  141. let caps: Ammo.btCapsuleShape = caps_z;
  142. pb.btshape = caps;
  143. }
  144. else if (pb.shape == shape_type_t.MESH) {
  145. let mesh_interface: Ammo.btTriangleMesh = physics_body_fill_triangle_mesh(pb, transform.scale);
  146. if (physics_body_get_mass(pb) > 0) {
  147. let shape_gimpact: Ammo.btGImpactMeshShape = new Ammo.btGImpactMeshShape(mesh_interface);
  148. shape_gimpact.updateBound();
  149. let shape_concave: Ammo.btConcaveShape = shape_gimpact;
  150. pb.btshape = shape_concave;
  151. if (!physics_body_gimpact_registered) {
  152. physics_body_gimpact_registered = true;
  153. new Ammo.GImpactCollisionAlgorithm().registerAlgorithm(physics.dispatcher);
  154. }
  155. }
  156. else {
  157. let shape_bvh: Ammo.btBvhTriangleMeshShape = new Ammo.btBvhTriangleMeshShape(mesh_interface, true, true);
  158. let shape_tri: Ammo.btTriangleMeshShape = shape_bvh;
  159. let shape_concave: Ammo.btConcaveShape = shape_tri;
  160. pb.btshape = shape_concave;
  161. }
  162. }
  163. else if (pb.shape == shape_type_t.TERRAIN) {
  164. let length: i32 = pb.height_data.length;
  165. if (physics_body_ammo_array == -1) {
  166. physics_body_ammo_array = Ammo._malloc(length);
  167. }
  168. // From texture bytes
  169. for (let i: i32 = 0; i < length; ++i) {
  170. Ammo.HEAPU8[physics_body_ammo_array + i] = pb.height_data[i];
  171. }
  172. let slice: i32 = math_floor(math_sqrt(length)); // Assuming square terrain data
  173. let axis: i32 = 2; // z
  174. let data_type: i32 = 5; // u8
  175. pb.btshape = new Ammo.btHeightfieldTerrainShape(slice, slice, physics_body_ammo_array, 1 / 255, 0, 1, axis, data_type, false);
  176. physics_body_vec1.setX(transform.dim.x / slice);
  177. physics_body_vec1.setY(transform.dim.y / slice);
  178. physics_body_vec1.setZ(transform.dim.z);
  179. pb.btshape.setLocalScaling(physics_body_vec1);
  180. }
  181. physics_body_trans1.setIdentity();
  182. physics_body_vec1.setX(transform_world_x(transform));
  183. physics_body_vec1.setY(transform_world_y(transform));
  184. physics_body_vec1.setZ(transform_world_z(transform));
  185. physics_body_trans1.setOrigin(physics_body_vec1);
  186. quat_from_mat(physics_body_quat, transform.world);
  187. physics_body_quat1.setValue(physics_body_quat.x, physics_body_quat.y, physics_body_quat.z, physics_body_quat.w);
  188. physics_body_trans1.setRotation(physics_body_quat1);
  189. physics_body_trans2.setIdentity();
  190. pb.motion_state = new Ammo.btDefaultMotionState(physics_body_trans1, physics_body_trans2); // Transform, center of mass offset
  191. physics_body_vec1.setX(0);
  192. physics_body_vec1.setY(0);
  193. physics_body_vec1.setZ(0);
  194. let inertia: Ammo.btVector3 = physics_body_vec1;
  195. if (physics_body_get_mass(pb) > 0) {
  196. pb.btshape.calculateLocalInertia(physics_body_get_mass(pb), inertia);
  197. }
  198. let body_ci: Ammo.btRigidBodyConstructionInfo = new Ammo.btRigidBodyConstructionInfo(physics_body_get_mass(pb), pb.motion_state, pb.btshape, inertia);
  199. pb.body = new Ammo.btRigidBody(body_ci);
  200. pb.body.setFriction(pb.friction);
  201. if (pb.shape == shape_type_t.SPHERE || pb.shape == shape_type_t.CYLINDER || pb.shape == shape_type_t.CONE || pb.shape == shape_type_t.CAPSULE) {
  202. pb.angular_damping += pb.friction;
  203. }
  204. pb.body.setRestitution(pb.restitution);
  205. // pb.body.setSleepingThresholds(linearThreshold, angularThreshold);
  206. // pb.body.setDeactivationTime(deactivationTime);
  207. pb.body.setDamping(pb.linear_damping, pb.angular_damping);
  208. physics_body_set_linear_factor(pb, pb.linear_factors[0], pb.linear_factors[1], pb.linear_factors[2]);
  209. physics_body_set_angular_factor(pb, pb.angular_factors[0], pb.angular_factors[1], pb.angular_factors[2]);
  210. if (pb.trigger) {
  211. pb.body.setCollisionFlags(pb.body.getCollisionFlags() | collision_flags_t.CF_NO_CONTACT_RESPONSE);
  212. }
  213. if (physics_body_get_mass(pb) == 0.0) {
  214. pb.body.setCollisionFlags(pb.body.getCollisionFlags() | collision_flags_t.CF_STATIC_OBJECT);
  215. }
  216. if (pb.ccd) {
  217. physics_body_set_ccd(pb, transform.radius);
  218. }
  219. pb.body_scale_x = pb.current_scale_x = transform.scale.x;
  220. pb.body_scale_y = pb.current_scale_y = transform.scale.y;
  221. pb.body_scale_z = pb.current_scale_z = transform.scale.z;
  222. pb.id = physics_body_next_id++;
  223. pb.body.userIndex = pb.id;
  224. physics_world_add_body(physics, pb);
  225. // notifyOnRemove(removeFromWorld);
  226. Ammo.destroy(body_ci);
  227. }
  228. function physics_body_physics_update(pb: physics_body_t) {
  229. if (!pb.ready) {
  230. return;
  231. }
  232. let trans: Ammo.btTransform = pb.body.getWorldTransform();
  233. let p: Ammo.btVector3 = trans.getOrigin();
  234. let q: Ammo.btQuaternion = trans.getRotation();
  235. let qw: Ammo.btQuadWord = q;
  236. let transform: transform_t = pb.object.transform;
  237. vec4_set(transform.loc, p.x(), p.y(), p.z());
  238. quat_set(transform.rot, qw.x(), qw.y(), qw.z(), qw.w());
  239. if (pb.object.parent != null) {
  240. let ptransform: transform_t = pb.object.parent.transform;
  241. transform.loc.x -= transform_world_x(ptransform);
  242. transform.loc.y -= transform_world_y(ptransform);
  243. transform.loc.z -= transform_world_z(ptransform);
  244. }
  245. transform_build_matrix(transform);
  246. }
  247. function physics_body_remove_from_world(pb: physics_body_t) {
  248. physics_world_remove_body(physics_world_active, pb);
  249. }
  250. function physics_body_activate(pb: physics_body_t) {
  251. pb.body.activate(false);
  252. }
  253. function physics_body_set_gravity(pb: physics_body_t, v: vec4_t) {
  254. physics_body_vec1.setValue(v.x, v.y, v.z);
  255. pb.body.setGravity(physics_body_vec1);
  256. }
  257. function physics_body_apply_force(pb: physics_body_t, force: vec4_t, loc: vec4_t = null) {
  258. physics_body_activate(pb);
  259. physics_body_vec1.setValue(force.x, force.y, force.z);
  260. if (loc == null) {
  261. pb.body.applyCentralForce(physics_body_vec1);
  262. }
  263. else {
  264. physics_body_vec2.setValue(loc.x, loc.y, loc.z);
  265. pb.body.applyForce(physics_body_vec1, physics_body_vec2);
  266. }
  267. }
  268. function physics_body_apply_impulse(pb: physics_body_t, impulse: vec4_t, loc: vec4_t = null) {
  269. physics_body_activate(pb);
  270. physics_body_vec1.setValue(impulse.x, impulse.y, impulse.z);
  271. if (loc == null) {
  272. pb.body.applyCentralImpulse(physics_body_vec1);
  273. }
  274. else {
  275. physics_body_vec2.setValue(loc.x, loc.y, loc.z);
  276. pb.body.applyImpulse(physics_body_vec1, physics_body_vec2);
  277. }
  278. }
  279. function physics_body_apply_torque(pb: physics_body_t, torque: vec4_t) {
  280. physics_body_activate(pb);
  281. physics_body_vec1.setValue(torque.x, torque.y, torque.z);
  282. pb.body.applyTorque(physics_body_vec1);
  283. }
  284. function physics_body_apply_torque_impulse(pb: physics_body_t, torque: vec4_t) {
  285. physics_body_activate(pb);
  286. physics_body_vec1.setValue(torque.x, torque.y, torque.z);
  287. pb.body.applyTorqueImpulse(physics_body_vec1);
  288. }
  289. function physics_body_set_linear_factor(pb: physics_body_t, x: f32, y: f32, z: f32) {
  290. physics_body_vec1.setValue(x, y, z);
  291. pb.body.setLinearFactor(physics_body_vec1);
  292. }
  293. function physics_body_set_angular_factor(pb: physics_body_t, x: f32, y: f32, z: f32) {
  294. physics_body_vec1.setValue(x, y, z);
  295. pb.body.setAngularFactor(physics_body_vec1);
  296. }
  297. function physics_body_get_linear_velocity(pb: physics_body_t): vec4_t {
  298. let v: Ammo.btVector3 = pb.body.getLinearVelocity();
  299. return vec4_create(v.x(), v.y(), v.z());
  300. }
  301. function physics_body_set_linear_velocity(pb: physics_body_t, x: f32, y: f32, z: f32) {
  302. physics_body_vec1.setValue(x, y, z);
  303. pb.body.setLinearVelocity(physics_body_vec1);
  304. }
  305. function physics_body_get_angular_velocity(pb: physics_body_t): vec4_t {
  306. let v: Ammo.btVector3 = pb.body.getAngularVelocity();
  307. return vec4_create(v.x(), v.y(), v.z());
  308. }
  309. function physics_body_set_angular_velocity(pb: physics_body_t, x: f32, y: f32, z: f32) {
  310. physics_body_vec1.setValue(x, y, z);
  311. pb.body.setAngularVelocity(physics_body_vec1);
  312. }
  313. function physics_body_set_friction(pb: physics_body_t, f: f32) {
  314. pb.body.setFriction(f);
  315. pb.friction = f;
  316. }
  317. function physics_body_set_scale(pb: physics_body_t, v: vec4_t) {
  318. pb.current_scale_x = v.x;
  319. pb.current_scale_y = v.y;
  320. pb.current_scale_z = v.z;
  321. physics_body_vec1.setX(v.x / pb.body_scale_x);
  322. physics_body_vec1.setY(v.y / pb.body_scale_y);
  323. physics_body_vec1.setZ(v.z / pb.body_scale_z);
  324. pb.btshape.setLocalScaling(physics_body_vec1);
  325. let world_dyn: Ammo.btDynamicsWorld = physics_world_active.world;
  326. let world_col: Ammo.btCollisionWorld = world_dyn;
  327. world_col.updateSingleAabb(pb.body);
  328. }
  329. function physics_body_sync_transform(pb: physics_body_t) {
  330. let t: transform_t = pb.object.transform;
  331. transform_build_matrix(t);
  332. physics_body_vec1.setValue(transform_world_x(t), transform_world_y(t), transform_world_z(t));
  333. physics_body_trans1.setOrigin(physics_body_vec1);
  334. quat_from_mat(physics_body_quat, t.world);
  335. physics_body_quat1.setValue(physics_body_quat.x, physics_body_quat.y, physics_body_quat.z, physics_body_quat.w);
  336. physics_body_trans1.setRotation(physics_body_quat1);
  337. pb.body.setWorldTransform(physics_body_trans1);
  338. if (pb.current_scale_x != t.scale.x || pb.current_scale_y != t.scale.y || pb.current_scale_z != t.scale.z) {
  339. physics_body_set_scale(pb, t.scale);
  340. }
  341. physics_body_activate(pb);
  342. }
  343. function physics_body_set_ccd(pb: physics_body_t, sphereRadius: f32, motionThreshold = 1e-7) {
  344. pb.body.setCcdSweptSphereRadius(sphereRadius);
  345. pb.body.setCcdMotionThreshold(motionThreshold);
  346. }
  347. function physics_body_fill_convex_hull(pb: physics_body_t, scale: vec4_t, margin: f32): Ammo.btConvexHullShape {
  348. // Check whether shape already exists
  349. let data: any = pb.object.ext.data;
  350. let shape: Ammo.btConvexHullShape = map_get(physics_body_convex_hull_cache, data);
  351. if (shape != null) {
  352. map_set(physics_body_users_cache, data, map_get(physics_body_users_cache, data) + 1);
  353. return shape;
  354. }
  355. shape = new Ammo.btConvexHullShape();
  356. map_set(physics_body_convex_hull_cache, data, shape);
  357. map_set(physics_body_users_cache, data, 1);
  358. let positions: i16_array_t = mesh_data_get_vertex_array(data, "pos").values;
  359. let sx: f32 = scale.x * (1.0 - margin) * (1 / 32767);
  360. let sy: f32 = scale.y * (1.0 - margin) * (1 / 32767);
  361. let sz: f32 = scale.z * (1.0 - margin) * (1 / 32767);
  362. sx *= data.scale_pos;
  363. sy *= data.scale_pos;
  364. sz *= data.scale_pos;
  365. for (let i: i32 = 0; i < math_floor(positions.length / 4); ++i) {
  366. physics_body_vec1.setX(positions[i * 4 ] * sx);
  367. physics_body_vec1.setY(positions[i * 4 + 1] * sy);
  368. physics_body_vec1.setZ(positions[i * 4 + 2] * sz);
  369. shape.addPoint(physics_body_vec1, true);
  370. }
  371. return shape;
  372. }
  373. function physics_body_fill_triangle_mesh(pb: physics_body_t, scale: vec4_t): Ammo.btTriangleMesh {
  374. // Check whether shape already exists
  375. let data: any = pb.object.ext.data;
  376. let triangle_mesh: Ammo.btTriangleMesh = map_get(physics_body_triangle_mesh_cache, data);
  377. if (triangle_mesh != null) {
  378. map_set(physics_body_users_cache, data, map_get(physics_body_users_cache, data) + 1);
  379. return triangle_mesh;
  380. }
  381. triangle_mesh = new Ammo.btTriangleMesh(true, true);
  382. map_set(physics_body_triangle_mesh_cache, data, triangle_mesh);
  383. map_set(physics_body_users_cache, data, 1);
  384. let positions: i16_array_t = mesh_data_get_vertex_array(data, "pos").values;
  385. let indices: any = data._indices;
  386. let sx: f32 = scale.x * (1 / 32767);
  387. let sy: f32 = scale.y * (1 / 32767);
  388. let sz: f32 = scale.z * (1 / 32767);
  389. sx *= data.scale_pos;
  390. sy *= data.scale_pos;
  391. sz *= data.scale_pos;
  392. for (let i: i32 = 0; i < indices.length; ++i) {
  393. let ar: any = indices[i];
  394. for (let i: i32 = 0; i < math_floor(ar.length / 3); ++i) {
  395. physics_body_vec1.setX(positions[ar[i * 3 ] * 4 ] * sx);
  396. physics_body_vec1.setY(positions[ar[i * 3 ] * 4 + 1] * sy);
  397. physics_body_vec1.setZ(positions[ar[i * 3 ] * 4 + 2] * sz);
  398. physics_body_vec2.setX(positions[ar[i * 3 + 1] * 4 ] * sx);
  399. physics_body_vec2.setY(positions[ar[i * 3 + 1] * 4 + 1] * sy);
  400. physics_body_vec2.setZ(positions[ar[i * 3 + 1] * 4 + 2] * sz);
  401. physics_body_vec3.setX(positions[ar[i * 3 + 2] * 4 ] * sx);
  402. physics_body_vec3.setY(positions[ar[i * 3 + 2] * 4 + 1] * sy);
  403. physics_body_vec3.setZ(positions[ar[i * 3 + 2] * 4 + 2] * sz);
  404. triangle_mesh.addTriangle(physics_body_vec1, physics_body_vec2, physics_body_vec3);
  405. }
  406. }
  407. return triangle_mesh;
  408. }
  409. function physics_body_delete(pb: physics_body_t) {
  410. Ammo.destroy(pb.motion_state);
  411. Ammo.destroy(pb.body);
  412. // Delete shape if no other user is found
  413. if (pb.shape == shape_type_t.CONVEX_HULL || pb.shape == shape_type_t.MESH) {
  414. let data: any = pb.object.ext.data;
  415. let i: i32 = map_get(physics_body_users_cache, data) - 1;
  416. map_set(physics_body_users_cache, data, i);
  417. if (i <= 0) {
  418. Ammo.destroy(pb.btshape);
  419. pb.shape == shape_type_t.CONVEX_HULL ?
  420. map_delete(physics_body_convex_hull_cache, data) :
  421. map_delete(physics_body_triangle_mesh_cache, data);
  422. }
  423. }
  424. else Ammo.destroy(pb.btshape);
  425. }
  426. enum shape_type_t {
  427. BOX,
  428. SPHERE,
  429. CONVEX_HULL,
  430. MESH,
  431. CONE,
  432. CYLINDER,
  433. CAPSULE,
  434. TERRAIN,
  435. }
  436. enum collision_flags_t {
  437. CF_STATIC_OBJECT = 1,
  438. CF_KINEMATIC_OBJECT = 2,
  439. CF_NO_CONTACT_RESPONSE = 4,
  440. CF_CHARACTER_OBJECT = 16,
  441. }
  442. ///end