physics_resource.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674
  1. /*
  2. * Copyright (c) 2012-2021 Daniele Bartolini et al.
  3. * License: https://github.com/dbartolini/crown/blob/master/LICENSE
  4. */
  5. #include "config.h"
  6. #include "core/containers/array.inl"
  7. #include "core/containers/hash_map.inl"
  8. #include "core/filesystem/file.h"
  9. #include "core/filesystem/file_buffer.inl"
  10. #include "core/filesystem/filesystem.h"
  11. #include "core/json/json_object.inl"
  12. #include "core/json/sjson.h"
  13. #include "core/math/aabb.inl"
  14. #include "core/math/constants.h"
  15. #include "core/math/quaternion.inl"
  16. #include "core/math/sphere.inl"
  17. #include "core/memory/temp_allocator.inl"
  18. #include "core/strings/dynamic_string.inl"
  19. #include "core/strings/string.inl"
  20. #include "core/strings/string_id.inl"
  21. #include "resource/compile_options.inl"
  22. #include "resource/physics_resource.h"
  23. #include "world/types.h"
  24. namespace crown
  25. {
  26. namespace physics_config_resource
  27. {
  28. const PhysicsMaterial* material(const PhysicsConfigResource* pcr, StringId32 name)
  29. {
  30. const PhysicsMaterial* begin = (PhysicsMaterial*)((const char*)pcr + pcr->materials_offset);
  31. for (u32 i = 0; i < pcr->num_materials; ++i)
  32. {
  33. if (begin[i].name == name)
  34. return &begin[i];
  35. }
  36. CE_FATAL("Material not found");
  37. return NULL;
  38. }
  39. const PhysicsActor* actor(const PhysicsConfigResource* pcr, StringId32 name)
  40. {
  41. const PhysicsActor* begin = (PhysicsActor*)((const char*)pcr + pcr->actors_offset);
  42. for (u32 i = 0; i < pcr->num_actors; ++i)
  43. {
  44. if (begin[i].name == name)
  45. return &begin[i];
  46. }
  47. CE_FATAL("Actor not found");
  48. return NULL;
  49. }
  50. const PhysicsCollisionFilter* filter(const PhysicsConfigResource* pcr, StringId32 name)
  51. {
  52. const PhysicsCollisionFilter* begin = (PhysicsCollisionFilter*)((const char*)pcr + pcr->filters_offset);
  53. for (u32 i = 0; i < pcr->num_filters; ++i)
  54. {
  55. if (begin[i].name == name)
  56. return &begin[i];
  57. }
  58. CE_FATAL("Filter not found");
  59. return NULL;
  60. }
  61. } // namespace physics_config_resource
  62. #if CROWN_CAN_COMPILE
  63. namespace physics_resource_internal
  64. {
  65. struct ColliderInfo
  66. {
  67. const char* name;
  68. ColliderType::Enum type;
  69. };
  70. static const ColliderInfo s_collider[] =
  71. {
  72. { "sphere", ColliderType::SPHERE },
  73. { "capsule", ColliderType::CAPSULE },
  74. { "box", ColliderType::BOX },
  75. { "convex_hull", ColliderType::CONVEX_HULL },
  76. { "mesh", ColliderType::MESH },
  77. { "heightfield", ColliderType::HEIGHTFIELD }
  78. };
  79. CE_STATIC_ASSERT(countof(s_collider) == ColliderType::COUNT);
  80. struct JointInfo
  81. {
  82. const char* name;
  83. JointType::Enum type;
  84. };
  85. static const JointInfo s_joint[] =
  86. {
  87. { "fixed", JointType::FIXED },
  88. { "hinge", JointType::HINGE },
  89. { "spring", JointType::SPRING }
  90. };
  91. CE_STATIC_ASSERT(countof(s_joint) == JointType::COUNT);
  92. static ColliderType::Enum shape_type_to_enum(const char* type)
  93. {
  94. for (u32 i = 0; i < countof(s_collider); ++i)
  95. {
  96. if (strcmp(type, s_collider[i].name) == 0)
  97. return s_collider[i].type;
  98. }
  99. return ColliderType::COUNT;
  100. }
  101. static JointType::Enum joint_type_to_enum(const char* type)
  102. {
  103. for (u32 i = 0; i < countof(s_joint); ++i)
  104. {
  105. if (strcmp(type, s_joint[i].name) == 0)
  106. return s_joint[i].type;
  107. }
  108. return JointType::COUNT;
  109. }
  110. void compile_sphere(ColliderDesc& sd, const Array<Vector3>& points)
  111. {
  112. AABB aabb;
  113. aabb::from_points(aabb, array::size(points), array::begin(points));
  114. const Vector3 origin = aabb::center(aabb);
  115. sd.local_tm.t = vector4(origin.x, origin.y, origin.z, 1.0f);
  116. sd.sphere.radius = max( 0.0f, aabb.max.x - aabb.min.x);
  117. sd.sphere.radius = max(sd.sphere.radius, aabb.max.y - aabb.min.y);
  118. sd.sphere.radius = max(sd.sphere.radius, aabb.max.z - aabb.min.z);
  119. sd.sphere.radius *= 0.5f;
  120. }
  121. void compile_capsule(ColliderDesc& sd, const Array<Vector3>& points)
  122. {
  123. AABB aabb;
  124. aabb::from_points(aabb, array::size(points), array::begin(points));
  125. const Vector3 origin = aabb::center(aabb);
  126. sd.local_tm.t = vector4(origin.x, origin.y, origin.z, 1.0f);
  127. sd.capsule.radius = aabb::radius(aabb) / 2.0f;
  128. sd.capsule.height = (aabb.max.y - aabb.min.y) / 2.0f;
  129. }
  130. void compile_box(ColliderDesc& sd, const Array<Vector3>& points)
  131. {
  132. AABB aabb;
  133. aabb::from_points(aabb, array::size(points), array::begin(points));
  134. const Vector3 origin = aabb::center(aabb);
  135. sd.local_tm.t = vector4(origin.x, origin.y, origin.z, 1.0f);
  136. sd.box.half_size = (aabb.max - aabb.min) * 0.5f;
  137. }
  138. const char* find_node_by_name(const JsonObject& nodes, const char* name)
  139. {
  140. auto cur = json_object::begin(nodes);
  141. auto end = json_object::end(nodes);
  142. for (; cur != end; ++cur)
  143. {
  144. JSON_OBJECT_SKIP_HOLE(nodes, cur);
  145. if (cur->first == name)
  146. return cur->second;
  147. TempAllocator512 ta;
  148. JsonObject node(ta);
  149. JsonObject children(ta);
  150. sjson::parse_object(node, cur->second);
  151. if (json_object::has(node, "children"))
  152. {
  153. sjson::parse_object(children, node["children"]);
  154. return find_node_by_name(children, name);
  155. }
  156. }
  157. return NULL;
  158. }
  159. s32 compile_collider(Buffer& output, const char* json, CompileOptions& opts)
  160. {
  161. TempAllocator4096 ta;
  162. JsonObject obj(ta);
  163. sjson::parse(obj, json);
  164. DynamicString type(ta);
  165. sjson::parse_string(type, obj["shape"]);
  166. ColliderType::Enum st = shape_type_to_enum(type.c_str());
  167. DATA_COMPILER_ASSERT(st != ColliderType::COUNT
  168. , opts
  169. , "Unknown shape type: '%s'"
  170. , type.c_str()
  171. );
  172. ColliderDesc cd;
  173. memset((void*)&cd, 0, sizeof(cd));
  174. cd.type = st;
  175. cd.local_tm = MATRIX4X4_IDENTITY;
  176. cd.size = 0;
  177. Array<Vector3> points(default_allocator());
  178. Array<u16> point_indices(default_allocator());
  179. DynamicString source(ta);
  180. if (json_object::has(obj, "source"))
  181. sjson::parse_string(source, obj["source"]);
  182. bool explicit_collider = source == "mesh" || json_object::has(obj, "scene");
  183. if (explicit_collider)
  184. {
  185. // Parse .mesh
  186. DynamicString scene(ta);
  187. DynamicString name(ta);
  188. sjson::parse_string(scene, obj["scene"]);
  189. sjson::parse_string(name, obj["name"]);
  190. DATA_COMPILER_ASSERT_RESOURCE_EXISTS("mesh", scene.c_str(), opts);
  191. scene += ".mesh";
  192. Buffer file = opts.read(scene.c_str());
  193. JsonObject json_mesh(ta);
  194. JsonObject geometries(ta);
  195. JsonObject geometry(ta);
  196. JsonObject nodes(ta);
  197. JsonObject node(ta);
  198. sjson::parse(json_mesh, file);
  199. sjson::parse(geometries, json_mesh["geometries"]);
  200. DATA_COMPILER_ASSERT(json_object::has(geometries, name.c_str())
  201. , opts
  202. , "Geometry '%s' does not exist"
  203. , name.c_str()
  204. );
  205. sjson::parse(geometry, geometries[name.c_str()]);
  206. // Find node
  207. sjson::parse(nodes, json_mesh["nodes"]);
  208. const char* node_data = find_node_by_name(nodes, name.c_str());
  209. DATA_COMPILER_ASSERT(node_data != NULL
  210. , opts
  211. , "Node '%s' does not exist"
  212. , name.c_str()
  213. );
  214. sjson::parse(node, node_data);
  215. JsonArray positions(ta);
  216. sjson::parse_array(positions, geometry["position"]);
  217. JsonObject indices(ta);
  218. JsonArray indices_data(ta);
  219. JsonArray position_indices(ta);
  220. sjson::parse_object(indices, geometry["indices"]);
  221. sjson::parse_array(indices_data, indices["data"]);
  222. sjson::parse_array(position_indices, indices_data[0]);
  223. for (u32 i = 0; i < array::size(positions); i += 3)
  224. {
  225. Vector3 p;
  226. p.x = sjson::parse_float(positions[i + 0]);
  227. p.y = sjson::parse_float(positions[i + 1]);
  228. p.z = sjson::parse_float(positions[i + 2]);
  229. array::push_back(points, p);
  230. }
  231. for (u32 i = 0; i < array::size(position_indices); ++i)
  232. {
  233. array::push_back(point_indices, (u16)sjson::parse_int(position_indices[i]));
  234. }
  235. switch (cd.type)
  236. {
  237. case ColliderType::SPHERE: compile_sphere(cd, points); break;
  238. case ColliderType::CAPSULE: compile_capsule(cd, points); break;
  239. case ColliderType::BOX: compile_box(cd, points); break;
  240. case ColliderType::CONVEX_HULL: break;
  241. case ColliderType::MESH: break;
  242. case ColliderType::HEIGHTFIELD:
  243. DATA_COMPILER_ASSERT(false, opts, "Not implemented yet");
  244. break;
  245. }
  246. }
  247. else
  248. {
  249. JsonObject collider_data(ta);
  250. JsonArray org(ta);
  251. DATA_COMPILER_ASSERT(json_object::has(obj, "collider_data")
  252. , opts
  253. , "No collider_data found"
  254. );
  255. sjson::parse_object(collider_data, obj["collider_data"]);
  256. Quaternion rotation = sjson::parse_quaternion(collider_data["rotation"]);
  257. Vector3 position = sjson::parse_vector3(collider_data["position"]);
  258. Matrix4x4 matrix_local = from_quaternion_translation(rotation, position);
  259. cd.local_tm = matrix_local;
  260. if (cd.type == ColliderType::SPHERE) {
  261. cd.sphere.radius = sjson::parse_float(collider_data["radius"]);
  262. } else if (cd.type == ColliderType::BOX) {
  263. cd.box.half_size = sjson::parse_vector3(collider_data["half_extents"]);;
  264. } else if (cd.type == ColliderType::CAPSULE) {
  265. cd.capsule.radius = sjson::parse_float(collider_data["radius"]);
  266. cd.capsule.height = sjson::parse_float(collider_data["height"]);
  267. }
  268. }
  269. const bool needs_points = cd.type == ColliderType::CONVEX_HULL
  270. || cd.type == ColliderType::MESH;
  271. if (needs_points)
  272. {
  273. cd.size += sizeof(u32) + sizeof(Vector3)*array::size(points);
  274. if (cd.type == ColliderType::MESH)
  275. cd.size += sizeof(u32) + sizeof(u16)*array::size(point_indices);
  276. }
  277. FileBuffer fb(output);
  278. BinaryWriter bw(fb);
  279. bw.write(cd.type);
  280. bw.write(cd.local_tm);
  281. bw.write(cd.sphere.radius);
  282. bw.write(cd.capsule.radius);
  283. bw.write(cd.capsule.height);
  284. bw.write(cd.box.half_size);
  285. bw.write(cd.heightfield.width);
  286. bw.write(cd.heightfield.length);
  287. bw.write(cd.heightfield.height_scale);
  288. bw.write(cd.heightfield.height_min);
  289. bw.write(cd.heightfield.height_max);
  290. bw.write(cd.size);
  291. if (needs_points)
  292. {
  293. bw.write(array::size(points));
  294. for (u32 ii = 0; ii < array::size(points); ++ii)
  295. bw.write(points[ii]);
  296. if (cd.type == ColliderType::MESH)
  297. {
  298. bw.write(array::size(point_indices));
  299. for (u32 ii = 0; ii < array::size(point_indices); ++ii)
  300. bw.write(point_indices[ii]);
  301. }
  302. }
  303. return 0;
  304. }
  305. s32 compile_actor(Buffer& output, const char* json, CompileOptions& /*opts*/)
  306. {
  307. TempAllocator4096 ta;
  308. JsonObject obj(ta);
  309. sjson::parse(obj, json);
  310. u32 flags = 0;
  311. flags |= (json_object::has(obj, "lock_translation_x") && sjson::parse_bool(obj["lock_translation_x"])) ? ActorFlags::LOCK_TRANSLATION_X : 0;
  312. flags |= (json_object::has(obj, "lock_translation_y") && sjson::parse_bool(obj["lock_translation_y"])) ? ActorFlags::LOCK_TRANSLATION_Y : 0;
  313. flags |= (json_object::has(obj, "lock_translation_z") && sjson::parse_bool(obj["lock_translation_z"])) ? ActorFlags::LOCK_TRANSLATION_Z : 0;
  314. flags |= (json_object::has(obj, "lock_rotation_x") && sjson::parse_bool(obj["lock_rotation_x"])) ? ActorFlags::LOCK_ROTATION_X : 0;
  315. flags |= (json_object::has(obj, "lock_rotation_y") && sjson::parse_bool(obj["lock_rotation_y"])) ? ActorFlags::LOCK_ROTATION_Y : 0;
  316. flags |= (json_object::has(obj, "lock_rotation_z") && sjson::parse_bool(obj["lock_rotation_z"])) ? ActorFlags::LOCK_ROTATION_Z : 0;
  317. ActorResource ar;
  318. ar.actor_class = sjson::parse_string_id(obj["class"]);
  319. ar.mass = sjson::parse_float (obj["mass"]);
  320. ar.flags = flags;
  321. ar.collision_filter = sjson::parse_string_id(obj["collision_filter"]);
  322. ar.material = sjson::parse_string_id(obj["material"]);
  323. FileBuffer fb(output);
  324. BinaryWriter bw(fb);
  325. bw.write(ar.actor_class);
  326. bw.write(ar.mass);
  327. bw.write(ar.flags);
  328. bw.write(ar.collision_filter);
  329. bw.write(ar.material);
  330. return 0;
  331. }
  332. s32 compile_joint(Buffer& output, const char* json, CompileOptions& opts)
  333. {
  334. TempAllocator4096 ta;
  335. JsonObject obj(ta);
  336. sjson::parse(obj, json);
  337. DynamicString type(ta);
  338. sjson::parse_string(type, obj["type"]);
  339. JointType::Enum jt = joint_type_to_enum(type.c_str());
  340. DATA_COMPILER_ASSERT(jt != JointType::COUNT
  341. , opts
  342. , "Unknown joint type: '%s'"
  343. , type.c_str()
  344. );
  345. JointDesc jd;
  346. jd.type = jt;
  347. jd.anchor_0 = sjson::parse_vector3(obj["anchor_0"]);
  348. jd.anchor_1 = sjson::parse_vector3(obj["anchor_1"]);
  349. switch (jd.type)
  350. {
  351. case JointType::HINGE:
  352. jd.hinge.use_motor = sjson::parse_bool (obj["use_motor"]);
  353. jd.hinge.target_velocity = sjson::parse_float(obj["target_velocity"]);
  354. jd.hinge.max_motor_impulse = sjson::parse_float(obj["max_motor_impulse"]);
  355. jd.hinge.lower_limit = sjson::parse_float(obj["lower_limit"]);
  356. jd.hinge.upper_limit = sjson::parse_float(obj["upper_limit"]);
  357. jd.hinge.bounciness = sjson::parse_float(obj["bounciness"]);
  358. break;
  359. }
  360. FileBuffer fb(output);
  361. BinaryWriter bw(fb);
  362. bw.write(jd.type);
  363. bw.write(jd.anchor_0);
  364. bw.write(jd.anchor_1);
  365. bw.write(jd.breakable);
  366. bw.write(jd._pad[0]);
  367. bw.write(jd._pad[1]);
  368. bw.write(jd._pad[2]);
  369. bw.write(jd.break_force);
  370. bw.write(jd.hinge);
  371. bw.write(jd.hinge.axis);
  372. bw.write(jd.hinge.use_motor);
  373. bw.write(jd.hinge.target_velocity);
  374. bw.write(jd.hinge.max_motor_impulse);
  375. bw.write(jd.hinge.use_limits);
  376. bw.write(jd.hinge.lower_limit);
  377. bw.write(jd.hinge.upper_limit);
  378. bw.write(jd.hinge.bounciness);
  379. return 0;
  380. }
  381. } // namespace physics_resource_internal
  382. namespace physics_config_resource_internal
  383. {
  384. void parse_materials(const char* json, Array<PhysicsMaterial>& objects)
  385. {
  386. TempAllocator4096 ta;
  387. JsonObject obj(ta);
  388. sjson::parse(obj, json);
  389. auto cur = json_object::begin(obj);
  390. auto end = json_object::end(obj);
  391. for (; cur != end; ++cur)
  392. {
  393. JSON_OBJECT_SKIP_HOLE(obj, cur);
  394. const StringView key = cur->first;
  395. const char* value = cur->second;
  396. JsonObject material(ta);
  397. sjson::parse_object(material, value);
  398. PhysicsMaterial mat;
  399. mat.name = StringId32(key.data(), key.length());
  400. mat.friction = sjson::parse_float(material["friction"]);
  401. mat.rolling_friction = sjson::parse_float(material["rolling_friction"]);
  402. mat.restitution = sjson::parse_float(material["restitution"]);
  403. array::push_back(objects, mat);
  404. }
  405. }
  406. void parse_actors(const char* json, Array<PhysicsActor>& objects)
  407. {
  408. TempAllocator4096 ta;
  409. JsonObject obj(ta);
  410. sjson::parse(obj, json);
  411. auto cur = json_object::begin(obj);
  412. auto end = json_object::end(obj);
  413. for (; cur != end; ++cur)
  414. {
  415. JSON_OBJECT_SKIP_HOLE(obj, cur);
  416. const StringView key = cur->first;
  417. const char* value = cur->second;
  418. JsonObject actor(ta);
  419. sjson::parse_object(actor, value);
  420. PhysicsActor pa;
  421. pa.name = StringId32(key.data(), key.length());
  422. pa.linear_damping = 0.0f;
  423. pa.angular_damping = 0.0f;
  424. if (json_object::has(actor, "linear_damping"))
  425. pa.linear_damping = sjson::parse_float(actor["linear_damping"]);
  426. if (json_object::has(actor, "angular_damping"))
  427. pa.angular_damping = sjson::parse_float(actor["angular_damping"]);
  428. pa.flags = 0;
  429. pa.flags |= (json_object::has(actor, "dynamic") && sjson::parse_bool(actor["dynamic"]) ) ? PhysicsActor::DYNAMIC : 0;
  430. pa.flags |= (json_object::has(actor, "kinematic") && sjson::parse_bool(actor["kinematic"]) ) ? PhysicsActor::KINEMATIC : 0;
  431. pa.flags |= (json_object::has(actor, "disable_gravity") && sjson::parse_bool(actor["disable_gravity"])) ? PhysicsActor::DISABLE_GRAVITY : 0;
  432. pa.flags |= (json_object::has(actor, "trigger") && sjson::parse_bool(actor["trigger"]) ) ? PhysicsActor::TRIGGER : 0;
  433. array::push_back(objects, pa);
  434. }
  435. }
  436. struct CollisionFilterCompiler
  437. {
  438. CompileOptions& _opts;
  439. HashMap<StringId32, u32> _filter_map;
  440. Array<PhysicsCollisionFilter> _filters;
  441. u32 _filter;
  442. explicit CollisionFilterCompiler(CompileOptions& opts)
  443. : _opts(opts)
  444. , _filter_map(default_allocator())
  445. , _filters(default_allocator())
  446. , _filter(1)
  447. {
  448. }
  449. void parse(const char* json)
  450. {
  451. TempAllocator4096 ta;
  452. JsonObject obj(ta);
  453. sjson::parse(obj, json);
  454. auto cur = json_object::begin(obj);
  455. auto end = json_object::end(obj);
  456. for (; cur != end; ++cur)
  457. {
  458. JSON_OBJECT_SKIP_HOLE(obj, cur);
  459. const StringView key = cur->first;
  460. const StringId32 id = StringId32(key.data(), key.length());
  461. hash_map::set(_filter_map, id, new_filter_mask());
  462. }
  463. cur = json_object::begin(obj);
  464. end = json_object::end(obj);
  465. for (; cur != end; ++cur)
  466. {
  467. JSON_OBJECT_SKIP_HOLE(obj, cur);
  468. const StringView key = cur->first;
  469. const char* value = cur->second;
  470. const StringId32 id = StringId32(key.data(), key.length());
  471. TempAllocator4096 ta;
  472. JsonObject filter(ta);
  473. sjson::parse_object(filter, value);
  474. JsonArray collides_with(ta);
  475. sjson::parse_array(collides_with, filter["collides_with"]);
  476. u32 mask = 0;
  477. for (u32 i = 0; i < array::size(collides_with); ++i)
  478. {
  479. const StringId32 fi = sjson::parse_string_id(collides_with[i]);
  480. mask |= filter_to_mask(fi);
  481. }
  482. // Build mask
  483. PhysicsCollisionFilter pcf;
  484. pcf.name = id;
  485. pcf.me = filter_to_mask(id);
  486. pcf.mask = mask;
  487. array::push_back(_filters, pcf);
  488. }
  489. }
  490. u32 new_filter_mask()
  491. {
  492. DATA_COMPILER_ASSERT(_filter != 0x80000000u
  493. , _opts
  494. , "Too many collision filters"
  495. );
  496. const u32 f = _filter;
  497. _filter = _filter << 1;
  498. return f;
  499. }
  500. u32 filter_to_mask(StringId32 filter)
  501. {
  502. DATA_COMPILER_ASSERT(hash_map::has(_filter_map, filter)
  503. , _opts
  504. , "Filter not found"
  505. );
  506. return hash_map::get(_filter_map, filter, 0u);
  507. }
  508. };
  509. s32 compile(CompileOptions& opts)
  510. {
  511. Buffer buf = opts.read();
  512. TempAllocator4096 ta;
  513. JsonObject obj(ta);
  514. sjson::parse(obj, buf);
  515. Array<PhysicsMaterial> materials(default_allocator());
  516. Array<PhysicsActor> actors(default_allocator());
  517. CollisionFilterCompiler cfc(opts);
  518. // Parse materials
  519. if (json_object::has(obj, "collision_filters"))
  520. cfc.parse(obj["collision_filters"]);
  521. if (json_object::has(obj, "materials"))
  522. parse_materials(obj["materials"], materials);
  523. if (json_object::has(obj, "actors"))
  524. parse_actors(obj["actors"], actors);
  525. // Setup struct for writing
  526. PhysicsConfigResource pcr;
  527. pcr.version = RESOURCE_HEADER(RESOURCE_VERSION_PHYSICS_CONFIG);
  528. pcr.num_materials = array::size(materials);
  529. pcr.num_actors = array::size(actors);
  530. pcr.num_filters = array::size(cfc._filters);
  531. u32 offt = sizeof(PhysicsConfigResource);
  532. pcr.materials_offset = offt;
  533. offt += sizeof(PhysicsMaterial) * pcr.num_materials;
  534. pcr.actors_offset = offt;
  535. offt += sizeof(PhysicsActor) * pcr.num_actors;
  536. pcr.filters_offset = offt;
  537. // Write all
  538. opts.write(pcr.version);
  539. opts.write(pcr.num_materials);
  540. opts.write(pcr.materials_offset);
  541. opts.write(pcr.num_actors);
  542. opts.write(pcr.actors_offset);
  543. opts.write(pcr.num_filters);
  544. opts.write(pcr.filters_offset);
  545. // Write materials
  546. for (u32 i = 0; i < pcr.num_materials; ++i)
  547. {
  548. opts.write(materials[i].name._id);
  549. opts.write(materials[i].friction);
  550. opts.write(materials[i].rolling_friction);
  551. opts.write(materials[i].restitution);
  552. }
  553. // Write actors
  554. for (u32 i = 0; i < pcr.num_actors; ++i)
  555. {
  556. opts.write(actors[i].name._id);
  557. opts.write(actors[i].linear_damping);
  558. opts.write(actors[i].angular_damping);
  559. opts.write(actors[i].flags);
  560. }
  561. // Write collision filters
  562. for (u32 i = 0; i < array::size(cfc._filters); ++i)
  563. {
  564. opts.write(cfc._filters[i].name._id);
  565. opts.write(cfc._filters[i].me);
  566. opts.write(cfc._filters[i].mask);
  567. }
  568. return 0;
  569. }
  570. } // namespace physics_config_resource_internal
  571. #endif // CROWN_CAN_COMPILE
  572. } // namespace crown