@@ -1125,3 +1125,299 @@ pub extern "C" fn bloom_commit_music(staging_handle: f64) -> f64 {
11251125pub extern "C" fn bloom_run_game ( _callback : extern "C" fn ( f64 ) ) {
11261126 // No-op on native. The TypeScript runGame() helper provides the while loop.
11271127}
1128+
1129+
1130+ // ============================================================
1131+ // Physics (Rapier 3D)
1132+ // ============================================================
1133+
1134+ #[ cfg( feature = "physics" ) ]
1135+ use bloom_shared:: physics:: PhysicsWorld ;
1136+
1137+ #[ cfg( feature = "physics" ) ]
1138+ fn physics ( ) -> & ' static mut PhysicsWorld {
1139+ engine ( ) . physics . as_mut ( ) . expect ( "Physics world not created. Call bloom_physics_create_world first." )
1140+ }
1141+
1142+ #[ no_mangle]
1143+ pub extern "C" fn bloom_physics_create_world ( gx : f64 , gy : f64 , gz : f64 ) {
1144+ #[ cfg( feature = "physics" ) ]
1145+ { engine ( ) . physics = Some ( PhysicsWorld :: new ( gx as f32 , gy as f32 , gz as f32 ) ) ; }
1146+ }
1147+ #[ no_mangle]
1148+ pub extern "C" fn bloom_physics_set_gravity ( gx : f64 , gy : f64 , gz : f64 ) {
1149+ #[ cfg( feature = "physics" ) ]
1150+ if let Some ( phys) = engine ( ) . physics . as_mut ( ) { phys. set_gravity ( gx as f32 , gy as f32 , gz as f32 ) ; }
1151+ }
1152+ #[ no_mangle]
1153+ pub extern "C" fn bloom_physics_set_timestep ( dt : f64 , max_substeps : f64 ) {
1154+ #[ cfg( feature = "physics" ) ]
1155+ if let Some ( phys) = engine ( ) . physics . as_mut ( ) { phys. set_timestep ( dt, max_substeps as u32 ) ; }
1156+ }
1157+ #[ no_mangle]
1158+ pub extern "C" fn bloom_physics_create_body ( body_type : f64 , px : f64 , py : f64 , pz : f64 , rx : f64 , ry : f64 , rz : f64 , rw : f64 ) -> f64 {
1159+ #[ cfg( feature = "physics" ) ]
1160+ { return physics ( ) . create_body ( body_type, px, py, pz, rx, ry, rz, rw) ; }
1161+ #[ cfg( not( feature = "physics" ) ) ] 0.0
1162+ }
1163+ #[ no_mangle]
1164+ pub extern "C" fn bloom_physics_destroy_body ( handle : f64 ) {
1165+ #[ cfg( feature = "physics" ) ]
1166+ if let Some ( phys) = engine ( ) . physics . as_mut ( ) { phys. destroy_body ( handle) ; }
1167+ }
1168+ #[ no_mangle]
1169+ pub extern "C" fn bloom_physics_set_body_enabled ( handle : f64 , enabled : f64 ) {
1170+ #[ cfg( feature = "physics" ) ]
1171+ if let Some ( phys) = engine ( ) . physics . as_mut ( ) { phys. set_body_enabled ( handle, enabled != 0.0 ) ; }
1172+ }
1173+ #[ no_mangle]
1174+ pub extern "C" fn bloom_physics_set_body_ccd ( handle : f64 , enabled : f64 ) {
1175+ #[ cfg( feature = "physics" ) ]
1176+ if let Some ( phys) = engine ( ) . physics . as_mut ( ) { phys. set_body_ccd ( handle, enabled != 0.0 ) ; }
1177+ }
1178+ #[ no_mangle]
1179+ pub extern "C" fn bloom_physics_set_body_gravity_scale ( handle : f64 , scale : f64 ) {
1180+ #[ cfg( feature = "physics" ) ]
1181+ if let Some ( phys) = engine ( ) . physics . as_mut ( ) { phys. set_body_gravity_scale ( handle, scale as f32 ) ; }
1182+ }
1183+ #[ no_mangle]
1184+ pub extern "C" fn bloom_physics_set_kinematic_target ( handle : f64 , px : f64 , py : f64 , pz : f64 , rx : f64 , ry : f64 , rz : f64 , rw : f64 ) {
1185+ #[ cfg( feature = "physics" ) ]
1186+ if let Some ( phys) = engine ( ) . physics . as_mut ( ) { phys. set_kinematic_target ( handle, px, py, pz, rx, ry, rz, rw) ; }
1187+ }
1188+ #[ no_mangle]
1189+ pub extern "C" fn bloom_physics_lock_rotations ( handle : f64 , lock_x : f64 , lock_y : f64 , lock_z : f64 ) {
1190+ #[ cfg( feature = "physics" ) ]
1191+ if let Some ( phys) = engine ( ) . physics . as_mut ( ) { phys. lock_rotations ( handle, lock_x != 0.0 , lock_y != 0.0 , lock_z != 0.0 ) ; }
1192+ }
1193+ #[ no_mangle]
1194+ pub extern "C" fn bloom_physics_add_box_collider ( body : f64 , hx : f64 , hy : f64 , hz : f64 ) -> f64 {
1195+ #[ cfg( feature = "physics" ) ]
1196+ { return physics ( ) . add_box_collider ( body, hx as f32 , hy as f32 , hz as f32 ) ; }
1197+ #[ cfg( not( feature = "physics" ) ) ] 0.0
1198+ }
1199+ #[ no_mangle]
1200+ pub extern "C" fn bloom_physics_add_sphere_collider ( body : f64 , radius : f64 ) -> f64 {
1201+ #[ cfg( feature = "physics" ) ]
1202+ { return physics ( ) . add_sphere_collider ( body, radius as f32 ) ; }
1203+ #[ cfg( not( feature = "physics" ) ) ] 0.0
1204+ }
1205+ #[ no_mangle]
1206+ pub extern "C" fn bloom_physics_add_capsule_collider ( body : f64 , half_height : f64 , radius : f64 ) -> f64 {
1207+ #[ cfg( feature = "physics" ) ]
1208+ { return physics ( ) . add_capsule_collider ( body, half_height as f32 , radius as f32 ) ; }
1209+ #[ cfg( not( feature = "physics" ) ) ] 0.0
1210+ }
1211+ #[ no_mangle]
1212+ pub extern "C" fn bloom_physics_add_cylinder_collider ( body : f64 , half_height : f64 , radius : f64 ) -> f64 {
1213+ #[ cfg( feature = "physics" ) ]
1214+ { return physics ( ) . add_cylinder_collider ( body, half_height as f32 , radius as f32 ) ; }
1215+ #[ cfg( not( feature = "physics" ) ) ] 0.0
1216+ }
1217+ #[ no_mangle]
1218+ pub extern "C" fn bloom_physics_set_collider_properties ( collider : f64 , friction : f64 , restitution : f64 , density : f64 ) {
1219+ #[ cfg( feature = "physics" ) ]
1220+ if let Some ( phys) = engine ( ) . physics . as_mut ( ) { phys. set_collider_properties ( collider, friction as f32 , restitution as f32 , density as f32 ) ; }
1221+ }
1222+ #[ no_mangle]
1223+ pub extern "C" fn bloom_physics_apply_force ( body : f64 , fx : f64 , fy : f64 , fz : f64 ) {
1224+ #[ cfg( feature = "physics" ) ]
1225+ if let Some ( phys) = engine ( ) . physics . as_mut ( ) { phys. apply_force ( body, fx as f32 , fy as f32 , fz as f32 ) ; }
1226+ }
1227+ #[ no_mangle]
1228+ pub extern "C" fn bloom_physics_apply_impulse ( body : f64 , ix : f64 , iy : f64 , iz : f64 ) {
1229+ #[ cfg( feature = "physics" ) ]
1230+ if let Some ( phys) = engine ( ) . physics . as_mut ( ) { phys. apply_impulse ( body, ix as f32 , iy as f32 , iz as f32 ) ; }
1231+ }
1232+ #[ no_mangle]
1233+ pub extern "C" fn bloom_physics_apply_torque ( body : f64 , tx : f64 , ty : f64 , tz : f64 ) {
1234+ #[ cfg( feature = "physics" ) ]
1235+ if let Some ( phys) = engine ( ) . physics . as_mut ( ) { phys. apply_torque ( body, tx as f32 , ty as f32 , tz as f32 ) ; }
1236+ }
1237+ #[ no_mangle]
1238+ pub extern "C" fn bloom_physics_apply_torque_impulse ( body : f64 , tx : f64 , ty : f64 , tz : f64 ) {
1239+ #[ cfg( feature = "physics" ) ]
1240+ if let Some ( phys) = engine ( ) . physics . as_mut ( ) { phys. apply_torque_impulse ( body, tx as f32 , ty as f32 , tz as f32 ) ; }
1241+ }
1242+ #[ no_mangle]
1243+ pub extern "C" fn bloom_physics_set_linear_velocity ( body : f64 , vx : f64 , vy : f64 , vz : f64 ) {
1244+ #[ cfg( feature = "physics" ) ]
1245+ if let Some ( phys) = engine ( ) . physics . as_mut ( ) { phys. set_linear_velocity ( body, vx as f32 , vy as f32 , vz as f32 ) ; }
1246+ }
1247+ #[ no_mangle]
1248+ pub extern "C" fn bloom_physics_set_angular_velocity ( body : f64 , vx : f64 , vy : f64 , vz : f64 ) {
1249+ #[ cfg( feature = "physics" ) ]
1250+ if let Some ( phys) = engine ( ) . physics . as_mut ( ) { phys. set_angular_velocity ( body, vx as f32 , vy as f32 , vz as f32 ) ; }
1251+ }
1252+ #[ no_mangle]
1253+ pub extern "C" fn bloom_physics_step ( delta_time : f64 ) {
1254+ #[ cfg( feature = "physics" ) ]
1255+ {
1256+ let eng = engine ( ) ;
1257+ let ( physics, scene) = ( & mut eng. physics , & mut eng. scene ) ;
1258+ if let Some ( phys) = physics. as_mut ( ) { phys. step ( delta_time) ; phys. sync_transforms ( scene) ; }
1259+ }
1260+ }
1261+ #[ no_mangle]
1262+ pub extern "C" fn bloom_physics_sync_transforms ( ) {
1263+ #[ cfg( feature = "physics" ) ]
1264+ {
1265+ let eng = engine ( ) ;
1266+ let ( physics, scene) = ( & mut eng. physics , & mut eng. scene ) ;
1267+ if let Some ( phys) = physics. as_mut ( ) { phys. sync_transforms ( scene) ; }
1268+ }
1269+ }
1270+ #[ no_mangle]
1271+ pub extern "C" fn bloom_physics_get_body_position_x ( body : f64 ) -> f64 {
1272+ #[ cfg( feature = "physics" ) ] { return physics ( ) . get_body_position_x ( body) ; }
1273+ #[ cfg( not( feature = "physics" ) ) ] 0.0
1274+ }
1275+ #[ no_mangle]
1276+ pub extern "C" fn bloom_physics_get_body_position_y ( body : f64 ) -> f64 {
1277+ #[ cfg( feature = "physics" ) ] { return physics ( ) . get_body_position_y ( body) ; }
1278+ #[ cfg( not( feature = "physics" ) ) ] 0.0
1279+ }
1280+ #[ no_mangle]
1281+ pub extern "C" fn bloom_physics_get_body_position_z ( body : f64 ) -> f64 {
1282+ #[ cfg( feature = "physics" ) ] { return physics ( ) . get_body_position_z ( body) ; }
1283+ #[ cfg( not( feature = "physics" ) ) ] 0.0
1284+ }
1285+ #[ no_mangle]
1286+ pub extern "C" fn bloom_physics_get_body_rotation_x ( body : f64 ) -> f64 {
1287+ #[ cfg( feature = "physics" ) ] { return physics ( ) . get_body_rotation_x ( body) ; }
1288+ #[ cfg( not( feature = "physics" ) ) ] 0.0
1289+ }
1290+ #[ no_mangle]
1291+ pub extern "C" fn bloom_physics_get_body_rotation_y ( body : f64 ) -> f64 {
1292+ #[ cfg( feature = "physics" ) ] { return physics ( ) . get_body_rotation_y ( body) ; }
1293+ #[ cfg( not( feature = "physics" ) ) ] 0.0
1294+ }
1295+ #[ no_mangle]
1296+ pub extern "C" fn bloom_physics_get_body_rotation_z ( body : f64 ) -> f64 {
1297+ #[ cfg( feature = "physics" ) ] { return physics ( ) . get_body_rotation_z ( body) ; }
1298+ #[ cfg( not( feature = "physics" ) ) ] 0.0
1299+ }
1300+ #[ no_mangle]
1301+ pub extern "C" fn bloom_physics_get_body_rotation_w ( body : f64 ) -> f64 {
1302+ #[ cfg( feature = "physics" ) ] { return physics ( ) . get_body_rotation_w ( body) ; }
1303+ #[ cfg( not( feature = "physics" ) ) ] 1.0
1304+ }
1305+ #[ no_mangle]
1306+ pub extern "C" fn bloom_physics_get_linear_velocity_x ( body : f64 ) -> f64 {
1307+ #[ cfg( feature = "physics" ) ] { return physics ( ) . get_linear_velocity_x ( body) ; }
1308+ #[ cfg( not( feature = "physics" ) ) ] 0.0
1309+ }
1310+ #[ no_mangle]
1311+ pub extern "C" fn bloom_physics_get_linear_velocity_y ( body : f64 ) -> f64 {
1312+ #[ cfg( feature = "physics" ) ] { return physics ( ) . get_linear_velocity_y ( body) ; }
1313+ #[ cfg( not( feature = "physics" ) ) ] 0.0
1314+ }
1315+ #[ no_mangle]
1316+ pub extern "C" fn bloom_physics_get_linear_velocity_z ( body : f64 ) -> f64 {
1317+ #[ cfg( feature = "physics" ) ] { return physics ( ) . get_linear_velocity_z ( body) ; }
1318+ #[ cfg( not( feature = "physics" ) ) ] 0.0
1319+ }
1320+ #[ no_mangle]
1321+ pub extern "C" fn bloom_physics_get_angular_velocity_x ( body : f64 ) -> f64 {
1322+ #[ cfg( feature = "physics" ) ] { return physics ( ) . get_angular_velocity_x ( body) ; }
1323+ #[ cfg( not( feature = "physics" ) ) ] 0.0
1324+ }
1325+ #[ no_mangle]
1326+ pub extern "C" fn bloom_physics_get_angular_velocity_y ( body : f64 ) -> f64 {
1327+ #[ cfg( feature = "physics" ) ] { return physics ( ) . get_angular_velocity_y ( body) ; }
1328+ #[ cfg( not( feature = "physics" ) ) ] 0.0
1329+ }
1330+ #[ no_mangle]
1331+ pub extern "C" fn bloom_physics_get_angular_velocity_z ( body : f64 ) -> f64 {
1332+ #[ cfg( feature = "physics" ) ] { return physics ( ) . get_angular_velocity_z ( body) ; }
1333+ #[ cfg( not( feature = "physics" ) ) ] 0.0
1334+ }
1335+ #[ no_mangle]
1336+ pub extern "C" fn bloom_physics_raycast ( ox : f64 , oy : f64 , oz : f64 , dx : f64 , dy : f64 , dz : f64 , max_dist : f64 ) -> f64 {
1337+ #[ cfg( feature = "physics" ) ]
1338+ { if physics ( ) . raycast ( ox, oy, oz, dx, dy, dz, max_dist) { return 1.0 ; } else { return 0.0 ; } }
1339+ #[ cfg( not( feature = "physics" ) ) ] 0.0
1340+ }
1341+ #[ no_mangle]
1342+ pub extern "C" fn bloom_physics_ray_hit_body ( ) -> f64 {
1343+ #[ cfg( feature = "physics" ) ] { return physics ( ) . last_ray_hit . as_ref ( ) . map_or ( 0.0 , |h| h. body_handle ) ; }
1344+ #[ cfg( not( feature = "physics" ) ) ] 0.0
1345+ }
1346+ #[ no_mangle]
1347+ pub extern "C" fn bloom_physics_ray_hit_distance ( ) -> f64 {
1348+ #[ cfg( feature = "physics" ) ] { return physics ( ) . last_ray_hit . as_ref ( ) . map_or ( 0.0 , |h| h. distance ) ; }
1349+ #[ cfg( not( feature = "physics" ) ) ] 0.0
1350+ }
1351+ #[ no_mangle]
1352+ pub extern "C" fn bloom_physics_ray_hit_x ( ) -> f64 {
1353+ #[ cfg( feature = "physics" ) ] { return physics ( ) . last_ray_hit . as_ref ( ) . map_or ( 0.0 , |h| h. point [ 0 ] ) ; }
1354+ #[ cfg( not( feature = "physics" ) ) ] 0.0
1355+ }
1356+ #[ no_mangle]
1357+ pub extern "C" fn bloom_physics_ray_hit_y ( ) -> f64 {
1358+ #[ cfg( feature = "physics" ) ] { return physics ( ) . last_ray_hit . as_ref ( ) . map_or ( 0.0 , |h| h. point [ 1 ] ) ; }
1359+ #[ cfg( not( feature = "physics" ) ) ] 0.0
1360+ }
1361+ #[ no_mangle]
1362+ pub extern "C" fn bloom_physics_ray_hit_z ( ) -> f64 {
1363+ #[ cfg( feature = "physics" ) ] { return physics ( ) . last_ray_hit . as_ref ( ) . map_or ( 0.0 , |h| h. point [ 2 ] ) ; }
1364+ #[ cfg( not( feature = "physics" ) ) ] 0.0
1365+ }
1366+ #[ no_mangle]
1367+ pub extern "C" fn bloom_physics_get_collision_count ( ) -> f64 {
1368+ #[ cfg( feature = "physics" ) ] { return physics ( ) . collision_events . len ( ) as f64 ; }
1369+ #[ cfg( not( feature = "physics" ) ) ] 0.0
1370+ }
1371+ #[ no_mangle]
1372+ pub extern "C" fn bloom_physics_get_collision_event ( index : f64 ) -> f64 {
1373+ #[ cfg( feature = "physics" ) ]
1374+ {
1375+ let phys = physics ( ) ;
1376+ let i = index as usize ;
1377+ if i < phys. collision_events . len ( ) {
1378+ let evt = & phys. collision_events [ i] ;
1379+ phys. last_collision_read = ( evt. body_a , evt. body_b , evt. started ) ;
1380+ return evt. body_a ;
1381+ }
1382+ return 0.0 ;
1383+ }
1384+ #[ cfg( not( feature = "physics" ) ) ] 0.0
1385+ }
1386+ #[ no_mangle]
1387+ pub extern "C" fn bloom_physics_get_collision_body_b ( ) -> f64 {
1388+ #[ cfg( feature = "physics" ) ] { return physics ( ) . last_collision_read . 1 ; }
1389+ #[ cfg( not( feature = "physics" ) ) ] 0.0
1390+ }
1391+ #[ no_mangle]
1392+ pub extern "C" fn bloom_physics_get_collision_started ( ) -> f64 {
1393+ #[ cfg( feature = "physics" ) ] { return if physics ( ) . last_collision_read . 2 { 1.0 } else { 0.0 } ; }
1394+ #[ cfg( not( feature = "physics" ) ) ] 0.0
1395+ }
1396+ #[ no_mangle]
1397+ pub extern "C" fn bloom_physics_attach_scene_node ( body : f64 , scene_node : f64 ) {
1398+ #[ cfg( feature = "physics" ) ]
1399+ if let Some ( phys) = engine ( ) . physics . as_mut ( ) { phys. attach_scene_node ( body, scene_node) ; }
1400+ }
1401+ #[ no_mangle]
1402+ pub extern "C" fn bloom_physics_create_fixed_joint ( body_a : f64 , body_b : f64 , ax : f64 , ay : f64 , az : f64 , bx : f64 , by : f64 , bz : f64 ) -> f64 {
1403+ #[ cfg( feature = "physics" ) ]
1404+ { return physics ( ) . create_fixed_joint ( body_a, body_b, ax as f32 , ay as f32 , az as f32 , bx as f32 , by as f32 , bz as f32 ) ; }
1405+ #[ cfg( not( feature = "physics" ) ) ] 0.0
1406+ }
1407+ #[ no_mangle]
1408+ pub extern "C" fn bloom_physics_create_revolute_joint ( body_a : f64 , body_b : f64 , ax : f64 , ay : f64 , az : f64 , axis_x : f64 , axis_y : f64 , axis_z : f64 ) -> f64 {
1409+ #[ cfg( feature = "physics" ) ]
1410+ { return physics ( ) . create_revolute_joint ( body_a, body_b, ax as f32 , ay as f32 , az as f32 , axis_x as f32 , axis_y as f32 , axis_z as f32 ) ; }
1411+ #[ cfg( not( feature = "physics" ) ) ] 0.0
1412+ }
1413+ #[ no_mangle]
1414+ pub extern "C" fn bloom_physics_create_prismatic_joint ( body_a : f64 , body_b : f64 , ax : f64 , ay : f64 , az : f64 , axis_x : f64 , axis_y : f64 , axis_z : f64 ) -> f64 {
1415+ #[ cfg( feature = "physics" ) ]
1416+ { return physics ( ) . create_prismatic_joint ( body_a, body_b, ax as f32 , ay as f32 , az as f32 , axis_x as f32 , axis_y as f32 , axis_z as f32 ) ; }
1417+ #[ cfg( not( feature = "physics" ) ) ] 0.0
1418+ }
1419+ #[ no_mangle]
1420+ pub extern "C" fn bloom_physics_destroy_joint ( handle : f64 ) {
1421+ #[ cfg( feature = "physics" ) ]
1422+ if let Some ( phys) = engine ( ) . physics . as_mut ( ) { phys. destroy_joint ( handle) ; }
1423+ }
0 commit comments