PhysicsCollisionShape.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. #include "Base.h"
  2. #include "PhysicsCollisionShape.h"
  3. #include "Node.h"
  4. #include "Properties.h"
  5. namespace gameplay
  6. {
  7. PhysicsCollisionShape::PhysicsCollisionShape(Type type, btCollisionShape* shape)
  8. : _type(type), _shape(shape)
  9. {
  10. memset(&_shapeData, 0, sizeof(_shapeData));
  11. }
  12. PhysicsCollisionShape::PhysicsCollisionShape(const PhysicsCollisionShape& copy)
  13. {
  14. // hidden
  15. }
  16. PhysicsCollisionShape::~PhysicsCollisionShape()
  17. {
  18. if (_shape)
  19. {
  20. // Cleanup shape-specific cached data.
  21. switch (_type)
  22. {
  23. case SHAPE_MESH:
  24. if (_shapeData.meshData)
  25. {
  26. SAFE_DELETE_ARRAY(_shapeData.meshData->vertexData);
  27. for (unsigned int i = 0; i < _shapeData.meshData->indexData.size(); i++)
  28. {
  29. SAFE_DELETE_ARRAY(_shapeData.meshData->indexData[i]);
  30. }
  31. SAFE_DELETE(_shapeData.meshData);
  32. }
  33. break;
  34. case SHAPE_HEIGHTFIELD:
  35. if (_shapeData.heightfieldData)
  36. {
  37. SAFE_DELETE_ARRAY(_shapeData.heightfieldData->heightData);
  38. SAFE_DELETE(_shapeData.heightfieldData);
  39. }
  40. break;
  41. }
  42. // Free the bullet shape.
  43. SAFE_DELETE(_shape);
  44. }
  45. }
  46. PhysicsCollisionShape::Type PhysicsCollisionShape::getType() const
  47. {
  48. return _type;
  49. }
  50. PhysicsCollisionShape::Definition::Definition()
  51. : isExplicit(false), centerAbsolute(false)
  52. {
  53. memset(&data, 0, sizeof(data));
  54. }
  55. PhysicsCollisionShape::Definition::Definition(const Definition& definition)
  56. {
  57. // Bitwise-copy the definition object (equivalent to default copy constructor).
  58. memcpy(this, &definition, sizeof(PhysicsCollisionShape::Definition));
  59. // Handle the types that have reference-counted members.
  60. switch (type)
  61. {
  62. case PhysicsCollisionShape::SHAPE_HEIGHTFIELD:
  63. GP_ASSERT(data.heightfield);
  64. data.heightfield->addRef();
  65. break;
  66. case PhysicsCollisionShape::SHAPE_MESH:
  67. GP_ASSERT(data.mesh);
  68. data.mesh->addRef();
  69. break;
  70. }
  71. }
  72. PhysicsCollisionShape::Definition::~Definition()
  73. {
  74. switch (type)
  75. {
  76. case PhysicsCollisionShape::SHAPE_HEIGHTFIELD:
  77. SAFE_RELEASE(data.heightfield);
  78. break;
  79. case PhysicsCollisionShape::SHAPE_MESH:
  80. SAFE_RELEASE(data.mesh);
  81. break;
  82. }
  83. }
  84. PhysicsCollisionShape::Definition& PhysicsCollisionShape::Definition::operator=(const Definition& definition)
  85. {
  86. if (this != &definition)
  87. {
  88. // Bitwise-copy the definition object (equivalent to default copy constructor).
  89. memcpy(this, &definition, sizeof(PhysicsCollisionShape::Definition));
  90. // Handle the types that have reference-counted members.
  91. switch (type)
  92. {
  93. case PhysicsCollisionShape::SHAPE_HEIGHTFIELD:
  94. GP_ASSERT(data.heightfield);
  95. data.heightfield->addRef();
  96. break;
  97. case PhysicsCollisionShape::SHAPE_MESH:
  98. GP_ASSERT(data.mesh);
  99. data.mesh->addRef();
  100. break;
  101. }
  102. }
  103. return *this;
  104. }
  105. PhysicsCollisionShape::Definition* PhysicsCollisionShape::Definition::create(Node* node, Properties* properties)
  106. {
  107. GP_ASSERT(node);
  108. // Check if the properties is valid and has a valid namespace.
  109. if (!properties || !(strcmp(properties->getNamespace(), "collisionObject") == 0))
  110. {
  111. GP_ERROR("Failed to load physics collision shape from properties object: must be non-null object and have namespace equal to 'collisionObject'.");
  112. return NULL;
  113. }
  114. // Set values to their defaults.
  115. PhysicsCollisionShape::Type type = PhysicsCollisionShape::SHAPE_BOX;
  116. Vector3* extents = NULL;
  117. Vector3* center = NULL;
  118. float radius = -1.0f;
  119. float height = -1.0f;
  120. bool centerIsAbsolute = false;
  121. const char* imagePath = NULL;
  122. bool shapeSpecified = false;
  123. // Load the defined properties.
  124. properties->rewind();
  125. const char* name;
  126. while (name = properties->getNextProperty())
  127. {
  128. if (strcmp(name, "shape") == 0)
  129. {
  130. std::string shapeStr = properties->getString();
  131. if (shapeStr == "BOX")
  132. type = SHAPE_BOX;
  133. else if (shapeStr == "SPHERE")
  134. type = SHAPE_SPHERE;
  135. else if (shapeStr == "MESH")
  136. type = SHAPE_MESH;
  137. else if (shapeStr == "HEIGHTFIELD")
  138. type = SHAPE_HEIGHTFIELD;
  139. else if (shapeStr == "CAPSULE")
  140. type = SHAPE_CAPSULE;
  141. else
  142. {
  143. GP_ERROR("Could not create physics collision shape; unsupported value for collision shape type: '%s'.", shapeStr.c_str());
  144. return NULL;
  145. }
  146. shapeSpecified = true;
  147. }
  148. else if (strcmp(name, "image") == 0)
  149. {
  150. imagePath = properties->getString();
  151. }
  152. else if (strcmp(name, "radius") == 0)
  153. {
  154. radius = properties->getFloat();
  155. }
  156. else if (strcmp(name, "height") == 0)
  157. {
  158. height = properties->getFloat();
  159. }
  160. else if (strcmp(name, "extents") == 0)
  161. {
  162. extents = new Vector3();
  163. properties->getVector3("extents", extents);
  164. }
  165. else if (strcmp(name, "center") == 0)
  166. {
  167. center = new Vector3();
  168. properties->getVector3("center", center);
  169. }
  170. else if (strcmp(name, "centerAbsolute") == 0)
  171. {
  172. centerIsAbsolute = properties->getBool();
  173. }
  174. else
  175. {
  176. // Ignore this case (these are the properties for the rigid body, character, or ghost object that this collision shape is for).
  177. }
  178. }
  179. if (!shapeSpecified)
  180. {
  181. GP_ERROR("Missing 'shape' specifier for collision shape definition.");
  182. return NULL;
  183. }
  184. // Create the collision shape.
  185. PhysicsCollisionShape::Definition* shape = new PhysicsCollisionShape::Definition();
  186. switch (type)
  187. {
  188. case SHAPE_BOX:
  189. if (extents)
  190. {
  191. if (center)
  192. {
  193. *shape = box(*extents, *center, centerIsAbsolute);
  194. }
  195. else
  196. {
  197. *shape = box(*extents);
  198. }
  199. }
  200. else
  201. {
  202. *shape = box();
  203. }
  204. break;
  205. case SHAPE_SPHERE:
  206. if (radius != -1.0f)
  207. {
  208. if (center)
  209. {
  210. *shape = sphere(radius, *center, centerIsAbsolute);
  211. }
  212. else
  213. {
  214. *shape = sphere(radius);
  215. }
  216. }
  217. else
  218. {
  219. *shape = sphere();
  220. }
  221. break;
  222. case SHAPE_CAPSULE:
  223. if (radius != -1.0f && height != -1.0f)
  224. {
  225. if (center)
  226. {
  227. *shape = capsule(radius, height, *center, centerIsAbsolute);
  228. }
  229. else
  230. {
  231. *shape = capsule(radius, height);
  232. }
  233. }
  234. else
  235. {
  236. *shape = capsule();
  237. }
  238. break;
  239. case SHAPE_MESH:
  240. {
  241. // Mesh is required on node.
  242. Mesh* nodeMesh = node->getModel() ? node->getModel()->getMesh() : NULL;
  243. if (nodeMesh == NULL)
  244. {
  245. GP_ERROR("Cannot create mesh collision object for node without model/mesh.");
  246. return NULL;
  247. }
  248. // Check that the node's mesh's primitive type is supported.
  249. switch (nodeMesh->getPrimitiveType())
  250. {
  251. case Mesh::TRIANGLES:
  252. {
  253. *shape = mesh(nodeMesh);
  254. break;
  255. }
  256. case Mesh::LINES:
  257. case Mesh::LINE_STRIP:
  258. case Mesh::POINTS:
  259. case Mesh::TRIANGLE_STRIP:
  260. GP_ERROR("Mesh collision objects are currently only supported on meshes with primitive type equal to TRIANGLES.");
  261. SAFE_DELETE(shape);
  262. break;
  263. }
  264. break;
  265. }
  266. case SHAPE_HEIGHTFIELD:
  267. if (imagePath == NULL)
  268. {
  269. GP_ERROR("Heightfield collision objects require an image path.");
  270. SAFE_DELETE(shape);
  271. return NULL;
  272. }
  273. else
  274. {
  275. // Load the image data from the given file path.
  276. Image* image = Image::create(imagePath);
  277. if (!image)
  278. {
  279. GP_ERROR("Failed create image for heightfield collision object from file '%s'.", imagePath);
  280. SAFE_DELETE(shape);
  281. return NULL;
  282. }
  283. // Ensure that the image's pixel format is supported.
  284. switch (image->getFormat())
  285. {
  286. case Image::RGB:
  287. case Image::RGBA:
  288. break;
  289. default:
  290. GP_ERROR("Heightmap: pixel format is not supported: %d.", image->getFormat());
  291. SAFE_RELEASE(image);
  292. SAFE_DELETE(shape);
  293. return NULL;
  294. }
  295. *shape = PhysicsCollisionShape::heightfield(image);
  296. SAFE_RELEASE(image);
  297. }
  298. break;
  299. default:
  300. GP_ERROR("Unsupported physics collision shape type (%d).", type);
  301. SAFE_DELETE(shape);
  302. return NULL;
  303. }
  304. SAFE_DELETE(extents);
  305. SAFE_DELETE(center);
  306. return shape;
  307. }
  308. PhysicsCollisionShape::Definition PhysicsCollisionShape::box()
  309. {
  310. Definition d;
  311. d.type = SHAPE_BOX;
  312. d.isExplicit = false;
  313. d.centerAbsolute = false;
  314. return d;
  315. }
  316. PhysicsCollisionShape::Definition PhysicsCollisionShape::box(const Vector3& extents, const Vector3& center, bool absolute)
  317. {
  318. Definition d;
  319. d.type = SHAPE_BOX;
  320. memcpy(d.data.box.extents, &extents.x, sizeof(float) * 3);
  321. memcpy(d.data.box.center, &center.x, sizeof(float) * 3);
  322. d.isExplicit = true;
  323. d.centerAbsolute = absolute;
  324. return d;
  325. }
  326. PhysicsCollisionShape::Definition PhysicsCollisionShape::sphere()
  327. {
  328. Definition d;
  329. d.type = SHAPE_SPHERE;
  330. d.isExplicit = false;
  331. d.centerAbsolute = false;
  332. return d;
  333. }
  334. PhysicsCollisionShape::Definition PhysicsCollisionShape::sphere(float radius, const Vector3& center, bool absolute)
  335. {
  336. Definition d;
  337. d.type = SHAPE_SPHERE;
  338. d.data.sphere.radius = radius;
  339. memcpy(d.data.sphere.center, &center.x, sizeof(float) * 3);
  340. d.isExplicit = true;
  341. d.centerAbsolute = absolute;
  342. return d;
  343. }
  344. PhysicsCollisionShape::Definition PhysicsCollisionShape::capsule()
  345. {
  346. Definition d;
  347. d.type = SHAPE_CAPSULE;
  348. d.isExplicit = false;
  349. d.centerAbsolute = false;
  350. return d;
  351. }
  352. PhysicsCollisionShape::Definition PhysicsCollisionShape::capsule(float radius, float height, const Vector3& center, bool absolute)
  353. {
  354. Definition d;
  355. d.type = SHAPE_CAPSULE;
  356. d.data.capsule.radius = radius;
  357. d.data.capsule.height = height;
  358. memcpy(d.data.capsule.center, &center.x, sizeof(float) * 3);
  359. d.isExplicit = true;
  360. d.centerAbsolute = absolute;
  361. return d;
  362. }
  363. PhysicsCollisionShape::Definition PhysicsCollisionShape::heightfield(Image* image)
  364. {
  365. GP_ASSERT(image);
  366. image->addRef();
  367. Definition d;
  368. d.type = SHAPE_HEIGHTFIELD;
  369. d.data.heightfield = image;
  370. d.isExplicit = true;
  371. d.centerAbsolute = false;
  372. return d;
  373. }
  374. PhysicsCollisionShape::Definition PhysicsCollisionShape::mesh(Mesh* mesh)
  375. {
  376. GP_ASSERT(mesh);
  377. mesh->addRef();
  378. Definition d;
  379. d.type = SHAPE_MESH;
  380. d.data.mesh = mesh;
  381. d.isExplicit = true;
  382. d.centerAbsolute = false;
  383. return d;
  384. }
  385. }