| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499 |
- ///if arm_physics
- type physics_body_t = {
- _mass?: f32;
- object?: object_t;
- friction?: f32;
- restitution?: f32;
- collision_margin?: f32;
- linear_damping?: f32;
- angular_damping?: f32;
- linear_factors?: f32[];
- angular_factors?: f32[];
- linear_threshold?: f32;
- angular_threshold?: f32;
- ccd?: bool; // Continuous collision detection
- trigger?: bool;
- group?: i32;
- mask?: i32;
- shape?: shape_type_t;
- destroyed?: bool;
- body_scale_x?: f32; // Transform scale at creation time
- body_scale_y?: f32;
- body_scale_z?: f32;
- current_scale_x?: f32;
- current_scale_y?: f32;
- current_scale_z?: f32;
- body?: Ammo.btRigidBody;
- motion_state?: Ammo.btMotionState;
- btshape?: Ammo.btCollisionShape;
- ready?: bool;
- id?: i32;
- height_data?: u8_array_t;
- };
- let physics_body_next_id: i32 = 0;
- let physics_body_ammo_array: i32 = -1;
- let physics_body_gimpact_registered: bool = false;
- let physics_body_first: bool = true;
- let physics_body_vec1: Ammo.btVector3;
- let physics_body_vec2: Ammo.btVector3;
- let physics_body_vec3: Ammo.btVector3;
- let physics_body_quat1: Ammo.btQuaternion;
- let physics_body_trans1: Ammo.btTransform;
- let physics_body_trans2: Ammo.btTransform;
- let physics_body_quat: quat_t = quat_create();
- let physics_body_convex_hull_cache: map_t<mesh_data_t, Ammo.btConvexHullShape> = map_create();
- let physics_body_triangle_mesh_cache: map_t<mesh_data_t, Ammo.btTriangleMesh> = map_create();
- let physics_body_users_cache: map_t<mesh_data_t, i32> = map_create();
- let physics_body_object_map: map_t<object_t, physics_body_t> = map_create();
- function physics_body_create(): physics_body_t {
- if (physics_body_first) {
- physics_body_first = false;
- physics_body_vec1 = new Ammo.btVector3(0, 0, 0);
- physics_body_vec2 = new Ammo.btVector3(0, 0, 0);
- physics_body_vec3 = new Ammo.btVector3(0, 0, 0);
- physics_body_quat1 = new Ammo.btQuaternion(0, 0, 0, 0);
- physics_body_trans1 = new Ammo.btTransform();
- physics_body_trans2 = new Ammo.btTransform();
- }
- let pb: physics_body_t = {};
- pb._mass = 0.0;
- pb.friction = 0.5;
- pb.restitution = 0.0;
- pb.collision_margin = 0.0;
- pb.linear_damping = 0.04;
- pb.angular_damping = 0.1;
- pb.linear_factors = [1.0, 1.0, 1.0];
- pb.angular_factors = [1.0, 1.0, 1.0];
- pb.linear_threshold = 0.0;
- pb.angular_threshold = 0.0;
- pb.ccd = false;
- pb.trigger = false;
- pb.group = 1;
- pb.mask = 1;
- pb.shape = shape_type_t.BOX;
- pb.destroyed = false;
- pb.ready = false;
- pb.id = 0;
- return pb;
- }
- function physics_body_get_mass(pb: physics_body_t): f32 {
- return pb._mass;
- }
- function physics_body_set_mass(pb: physics_body_t, f: f32) {
- if (pb.ready) {
- // remove();
- let t: physics_body_t = physics_body_create();
- t._mass = f;
- physics_body_init(t, pb.object);
- map_set(physics_body_object_map, pb.object, t);
- }
- else {
- pb._mass = f;
- }
- }
- function physics_body_with_margin(pb: physics_body_t, f: f32) {
- return f - f * pb.collision_margin;
- }
- function physics_body_init(pb: physics_body_t, o: object_t) {
- pb.object = o;
- if (pb.ready) {
- return;
- }
- pb.ready = true;
- if (pb.object.ext_type != "mesh_object_t") {
- return; // No mesh data
- }
- let transform: transform_t = o.transform;
- let physics: physics_world_t = physics_world_active;
- if (pb.shape == shape_type_t.BOX) {
- physics_world_vec1.setX(physics_body_with_margin(pb, transform.dim.x / 2));
- physics_world_vec1.setY(physics_body_with_margin(pb, transform.dim.y / 2));
- physics_world_vec1.setZ(physics_body_with_margin(pb, transform.dim.z / 2));
- pb.btshape = new Ammo.btBoxShape(physics_world_vec1);
- }
- else if (pb.shape == shape_type_t.SPHERE) {
- pb.btshape = new Ammo.btSphereShape(physics_body_with_margin(pb, transform.dim.x / 2));
- }
- else if (pb.shape == shape_type_t.CONVEX_HULL) {
- let shape_convex: Ammo.btConvexHullShape = physics_body_fill_convex_hull(pb, transform.scale, pb.collision_margin);
- pb.btshape = shape_convex;
- }
- else if (pb.shape == shape_type_t.CONE) {
- let cone_z: Ammo.btConeShapeZ = new Ammo.btConeShapeZ(
- physics_body_with_margin(pb, transform.dim.x / 2), // Radius
- physics_body_with_margin(pb, transform.dim.z)); // Height
- let cone: Ammo.btConeShape = cone_z;
- pb.btshape = cone;
- }
- else if (pb.shape == shape_type_t.CYLINDER) {
- physics_world_vec1.setX(physics_body_with_margin(pb, transform.dim.x / 2));
- physics_world_vec1.setY(physics_body_with_margin(pb, transform.dim.y / 2));
- physics_world_vec1.setZ(physics_body_with_margin(pb, transform.dim.z / 2));
- let cyl_z: Ammo.btCylinderShapeZ = new Ammo.btCylinderShapeZ(physics_world_vec1);
- let cyl: Ammo.btCylinderShape = cyl_z;
- pb.btshape = cyl;
- }
- else if (pb.shape == shape_type_t.CAPSULE) {
- let r: f32 = transform.dim.x / 2;
- let caps_z: Ammo.btCapsuleShapeZ = new Ammo.btCapsuleShapeZ(
- physics_body_with_margin(pb, r), // Radius
- physics_body_with_margin(pb, transform.dim.z - r * 2)); // Distance between 2 sphere centers
- let caps: Ammo.btCapsuleShape = caps_z;
- pb.btshape = caps;
- }
- else if (pb.shape == shape_type_t.MESH) {
- let mesh_interface: Ammo.btTriangleMesh = physics_body_fill_triangle_mesh(pb, transform.scale);
- if (physics_body_get_mass(pb) > 0) {
- let shape_gimpact: Ammo.btGImpactMeshShape = new Ammo.btGImpactMeshShape(mesh_interface);
- shape_gimpact.updateBound();
- let shape_concave: Ammo.btConcaveShape = shape_gimpact;
- pb.btshape = shape_concave;
- if (!physics_body_gimpact_registered) {
- physics_body_gimpact_registered = true;
- new Ammo.GImpactCollisionAlgorithm().registerAlgorithm(physics.dispatcher);
- }
- }
- else {
- let shape_bvh: Ammo.btBvhTriangleMeshShape = new Ammo.btBvhTriangleMeshShape(mesh_interface, true, true);
- let shape_tri: Ammo.btTriangleMeshShape = shape_bvh;
- let shape_concave: Ammo.btConcaveShape = shape_tri;
- pb.btshape = shape_concave;
- }
- }
- else if (pb.shape == shape_type_t.TERRAIN) {
- let length: i32 = pb.height_data.length;
- if (physics_body_ammo_array == -1) {
- physics_body_ammo_array = Ammo._malloc(length);
- }
- // From texture bytes
- for (let i: i32 = 0; i < length; ++i) {
- Ammo.HEAPU8[physics_body_ammo_array + i] = pb.height_data[i];
- }
- let slice: i32 = math_floor(math_sqrt(length)); // Assuming square terrain data
- let axis: i32 = 2; // z
- let data_type: i32 = 5; // u8
- pb.btshape = new Ammo.btHeightfieldTerrainShape(slice, slice, physics_body_ammo_array, 1 / 255, 0, 1, axis, data_type, false);
- physics_body_vec1.setX(transform.dim.x / slice);
- physics_body_vec1.setY(transform.dim.y / slice);
- physics_body_vec1.setZ(transform.dim.z);
- pb.btshape.setLocalScaling(physics_body_vec1);
- }
- physics_body_trans1.setIdentity();
- physics_body_vec1.setX(transform_world_x(transform));
- physics_body_vec1.setY(transform_world_y(transform));
- physics_body_vec1.setZ(transform_world_z(transform));
- physics_body_trans1.setOrigin(physics_body_vec1);
- quat_from_mat(physics_body_quat, transform.world);
- physics_body_quat1.setValue(physics_body_quat.x, physics_body_quat.y, physics_body_quat.z, physics_body_quat.w);
- physics_body_trans1.setRotation(physics_body_quat1);
- physics_body_trans2.setIdentity();
- pb.motion_state = new Ammo.btDefaultMotionState(physics_body_trans1, physics_body_trans2); // Transform, center of mass offset
- physics_body_vec1.setX(0);
- physics_body_vec1.setY(0);
- physics_body_vec1.setZ(0);
- let inertia: Ammo.btVector3 = physics_body_vec1;
- if (physics_body_get_mass(pb) > 0) {
- pb.btshape.calculateLocalInertia(physics_body_get_mass(pb), inertia);
- }
- let body_ci: Ammo.btRigidBodyConstructionInfo = new Ammo.btRigidBodyConstructionInfo(physics_body_get_mass(pb), pb.motion_state, pb.btshape, inertia);
- pb.body = new Ammo.btRigidBody(body_ci);
- pb.body.setFriction(pb.friction);
- 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) {
- pb.angular_damping += pb.friction;
- }
- pb.body.setRestitution(pb.restitution);
- // pb.body.setSleepingThresholds(linearThreshold, angularThreshold);
- // pb.body.setDeactivationTime(deactivationTime);
- pb.body.setDamping(pb.linear_damping, pb.angular_damping);
- physics_body_set_linear_factor(pb, pb.linear_factors[0], pb.linear_factors[1], pb.linear_factors[2]);
- physics_body_set_angular_factor(pb, pb.angular_factors[0], pb.angular_factors[1], pb.angular_factors[2]);
- if (pb.trigger) {
- pb.body.setCollisionFlags(pb.body.getCollisionFlags() | collision_flags_t.CF_NO_CONTACT_RESPONSE);
- }
- if (physics_body_get_mass(pb) == 0.0) {
- pb.body.setCollisionFlags(pb.body.getCollisionFlags() | collision_flags_t.CF_STATIC_OBJECT);
- }
- if (pb.ccd) {
- physics_body_set_ccd(pb, transform.radius);
- }
- pb.body_scale_x = pb.current_scale_x = transform.scale.x;
- pb.body_scale_y = pb.current_scale_y = transform.scale.y;
- pb.body_scale_z = pb.current_scale_z = transform.scale.z;
- pb.id = physics_body_next_id++;
- pb.body.userIndex = pb.id;
- physics_world_add_body(physics, pb);
- // notifyOnRemove(removeFromWorld);
- Ammo.destroy(body_ci);
- }
- function physics_body_physics_update(pb: physics_body_t) {
- if (!pb.ready) {
- return;
- }
- let trans: Ammo.btTransform = pb.body.getWorldTransform();
- let p: Ammo.btVector3 = trans.getOrigin();
- let q: Ammo.btQuaternion = trans.getRotation();
- let qw: Ammo.btQuadWord = q;
- let transform: transform_t = pb.object.transform;
- vec4_set(transform.loc, p.x(), p.y(), p.z());
- quat_set(transform.rot, qw.x(), qw.y(), qw.z(), qw.w());
- if (pb.object.parent != null) {
- let ptransform: transform_t = pb.object.parent.transform;
- transform.loc.x -= transform_world_x(ptransform);
- transform.loc.y -= transform_world_y(ptransform);
- transform.loc.z -= transform_world_z(ptransform);
- }
- transform_build_matrix(transform);
- }
- function physics_body_remove_from_world(pb: physics_body_t) {
- physics_world_remove_body(physics_world_active, pb);
- }
- function physics_body_activate(pb: physics_body_t) {
- pb.body.activate(false);
- }
- function physics_body_set_gravity(pb: physics_body_t, v: vec4_t) {
- physics_body_vec1.setValue(v.x, v.y, v.z);
- pb.body.setGravity(physics_body_vec1);
- }
- function physics_body_apply_force(pb: physics_body_t, force: vec4_t, loc: vec4_t = null) {
- physics_body_activate(pb);
- physics_body_vec1.setValue(force.x, force.y, force.z);
- if (loc == null) {
- pb.body.applyCentralForce(physics_body_vec1);
- }
- else {
- physics_body_vec2.setValue(loc.x, loc.y, loc.z);
- pb.body.applyForce(physics_body_vec1, physics_body_vec2);
- }
- }
- function physics_body_apply_impulse(pb: physics_body_t, impulse: vec4_t, loc: vec4_t = null) {
- physics_body_activate(pb);
- physics_body_vec1.setValue(impulse.x, impulse.y, impulse.z);
- if (loc == null) {
- pb.body.applyCentralImpulse(physics_body_vec1);
- }
- else {
- physics_body_vec2.setValue(loc.x, loc.y, loc.z);
- pb.body.applyImpulse(physics_body_vec1, physics_body_vec2);
- }
- }
- function physics_body_apply_torque(pb: physics_body_t, torque: vec4_t) {
- physics_body_activate(pb);
- physics_body_vec1.setValue(torque.x, torque.y, torque.z);
- pb.body.applyTorque(physics_body_vec1);
- }
- function physics_body_apply_torque_impulse(pb: physics_body_t, torque: vec4_t) {
- physics_body_activate(pb);
- physics_body_vec1.setValue(torque.x, torque.y, torque.z);
- pb.body.applyTorqueImpulse(physics_body_vec1);
- }
- function physics_body_set_linear_factor(pb: physics_body_t, x: f32, y: f32, z: f32) {
- physics_body_vec1.setValue(x, y, z);
- pb.body.setLinearFactor(physics_body_vec1);
- }
- function physics_body_set_angular_factor(pb: physics_body_t, x: f32, y: f32, z: f32) {
- physics_body_vec1.setValue(x, y, z);
- pb.body.setAngularFactor(physics_body_vec1);
- }
- function physics_body_get_linear_velocity(pb: physics_body_t): vec4_t {
- let v: Ammo.btVector3 = pb.body.getLinearVelocity();
- return vec4_create(v.x(), v.y(), v.z());
- }
- function physics_body_set_linear_velocity(pb: physics_body_t, x: f32, y: f32, z: f32) {
- physics_body_vec1.setValue(x, y, z);
- pb.body.setLinearVelocity(physics_body_vec1);
- }
- function physics_body_get_angular_velocity(pb: physics_body_t): vec4_t {
- let v: Ammo.btVector3 = pb.body.getAngularVelocity();
- return vec4_create(v.x(), v.y(), v.z());
- }
- function physics_body_set_angular_velocity(pb: physics_body_t, x: f32, y: f32, z: f32) {
- physics_body_vec1.setValue(x, y, z);
- pb.body.setAngularVelocity(physics_body_vec1);
- }
- function physics_body_set_friction(pb: physics_body_t, f: f32) {
- pb.body.setFriction(f);
- pb.friction = f;
- }
- function physics_body_set_scale(pb: physics_body_t, v: vec4_t) {
- pb.current_scale_x = v.x;
- pb.current_scale_y = v.y;
- pb.current_scale_z = v.z;
- physics_body_vec1.setX(v.x / pb.body_scale_x);
- physics_body_vec1.setY(v.y / pb.body_scale_y);
- physics_body_vec1.setZ(v.z / pb.body_scale_z);
- pb.btshape.setLocalScaling(physics_body_vec1);
- let world_dyn: Ammo.btDynamicsWorld = physics_world_active.world;
- let world_col: Ammo.btCollisionWorld = world_dyn;
- world_col.updateSingleAabb(pb.body);
- }
- function physics_body_sync_transform(pb: physics_body_t) {
- let t: transform_t = pb.object.transform;
- transform_build_matrix(t);
- physics_body_vec1.setValue(transform_world_x(t), transform_world_y(t), transform_world_z(t));
- physics_body_trans1.setOrigin(physics_body_vec1);
- quat_from_mat(physics_body_quat, t.world);
- physics_body_quat1.setValue(physics_body_quat.x, physics_body_quat.y, physics_body_quat.z, physics_body_quat.w);
- physics_body_trans1.setRotation(physics_body_quat1);
- pb.body.setWorldTransform(physics_body_trans1);
- if (pb.current_scale_x != t.scale.x || pb.current_scale_y != t.scale.y || pb.current_scale_z != t.scale.z) {
- physics_body_set_scale(pb, t.scale);
- }
- physics_body_activate(pb);
- }
- function physics_body_set_ccd(pb: physics_body_t, sphereRadius: f32, motionThreshold = 1e-7) {
- pb.body.setCcdSweptSphereRadius(sphereRadius);
- pb.body.setCcdMotionThreshold(motionThreshold);
- }
- function physics_body_fill_convex_hull(pb: physics_body_t, scale: vec4_t, margin: f32): Ammo.btConvexHullShape {
- // Check whether shape already exists
- let data: any = pb.object.ext.data;
- let shape: Ammo.btConvexHullShape = map_get(physics_body_convex_hull_cache, data);
- if (shape != null) {
- map_set(physics_body_users_cache, data, map_get(physics_body_users_cache, data) + 1);
- return shape;
- }
- shape = new Ammo.btConvexHullShape();
- map_set(physics_body_convex_hull_cache, data, shape);
- map_set(physics_body_users_cache, data, 1);
- let positions: i16_array_t = mesh_data_get_vertex_array(data, "pos").values;
- let sx: f32 = scale.x * (1.0 - margin) * (1 / 32767);
- let sy: f32 = scale.y * (1.0 - margin) * (1 / 32767);
- let sz: f32 = scale.z * (1.0 - margin) * (1 / 32767);
- sx *= data.scale_pos;
- sy *= data.scale_pos;
- sz *= data.scale_pos;
- for (let i: i32 = 0; i < math_floor(positions.length / 4); ++i) {
- physics_body_vec1.setX(positions[i * 4 ] * sx);
- physics_body_vec1.setY(positions[i * 4 + 1] * sy);
- physics_body_vec1.setZ(positions[i * 4 + 2] * sz);
- shape.addPoint(physics_body_vec1, true);
- }
- return shape;
- }
- function physics_body_fill_triangle_mesh(pb: physics_body_t, scale: vec4_t): Ammo.btTriangleMesh {
- // Check whether shape already exists
- let data: any = pb.object.ext.data;
- let triangle_mesh: Ammo.btTriangleMesh = map_get(physics_body_triangle_mesh_cache, data);
- if (triangle_mesh != null) {
- map_set(physics_body_users_cache, data, map_get(physics_body_users_cache, data) + 1);
- return triangle_mesh;
- }
- triangle_mesh = new Ammo.btTriangleMesh(true, true);
- map_set(physics_body_triangle_mesh_cache, data, triangle_mesh);
- map_set(physics_body_users_cache, data, 1);
- let positions: i16_array_t = mesh_data_get_vertex_array(data, "pos").values;
- let indices: any = data._indices;
- let sx: f32 = scale.x * (1 / 32767);
- let sy: f32 = scale.y * (1 / 32767);
- let sz: f32 = scale.z * (1 / 32767);
- sx *= data.scale_pos;
- sy *= data.scale_pos;
- sz *= data.scale_pos;
- for (let i: i32 = 0; i < indices.length; ++i) {
- let ar: any = indices[i];
- for (let i: i32 = 0; i < math_floor(ar.length / 3); ++i) {
- physics_body_vec1.setX(positions[ar[i * 3 ] * 4 ] * sx);
- physics_body_vec1.setY(positions[ar[i * 3 ] * 4 + 1] * sy);
- physics_body_vec1.setZ(positions[ar[i * 3 ] * 4 + 2] * sz);
- physics_body_vec2.setX(positions[ar[i * 3 + 1] * 4 ] * sx);
- physics_body_vec2.setY(positions[ar[i * 3 + 1] * 4 + 1] * sy);
- physics_body_vec2.setZ(positions[ar[i * 3 + 1] * 4 + 2] * sz);
- physics_body_vec3.setX(positions[ar[i * 3 + 2] * 4 ] * sx);
- physics_body_vec3.setY(positions[ar[i * 3 + 2] * 4 + 1] * sy);
- physics_body_vec3.setZ(positions[ar[i * 3 + 2] * 4 + 2] * sz);
- triangle_mesh.addTriangle(physics_body_vec1, physics_body_vec2, physics_body_vec3);
- }
- }
- return triangle_mesh;
- }
- function physics_body_delete(pb: physics_body_t) {
- Ammo.destroy(pb.motion_state);
- Ammo.destroy(pb.body);
- // Delete shape if no other user is found
- if (pb.shape == shape_type_t.CONVEX_HULL || pb.shape == shape_type_t.MESH) {
- let data: any = pb.object.ext.data;
- let i: i32 = map_get(physics_body_users_cache, data) - 1;
- map_set(physics_body_users_cache, data, i);
- if (i <= 0) {
- Ammo.destroy(pb.btshape);
- pb.shape == shape_type_t.CONVEX_HULL ?
- map_delete(physics_body_convex_hull_cache, data) :
- map_delete(physics_body_triangle_mesh_cache, data);
- }
- }
- else Ammo.destroy(pb.btshape);
- }
- enum shape_type_t {
- BOX,
- SPHERE,
- CONVEX_HULL,
- MESH,
- CONE,
- CYLINDER,
- CAPSULE,
- TERRAIN,
- }
- enum collision_flags_t {
- CF_STATIC_OBJECT = 1,
- CF_KINEMATIC_OBJECT = 2,
- CF_NO_CONTACT_RESPONSE = 4,
- CF_CHARACTER_OBJECT = 16,
- }
- ///end
|