body_shape.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922
  1. /*************************************************************************/
  2. /* body_shape.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* http://www.godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
  9. /* */
  10. /* Permission is hereby granted, free of charge, to any person obtaining */
  11. /* a copy of this software and associated documentation files (the */
  12. /* "Software"), to deal in the Software without restriction, including */
  13. /* without limitation the rights to use, copy, modify, merge, publish, */
  14. /* distribute, sublicense, and/or sell copies of the Software, and to */
  15. /* permit persons to whom the Software is furnished to do so, subject to */
  16. /* the following conditions: */
  17. /* */
  18. /* The above copyright notice and this permission notice shall be */
  19. /* included in all copies or substantial portions of the Software. */
  20. /* */
  21. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  22. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  23. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
  24. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  25. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  26. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  27. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  28. /*************************************************************************/
  29. #include "body_shape.h"
  30. #include "servers/visual_server.h"
  31. #include "scene/resources/sphere_shape.h"
  32. #include "scene/resources/ray_shape.h"
  33. #include "scene/resources/box_shape.h"
  34. #include "scene/resources/capsule_shape.h"
  35. //#include "scene/resources/cylinder_shape.h"
  36. #include "scene/resources/convex_polygon_shape.h"
  37. #include "scene/resources/concave_polygon_shape.h"
  38. #include "scene/resources/height_map_shape.h"
  39. #include "scene/resources/plane_shape.h"
  40. #include "mesh_instance.h"
  41. #include "physics_body.h"
  42. #include "quick_hull.h"
  43. void CollisionShape::_update_body() {
  44. if (!is_inside_tree() || !can_update_body)
  45. return;
  46. if (!get_tree()->is_editor_hint())
  47. return;
  48. if (get_parent() && get_parent()->cast_to<CollisionObject>())
  49. get_parent()->cast_to<CollisionObject>()->_update_shapes_from_children();
  50. }
  51. void CollisionShape::make_convex_from_brothers() {
  52. Node *p = get_parent();
  53. if (!p)
  54. return;
  55. for(int i=0;i<p->get_child_count();i++) {
  56. Node *n = p->get_child(i);
  57. if (n->cast_to<MeshInstance>()) {
  58. MeshInstance *mi=n->cast_to<MeshInstance>();
  59. Ref<Mesh> m = mi->get_mesh();
  60. if (m.is_valid()) {
  61. Ref<Shape> s = m->create_convex_shape();
  62. set_shape(s);
  63. }
  64. }
  65. }
  66. }
  67. /*
  68. void CollisionShape::_update_indicator() {
  69. while (VisualServer::get_singleton()->mesh_get_surface_count(indicator))
  70. VisualServer::get_singleton()->mesh_remove_surface(indicator,0);
  71. if (shape.is_null())
  72. return;
  73. DVector<Vector3> points;
  74. DVector<Vector3> normals;
  75. VS::PrimitiveType pt = VS::PRIMITIVE_TRIANGLES;
  76. if (shape->cast_to<RayShape>()) {
  77. RayShape *rs = shape->cast_to<RayShape>();
  78. points.push_back(Vector3());
  79. points.push_back(Vector3(0,0,rs->get_length()));
  80. pt = VS::PRIMITIVE_LINES;
  81. } else if (shape->cast_to<SphereShape>()) {
  82. // VisualServer *vs=VisualServer::get_singleton();
  83. SphereShape *shapeptr=shape->cast_to<SphereShape>();
  84. Color col(0.4,1.0,1.0,0.5);
  85. int lats=6;
  86. int lons=12;
  87. float size=shapeptr->get_radius();
  88. for(int i = 1; i <= lats; i++) {
  89. double lat0 = Math_PI * (-0.5 + (double) (i - 1) / lats);
  90. double z0 = Math::sin(lat0);
  91. double zr0 = Math::cos(lat0);
  92. double lat1 = Math_PI * (-0.5 + (double) i / lats);
  93. double z1 = Math::sin(lat1);
  94. double zr1 = Math::cos(lat1);
  95. for(int j = lons; j >= 1; j--) {
  96. double lng0 = 2 * Math_PI * (double) (j - 1) / lons;
  97. double x0 = Math::cos(lng0);
  98. double y0 = Math::sin(lng0);
  99. double lng1 = 2 * Math_PI * (double) (j) / lons;
  100. double x1 = Math::cos(lng1);
  101. double y1 = Math::sin(lng1);
  102. Vector3 v4=Vector3(x0 * zr0, z0, y0 *zr0)*size;
  103. Vector3 v3=Vector3(x0 * zr1, z1, y0 *zr1)*size;
  104. Vector3 v2=Vector3(x1 * zr1, z1, y1 *zr1)*size;
  105. Vector3 v1=Vector3(x1 * zr0, z0, y1 *zr0)*size;
  106. Vector<Vector3> line;
  107. line.push_back(v1);
  108. line.push_back(v2);
  109. line.push_back(v3);
  110. line.push_back(v4);
  111. points.push_back(v1);
  112. points.push_back(v2);
  113. points.push_back(v3);
  114. points.push_back(v1);
  115. points.push_back(v3);
  116. points.push_back(v4);
  117. normals.push_back(v1.normalized());
  118. normals.push_back(v2.normalized());
  119. normals.push_back(v3.normalized());
  120. normals.push_back(v1.normalized());
  121. normals.push_back(v3.normalized());
  122. normals.push_back(v4.normalized());
  123. }
  124. }
  125. } else if (shape->cast_to<BoxShape>()) {
  126. BoxShape *shapeptr=shape->cast_to<BoxShape>();
  127. for (int i=0;i<6;i++) {
  128. Vector3 face_points[4];
  129. for (int j=0;j<4;j++) {
  130. float v[3];
  131. v[0]=1.0;
  132. v[1]=1-2*((j>>1)&1);
  133. v[2]=v[1]*(1-2*(j&1));
  134. for (int k=0;k<3;k++) {
  135. if (i<3)
  136. face_points[j][(i+k)%3]=v[k]*(i>=3?-1:1);
  137. else
  138. face_points[3-j][(i+k)%3]=v[k]*(i>=3?-1:1);
  139. }
  140. }
  141. Vector3 normal;
  142. normal[i%3]=(i>=3?-1:1);
  143. for(int j=0;j<4;j++)
  144. face_points[j]*=shapeptr->get_extents();
  145. points.push_back(face_points[0]);
  146. points.push_back(face_points[1]);
  147. points.push_back(face_points[2]);
  148. points.push_back(face_points[0]);
  149. points.push_back(face_points[2]);
  150. points.push_back(face_points[3]);
  151. for(int n=0;n<6;n++)
  152. normals.push_back(normal);
  153. }
  154. } else if (shape->cast_to<ConvexPolygonShape>()) {
  155. ConvexPolygonShape *shapeptr=shape->cast_to<ConvexPolygonShape>();
  156. Geometry::MeshData md;
  157. QuickHull::build(Variant(shapeptr->get_points()),md);
  158. for(int i=0;i<md.faces.size();i++) {
  159. for(int j=2;j<md.faces[i].indices.size();j++) {
  160. points.push_back(md.vertices[md.faces[i].indices[0]]);
  161. points.push_back(md.vertices[md.faces[i].indices[j-1]]);
  162. points.push_back(md.vertices[md.faces[i].indices[j]]);
  163. normals.push_back(md.faces[i].plane.normal);
  164. normals.push_back(md.faces[i].plane.normal);
  165. normals.push_back(md.faces[i].plane.normal);
  166. }
  167. }
  168. } else if (shape->cast_to<ConcavePolygonShape>()) {
  169. ConcavePolygonShape *shapeptr=shape->cast_to<ConcavePolygonShape>();
  170. points = shapeptr->get_faces();
  171. for(int i=0;i<points.size()/3;i++) {
  172. Vector3 n = Plane( points[i*3+0],points[i*3+1],points[i*3+2] ).normal;
  173. normals.push_back(n);
  174. normals.push_back(n);
  175. normals.push_back(n);
  176. }
  177. } else if (shape->cast_to<CapsuleShape>()) {
  178. CapsuleShape *shapeptr=shape->cast_to<CapsuleShape>();
  179. DVector<Plane> planes = Geometry::build_capsule_planes(shapeptr->get_radius(), shapeptr->get_height()/2.0, 12, Vector3::AXIS_Z);
  180. Geometry::MeshData md = Geometry::build_convex_mesh(planes);
  181. for(int i=0;i<md.faces.size();i++) {
  182. for(int j=2;j<md.faces[i].indices.size();j++) {
  183. points.push_back(md.vertices[md.faces[i].indices[0]]);
  184. points.push_back(md.vertices[md.faces[i].indices[j-1]]);
  185. points.push_back(md.vertices[md.faces[i].indices[j]]);
  186. normals.push_back(md.faces[i].plane.normal);
  187. normals.push_back(md.faces[i].plane.normal);
  188. normals.push_back(md.faces[i].plane.normal);
  189. }
  190. }
  191. } else if (shape->cast_to<PlaneShape>()) {
  192. PlaneShape *shapeptr=shape->cast_to<PlaneShape>();
  193. Plane p = shapeptr->get_plane();
  194. Vector3 n1 = p.get_any_perpendicular_normal();
  195. Vector3 n2 = p.normal.cross(n1).normalized();
  196. Vector3 pface[4]={
  197. p.normal*p.d+n1*100.0+n2*100.0,
  198. p.normal*p.d+n1*100.0+n2*-100.0,
  199. p.normal*p.d+n1*-100.0+n2*-100.0,
  200. p.normal*p.d+n1*-100.0+n2*100.0,
  201. };
  202. points.push_back(pface[0]);
  203. points.push_back(pface[1]);
  204. points.push_back(pface[2]);
  205. points.push_back(pface[0]);
  206. points.push_back(pface[2]);
  207. points.push_back(pface[3]);
  208. normals.push_back(p.normal);
  209. normals.push_back(p.normal);
  210. normals.push_back(p.normal);
  211. normals.push_back(p.normal);
  212. normals.push_back(p.normal);
  213. normals.push_back(p.normal);
  214. }
  215. if (!points.size())
  216. return;
  217. RID material = VisualServer::get_singleton()->fixed_material_create();
  218. VisualServer::get_singleton()->fixed_material_set_param(material,VS::FIXED_MATERIAL_PARAM_DIFFUSE,Color(0,0.6,0.7,0.3));
  219. VisualServer::get_singleton()->fixed_material_set_param(material,VS::FIXED_MATERIAL_PARAM_EMISSION,0.7);
  220. if (normals.size()==0)
  221. VisualServer::get_singleton()->material_set_flag(material,VS::MATERIAL_FLAG_UNSHADED,true);
  222. VisualServer::get_singleton()->material_set_flag(material,VS::MATERIAL_FLAG_DOUBLE_SIDED,true);
  223. Array d;
  224. d.resize(VS::ARRAY_MAX);
  225. d[VS::ARRAY_VERTEX]=points;
  226. if (normals.size())
  227. d[VS::ARRAY_NORMAL]=normals;
  228. VisualServer::get_singleton()->mesh_add_surface(indicator,pt,d);
  229. VisualServer::get_singleton()->mesh_surface_set_material(indicator,0,material,true);
  230. }
  231. */
  232. void CollisionShape::_add_to_collision_object(Object* p_cshape) {
  233. if (unparenting)
  234. return;
  235. CollisionObject *co=p_cshape->cast_to<CollisionObject>();
  236. ERR_FAIL_COND(!co);
  237. if (shape.is_valid()) {
  238. update_shape_index=co->get_shape_count();
  239. co->add_shape(shape,get_transform());
  240. if (trigger)
  241. co->set_shape_as_trigger( co->get_shape_count() -1, true );
  242. } else {
  243. update_shape_index=-1;
  244. }
  245. }
  246. void CollisionShape::_notification(int p_what) {
  247. switch(p_what) {
  248. case NOTIFICATION_ENTER_TREE: {
  249. unparenting=false;
  250. can_update_body=get_tree()->is_editor_hint();
  251. set_notify_local_transform(!can_update_body);
  252. if (get_tree()->is_debugging_collisions_hint()) {
  253. _create_debug_shape();
  254. }
  255. //indicator_instance = VisualServer::get_singleton()->instance_create2(indicator,get_world()->get_scenario());
  256. } break;
  257. case NOTIFICATION_TRANSFORM_CHANGED: {
  258. // VisualServer::get_singleton()->instance_set_transform(indicator_instance,get_global_transform());
  259. if (can_update_body && updating_body) {
  260. _update_body();
  261. }
  262. } break;
  263. case NOTIFICATION_EXIT_TREE: {
  264. /* if (indicator_instance.is_valid()) {
  265. VisualServer::get_singleton()->free(indicator_instance);
  266. indicator_instance=RID();
  267. }*/
  268. can_update_body=false;
  269. set_notify_local_transform(false);
  270. if (debug_shape) {
  271. debug_shape->queue_delete();
  272. debug_shape=NULL;
  273. }
  274. } break;
  275. case NOTIFICATION_UNPARENTED: {
  276. unparenting=true;
  277. if (can_update_body && updating_body)
  278. _update_body();
  279. } break;
  280. case NOTIFICATION_PARENTED: {
  281. if (can_update_body && updating_body)
  282. _update_body();
  283. } break;
  284. case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
  285. if (!can_update_body && update_shape_index>=0) {
  286. CollisionObject *co = get_parent()->cast_to<CollisionObject>();
  287. if (co) {
  288. co->set_shape_transform(update_shape_index,get_transform());
  289. }
  290. }
  291. } break;
  292. }
  293. }
  294. void CollisionShape::resource_changed(RES res) {
  295. update_gizmo();
  296. }
  297. void CollisionShape::_set_update_shape_index(int p_index) {
  298. update_shape_index=p_index;
  299. }
  300. int CollisionShape::_get_update_shape_index() const{
  301. return update_shape_index;
  302. }
  303. void CollisionShape::_bind_methods() {
  304. //not sure if this should do anything
  305. ObjectTypeDB::bind_method(_MD("resource_changed","resource"),&CollisionShape::resource_changed);
  306. ObjectTypeDB::bind_method(_MD("set_shape","shape"),&CollisionShape::set_shape);
  307. ObjectTypeDB::bind_method(_MD("get_shape"),&CollisionShape::get_shape);
  308. ObjectTypeDB::bind_method(_MD("_add_to_collision_object"),&CollisionShape::_add_to_collision_object);
  309. ObjectTypeDB::bind_method(_MD("set_trigger","enable"),&CollisionShape::set_trigger);
  310. ObjectTypeDB::bind_method(_MD("is_trigger"),&CollisionShape::is_trigger);
  311. ObjectTypeDB::bind_method(_MD("make_convex_from_brothers"),&CollisionShape::make_convex_from_brothers);
  312. ObjectTypeDB::set_method_flags("CollisionShape","make_convex_from_brothers",METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR);
  313. ObjectTypeDB::bind_method(_MD("_set_update_shape_index","index"),&CollisionShape::_set_update_shape_index);
  314. ObjectTypeDB::bind_method(_MD("_get_update_shape_index"),&CollisionShape::_get_update_shape_index);
  315. ObjectTypeDB::bind_method(_MD("get_collision_object_shape_index"),&CollisionShape::get_collision_object_shape_index);
  316. ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape"), _SCS("set_shape"), _SCS("get_shape"));
  317. ADD_PROPERTY(PropertyInfo(Variant::BOOL,"trigger"),_SCS("set_trigger"),_SCS("is_trigger"));
  318. ADD_PROPERTY( PropertyInfo( Variant::INT, "_update_shape_index", PROPERTY_HINT_NONE, "",PROPERTY_USAGE_NOEDITOR), _SCS("_set_update_shape_index"), _SCS("_get_update_shape_index"));
  319. }
  320. void CollisionShape::set_shape(const Ref<Shape> &p_shape) {
  321. if (!shape.is_null())
  322. shape->unregister_owner(this);
  323. shape=p_shape;
  324. if (!shape.is_null())
  325. shape->register_owner(this);
  326. update_gizmo();
  327. if (updating_body) {
  328. _update_body();
  329. } else if (can_update_body && update_shape_index>=0 && is_inside_tree()){
  330. CollisionObject *co = get_parent()->cast_to<CollisionObject>();
  331. if (co) {
  332. co->set_shape(update_shape_index,p_shape);
  333. }
  334. }
  335. }
  336. Ref<Shape> CollisionShape::get_shape() const {
  337. return shape;
  338. }
  339. void CollisionShape::set_updating_body(bool p_update) {
  340. updating_body=p_update;
  341. }
  342. bool CollisionShape::is_updating_body() const {
  343. return updating_body;
  344. }
  345. void CollisionShape::set_trigger(bool p_trigger) {
  346. trigger=p_trigger;
  347. if (updating_body) {
  348. _update_body();
  349. } else if (can_update_body && update_shape_index>=0 && is_inside_tree()){
  350. CollisionObject *co = get_parent()->cast_to<CollisionObject>();
  351. if (co) {
  352. co->set_shape_as_trigger(update_shape_index,p_trigger);
  353. }
  354. }
  355. }
  356. bool CollisionShape::is_trigger() const{
  357. return trigger;
  358. }
  359. CollisionShape::CollisionShape() {
  360. //indicator = VisualServer::get_singleton()->mesh_create();
  361. updating_body=true;
  362. unparenting=false;
  363. update_shape_index=-1;
  364. trigger=false;
  365. can_update_body=false;
  366. debug_shape=NULL;
  367. }
  368. CollisionShape::~CollisionShape() {
  369. if (!shape.is_null())
  370. shape->unregister_owner(this);
  371. //VisualServer::get_singleton()->free(indicator);
  372. }
  373. void CollisionShape::_create_debug_shape() {
  374. if (debug_shape) {
  375. debug_shape->queue_delete();;
  376. debug_shape=NULL;
  377. }
  378. Ref<Shape> s = get_shape();
  379. if (s.is_null())
  380. return;
  381. Ref<Mesh> mesh = s->get_debug_mesh();
  382. MeshInstance *mi = memnew( MeshInstance );
  383. mi->set_mesh(mesh);
  384. add_child(mi);
  385. debug_shape=mi;
  386. }
  387. #if 0
  388. #include "body_volume.h"
  389. #include "scene/3d/physics_body.h"
  390. #include "geometry.h"
  391. #define ADD_TRIANGLE( m_a, m_b, m_c, m_color)\
  392. {\
  393. Vector<Vector3> points;\
  394. points.resize(3);\
  395. points[0]=m_a;\
  396. points[1]=m_b;\
  397. points[2]=m_c;\
  398. Vector<Color> colors;\
  399. colors.resize(3);\
  400. colors[0]=m_color;\
  401. colors[1]=m_color;\
  402. colors[2]=m_color;\
  403. vs->poly_add_primitive(p_indicator,points,Vector<Vector3>(),colors,Vector<Vector3>());\
  404. }
  405. void CollisionShape::_notification(int p_what) {
  406. switch (p_what) {
  407. case NOTIFICATION_ENTER_SCENE: {
  408. if (get_root_node()->get_editor() && !indicator.is_valid()) {
  409. indicator=VisualServer::get_singleton()->poly_create();
  410. RID mat=VisualServer::get_singleton()->fixed_material_create();
  411. VisualServer::get_singleton()->material_set_flag( mat, VisualServer::MATERIAL_FLAG_UNSHADED, true );
  412. VisualServer::get_singleton()->material_set_flag( mat, VisualServer::MATERIAL_FLAG_WIREFRAME, true );
  413. VisualServer::get_singleton()->material_set_flag( mat, VisualServer::MATERIAL_FLAG_DOUBLE_SIDED, true );
  414. VisualServer::get_singleton()->material_set_line_width( mat, 3 );
  415. VisualServer::get_singleton()->poly_set_material(indicator,mat,true);
  416. update_indicator(indicator);
  417. }
  418. if (indicator.is_valid()) {
  419. indicator_instance=VisualServer::get_singleton()->instance_create2(indicator,get_world()->get_scenario());
  420. VisualServer::get_singleton()->instance_attach_object_instance_ID(indicator_instance,get_instance_ID());
  421. }
  422. volume_changed();
  423. } break;
  424. case NOTIFICATION_EXIT_SCENE: {
  425. if (indicator_instance.is_valid()) {
  426. VisualServer::get_singleton()->free(indicator_instance);
  427. }
  428. volume_changed();
  429. } break;
  430. case NOTIFICATION_TRANSFORM_CHANGED: {
  431. if (indicator_instance.is_valid()) {
  432. VisualServer::get_singleton()->instance_set_transform(indicator_instance,get_global_transform());
  433. }
  434. volume_changed();
  435. } break;
  436. default: {}
  437. }
  438. }
  439. void CollisionShape::volume_changed() {
  440. if (indicator.is_valid())
  441. update_indicator(indicator);
  442. Object *parent=get_parent();
  443. if (!parent)
  444. return;
  445. PhysicsBody *physics_body=parent->cast_to<PhysicsBody>();
  446. ERR_EXPLAIN("CollisionShape parent is not of type PhysicsBody");
  447. ERR_FAIL_COND(!physics_body);
  448. physics_body->recompute_child_volumes();
  449. }
  450. RID CollisionShape::_get_visual_instance_rid() const {
  451. return indicator_instance;
  452. }
  453. void CollisionShape::_bind_methods() {
  454. ObjectTypeDB::bind_method("_get_visual_instance_rid",&CollisionShape::_get_visual_instance_rid);
  455. }
  456. CollisionShape::CollisionShape() {
  457. }
  458. CollisionShape::~CollisionShape() {
  459. if (indicator.is_valid()) {
  460. VisualServer::get_singleton()->free(indicator);
  461. }
  462. }
  463. void CollisionShapeSphere::_set(const String& p_name, const Variant& p_value) {
  464. if (p_name=="radius") {
  465. radius=p_value;
  466. volume_changed();
  467. }
  468. }
  469. Variant CollisionShapeSphere::_get(const String& p_name) const {
  470. if (p_name=="radius") {
  471. return radius;
  472. }
  473. return Variant();
  474. }
  475. void CollisionShapeSphere::_get_property_list( List<PropertyInfo> *p_list) const {
  476. p_list->push_back( PropertyInfo(Variant::REAL,"radius",PROPERTY_HINT_RANGE,"0.01,16384,0.01") );
  477. }
  478. void CollisionShapeSphere::update_indicator(RID p_indicator) {
  479. VisualServer *vs=VisualServer::get_singleton();
  480. vs->poly_clear(p_indicator);
  481. Color col(0.4,1.0,1.0,0.5);
  482. int lats=6;
  483. int lons=12;
  484. float size=radius;
  485. for(int i = 1; i <= lats; i++) {
  486. double lat0 = Math_PI * (-0.5 + (double) (i - 1) / lats);
  487. double z0 = Math::sin(lat0);
  488. double zr0 = Math::cos(lat0);
  489. double lat1 = Math_PI * (-0.5 + (double) i / lats);
  490. double z1 = Math::sin(lat1);
  491. double zr1 = Math::cos(lat1);
  492. for(int j = lons; j >= 1; j--) {
  493. double lng0 = 2 * Math_PI * (double) (j - 1) / lons;
  494. double x0 = Math::cos(lng0);
  495. double y0 = Math::sin(lng0);
  496. double lng1 = 2 * Math_PI * (double) (j) / lons;
  497. double x1 = Math::cos(lng1);
  498. double y1 = Math::sin(lng1);
  499. Vector3 v4=Vector3(x0 * zr0, z0, y0 *zr0)*size;
  500. Vector3 v3=Vector3(x0 * zr1, z1, y0 *zr1)*size;
  501. Vector3 v2=Vector3(x1 * zr1, z1, y1 *zr1)*size;
  502. Vector3 v1=Vector3(x1 * zr0, z0, y1 *zr0)*size;
  503. Vector<Vector3> line;
  504. line.push_back(v1);
  505. line.push_back(v2);
  506. line.push_back(v3);
  507. line.push_back(v4);
  508. Vector<Color> cols;
  509. cols.push_back(col);
  510. cols.push_back(col);
  511. cols.push_back(col);
  512. cols.push_back(col);
  513. VisualServer::get_singleton()->poly_add_primitive(p_indicator,line,Vector<Vector3>(),cols,Vector<Vector3>());
  514. }
  515. }
  516. }
  517. void CollisionShapeSphere::append_to_volume(Ref<Shape> p_volume) {
  518. p_volume->add_sphere_shape(radius,get_transform());
  519. }
  520. CollisionShapeSphere::CollisionShapeSphere() {
  521. radius=1.0;
  522. }
  523. /* BOX */
  524. void CollisionShapeBox::_set(const String& p_name, const Variant& p_value) {
  525. if (p_name=="half_extents") {
  526. half_extents=p_value;
  527. volume_changed();
  528. }
  529. }
  530. Variant CollisionShapeBox::_get(const String& p_name) const {
  531. if (p_name=="half_extents") {
  532. return half_extents;
  533. }
  534. return Variant();
  535. }
  536. void CollisionShapeBox::_get_property_list( List<PropertyInfo> *p_list) const {
  537. p_list->push_back( PropertyInfo(Variant::VECTOR3,"half_extents" ) );
  538. }
  539. void CollisionShapeBox::update_indicator(RID p_indicator) {
  540. VisualServer *vs=VisualServer::get_singleton();
  541. vs->poly_clear(p_indicator);
  542. Color col(0.4,1.0,1.0,0.5);
  543. for (int i=0;i<6;i++) {
  544. Vector3 face_points[4];
  545. for (int j=0;j<4;j++) {
  546. float v[3];
  547. v[0]=1.0;
  548. v[1]=1-2*((j>>1)&1);
  549. v[2]=v[1]*(1-2*(j&1));
  550. for (int k=0;k<3;k++) {
  551. if (i<3)
  552. face_points[j][(i+k)%3]=v[k]*(i>=3?-1:1);
  553. else
  554. face_points[3-j][(i+k)%3]=v[k]*(i>=3?-1:1);
  555. }
  556. }
  557. for(int j=0;j<4;j++)
  558. face_points[i]*=half_extents;
  559. ADD_TRIANGLE(face_points[0],face_points[1],face_points[2],col);
  560. ADD_TRIANGLE(face_points[2],face_points[3],face_points[0],col);
  561. }
  562. }
  563. void CollisionShapeBox::append_to_volume(Ref<Shape> p_volume) {
  564. p_volume->add_box_shape(half_extents,get_transform());
  565. }
  566. CollisionShapeBox::CollisionShapeBox() {
  567. half_extents=Vector3(1,1,1);
  568. }
  569. /* CYLINDER */
  570. void CollisionShapeCylinder::_set(const String& p_name, const Variant& p_value) {
  571. if (p_name=="radius") {
  572. radius=p_value;
  573. volume_changed();
  574. }
  575. if (p_name=="height") {
  576. height=p_value;
  577. volume_changed();
  578. }
  579. }
  580. Variant CollisionShapeCylinder::_get(const String& p_name) const {
  581. if (p_name=="radius") {
  582. return radius;
  583. }
  584. if (p_name=="height") {
  585. return height;
  586. }
  587. return Variant();
  588. }
  589. void CollisionShapeCylinder::_get_property_list( List<PropertyInfo> *p_list) const {
  590. p_list->push_back( PropertyInfo(Variant::REAL,"radius",PROPERTY_HINT_RANGE,"0.01,16384,0.01") );
  591. p_list->push_back( PropertyInfo(Variant::REAL,"height",PROPERTY_HINT_RANGE,"0.01,16384,0.01") );
  592. }
  593. void CollisionShapeCylinder::update_indicator(RID p_indicator) {
  594. VisualServer *vs=VisualServer::get_singleton();
  595. vs->poly_clear(p_indicator);
  596. Color col(0.4,1.0,1.0,0.5);
  597. DVector<Plane> planes = Geometry::build_cylinder_planes(radius, height, 12, Vector3::AXIS_Z);
  598. Geometry::MeshData md = Geometry::build_convex_mesh(planes);
  599. for(int i=0;i<md.faces.size();i++) {
  600. for(int j=2;j<md.faces[i].indices.size();j++) {
  601. ADD_TRIANGLE(md.vertices[md.faces[i].indices[0]],md.vertices[md.faces[i].indices[j-1]],md.vertices[md.faces[i].indices[j]],col);
  602. }
  603. }
  604. }
  605. void CollisionShapeCylinder::append_to_volume(Ref<Shape> p_volume) {
  606. p_volume->add_cylinder_shape(radius,height*2.0,get_transform());
  607. }
  608. CollisionShapeCylinder::CollisionShapeCylinder() {
  609. height=1;
  610. radius=1;
  611. }
  612. /* CAPSULE */
  613. void CollisionShapeCapsule::_set(const String& p_name, const Variant& p_value) {
  614. if (p_name=="radius") {
  615. radius=p_value;
  616. volume_changed();
  617. }
  618. if (p_name=="height") {
  619. height=p_value;
  620. volume_changed();
  621. }
  622. }
  623. Variant CollisionShapeCapsule::_get(const String& p_name) const {
  624. if (p_name=="radius") {
  625. return radius;
  626. }
  627. if (p_name=="height") {
  628. return height;
  629. }
  630. return Variant();
  631. }
  632. void CollisionShapeCapsule::_get_property_list( List<PropertyInfo> *p_list) const {
  633. p_list->push_back( PropertyInfo(Variant::REAL,"radius",PROPERTY_HINT_RANGE,"0.01,16384,0.01") );
  634. p_list->push_back( PropertyInfo(Variant::REAL,"height",PROPERTY_HINT_RANGE,"0.01,16384,0.01") );
  635. }
  636. void CollisionShapeCapsule::update_indicator(RID p_indicator) {
  637. VisualServer *vs=VisualServer::get_singleton();
  638. vs->poly_clear(p_indicator);
  639. Color col(0.4,1.0,1.0,0.5);
  640. DVector<Plane> planes = Geometry::build_capsule_planes(radius, height, 12, 3, Vector3::AXIS_Z);
  641. Geometry::MeshData md = Geometry::build_convex_mesh(planes);
  642. for(int i=0;i<md.faces.size();i++) {
  643. for(int j=2;j<md.faces[i].indices.size();j++) {
  644. ADD_TRIANGLE(md.vertices[md.faces[i].indices[0]],md.vertices[md.faces[i].indices[j-1]],md.vertices[md.faces[i].indices[j]],col);
  645. }
  646. }
  647. }
  648. void CollisionShapeCapsule::append_to_volume(Ref<Shape> p_volume) {
  649. p_volume->add_capsule_shape(radius,height,get_transform());
  650. }
  651. CollisionShapeCapsule::CollisionShapeCapsule() {
  652. height=1;
  653. radius=1;
  654. }
  655. #endif