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