primitive_meshes.cpp 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490
  1. /*************************************************************************/
  2. /* primitive_meshes.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
  9. /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /*************************************************************************/
  30. #include "primitive_meshes.h"
  31. #include "servers/visual_server.h"
  32. /**
  33. PrimitiveMesh
  34. */
  35. void PrimitiveMesh::_update() const {
  36. Array arr;
  37. arr.resize(VS::ARRAY_MAX);
  38. _create_mesh_array(arr);
  39. PoolVector<Vector3> points = arr[VS::ARRAY_VERTEX];
  40. aabb = Rect3();
  41. int pc = points.size();
  42. ERR_FAIL_COND(pc == 0);
  43. {
  44. PoolVector<Vector3>::Read r = points.read();
  45. for (int i = 0; i < pc; i++) {
  46. if (i == 0)
  47. aabb.position = r[i];
  48. else
  49. aabb.expand_to(r[i]);
  50. }
  51. }
  52. // in with the new
  53. VisualServer::get_singleton()->mesh_clear(mesh);
  54. VisualServer::get_singleton()->mesh_add_surface_from_arrays(mesh, (VisualServer::PrimitiveType)primitive_type, arr);
  55. VisualServer::get_singleton()->mesh_surface_set_material(mesh, 0, material.is_null() ? RID() : material->get_rid());
  56. pending_request = false;
  57. _clear_triangle_mesh();
  58. }
  59. void PrimitiveMesh::_request_update() {
  60. if (pending_request)
  61. return;
  62. _update();
  63. }
  64. int PrimitiveMesh::get_surface_count() const {
  65. return 1;
  66. }
  67. int PrimitiveMesh::surface_get_array_len(int p_idx) const {
  68. ERR_FAIL_INDEX_V(p_idx, 1, -1);
  69. if (pending_request) {
  70. _update();
  71. }
  72. return VisualServer::get_singleton()->mesh_surface_get_array_len(mesh, 0);
  73. }
  74. int PrimitiveMesh::surface_get_array_index_len(int p_idx) const {
  75. ERR_FAIL_INDEX_V(p_idx, 1, -1);
  76. if (pending_request) {
  77. _update();
  78. }
  79. return VisualServer::get_singleton()->mesh_surface_get_array_index_len(mesh, 0);
  80. }
  81. Array PrimitiveMesh::surface_get_arrays(int p_surface) const {
  82. ERR_FAIL_INDEX_V(p_surface, 1, Array());
  83. if (pending_request) {
  84. _update();
  85. }
  86. return VisualServer::get_singleton()->mesh_surface_get_arrays(mesh, 0);
  87. }
  88. Array PrimitiveMesh::surface_get_blend_shape_arrays(int p_surface) const {
  89. ERR_FAIL_INDEX_V(p_surface, 1, Array());
  90. if (pending_request) {
  91. _update();
  92. }
  93. return Array();
  94. }
  95. uint32_t PrimitiveMesh::surface_get_format(int p_idx) const {
  96. ERR_FAIL_INDEX_V(p_idx, 1, 0);
  97. if (pending_request) {
  98. _update();
  99. }
  100. return VisualServer::get_singleton()->mesh_surface_get_format(mesh, 0);
  101. }
  102. Mesh::PrimitiveType PrimitiveMesh::surface_get_primitive_type(int p_idx) const {
  103. return primitive_type;
  104. }
  105. Ref<Material> PrimitiveMesh::surface_get_material(int p_idx) const {
  106. ERR_FAIL_INDEX_V(p_idx, 1, NULL);
  107. return material;
  108. }
  109. int PrimitiveMesh::get_blend_shape_count() const {
  110. return 0;
  111. }
  112. StringName PrimitiveMesh::get_blend_shape_name(int p_index) const {
  113. return StringName();
  114. }
  115. Rect3 PrimitiveMesh::get_aabb() const {
  116. if (pending_request) {
  117. _update();
  118. }
  119. return aabb;
  120. }
  121. RID PrimitiveMesh::get_rid() const {
  122. if (pending_request) {
  123. _update();
  124. }
  125. return mesh;
  126. }
  127. void PrimitiveMesh::_bind_methods() {
  128. ClassDB::bind_method(D_METHOD("_update"), &PrimitiveMesh::_update);
  129. ClassDB::bind_method(D_METHOD("set_material", "material"), &PrimitiveMesh::set_material);
  130. ClassDB::bind_method(D_METHOD("get_material"), &PrimitiveMesh::get_material);
  131. ClassDB::bind_method(D_METHOD("get_mesh_arrays"), &PrimitiveMesh::get_mesh_arrays);
  132. ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "Material"), "set_material", "get_material");
  133. }
  134. void PrimitiveMesh::set_material(const Ref<Material> &p_material) {
  135. material = p_material;
  136. if (!pending_request) {
  137. // just apply it, else it'll happen when _update is called.
  138. VisualServer::get_singleton()->mesh_surface_set_material(mesh, 0, material.is_null() ? RID() : material->get_rid());
  139. _change_notify();
  140. emit_changed();
  141. };
  142. }
  143. Ref<Material> PrimitiveMesh::get_material() const {
  144. return material;
  145. }
  146. Array PrimitiveMesh::get_mesh_arrays() const {
  147. return surface_get_arrays(0);
  148. }
  149. PrimitiveMesh::PrimitiveMesh() {
  150. // defaults
  151. mesh = VisualServer::get_singleton()->mesh_create();
  152. // assume primitive triangles as the type, correct for all but one and it will change this :)
  153. primitive_type = Mesh::PRIMITIVE_TRIANGLES;
  154. // make sure we do an update after we've finished constructing our object
  155. pending_request = true;
  156. }
  157. PrimitiveMesh::~PrimitiveMesh() {
  158. VisualServer::get_singleton()->free(mesh);
  159. }
  160. /**
  161. CapsuleMesh
  162. */
  163. void CapsuleMesh::_create_mesh_array(Array &p_arr) const {
  164. int i, j, prevrow, thisrow, point;
  165. float x, y, z, u, v, w;
  166. float onethird = 1.0 / 3.0;
  167. float twothirds = 2.0 / 3.0;
  168. // note, this has been aligned with our collision shape but I've left the descriptions as top/middle/bottom
  169. PoolVector<Vector3> points;
  170. PoolVector<Vector3> normals;
  171. PoolVector<float> tangents;
  172. PoolVector<Vector2> uvs;
  173. PoolVector<int> indices;
  174. point = 0;
  175. #define ADD_TANGENT(m_x, m_y, m_z, m_d) \
  176. tangents.push_back(m_x); \
  177. tangents.push_back(m_y); \
  178. tangents.push_back(m_z); \
  179. tangents.push_back(m_d);
  180. /* top hemisphere */
  181. thisrow = 0;
  182. prevrow = 0;
  183. for (j = 0; j <= (rings + 1); j++) {
  184. v = j;
  185. v /= (rings + 1);
  186. w = sin(0.5 * Math_PI * v);
  187. z = radius * cos(0.5 * Math_PI * v);
  188. for (i = 0; i <= radial_segments; i++) {
  189. u = i;
  190. u /= radial_segments;
  191. x = sin(u * (Math_PI * 2.0));
  192. y = -cos(u * (Math_PI * 2.0));
  193. Vector3 p = Vector3(x * radius * w, y * radius * w, z);
  194. points.push_back(p + Vector3(0.0, 0.0, 0.5 * mid_height));
  195. normals.push_back(p.normalized());
  196. ADD_TANGENT(y, -x, 0.0, -1.0)
  197. uvs.push_back(Vector2(u, v * onethird));
  198. point++;
  199. if (i > 0 && j > 0) {
  200. indices.push_back(prevrow + i - 1);
  201. indices.push_back(prevrow + i);
  202. indices.push_back(thisrow + i - 1);
  203. indices.push_back(prevrow + i);
  204. indices.push_back(thisrow + i);
  205. indices.push_back(thisrow + i - 1);
  206. };
  207. };
  208. prevrow = thisrow;
  209. thisrow = point;
  210. };
  211. /* cylinder */
  212. thisrow = point;
  213. prevrow = 0;
  214. for (j = 0; j <= (rings + 1); j++) {
  215. v = j;
  216. v /= (rings + 1);
  217. z = mid_height * v;
  218. z = (mid_height * 0.5) - z;
  219. for (i = 0; i <= radial_segments; i++) {
  220. u = i;
  221. u /= radial_segments;
  222. x = sin(u * (Math_PI * 2.0));
  223. y = -cos(u * (Math_PI * 2.0));
  224. Vector3 p = Vector3(x * radius, y * radius, z);
  225. points.push_back(p);
  226. normals.push_back(Vector3(x, y, 0.0));
  227. ADD_TANGENT(y, -x, 0.0, -1.0)
  228. uvs.push_back(Vector2(u, onethird + (v * onethird)));
  229. point++;
  230. if (i > 0 && j > 0) {
  231. indices.push_back(prevrow + i - 1);
  232. indices.push_back(prevrow + i);
  233. indices.push_back(thisrow + i - 1);
  234. indices.push_back(prevrow + i);
  235. indices.push_back(thisrow + i);
  236. indices.push_back(thisrow + i - 1);
  237. };
  238. };
  239. prevrow = thisrow;
  240. thisrow = point;
  241. };
  242. /* bottom hemisphere */
  243. thisrow = point;
  244. prevrow = 0;
  245. for (j = 0; j <= (rings + 1); j++) {
  246. v = j;
  247. v /= (rings + 1);
  248. v += 1.0;
  249. w = sin(0.5 * Math_PI * v);
  250. z = radius * cos(0.5 * Math_PI * v);
  251. for (i = 0; i <= radial_segments; i++) {
  252. float u = i;
  253. u /= radial_segments;
  254. x = sin(u * (Math_PI * 2.0));
  255. y = -cos(u * (Math_PI * 2.0));
  256. Vector3 p = Vector3(x * radius * w, y * radius * w, z);
  257. points.push_back(p + Vector3(0.0, 0.0, -0.5 * mid_height));
  258. normals.push_back(p.normalized());
  259. ADD_TANGENT(y, -x, 0.0, -1.0)
  260. uvs.push_back(Vector2(u, twothirds + ((v - 1.0) * onethird)));
  261. point++;
  262. if (i > 0 && j > 0) {
  263. indices.push_back(prevrow + i - 1);
  264. indices.push_back(prevrow + i);
  265. indices.push_back(thisrow + i - 1);
  266. indices.push_back(prevrow + i);
  267. indices.push_back(thisrow + i);
  268. indices.push_back(thisrow + i - 1);
  269. };
  270. };
  271. prevrow = thisrow;
  272. thisrow = point;
  273. };
  274. p_arr[VS::ARRAY_VERTEX] = points;
  275. p_arr[VS::ARRAY_NORMAL] = normals;
  276. p_arr[VS::ARRAY_TANGENT] = tangents;
  277. p_arr[VS::ARRAY_TEX_UV] = uvs;
  278. p_arr[VS::ARRAY_INDEX] = indices;
  279. }
  280. void CapsuleMesh::_bind_methods() {
  281. ClassDB::bind_method(D_METHOD("set_radius", "radius"), &CapsuleMesh::set_radius);
  282. ClassDB::bind_method(D_METHOD("get_radius"), &CapsuleMesh::get_radius);
  283. ClassDB::bind_method(D_METHOD("set_mid_height", "mid_height"), &CapsuleMesh::set_mid_height);
  284. ClassDB::bind_method(D_METHOD("get_mid_height"), &CapsuleMesh::get_mid_height);
  285. ClassDB::bind_method(D_METHOD("set_radial_segments", "segments"), &CapsuleMesh::set_radial_segments);
  286. ClassDB::bind_method(D_METHOD("get_radial_segments"), &CapsuleMesh::get_radial_segments);
  287. ClassDB::bind_method(D_METHOD("set_rings", "rings"), &CapsuleMesh::set_rings);
  288. ClassDB::bind_method(D_METHOD("get_rings"), &CapsuleMesh::get_rings);
  289. ADD_PROPERTY(PropertyInfo(Variant::REAL, "radius", PROPERTY_HINT_RANGE, "0.1,100.0,0.1"), "set_radius", "get_radius");
  290. ADD_PROPERTY(PropertyInfo(Variant::REAL, "mid_height", PROPERTY_HINT_RANGE, "0.1,100.0,0.1"), "set_mid_height", "get_mid_height");
  291. ADD_PROPERTY(PropertyInfo(Variant::INT, "radial_segments", PROPERTY_HINT_RANGE, "1,100,1"), "set_radial_segments", "get_radial_segments");
  292. ADD_PROPERTY(PropertyInfo(Variant::INT, "rings", PROPERTY_HINT_RANGE, "1,100,1"), "set_rings", "get_rings");
  293. }
  294. void CapsuleMesh::set_radius(const float p_radius) {
  295. radius = p_radius;
  296. _request_update();
  297. }
  298. float CapsuleMesh::get_radius() const {
  299. return radius;
  300. }
  301. void CapsuleMesh::set_mid_height(const float p_mid_height) {
  302. mid_height = p_mid_height;
  303. _request_update();
  304. }
  305. float CapsuleMesh::get_mid_height() const {
  306. return mid_height;
  307. }
  308. void CapsuleMesh::set_radial_segments(const int p_segments) {
  309. radial_segments = p_segments > 4 ? p_segments : 4;
  310. _request_update();
  311. }
  312. int CapsuleMesh::get_radial_segments() const {
  313. return radial_segments;
  314. }
  315. void CapsuleMesh::set_rings(const int p_rings) {
  316. rings = p_rings > 1 ? p_rings : 1;
  317. _request_update();
  318. }
  319. int CapsuleMesh::get_rings() const {
  320. return rings;
  321. }
  322. CapsuleMesh::CapsuleMesh() {
  323. // defaults
  324. radius = 1.0;
  325. mid_height = 1.0;
  326. radial_segments = 64;
  327. rings = 8;
  328. }
  329. /**
  330. CubeMesh
  331. */
  332. void CubeMesh::_create_mesh_array(Array &p_arr) const {
  333. int i, j, prevrow, thisrow, point;
  334. float x, y, z;
  335. float onethird = 1.0 / 3.0;
  336. float twothirds = 2.0 / 3.0;
  337. Vector3 start_pos = size * -0.5;
  338. // set our bounding box
  339. PoolVector<Vector3> points;
  340. PoolVector<Vector3> normals;
  341. PoolVector<float> tangents;
  342. PoolVector<Vector2> uvs;
  343. PoolVector<int> indices;
  344. point = 0;
  345. #define ADD_TANGENT(m_x, m_y, m_z, m_d) \
  346. tangents.push_back(m_x); \
  347. tangents.push_back(m_y); \
  348. tangents.push_back(m_z); \
  349. tangents.push_back(m_d);
  350. // front + back
  351. y = start_pos.y;
  352. thisrow = point;
  353. prevrow = 0;
  354. for (j = 0; j <= subdivide_h + 1; j++) {
  355. x = start_pos.x;
  356. for (i = 0; i <= subdivide_w + 1; i++) {
  357. float u = i;
  358. float v = j;
  359. u /= (3.0 * (subdivide_w + 1.0));
  360. v /= (2.0 * (subdivide_h + 1.0));
  361. // front
  362. points.push_back(Vector3(x, -y, -start_pos.z)); // double negative on the Z!
  363. normals.push_back(Vector3(0.0, 0.0, 1.0));
  364. ADD_TANGENT(-1.0, 0.0, 0.0, -1.0);
  365. uvs.push_back(Vector2(u, v));
  366. point++;
  367. // back
  368. points.push_back(Vector3(-x, -y, start_pos.z));
  369. normals.push_back(Vector3(0.0, 0.0, -1.0));
  370. ADD_TANGENT(1.0, 0.0, 0.0, -1.0);
  371. uvs.push_back(Vector2(twothirds + u, v));
  372. point++;
  373. if (i > 0 && j > 0) {
  374. int i2 = i * 2;
  375. // front
  376. indices.push_back(prevrow + i2 - 2);
  377. indices.push_back(prevrow + i2);
  378. indices.push_back(thisrow + i2 - 2);
  379. indices.push_back(prevrow + i2);
  380. indices.push_back(thisrow + i2);
  381. indices.push_back(thisrow + i2 - 2);
  382. // back
  383. indices.push_back(prevrow + i2 - 1);
  384. indices.push_back(prevrow + i2 + 1);
  385. indices.push_back(thisrow + i2 - 1);
  386. indices.push_back(prevrow + i2 + 1);
  387. indices.push_back(thisrow + i2 + 1);
  388. indices.push_back(thisrow + i2 - 1);
  389. };
  390. x += size.x / (subdivide_w + 1.0);
  391. };
  392. y += size.y / (subdivide_h + 1.0);
  393. prevrow = thisrow;
  394. thisrow = point;
  395. };
  396. // left + right
  397. y = start_pos.y;
  398. thisrow = point;
  399. prevrow = 0;
  400. for (j = 0; j <= (subdivide_h + 1); j++) {
  401. z = start_pos.z;
  402. for (i = 0; i <= (subdivide_d + 1); i++) {
  403. float u = i;
  404. float v = j;
  405. u /= (3.0 * (subdivide_d + 1.0));
  406. v /= (2.0 * (subdivide_h + 1.0));
  407. // right
  408. points.push_back(Vector3(-start_pos.x, -y, -z));
  409. normals.push_back(Vector3(1.0, 0.0, 0.0));
  410. ADD_TANGENT(0.0, 0.0, 1.0, -1.0);
  411. uvs.push_back(Vector2(onethird + u, v));
  412. point++;
  413. // left
  414. points.push_back(Vector3(start_pos.x, -y, z));
  415. normals.push_back(Vector3(-1.0, 0.0, 0.0));
  416. ADD_TANGENT(0.0, 0.0, -1.0, -1.0);
  417. uvs.push_back(Vector2(u, 0.5 + v));
  418. point++;
  419. if (i > 0 && j > 0) {
  420. int i2 = i * 2;
  421. // right
  422. indices.push_back(prevrow + i2 - 2);
  423. indices.push_back(prevrow + i2);
  424. indices.push_back(thisrow + i2 - 2);
  425. indices.push_back(prevrow + i2);
  426. indices.push_back(thisrow + i2);
  427. indices.push_back(thisrow + i2 - 2);
  428. // left
  429. indices.push_back(prevrow + i2 - 1);
  430. indices.push_back(prevrow + i2 + 1);
  431. indices.push_back(thisrow + i2 - 1);
  432. indices.push_back(prevrow + i2 + 1);
  433. indices.push_back(thisrow + i2 + 1);
  434. indices.push_back(thisrow + i2 - 1);
  435. };
  436. z += size.z / (subdivide_d + 1.0);
  437. };
  438. y += size.y / (subdivide_h + 1.0);
  439. prevrow = thisrow;
  440. thisrow = point;
  441. };
  442. // top + bottom
  443. z = start_pos.z;
  444. thisrow = point;
  445. prevrow = 0;
  446. for (j = 0; j <= (subdivide_d + 1); j++) {
  447. x = start_pos.x;
  448. for (i = 0; i <= (subdivide_w + 1); i++) {
  449. float u = i;
  450. float v = j;
  451. u /= (3.0 * (subdivide_w + 1.0));
  452. v /= (2.0 * (subdivide_d + 1.0));
  453. // top
  454. points.push_back(Vector3(-x, -start_pos.y, -z));
  455. normals.push_back(Vector3(0.0, 1.0, 0.0));
  456. ADD_TANGENT(1.0, 0.0, 0.0, -1.0);
  457. uvs.push_back(Vector2(onethird + u, 0.5 + v));
  458. point++;
  459. // bottom
  460. points.push_back(Vector3(x, start_pos.y, -z));
  461. normals.push_back(Vector3(0.0, -1.0, 0.0));
  462. ADD_TANGENT(-1.0, 0.0, 0.0, -1.0);
  463. uvs.push_back(Vector2(twothirds + u, 0.5 + v));
  464. point++;
  465. if (i > 0 && j > 0) {
  466. int i2 = i * 2;
  467. // top
  468. indices.push_back(prevrow + i2 - 2);
  469. indices.push_back(prevrow + i2);
  470. indices.push_back(thisrow + i2 - 2);
  471. indices.push_back(prevrow + i2);
  472. indices.push_back(thisrow + i2);
  473. indices.push_back(thisrow + i2 - 2);
  474. // bottom
  475. indices.push_back(prevrow + i2 - 1);
  476. indices.push_back(prevrow + i2 + 1);
  477. indices.push_back(thisrow + i2 - 1);
  478. indices.push_back(prevrow + i2 + 1);
  479. indices.push_back(thisrow + i2 + 1);
  480. indices.push_back(thisrow + i2 - 1);
  481. };
  482. x += size.x / (subdivide_w + 1.0);
  483. };
  484. z += size.z / (subdivide_d + 1.0);
  485. prevrow = thisrow;
  486. thisrow = point;
  487. };
  488. p_arr[VS::ARRAY_VERTEX] = points;
  489. p_arr[VS::ARRAY_NORMAL] = normals;
  490. p_arr[VS::ARRAY_TANGENT] = tangents;
  491. p_arr[VS::ARRAY_TEX_UV] = uvs;
  492. p_arr[VS::ARRAY_INDEX] = indices;
  493. }
  494. void CubeMesh::_bind_methods() {
  495. ClassDB::bind_method(D_METHOD("set_size", "size"), &CubeMesh::set_size);
  496. ClassDB::bind_method(D_METHOD("get_size"), &CubeMesh::get_size);
  497. ClassDB::bind_method(D_METHOD("set_subdivide_width", "subdivide"), &CubeMesh::set_subdivide_width);
  498. ClassDB::bind_method(D_METHOD("get_subdivide_width"), &CubeMesh::get_subdivide_width);
  499. ClassDB::bind_method(D_METHOD("set_subdivide_height", "divisions"), &CubeMesh::set_subdivide_height);
  500. ClassDB::bind_method(D_METHOD("get_subdivide_height"), &CubeMesh::get_subdivide_height);
  501. ClassDB::bind_method(D_METHOD("set_subdivide_depth", "divisions"), &CubeMesh::set_subdivide_depth);
  502. ClassDB::bind_method(D_METHOD("get_subdivide_depth"), &CubeMesh::get_subdivide_depth);
  503. ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size"), "set_size", "get_size");
  504. ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_width", PROPERTY_HINT_RANGE, "0,100,1"), "set_subdivide_width", "get_subdivide_width");
  505. ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_height", PROPERTY_HINT_RANGE, "0,100,1"), "set_subdivide_height", "get_subdivide_height");
  506. ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_depth", PROPERTY_HINT_RANGE, "0,100,1"), "set_subdivide_depth", "get_subdivide_depth");
  507. }
  508. void CubeMesh::set_size(const Vector3 &p_size) {
  509. size = p_size;
  510. _request_update();
  511. }
  512. Vector3 CubeMesh::get_size() const {
  513. return size;
  514. }
  515. void CubeMesh::set_subdivide_width(const int p_divisions) {
  516. subdivide_w = p_divisions > 0 ? p_divisions : 0;
  517. _request_update();
  518. }
  519. int CubeMesh::get_subdivide_width() const {
  520. return subdivide_w;
  521. }
  522. void CubeMesh::set_subdivide_height(const int p_divisions) {
  523. subdivide_h = p_divisions > 0 ? p_divisions : 0;
  524. _request_update();
  525. }
  526. int CubeMesh::get_subdivide_height() const {
  527. return subdivide_h;
  528. }
  529. void CubeMesh::set_subdivide_depth(const int p_divisions) {
  530. subdivide_d = p_divisions > 0 ? p_divisions : 0;
  531. _request_update();
  532. }
  533. int CubeMesh::get_subdivide_depth() const {
  534. return subdivide_d;
  535. }
  536. CubeMesh::CubeMesh() {
  537. // defaults
  538. size = Vector3(2.0, 2.0, 2.0);
  539. subdivide_w = 0;
  540. subdivide_h = 0;
  541. subdivide_d = 0;
  542. }
  543. /**
  544. CylinderMesh
  545. */
  546. void CylinderMesh::_create_mesh_array(Array &p_arr) const {
  547. int i, j, prevrow, thisrow, point;
  548. float x, y, z, u, v, radius;
  549. radius = bottom_radius > top_radius ? bottom_radius : top_radius;
  550. PoolVector<Vector3> points;
  551. PoolVector<Vector3> normals;
  552. PoolVector<float> tangents;
  553. PoolVector<Vector2> uvs;
  554. PoolVector<int> indices;
  555. point = 0;
  556. #define ADD_TANGENT(m_x, m_y, m_z, m_d) \
  557. tangents.push_back(m_x); \
  558. tangents.push_back(m_y); \
  559. tangents.push_back(m_z); \
  560. tangents.push_back(m_d);
  561. thisrow = 0;
  562. prevrow = 0;
  563. for (j = 0; j <= (rings + 1); j++) {
  564. v = j;
  565. v /= (rings + 1);
  566. radius = top_radius + ((bottom_radius - top_radius) * v);
  567. y = height * v;
  568. y = (height * 0.5) - y;
  569. for (i = 0; i <= radial_segments; i++) {
  570. u = i;
  571. u /= radial_segments;
  572. x = sin(u * (Math_PI * 2.0));
  573. z = cos(u * (Math_PI * 2.0));
  574. Vector3 p = Vector3(x * radius, y, z * radius);
  575. points.push_back(p);
  576. normals.push_back(Vector3(x, 0.0, z));
  577. ADD_TANGENT(-z, 0.0, x, -1.0)
  578. uvs.push_back(Vector2(u, v * 0.5));
  579. point++;
  580. if (i > 0 && j > 0) {
  581. indices.push_back(prevrow + i - 1);
  582. indices.push_back(prevrow + i);
  583. indices.push_back(thisrow + i - 1);
  584. indices.push_back(prevrow + i);
  585. indices.push_back(thisrow + i);
  586. indices.push_back(thisrow + i - 1);
  587. };
  588. };
  589. prevrow = thisrow;
  590. thisrow = point;
  591. };
  592. // add top
  593. if (top_radius > 0.0) {
  594. y = height * 0.5;
  595. thisrow = point;
  596. points.push_back(Vector3(0.0, y, 0.0));
  597. normals.push_back(Vector3(0.0, 1.0, 0.0));
  598. ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
  599. uvs.push_back(Vector2(0.25, 0.75));
  600. point++;
  601. for (i = 0; i <= radial_segments; i++) {
  602. float r = i;
  603. r /= radial_segments;
  604. x = sin(r * (Math_PI * 2.0));
  605. z = cos(r * (Math_PI * 2.0));
  606. u = ((x + 1.0) * 0.25);
  607. v = 0.5 + ((z + 1.0) * 0.25);
  608. Vector3 p = Vector3(x * top_radius, y, z * top_radius);
  609. points.push_back(p);
  610. normals.push_back(Vector3(0.0, 1.0, 0.0));
  611. ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
  612. uvs.push_back(Vector2(u, v));
  613. point++;
  614. if (i > 0) {
  615. indices.push_back(thisrow);
  616. indices.push_back(point - 1);
  617. indices.push_back(point - 2);
  618. };
  619. };
  620. };
  621. // add bottom
  622. if (bottom_radius > 0.0) {
  623. y = height * -0.5;
  624. thisrow = point;
  625. points.push_back(Vector3(0.0, y, 0.0));
  626. normals.push_back(Vector3(0.0, -1.0, 0.0));
  627. ADD_TANGENT(-1.0, 0.0, 0.0, -1.0)
  628. uvs.push_back(Vector2(0.75, 0.75));
  629. point++;
  630. for (i = 0; i <= radial_segments; i++) {
  631. float r = i;
  632. r /= radial_segments;
  633. x = sin(r * (Math_PI * 2.0));
  634. z = cos(r * (Math_PI * 2.0));
  635. u = 0.5 + ((x + 1.0) * 0.25);
  636. v = 1.0 - ((z + 1.0) * 0.25);
  637. Vector3 p = Vector3(x * bottom_radius, y, z * bottom_radius);
  638. points.push_back(p);
  639. normals.push_back(Vector3(0.0, -1.0, 0.0));
  640. ADD_TANGENT(-1.0, 0.0, 0.0, -1.0)
  641. uvs.push_back(Vector2(u, v));
  642. point++;
  643. if (i > 0) {
  644. indices.push_back(thisrow);
  645. indices.push_back(point - 2);
  646. indices.push_back(point - 1);
  647. };
  648. };
  649. };
  650. p_arr[VS::ARRAY_VERTEX] = points;
  651. p_arr[VS::ARRAY_NORMAL] = normals;
  652. p_arr[VS::ARRAY_TANGENT] = tangents;
  653. p_arr[VS::ARRAY_TEX_UV] = uvs;
  654. p_arr[VS::ARRAY_INDEX] = indices;
  655. }
  656. void CylinderMesh::_bind_methods() {
  657. ClassDB::bind_method(D_METHOD("set_top_radius", "radius"), &CylinderMesh::set_top_radius);
  658. ClassDB::bind_method(D_METHOD("get_top_radius"), &CylinderMesh::get_top_radius);
  659. ClassDB::bind_method(D_METHOD("set_bottom_radius", "radius"), &CylinderMesh::set_bottom_radius);
  660. ClassDB::bind_method(D_METHOD("get_bottom_radius"), &CylinderMesh::get_bottom_radius);
  661. ClassDB::bind_method(D_METHOD("set_height", "height"), &CylinderMesh::set_height);
  662. ClassDB::bind_method(D_METHOD("get_height"), &CylinderMesh::get_height);
  663. ClassDB::bind_method(D_METHOD("set_radial_segments", "segments"), &CylinderMesh::set_radial_segments);
  664. ClassDB::bind_method(D_METHOD("get_radial_segments"), &CylinderMesh::get_radial_segments);
  665. ClassDB::bind_method(D_METHOD("set_rings", "rings"), &CylinderMesh::set_rings);
  666. ClassDB::bind_method(D_METHOD("get_rings"), &CylinderMesh::get_rings);
  667. ADD_PROPERTY(PropertyInfo(Variant::REAL, "top_radius", PROPERTY_HINT_RANGE, "0.1,100.0,0.1"), "set_top_radius", "get_top_radius");
  668. ADD_PROPERTY(PropertyInfo(Variant::REAL, "bottom_radius", PROPERTY_HINT_RANGE, "0.1,100.0,0.1"), "set_bottom_radius", "get_bottom_radius");
  669. ADD_PROPERTY(PropertyInfo(Variant::REAL, "height", PROPERTY_HINT_RANGE, "0.1,100.0,0.1"), "set_height", "get_height");
  670. ADD_PROPERTY(PropertyInfo(Variant::INT, "radial_segments", PROPERTY_HINT_RANGE, "1,100,1"), "set_radial_segments", "get_radial_segments");
  671. ADD_PROPERTY(PropertyInfo(Variant::INT, "rings", PROPERTY_HINT_RANGE, "1,100,1"), "set_rings", "get_rings");
  672. }
  673. void CylinderMesh::set_top_radius(const float p_radius) {
  674. top_radius = p_radius;
  675. _request_update();
  676. }
  677. float CylinderMesh::get_top_radius() const {
  678. return top_radius;
  679. }
  680. void CylinderMesh::set_bottom_radius(const float p_radius) {
  681. bottom_radius = p_radius;
  682. _request_update();
  683. }
  684. float CylinderMesh::get_bottom_radius() const {
  685. return bottom_radius;
  686. }
  687. void CylinderMesh::set_height(const float p_height) {
  688. height = p_height;
  689. _request_update();
  690. }
  691. float CylinderMesh::get_height() const {
  692. return height;
  693. }
  694. void CylinderMesh::set_radial_segments(const int p_segments) {
  695. radial_segments = p_segments > 4 ? p_segments : 4;
  696. _request_update();
  697. }
  698. int CylinderMesh::get_radial_segments() const {
  699. return radial_segments;
  700. }
  701. void CylinderMesh::set_rings(const int p_rings) {
  702. rings = p_rings > 0 ? p_rings : 0;
  703. _request_update();
  704. }
  705. int CylinderMesh::get_rings() const {
  706. return rings;
  707. }
  708. CylinderMesh::CylinderMesh() {
  709. // defaults
  710. top_radius = 1.0;
  711. bottom_radius = 1.0;
  712. height = 2.0;
  713. radial_segments = 64;
  714. rings = 4;
  715. }
  716. /**
  717. PlaneMesh
  718. */
  719. void PlaneMesh::_create_mesh_array(Array &p_arr) const {
  720. int i, j, prevrow, thisrow, point;
  721. float x, z;
  722. Size2 start_pos = size * -0.5;
  723. PoolVector<Vector3> points;
  724. PoolVector<Vector3> normals;
  725. PoolVector<float> tangents;
  726. PoolVector<Vector2> uvs;
  727. PoolVector<int> indices;
  728. point = 0;
  729. #define ADD_TANGENT(m_x, m_y, m_z, m_d) \
  730. tangents.push_back(m_x); \
  731. tangents.push_back(m_y); \
  732. tangents.push_back(m_z); \
  733. tangents.push_back(m_d);
  734. /* top + bottom */
  735. z = start_pos.y;
  736. thisrow = point;
  737. prevrow = 0;
  738. for (j = 0; j <= (subdivide_d + 1); j++) {
  739. x = start_pos.x;
  740. for (i = 0; i <= (subdivide_w + 1); i++) {
  741. float u = i;
  742. float v = j;
  743. u /= (subdivide_w + 1.0);
  744. v /= (subdivide_d + 1.0);
  745. points.push_back(Vector3(-x, 0.0, -z));
  746. normals.push_back(Vector3(0.0, 1.0, 0.0));
  747. ADD_TANGENT(1.0, 0.0, 0.0, -1.0);
  748. uvs.push_back(Vector2(u, v));
  749. point++;
  750. if (i > 0 && j > 0) {
  751. indices.push_back(prevrow + i - 1);
  752. indices.push_back(prevrow + i);
  753. indices.push_back(thisrow + i - 1);
  754. indices.push_back(prevrow + i);
  755. indices.push_back(thisrow + i);
  756. indices.push_back(thisrow + i - 1);
  757. };
  758. x += size.x / (subdivide_w + 1.0);
  759. };
  760. z += size.y / (subdivide_d + 1.0);
  761. prevrow = thisrow;
  762. thisrow = point;
  763. };
  764. p_arr[VS::ARRAY_VERTEX] = points;
  765. p_arr[VS::ARRAY_NORMAL] = normals;
  766. p_arr[VS::ARRAY_TANGENT] = tangents;
  767. p_arr[VS::ARRAY_TEX_UV] = uvs;
  768. p_arr[VS::ARRAY_INDEX] = indices;
  769. }
  770. void PlaneMesh::_bind_methods() {
  771. ClassDB::bind_method(D_METHOD("set_size", "size"), &PlaneMesh::set_size);
  772. ClassDB::bind_method(D_METHOD("get_size"), &PlaneMesh::get_size);
  773. ClassDB::bind_method(D_METHOD("set_subdivide_width", "subdivide"), &PlaneMesh::set_subdivide_width);
  774. ClassDB::bind_method(D_METHOD("get_subdivide_width"), &PlaneMesh::get_subdivide_width);
  775. ClassDB::bind_method(D_METHOD("set_subdivide_depth", "subdivide"), &PlaneMesh::set_subdivide_depth);
  776. ClassDB::bind_method(D_METHOD("get_subdivide_depth"), &PlaneMesh::get_subdivide_depth);
  777. ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size"), "set_size", "get_size");
  778. ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_width", PROPERTY_HINT_RANGE, "0,100,1"), "set_subdivide_width", "get_subdivide_width");
  779. ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_depth", PROPERTY_HINT_RANGE, "0,100,1"), "set_subdivide_depth", "get_subdivide_depth");
  780. }
  781. void PlaneMesh::set_size(const Size2 &p_size) {
  782. size = p_size;
  783. _request_update();
  784. }
  785. Size2 PlaneMesh::get_size() const {
  786. return size;
  787. }
  788. void PlaneMesh::set_subdivide_width(const int p_divisions) {
  789. subdivide_w = p_divisions > 0 ? p_divisions : 0;
  790. _request_update();
  791. }
  792. int PlaneMesh::get_subdivide_width() const {
  793. return subdivide_w;
  794. }
  795. void PlaneMesh::set_subdivide_depth(const int p_divisions) {
  796. subdivide_d = p_divisions > 0 ? p_divisions : 0;
  797. _request_update();
  798. }
  799. int PlaneMesh::get_subdivide_depth() const {
  800. return subdivide_d;
  801. }
  802. PlaneMesh::PlaneMesh() {
  803. // defaults
  804. size = Size2(2.0, 2.0);
  805. subdivide_w = 0;
  806. subdivide_d = 0;
  807. }
  808. /**
  809. PrismMesh
  810. */
  811. void PrismMesh::_create_mesh_array(Array &p_arr) const {
  812. int i, j, prevrow, thisrow, point;
  813. float x, y, z;
  814. float onethird = 1.0 / 3.0;
  815. float twothirds = 2.0 / 3.0;
  816. Vector3 start_pos = size * -0.5;
  817. // set our bounding box
  818. PoolVector<Vector3> points;
  819. PoolVector<Vector3> normals;
  820. PoolVector<float> tangents;
  821. PoolVector<Vector2> uvs;
  822. PoolVector<int> indices;
  823. point = 0;
  824. #define ADD_TANGENT(m_x, m_y, m_z, m_d) \
  825. tangents.push_back(m_x); \
  826. tangents.push_back(m_y); \
  827. tangents.push_back(m_z); \
  828. tangents.push_back(m_d);
  829. /* front + back */
  830. y = start_pos.y;
  831. thisrow = point;
  832. prevrow = 0;
  833. for (j = 0; j <= (subdivide_h + 1); j++) {
  834. float scale = (y - start_pos.y) / size.y;
  835. float scaled_size_x = size.x * scale;
  836. float start_x = start_pos.x + (1.0 - scale) * size.x * left_to_right;
  837. float offset_front = (1.0 - scale) * onethird * left_to_right;
  838. float offset_back = (1.0 - scale) * onethird * (1.0 - left_to_right);
  839. x = 0.0;
  840. for (i = 0; i <= (subdivide_w + 1); i++) {
  841. float u = i;
  842. float v = j;
  843. u /= (3.0 * (subdivide_w + 1.0));
  844. v /= (2.0 * (subdivide_h + 1.0));
  845. u *= scale;
  846. /* front */
  847. points.push_back(Vector3(start_x + x, -y, -start_pos.z)); // double negative on the Z!
  848. normals.push_back(Vector3(0.0, 0.0, 1.0));
  849. ADD_TANGENT(-1.0, 0.0, 0.0, -1.0);
  850. uvs.push_back(Vector2(offset_front + u, v));
  851. point++;
  852. /* back */
  853. points.push_back(Vector3(start_x + scaled_size_x - x, -y, start_pos.z));
  854. normals.push_back(Vector3(0.0, 0.0, -1.0));
  855. ADD_TANGENT(1.0, 0.0, 0.0, -1.0);
  856. uvs.push_back(Vector2(twothirds + offset_back + u, v));
  857. point++;
  858. if (i > 0 && j == 1) {
  859. int i2 = i * 2;
  860. /* front */
  861. indices.push_back(prevrow + i2);
  862. indices.push_back(thisrow + i2);
  863. indices.push_back(thisrow + i2 - 2);
  864. /* back */
  865. indices.push_back(prevrow + i2 + 1);
  866. indices.push_back(thisrow + i2 + 1);
  867. indices.push_back(thisrow + i2 - 1);
  868. } else if (i > 0 && j > 0) {
  869. int i2 = i * 2;
  870. /* front */
  871. indices.push_back(prevrow + i2 - 2);
  872. indices.push_back(prevrow + i2);
  873. indices.push_back(thisrow + i2 - 2);
  874. indices.push_back(prevrow + i2);
  875. indices.push_back(thisrow + i2);
  876. indices.push_back(thisrow + i2 - 2);
  877. /* back */
  878. indices.push_back(prevrow + i2 - 1);
  879. indices.push_back(prevrow + i2 + 1);
  880. indices.push_back(thisrow + i2 - 1);
  881. indices.push_back(prevrow + i2 + 1);
  882. indices.push_back(thisrow + i2 + 1);
  883. indices.push_back(thisrow + i2 - 1);
  884. };
  885. x += scale * size.x / (subdivide_w + 1.0);
  886. };
  887. y += size.y / (subdivide_h + 1.0);
  888. prevrow = thisrow;
  889. thisrow = point;
  890. };
  891. /* left + right */
  892. Vector3 normal_left, normal_right;
  893. normal_left = Vector3(-size.y, size.x * left_to_right, 0.0);
  894. normal_right = Vector3(size.y, size.x * left_to_right, 0.0);
  895. normal_left.normalize();
  896. normal_right.normalize();
  897. y = start_pos.y;
  898. thisrow = point;
  899. prevrow = 0;
  900. for (j = 0; j <= (subdivide_h + 1); j++) {
  901. float left, right;
  902. float scale = (y - start_pos.y) / size.y;
  903. left = start_pos.x + (size.x * (1.0 - scale) * left_to_right);
  904. right = left + (size.x * scale);
  905. z = start_pos.z;
  906. for (i = 0; i <= (subdivide_d + 1); i++) {
  907. float u = i;
  908. float v = j;
  909. u /= (3.0 * (subdivide_d + 1.0));
  910. v /= (2.0 * (subdivide_h + 1.0));
  911. /* right */
  912. points.push_back(Vector3(right, -y, -z));
  913. normals.push_back(normal_right);
  914. ADD_TANGENT(0.0, 0.0, 1.0, -1.0);
  915. uvs.push_back(Vector2(onethird + u, v));
  916. point++;
  917. /* left */
  918. points.push_back(Vector3(left, -y, z));
  919. normals.push_back(normal_left);
  920. ADD_TANGENT(0.0, 0.0, -1.0, -1.0);
  921. uvs.push_back(Vector2(u, 0.5 + v));
  922. point++;
  923. if (i > 0 && j > 0) {
  924. int i2 = i * 2;
  925. /* right */
  926. indices.push_back(prevrow + i2 - 2);
  927. indices.push_back(prevrow + i2);
  928. indices.push_back(thisrow + i2 - 2);
  929. indices.push_back(prevrow + i2);
  930. indices.push_back(thisrow + i2);
  931. indices.push_back(thisrow + i2 - 2);
  932. /* left */
  933. indices.push_back(prevrow + i2 - 1);
  934. indices.push_back(prevrow + i2 + 1);
  935. indices.push_back(thisrow + i2 - 1);
  936. indices.push_back(prevrow + i2 + 1);
  937. indices.push_back(thisrow + i2 + 1);
  938. indices.push_back(thisrow + i2 - 1);
  939. };
  940. z += size.z / (subdivide_d + 1.0);
  941. };
  942. y += size.y / (subdivide_h + 1.0);
  943. prevrow = thisrow;
  944. thisrow = point;
  945. };
  946. /* bottom */
  947. z = start_pos.z;
  948. thisrow = point;
  949. prevrow = 0;
  950. for (j = 0; j <= (subdivide_d + 1); j++) {
  951. x = start_pos.x;
  952. for (i = 0; i <= (subdivide_w + 1); i++) {
  953. float u = i;
  954. float v = j;
  955. u /= (3.0 * (subdivide_w + 1.0));
  956. v /= (2.0 * (subdivide_d + 1.0));
  957. /* bottom */
  958. points.push_back(Vector3(x, start_pos.y, -z));
  959. normals.push_back(Vector3(0.0, -1.0, 0.0));
  960. ADD_TANGENT(-1.0, 0.0, 0.0, -1.0);
  961. uvs.push_back(Vector2(twothirds + u, 0.5 + v));
  962. point++;
  963. if (i > 0 && j > 0) {
  964. /* bottom */
  965. indices.push_back(prevrow + i - 1);
  966. indices.push_back(prevrow + i);
  967. indices.push_back(thisrow + i - 1);
  968. indices.push_back(prevrow + i);
  969. indices.push_back(thisrow + i);
  970. indices.push_back(thisrow + i - 1);
  971. };
  972. x += size.x / (subdivide_w + 1.0);
  973. };
  974. z += size.z / (subdivide_d + 1.0);
  975. prevrow = thisrow;
  976. thisrow = point;
  977. };
  978. p_arr[VS::ARRAY_VERTEX] = points;
  979. p_arr[VS::ARRAY_NORMAL] = normals;
  980. p_arr[VS::ARRAY_TANGENT] = tangents;
  981. p_arr[VS::ARRAY_TEX_UV] = uvs;
  982. p_arr[VS::ARRAY_INDEX] = indices;
  983. }
  984. void PrismMesh::_bind_methods() {
  985. ClassDB::bind_method(D_METHOD("set_left_to_right", "left_to_right"), &PrismMesh::set_left_to_right);
  986. ClassDB::bind_method(D_METHOD("get_left_to_right"), &PrismMesh::get_left_to_right);
  987. ClassDB::bind_method(D_METHOD("set_size", "size"), &PrismMesh::set_size);
  988. ClassDB::bind_method(D_METHOD("get_size"), &PrismMesh::get_size);
  989. ClassDB::bind_method(D_METHOD("set_subdivide_width", "segments"), &PrismMesh::set_subdivide_width);
  990. ClassDB::bind_method(D_METHOD("get_subdivide_width"), &PrismMesh::get_subdivide_width);
  991. ClassDB::bind_method(D_METHOD("set_subdivide_height", "segments"), &PrismMesh::set_subdivide_height);
  992. ClassDB::bind_method(D_METHOD("get_subdivide_height"), &PrismMesh::get_subdivide_height);
  993. ClassDB::bind_method(D_METHOD("set_subdivide_depth", "segments"), &PrismMesh::set_subdivide_depth);
  994. ClassDB::bind_method(D_METHOD("get_subdivide_depth"), &PrismMesh::get_subdivide_depth);
  995. ADD_PROPERTY(PropertyInfo(Variant::REAL, "left_to_right", PROPERTY_HINT_RANGE, "-2.0,2.0,0.1"), "set_left_to_right", "get_left_to_right");
  996. ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size", PROPERTY_HINT_RANGE, "0.1,100.0,0.1"), "set_size", "get_size");
  997. ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_width", PROPERTY_HINT_RANGE, "0,100,1"), "set_subdivide_width", "get_subdivide_width");
  998. ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_height", PROPERTY_HINT_RANGE, "0,100,1"), "set_subdivide_height", "get_subdivide_height");
  999. ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_depth", PROPERTY_HINT_RANGE, "0,100,1"), "set_subdivide_depth", "get_subdivide_depth");
  1000. }
  1001. void PrismMesh::set_left_to_right(const float p_left_to_right) {
  1002. left_to_right = p_left_to_right;
  1003. _request_update();
  1004. }
  1005. float PrismMesh::get_left_to_right() const {
  1006. return left_to_right;
  1007. }
  1008. void PrismMesh::set_size(const Vector3 &p_size) {
  1009. size = p_size;
  1010. _request_update();
  1011. }
  1012. Vector3 PrismMesh::get_size() const {
  1013. return size;
  1014. }
  1015. void PrismMesh::set_subdivide_width(const int p_divisions) {
  1016. subdivide_w = p_divisions > 0 ? p_divisions : 0;
  1017. _request_update();
  1018. }
  1019. int PrismMesh::get_subdivide_width() const {
  1020. return subdivide_w;
  1021. }
  1022. void PrismMesh::set_subdivide_height(const int p_divisions) {
  1023. subdivide_h = p_divisions > 0 ? p_divisions : 0;
  1024. _request_update();
  1025. }
  1026. int PrismMesh::get_subdivide_height() const {
  1027. return subdivide_h;
  1028. }
  1029. void PrismMesh::set_subdivide_depth(const int p_divisions) {
  1030. subdivide_d = p_divisions > 0 ? p_divisions : 0;
  1031. _request_update();
  1032. }
  1033. int PrismMesh::get_subdivide_depth() const {
  1034. return subdivide_d;
  1035. }
  1036. PrismMesh::PrismMesh() {
  1037. // defaults
  1038. left_to_right = 0.5;
  1039. size = Vector3(2.0, 2.0, 2.0);
  1040. subdivide_w = 0;
  1041. subdivide_h = 0;
  1042. subdivide_d = 0;
  1043. }
  1044. /**
  1045. QuadMesh
  1046. */
  1047. void QuadMesh::_create_mesh_array(Array &p_arr) const {
  1048. PoolVector<Vector3> faces;
  1049. PoolVector<Vector3> normals;
  1050. PoolVector<float> tangents;
  1051. PoolVector<Vector2> uvs;
  1052. faces.resize(4);
  1053. normals.resize(4);
  1054. tangents.resize(4 * 4);
  1055. uvs.resize(4);
  1056. for (int i = 0; i < 4; i++) {
  1057. static const Vector3 quad_faces[4] = {
  1058. Vector3(-1, -1, 0),
  1059. Vector3(-1, 1, 0),
  1060. Vector3(1, 1, 0),
  1061. Vector3(1, -1, 0),
  1062. };
  1063. faces.set(i, quad_faces[i]);
  1064. normals.set(i, Vector3(0, 0, 1));
  1065. tangents.set(i * 4 + 0, 1.0);
  1066. tangents.set(i * 4 + 1, 0.0);
  1067. tangents.set(i * 4 + 2, 0.0);
  1068. tangents.set(i * 4 + 3, 1.0);
  1069. static const Vector2 quad_uv[4] = {
  1070. Vector2(0, 1),
  1071. Vector2(0, 0),
  1072. Vector2(1, 0),
  1073. Vector2(1, 1),
  1074. };
  1075. uvs.set(i, quad_uv[i]);
  1076. }
  1077. p_arr[ARRAY_VERTEX] = faces;
  1078. p_arr[ARRAY_NORMAL] = normals;
  1079. p_arr[ARRAY_TANGENT] = tangents;
  1080. p_arr[ARRAY_TEX_UV] = uvs;
  1081. };
  1082. void QuadMesh::_bind_methods() {
  1083. // nothing here yet...
  1084. }
  1085. QuadMesh::QuadMesh() {
  1086. primitive_type = PRIMITIVE_TRIANGLE_FAN;
  1087. }
  1088. /**
  1089. SphereMesh
  1090. */
  1091. void SphereMesh::_create_mesh_array(Array &p_arr) const {
  1092. int i, j, prevrow, thisrow, point;
  1093. float x, y, z;
  1094. // set our bounding box
  1095. PoolVector<Vector3> points;
  1096. PoolVector<Vector3> normals;
  1097. PoolVector<float> tangents;
  1098. PoolVector<Vector2> uvs;
  1099. PoolVector<int> indices;
  1100. point = 0;
  1101. #define ADD_TANGENT(m_x, m_y, m_z, m_d) \
  1102. tangents.push_back(m_x); \
  1103. tangents.push_back(m_y); \
  1104. tangents.push_back(m_z); \
  1105. tangents.push_back(m_d);
  1106. thisrow = 0;
  1107. prevrow = 0;
  1108. for (j = 0; j <= (rings + 1); j++) {
  1109. float v = j;
  1110. float w;
  1111. v /= (rings + 1);
  1112. w = sin(Math_PI * v);
  1113. y = height * (is_hemisphere ? 1.0 : 0.5) * cos(Math_PI * v);
  1114. for (i = 0; i <= radial_segments; i++) {
  1115. float u = i;
  1116. u /= radial_segments;
  1117. x = sin(u * (Math_PI * 2.0));
  1118. z = cos(u * (Math_PI * 2.0));
  1119. if (is_hemisphere && y < 0.0) {
  1120. points.push_back(Vector3(x * radius * w, 0.0, z * radius * w));
  1121. normals.push_back(Vector3(0.0, -1.0, 0.0));
  1122. } else {
  1123. Vector3 p = Vector3(x * radius * w, y, z * radius * w);
  1124. points.push_back(p);
  1125. normals.push_back(p.normalized());
  1126. };
  1127. ADD_TANGENT(-z, 0.0, x, -1.0)
  1128. uvs.push_back(Vector2(u, v));
  1129. point++;
  1130. if (i > 0 && j > 0) {
  1131. indices.push_back(prevrow + i - 1);
  1132. indices.push_back(prevrow + i);
  1133. indices.push_back(thisrow + i - 1);
  1134. indices.push_back(prevrow + i);
  1135. indices.push_back(thisrow + i);
  1136. indices.push_back(thisrow + i - 1);
  1137. };
  1138. };
  1139. prevrow = thisrow;
  1140. thisrow = point;
  1141. };
  1142. p_arr[VS::ARRAY_VERTEX] = points;
  1143. p_arr[VS::ARRAY_NORMAL] = normals;
  1144. p_arr[VS::ARRAY_TANGENT] = tangents;
  1145. p_arr[VS::ARRAY_TEX_UV] = uvs;
  1146. p_arr[VS::ARRAY_INDEX] = indices;
  1147. }
  1148. void SphereMesh::_bind_methods() {
  1149. ClassDB::bind_method(D_METHOD("set_radius", "radius"), &SphereMesh::set_radius);
  1150. ClassDB::bind_method(D_METHOD("get_radius"), &SphereMesh::get_radius);
  1151. ClassDB::bind_method(D_METHOD("set_height", "height"), &SphereMesh::set_height);
  1152. ClassDB::bind_method(D_METHOD("get_height"), &SphereMesh::get_height);
  1153. ClassDB::bind_method(D_METHOD("set_radial_segments", "radial_segments"), &SphereMesh::set_radial_segments);
  1154. ClassDB::bind_method(D_METHOD("get_radial_segments"), &SphereMesh::get_radial_segments);
  1155. ClassDB::bind_method(D_METHOD("set_rings", "rings"), &SphereMesh::set_rings);
  1156. ClassDB::bind_method(D_METHOD("get_rings"), &SphereMesh::get_rings);
  1157. ClassDB::bind_method(D_METHOD("set_is_hemisphere", "is_hemisphere"), &SphereMesh::set_is_hemisphere);
  1158. ClassDB::bind_method(D_METHOD("get_is_hemisphere"), &SphereMesh::get_is_hemisphere);
  1159. ADD_PROPERTY(PropertyInfo(Variant::REAL, "radius", PROPERTY_HINT_RANGE, "0.1,100.0,0.1"), "set_radius", "get_radius");
  1160. ADD_PROPERTY(PropertyInfo(Variant::REAL, "height", PROPERTY_HINT_RANGE, "0.1,100.0,0.1"), "set_height", "get_height");
  1161. ADD_PROPERTY(PropertyInfo(Variant::INT, "radial_segments", PROPERTY_HINT_RANGE, "1,100,1"), "set_radial_segments", "get_radial_segments");
  1162. ADD_PROPERTY(PropertyInfo(Variant::INT, "rings", PROPERTY_HINT_RANGE, "1,100,1"), "set_rings", "get_rings");
  1163. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "is_hemisphere"), "set_is_hemisphere", "get_is_hemisphere");
  1164. }
  1165. void SphereMesh::set_radius(const float p_radius) {
  1166. radius = p_radius;
  1167. _request_update();
  1168. }
  1169. float SphereMesh::get_radius() const {
  1170. return radius;
  1171. }
  1172. void SphereMesh::set_height(const float p_height) {
  1173. height = p_height;
  1174. _request_update();
  1175. }
  1176. float SphereMesh::get_height() const {
  1177. return height;
  1178. }
  1179. void SphereMesh::set_radial_segments(const int p_radial_segments) {
  1180. radial_segments = p_radial_segments > 4 ? p_radial_segments : 4;
  1181. _request_update();
  1182. }
  1183. int SphereMesh::get_radial_segments() const {
  1184. return radial_segments;
  1185. }
  1186. void SphereMesh::set_rings(const int p_rings) {
  1187. rings = p_rings > 1 ? p_rings : 1;
  1188. _request_update();
  1189. }
  1190. int SphereMesh::get_rings() const {
  1191. return rings;
  1192. }
  1193. void SphereMesh::set_is_hemisphere(const bool p_is_hemisphere) {
  1194. is_hemisphere = p_is_hemisphere;
  1195. _request_update();
  1196. }
  1197. bool SphereMesh::get_is_hemisphere() const {
  1198. return is_hemisphere;
  1199. }
  1200. SphereMesh::SphereMesh() {
  1201. // defaults
  1202. radius = 1.0;
  1203. height = 2.0;
  1204. radial_segments = 64;
  1205. rings = 32;
  1206. is_hemisphere = false;
  1207. }