primitive_meshes.cpp 112 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632
  1. /**************************************************************************/
  2. /* primitive_meshes.cpp */
  3. /**************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /**************************************************************************/
  8. /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
  9. /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
  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 "core/config/project_settings.h"
  32. #include "core/core_string_names.h"
  33. #include "scene/resources/theme.h"
  34. #include "scene/theme/theme_db.h"
  35. #include "servers/rendering_server.h"
  36. #include "thirdparty/misc/clipper.hpp"
  37. #include "thirdparty/misc/polypartition.h"
  38. #define PADDING_REF_SIZE 1024.0
  39. /**
  40. PrimitiveMesh
  41. */
  42. void PrimitiveMesh::_update() const {
  43. Array arr;
  44. if (GDVIRTUAL_CALL(_create_mesh_array, arr)) {
  45. ERR_FAIL_COND_MSG(arr.size() != RS::ARRAY_MAX, "_create_mesh_array must return an array of Mesh.ARRAY_MAX elements.");
  46. } else {
  47. arr.resize(RS::ARRAY_MAX);
  48. _create_mesh_array(arr);
  49. }
  50. Vector<Vector3> points = arr[RS::ARRAY_VERTEX];
  51. ERR_FAIL_COND_MSG(points.size() == 0, "_create_mesh_array must return at least a vertex array.");
  52. aabb = AABB();
  53. int pc = points.size();
  54. ERR_FAIL_COND(pc == 0);
  55. {
  56. const Vector3 *r = points.ptr();
  57. for (int i = 0; i < pc; i++) {
  58. if (i == 0) {
  59. aabb.position = r[i];
  60. } else {
  61. aabb.expand_to(r[i]);
  62. }
  63. }
  64. }
  65. Vector<int> indices = arr[RS::ARRAY_INDEX];
  66. if (flip_faces) {
  67. Vector<Vector3> normals = arr[RS::ARRAY_NORMAL];
  68. if (normals.size() && indices.size()) {
  69. {
  70. int nc = normals.size();
  71. Vector3 *w = normals.ptrw();
  72. for (int i = 0; i < nc; i++) {
  73. w[i] = -w[i];
  74. }
  75. }
  76. {
  77. int ic = indices.size();
  78. int *w = indices.ptrw();
  79. for (int i = 0; i < ic; i += 3) {
  80. SWAP(w[i + 0], w[i + 1]);
  81. }
  82. }
  83. arr[RS::ARRAY_NORMAL] = normals;
  84. arr[RS::ARRAY_INDEX] = indices;
  85. }
  86. }
  87. if (add_uv2) {
  88. // _create_mesh_array should populate our UV2, this is a fallback in case it doesn't.
  89. // As we don't know anything about the geometry we only pad the right and bottom edge
  90. // of our texture.
  91. Vector<Vector2> uv = arr[RS::ARRAY_TEX_UV];
  92. Vector<Vector2> uv2 = arr[RS::ARRAY_TEX_UV2];
  93. if (uv.size() > 0 && uv2.size() == 0) {
  94. Vector2 uv2_scale = get_uv2_scale();
  95. uv2.resize(uv.size());
  96. Vector2 *uv2w = uv2.ptrw();
  97. for (int i = 0; i < uv.size(); i++) {
  98. uv2w[i] = uv[i] * uv2_scale;
  99. }
  100. }
  101. arr[RS::ARRAY_TEX_UV2] = uv2;
  102. }
  103. array_len = pc;
  104. index_array_len = indices.size();
  105. // in with the new
  106. RenderingServer::get_singleton()->mesh_clear(mesh);
  107. RenderingServer::get_singleton()->mesh_add_surface_from_arrays(mesh, (RenderingServer::PrimitiveType)primitive_type, arr);
  108. RenderingServer::get_singleton()->mesh_surface_set_material(mesh, 0, material.is_null() ? RID() : material->get_rid());
  109. pending_request = false;
  110. clear_cache();
  111. const_cast<PrimitiveMesh *>(this)->emit_changed();
  112. }
  113. void PrimitiveMesh::_request_update() {
  114. if (pending_request) {
  115. return;
  116. }
  117. _update();
  118. }
  119. int PrimitiveMesh::get_surface_count() const {
  120. if (pending_request) {
  121. _update();
  122. }
  123. return 1;
  124. }
  125. int PrimitiveMesh::surface_get_array_len(int p_idx) const {
  126. ERR_FAIL_INDEX_V(p_idx, 1, -1);
  127. if (pending_request) {
  128. _update();
  129. }
  130. return array_len;
  131. }
  132. int PrimitiveMesh::surface_get_array_index_len(int p_idx) const {
  133. ERR_FAIL_INDEX_V(p_idx, 1, -1);
  134. if (pending_request) {
  135. _update();
  136. }
  137. return index_array_len;
  138. }
  139. Array PrimitiveMesh::surface_get_arrays(int p_surface) const {
  140. ERR_FAIL_INDEX_V(p_surface, 1, Array());
  141. if (pending_request) {
  142. _update();
  143. }
  144. return RenderingServer::get_singleton()->mesh_surface_get_arrays(mesh, 0);
  145. }
  146. Dictionary PrimitiveMesh::surface_get_lods(int p_surface) const {
  147. return Dictionary(); //not really supported
  148. }
  149. TypedArray<Array> PrimitiveMesh::surface_get_blend_shape_arrays(int p_surface) const {
  150. return TypedArray<Array>(); //not really supported
  151. }
  152. BitField<Mesh::ArrayFormat> PrimitiveMesh::surface_get_format(int p_idx) const {
  153. ERR_FAIL_INDEX_V(p_idx, 1, 0);
  154. uint32_t mesh_format = RS::ARRAY_FORMAT_VERTEX | RS::ARRAY_FORMAT_NORMAL | RS::ARRAY_FORMAT_TANGENT | RS::ARRAY_FORMAT_TEX_UV | RS::ARRAY_FORMAT_INDEX;
  155. if (add_uv2) {
  156. mesh_format |= RS::ARRAY_FORMAT_TEX_UV2;
  157. }
  158. return mesh_format;
  159. }
  160. Mesh::PrimitiveType PrimitiveMesh::surface_get_primitive_type(int p_idx) const {
  161. return primitive_type;
  162. }
  163. void PrimitiveMesh::surface_set_material(int p_idx, const Ref<Material> &p_material) {
  164. ERR_FAIL_INDEX(p_idx, 1);
  165. set_material(p_material);
  166. }
  167. Ref<Material> PrimitiveMesh::surface_get_material(int p_idx) const {
  168. ERR_FAIL_INDEX_V(p_idx, 1, nullptr);
  169. return material;
  170. }
  171. int PrimitiveMesh::get_blend_shape_count() const {
  172. return 0;
  173. }
  174. StringName PrimitiveMesh::get_blend_shape_name(int p_index) const {
  175. return StringName();
  176. }
  177. void PrimitiveMesh::set_blend_shape_name(int p_index, const StringName &p_name) {
  178. }
  179. AABB PrimitiveMesh::get_aabb() const {
  180. if (pending_request) {
  181. _update();
  182. }
  183. return aabb;
  184. }
  185. RID PrimitiveMesh::get_rid() const {
  186. if (pending_request) {
  187. _update();
  188. }
  189. return mesh;
  190. }
  191. void PrimitiveMesh::_bind_methods() {
  192. ClassDB::bind_method(D_METHOD("_update"), &PrimitiveMesh::_update);
  193. ClassDB::bind_method(D_METHOD("set_material", "material"), &PrimitiveMesh::set_material);
  194. ClassDB::bind_method(D_METHOD("get_material"), &PrimitiveMesh::get_material);
  195. ClassDB::bind_method(D_METHOD("get_mesh_arrays"), &PrimitiveMesh::get_mesh_arrays);
  196. ClassDB::bind_method(D_METHOD("set_custom_aabb", "aabb"), &PrimitiveMesh::set_custom_aabb);
  197. ClassDB::bind_method(D_METHOD("get_custom_aabb"), &PrimitiveMesh::get_custom_aabb);
  198. ClassDB::bind_method(D_METHOD("set_flip_faces", "flip_faces"), &PrimitiveMesh::set_flip_faces);
  199. ClassDB::bind_method(D_METHOD("get_flip_faces"), &PrimitiveMesh::get_flip_faces);
  200. ClassDB::bind_method(D_METHOD("set_add_uv2", "add_uv2"), &PrimitiveMesh::set_add_uv2);
  201. ClassDB::bind_method(D_METHOD("get_add_uv2"), &PrimitiveMesh::get_add_uv2);
  202. ClassDB::bind_method(D_METHOD("set_uv2_padding", "uv2_padding"), &PrimitiveMesh::set_uv2_padding);
  203. ClassDB::bind_method(D_METHOD("get_uv2_padding"), &PrimitiveMesh::get_uv2_padding);
  204. ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "BaseMaterial3D,ShaderMaterial"), "set_material", "get_material");
  205. ADD_PROPERTY(PropertyInfo(Variant::AABB, "custom_aabb", PROPERTY_HINT_NONE, "suffix:m"), "set_custom_aabb", "get_custom_aabb");
  206. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_faces"), "set_flip_faces", "get_flip_faces");
  207. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "add_uv2"), "set_add_uv2", "get_add_uv2");
  208. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "uv2_padding", PROPERTY_HINT_RANGE, "0,10,0.01,or_greater"), "set_uv2_padding", "get_uv2_padding");
  209. GDVIRTUAL_BIND(_create_mesh_array);
  210. }
  211. void PrimitiveMesh::set_material(const Ref<Material> &p_material) {
  212. material = p_material;
  213. if (!pending_request) {
  214. // just apply it, else it'll happen when _update is called.
  215. RenderingServer::get_singleton()->mesh_surface_set_material(mesh, 0, material.is_null() ? RID() : material->get_rid());
  216. notify_property_list_changed();
  217. emit_changed();
  218. }
  219. }
  220. Ref<Material> PrimitiveMesh::get_material() const {
  221. return material;
  222. }
  223. Array PrimitiveMesh::get_mesh_arrays() const {
  224. return surface_get_arrays(0);
  225. }
  226. void PrimitiveMesh::set_custom_aabb(const AABB &p_custom) {
  227. custom_aabb = p_custom;
  228. RS::get_singleton()->mesh_set_custom_aabb(mesh, custom_aabb);
  229. emit_changed();
  230. }
  231. AABB PrimitiveMesh::get_custom_aabb() const {
  232. return custom_aabb;
  233. }
  234. void PrimitiveMesh::set_flip_faces(bool p_enable) {
  235. flip_faces = p_enable;
  236. _request_update();
  237. }
  238. bool PrimitiveMesh::get_flip_faces() const {
  239. return flip_faces;
  240. }
  241. void PrimitiveMesh::set_add_uv2(bool p_enable) {
  242. add_uv2 = p_enable;
  243. _update_lightmap_size();
  244. _request_update();
  245. }
  246. void PrimitiveMesh::set_uv2_padding(float p_padding) {
  247. uv2_padding = p_padding;
  248. _update_lightmap_size();
  249. _request_update();
  250. }
  251. Vector2 PrimitiveMesh::get_uv2_scale(Vector2 p_margin_scale) const {
  252. Vector2 uv2_scale;
  253. Vector2 lightmap_size = get_lightmap_size_hint();
  254. // Calculate it as a margin, if no lightmap size hint is given we assume "PADDING_REF_SIZE" as our texture size.
  255. uv2_scale.x = p_margin_scale.x * uv2_padding / (lightmap_size.x == 0.0 ? PADDING_REF_SIZE : lightmap_size.x);
  256. uv2_scale.y = p_margin_scale.y * uv2_padding / (lightmap_size.y == 0.0 ? PADDING_REF_SIZE : lightmap_size.y);
  257. // Inverse it to turn our margin into a scale
  258. uv2_scale = Vector2(1.0, 1.0) - uv2_scale;
  259. return uv2_scale;
  260. }
  261. float PrimitiveMesh::get_lightmap_texel_size() const {
  262. float texel_size = GLOBAL_GET("rendering/lightmapping/primitive_meshes/texel_size");
  263. if (texel_size <= 0.0) {
  264. texel_size = 0.2;
  265. }
  266. return texel_size;
  267. }
  268. PrimitiveMesh::PrimitiveMesh() {
  269. mesh = RenderingServer::get_singleton()->mesh_create();
  270. }
  271. PrimitiveMesh::~PrimitiveMesh() {
  272. ERR_FAIL_NULL(RenderingServer::get_singleton());
  273. RenderingServer::get_singleton()->free(mesh);
  274. }
  275. /**
  276. CapsuleMesh
  277. */
  278. void CapsuleMesh::_update_lightmap_size() {
  279. if (get_add_uv2()) {
  280. // size must have changed, update lightmap size hint
  281. Size2i _lightmap_size_hint;
  282. float texel_size = get_lightmap_texel_size();
  283. float padding = get_uv2_padding();
  284. float radial_length = radius * Math_PI * 0.5; // circumference of 90 degree bend
  285. float vertical_length = radial_length * 2 + (height - 2.0 * radius); // total vertical length
  286. _lightmap_size_hint.x = MAX(1.0, 4.0 * radial_length / texel_size) + padding;
  287. _lightmap_size_hint.y = MAX(1.0, vertical_length / texel_size) + padding;
  288. set_lightmap_size_hint(_lightmap_size_hint);
  289. }
  290. }
  291. void CapsuleMesh::_create_mesh_array(Array &p_arr) const {
  292. bool _add_uv2 = get_add_uv2();
  293. float texel_size = get_lightmap_texel_size();
  294. float _uv2_padding = get_uv2_padding() * texel_size;
  295. create_mesh_array(p_arr, radius, height, radial_segments, rings, _add_uv2, _uv2_padding);
  296. }
  297. void CapsuleMesh::create_mesh_array(Array &p_arr, const float radius, const float height, const int radial_segments, const int rings, bool p_add_uv2, const float p_uv2_padding) {
  298. int i, j, prevrow, thisrow, point;
  299. float x, y, z, u, v, w;
  300. float onethird = 1.0 / 3.0;
  301. float twothirds = 2.0 / 3.0;
  302. // Only used if we calculate UV2
  303. float radial_width = 2.0 * radius * Math_PI;
  304. float radial_h = radial_width / (radial_width + p_uv2_padding);
  305. float radial_length = radius * Math_PI * 0.5; // circumference of 90 degree bend
  306. float vertical_length = radial_length * 2 + (height - 2.0 * radius) + p_uv2_padding; // total vertical length
  307. float radial_v = radial_length / vertical_length; // v size of top and bottom section
  308. float height_v = (height - 2.0 * radius) / vertical_length; // v size of height section
  309. // note, this has been aligned with our collision shape but I've left the descriptions as top/middle/bottom
  310. Vector<Vector3> points;
  311. Vector<Vector3> normals;
  312. Vector<float> tangents;
  313. Vector<Vector2> uvs;
  314. Vector<Vector2> uv2s;
  315. Vector<int> indices;
  316. point = 0;
  317. #define ADD_TANGENT(m_x, m_y, m_z, m_d) \
  318. tangents.push_back(m_x); \
  319. tangents.push_back(m_y); \
  320. tangents.push_back(m_z); \
  321. tangents.push_back(m_d);
  322. /* top hemisphere */
  323. thisrow = 0;
  324. prevrow = 0;
  325. for (j = 0; j <= (rings + 1); j++) {
  326. v = j;
  327. v /= (rings + 1);
  328. w = sin(0.5 * Math_PI * v);
  329. y = radius * cos(0.5 * Math_PI * v);
  330. for (i = 0; i <= radial_segments; i++) {
  331. u = i;
  332. u /= radial_segments;
  333. x = -sin(u * Math_TAU);
  334. z = cos(u * Math_TAU);
  335. Vector3 p = Vector3(x * radius * w, y, -z * radius * w);
  336. points.push_back(p + Vector3(0.0, 0.5 * height - radius, 0.0));
  337. normals.push_back(p.normalized());
  338. ADD_TANGENT(-z, 0.0, -x, 1.0)
  339. uvs.push_back(Vector2(u, v * onethird));
  340. if (p_add_uv2) {
  341. uv2s.push_back(Vector2(u * radial_h, v * radial_v));
  342. }
  343. point++;
  344. if (i > 0 && j > 0) {
  345. indices.push_back(prevrow + i - 1);
  346. indices.push_back(prevrow + i);
  347. indices.push_back(thisrow + i - 1);
  348. indices.push_back(prevrow + i);
  349. indices.push_back(thisrow + i);
  350. indices.push_back(thisrow + i - 1);
  351. }
  352. }
  353. prevrow = thisrow;
  354. thisrow = point;
  355. }
  356. /* cylinder */
  357. thisrow = point;
  358. prevrow = 0;
  359. for (j = 0; j <= (rings + 1); j++) {
  360. v = j;
  361. v /= (rings + 1);
  362. y = (height - 2.0 * radius) * v;
  363. y = (0.5 * height - radius) - y;
  364. for (i = 0; i <= radial_segments; i++) {
  365. u = i;
  366. u /= radial_segments;
  367. x = -sin(u * Math_TAU);
  368. z = cos(u * Math_TAU);
  369. Vector3 p = Vector3(x * radius, y, -z * radius);
  370. points.push_back(p);
  371. normals.push_back(Vector3(x, 0.0, -z));
  372. ADD_TANGENT(-z, 0.0, -x, 1.0)
  373. uvs.push_back(Vector2(u, onethird + (v * onethird)));
  374. if (p_add_uv2) {
  375. uv2s.push_back(Vector2(u * radial_h, radial_v + (v * height_v)));
  376. }
  377. point++;
  378. if (i > 0 && j > 0) {
  379. indices.push_back(prevrow + i - 1);
  380. indices.push_back(prevrow + i);
  381. indices.push_back(thisrow + i - 1);
  382. indices.push_back(prevrow + i);
  383. indices.push_back(thisrow + i);
  384. indices.push_back(thisrow + i - 1);
  385. }
  386. }
  387. prevrow = thisrow;
  388. thisrow = point;
  389. }
  390. /* bottom hemisphere */
  391. thisrow = point;
  392. prevrow = 0;
  393. for (j = 0; j <= (rings + 1); j++) {
  394. v = j;
  395. v /= (rings + 1);
  396. v += 1.0;
  397. w = sin(0.5 * Math_PI * v);
  398. y = radius * cos(0.5 * Math_PI * v);
  399. for (i = 0; i <= radial_segments; i++) {
  400. u = i;
  401. u /= radial_segments;
  402. x = -sin(u * Math_TAU);
  403. z = cos(u * Math_TAU);
  404. Vector3 p = Vector3(x * radius * w, y, -z * radius * w);
  405. points.push_back(p + Vector3(0.0, -0.5 * height + radius, 0.0));
  406. normals.push_back(p.normalized());
  407. ADD_TANGENT(-z, 0.0, -x, 1.0)
  408. uvs.push_back(Vector2(u, twothirds + ((v - 1.0) * onethird)));
  409. if (p_add_uv2) {
  410. uv2s.push_back(Vector2(u * radial_h, radial_v + height_v + ((v - 1.0) * radial_v)));
  411. }
  412. point++;
  413. if (i > 0 && j > 0) {
  414. indices.push_back(prevrow + i - 1);
  415. indices.push_back(prevrow + i);
  416. indices.push_back(thisrow + i - 1);
  417. indices.push_back(prevrow + i);
  418. indices.push_back(thisrow + i);
  419. indices.push_back(thisrow + i - 1);
  420. }
  421. }
  422. prevrow = thisrow;
  423. thisrow = point;
  424. }
  425. p_arr[RS::ARRAY_VERTEX] = points;
  426. p_arr[RS::ARRAY_NORMAL] = normals;
  427. p_arr[RS::ARRAY_TANGENT] = tangents;
  428. p_arr[RS::ARRAY_TEX_UV] = uvs;
  429. if (p_add_uv2) {
  430. p_arr[RS::ARRAY_TEX_UV2] = uv2s;
  431. }
  432. p_arr[RS::ARRAY_INDEX] = indices;
  433. }
  434. void CapsuleMesh::_bind_methods() {
  435. ClassDB::bind_method(D_METHOD("set_radius", "radius"), &CapsuleMesh::set_radius);
  436. ClassDB::bind_method(D_METHOD("get_radius"), &CapsuleMesh::get_radius);
  437. ClassDB::bind_method(D_METHOD("set_height", "height"), &CapsuleMesh::set_height);
  438. ClassDB::bind_method(D_METHOD("get_height"), &CapsuleMesh::get_height);
  439. ClassDB::bind_method(D_METHOD("set_radial_segments", "segments"), &CapsuleMesh::set_radial_segments);
  440. ClassDB::bind_method(D_METHOD("get_radial_segments"), &CapsuleMesh::get_radial_segments);
  441. ClassDB::bind_method(D_METHOD("set_rings", "rings"), &CapsuleMesh::set_rings);
  442. ClassDB::bind_method(D_METHOD("get_rings"), &CapsuleMesh::get_rings);
  443. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.001,100.0,0.001,or_greater,suffix:m"), "set_radius", "get_radius");
  444. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "height", PROPERTY_HINT_RANGE, "0.001,100.0,0.001,or_greater,suffix:m"), "set_height", "get_height");
  445. ADD_PROPERTY(PropertyInfo(Variant::INT, "radial_segments", PROPERTY_HINT_RANGE, "1,100,1,or_greater"), "set_radial_segments", "get_radial_segments");
  446. ADD_PROPERTY(PropertyInfo(Variant::INT, "rings", PROPERTY_HINT_RANGE, "1,100,1,or_greater"), "set_rings", "get_rings");
  447. ADD_LINKED_PROPERTY("radius", "height");
  448. ADD_LINKED_PROPERTY("height", "radius");
  449. }
  450. void CapsuleMesh::set_radius(const float p_radius) {
  451. radius = p_radius;
  452. if (radius > height * 0.5) {
  453. height = radius * 2.0;
  454. }
  455. _update_lightmap_size();
  456. _request_update();
  457. }
  458. float CapsuleMesh::get_radius() const {
  459. return radius;
  460. }
  461. void CapsuleMesh::set_height(const float p_height) {
  462. height = p_height;
  463. if (radius > height * 0.5) {
  464. radius = height * 0.5;
  465. }
  466. _update_lightmap_size();
  467. _request_update();
  468. }
  469. float CapsuleMesh::get_height() const {
  470. return height;
  471. }
  472. void CapsuleMesh::set_radial_segments(const int p_segments) {
  473. radial_segments = p_segments > 4 ? p_segments : 4;
  474. _request_update();
  475. }
  476. int CapsuleMesh::get_radial_segments() const {
  477. return radial_segments;
  478. }
  479. void CapsuleMesh::set_rings(const int p_rings) {
  480. rings = p_rings > 1 ? p_rings : 1;
  481. _request_update();
  482. }
  483. int CapsuleMesh::get_rings() const {
  484. return rings;
  485. }
  486. CapsuleMesh::CapsuleMesh() {}
  487. /**
  488. BoxMesh
  489. */
  490. void BoxMesh::_update_lightmap_size() {
  491. if (get_add_uv2()) {
  492. // size must have changed, update lightmap size hint
  493. Size2i _lightmap_size_hint;
  494. float texel_size = get_lightmap_texel_size();
  495. float padding = get_uv2_padding();
  496. float width = (size.x + size.z) / texel_size;
  497. float length = (size.y + size.y + MAX(size.x, size.z)) / texel_size;
  498. _lightmap_size_hint.x = MAX(1.0, width) + 2.0 * padding;
  499. _lightmap_size_hint.y = MAX(1.0, length) + 3.0 * padding;
  500. set_lightmap_size_hint(_lightmap_size_hint);
  501. }
  502. }
  503. void BoxMesh::_create_mesh_array(Array &p_arr) const {
  504. // Note about padding, with our box each face of the box faces a different direction so we want a seam
  505. // around every face. We thus add our padding to the right and bottom of each face.
  506. // With 3 faces along the width and 2 along the height of the texture we need to adjust our scale
  507. // accordingly.
  508. bool _add_uv2 = get_add_uv2();
  509. float texel_size = get_lightmap_texel_size();
  510. float _uv2_padding = get_uv2_padding() * texel_size;
  511. BoxMesh::create_mesh_array(p_arr, size, subdivide_w, subdivide_h, subdivide_d, _add_uv2, _uv2_padding);
  512. }
  513. void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int subdivide_h, int subdivide_d, bool p_add_uv2, const float p_uv2_padding) {
  514. int i, j, prevrow, thisrow, point;
  515. float x, y, z;
  516. float onethird = 1.0 / 3.0;
  517. float twothirds = 2.0 / 3.0;
  518. // Only used if we calculate UV2
  519. // TODO this could be improved by changing the order depending on which side is the longest (basically the below works best if size.y is the longest)
  520. float total_h = (size.x + size.z + (2.0 * p_uv2_padding));
  521. float padding_h = p_uv2_padding / total_h;
  522. float width_h = size.x / total_h;
  523. float depth_h = size.z / total_h;
  524. float total_v = (size.y + size.y + MAX(size.x, size.z) + (3.0 * p_uv2_padding));
  525. float padding_v = p_uv2_padding / total_v;
  526. float width_v = size.x / total_v;
  527. float height_v = size.y / total_v;
  528. float depth_v = size.z / total_v;
  529. Vector3 start_pos = size * -0.5;
  530. // set our bounding box
  531. Vector<Vector3> points;
  532. Vector<Vector3> normals;
  533. Vector<float> tangents;
  534. Vector<Vector2> uvs;
  535. Vector<Vector2> uv2s;
  536. Vector<int> indices;
  537. point = 0;
  538. #define ADD_TANGENT(m_x, m_y, m_z, m_d) \
  539. tangents.push_back(m_x); \
  540. tangents.push_back(m_y); \
  541. tangents.push_back(m_z); \
  542. tangents.push_back(m_d);
  543. // front + back
  544. y = start_pos.y;
  545. thisrow = point;
  546. prevrow = 0;
  547. for (j = 0; j <= subdivide_h + 1; j++) {
  548. float v = j;
  549. float v2 = v / (subdivide_w + 1.0);
  550. v /= (2.0 * (subdivide_h + 1.0));
  551. x = start_pos.x;
  552. for (i = 0; i <= subdivide_w + 1; i++) {
  553. float u = i;
  554. float u2 = u / (subdivide_w + 1.0);
  555. u /= (3.0 * (subdivide_w + 1.0));
  556. // front
  557. points.push_back(Vector3(x, -y, -start_pos.z)); // double negative on the Z!
  558. normals.push_back(Vector3(0.0, 0.0, 1.0));
  559. ADD_TANGENT(1.0, 0.0, 0.0, 1.0);
  560. uvs.push_back(Vector2(u, v));
  561. if (p_add_uv2) {
  562. uv2s.push_back(Vector2(u2 * width_h, v2 * height_v));
  563. }
  564. point++;
  565. // back
  566. points.push_back(Vector3(-x, -y, start_pos.z));
  567. normals.push_back(Vector3(0.0, 0.0, -1.0));
  568. ADD_TANGENT(-1.0, 0.0, 0.0, 1.0);
  569. uvs.push_back(Vector2(twothirds + u, v));
  570. if (p_add_uv2) {
  571. uv2s.push_back(Vector2(u2 * width_h, height_v + padding_v + (v2 * height_v)));
  572. }
  573. point++;
  574. if (i > 0 && j > 0) {
  575. int i2 = i * 2;
  576. // front
  577. indices.push_back(prevrow + i2 - 2);
  578. indices.push_back(prevrow + i2);
  579. indices.push_back(thisrow + i2 - 2);
  580. indices.push_back(prevrow + i2);
  581. indices.push_back(thisrow + i2);
  582. indices.push_back(thisrow + i2 - 2);
  583. // back
  584. indices.push_back(prevrow + i2 - 1);
  585. indices.push_back(prevrow + i2 + 1);
  586. indices.push_back(thisrow + i2 - 1);
  587. indices.push_back(prevrow + i2 + 1);
  588. indices.push_back(thisrow + i2 + 1);
  589. indices.push_back(thisrow + i2 - 1);
  590. }
  591. x += size.x / (subdivide_w + 1.0);
  592. }
  593. y += size.y / (subdivide_h + 1.0);
  594. prevrow = thisrow;
  595. thisrow = point;
  596. }
  597. // left + right
  598. y = start_pos.y;
  599. thisrow = point;
  600. prevrow = 0;
  601. for (j = 0; j <= (subdivide_h + 1); j++) {
  602. float v = j;
  603. float v2 = v / (subdivide_h + 1.0);
  604. v /= (2.0 * (subdivide_h + 1.0));
  605. z = start_pos.z;
  606. for (i = 0; i <= (subdivide_d + 1); i++) {
  607. float u = i;
  608. float u2 = u / (subdivide_d + 1.0);
  609. u /= (3.0 * (subdivide_d + 1.0));
  610. // right
  611. points.push_back(Vector3(-start_pos.x, -y, -z));
  612. normals.push_back(Vector3(1.0, 0.0, 0.0));
  613. ADD_TANGENT(0.0, 0.0, -1.0, 1.0);
  614. uvs.push_back(Vector2(onethird + u, v));
  615. if (p_add_uv2) {
  616. uv2s.push_back(Vector2(width_h + padding_h + (u2 * depth_h), v2 * height_v));
  617. }
  618. point++;
  619. // left
  620. points.push_back(Vector3(start_pos.x, -y, z));
  621. normals.push_back(Vector3(-1.0, 0.0, 0.0));
  622. ADD_TANGENT(0.0, 0.0, 1.0, 1.0);
  623. uvs.push_back(Vector2(u, 0.5 + v));
  624. if (p_add_uv2) {
  625. uv2s.push_back(Vector2(width_h + padding_h + (u2 * depth_h), height_v + padding_v + (v2 * height_v)));
  626. }
  627. point++;
  628. if (i > 0 && j > 0) {
  629. int i2 = i * 2;
  630. // right
  631. indices.push_back(prevrow + i2 - 2);
  632. indices.push_back(prevrow + i2);
  633. indices.push_back(thisrow + i2 - 2);
  634. indices.push_back(prevrow + i2);
  635. indices.push_back(thisrow + i2);
  636. indices.push_back(thisrow + i2 - 2);
  637. // left
  638. indices.push_back(prevrow + i2 - 1);
  639. indices.push_back(prevrow + i2 + 1);
  640. indices.push_back(thisrow + i2 - 1);
  641. indices.push_back(prevrow + i2 + 1);
  642. indices.push_back(thisrow + i2 + 1);
  643. indices.push_back(thisrow + i2 - 1);
  644. }
  645. z += size.z / (subdivide_d + 1.0);
  646. }
  647. y += size.y / (subdivide_h + 1.0);
  648. prevrow = thisrow;
  649. thisrow = point;
  650. }
  651. // top + bottom
  652. z = start_pos.z;
  653. thisrow = point;
  654. prevrow = 0;
  655. for (j = 0; j <= (subdivide_d + 1); j++) {
  656. float v = j;
  657. float v2 = v / (subdivide_d + 1.0);
  658. v /= (2.0 * (subdivide_d + 1.0));
  659. x = start_pos.x;
  660. for (i = 0; i <= (subdivide_w + 1); i++) {
  661. float u = i;
  662. float u2 = u / (subdivide_w + 1.0);
  663. u /= (3.0 * (subdivide_w + 1.0));
  664. // top
  665. points.push_back(Vector3(-x, -start_pos.y, -z));
  666. normals.push_back(Vector3(0.0, 1.0, 0.0));
  667. ADD_TANGENT(-1.0, 0.0, 0.0, 1.0);
  668. uvs.push_back(Vector2(onethird + u, 0.5 + v));
  669. if (p_add_uv2) {
  670. uv2s.push_back(Vector2(u2 * width_h, ((height_v + padding_v) * 2.0) + (v2 * depth_v)));
  671. }
  672. point++;
  673. // bottom
  674. points.push_back(Vector3(x, start_pos.y, -z));
  675. normals.push_back(Vector3(0.0, -1.0, 0.0));
  676. ADD_TANGENT(1.0, 0.0, 0.0, 1.0);
  677. uvs.push_back(Vector2(twothirds + u, 0.5 + v));
  678. if (p_add_uv2) {
  679. uv2s.push_back(Vector2(width_h + padding_h + (u2 * depth_h), ((height_v + padding_v) * 2.0) + (v2 * width_v)));
  680. }
  681. point++;
  682. if (i > 0 && j > 0) {
  683. int i2 = i * 2;
  684. // top
  685. indices.push_back(prevrow + i2 - 2);
  686. indices.push_back(prevrow + i2);
  687. indices.push_back(thisrow + i2 - 2);
  688. indices.push_back(prevrow + i2);
  689. indices.push_back(thisrow + i2);
  690. indices.push_back(thisrow + i2 - 2);
  691. // bottom
  692. indices.push_back(prevrow + i2 - 1);
  693. indices.push_back(prevrow + i2 + 1);
  694. indices.push_back(thisrow + i2 - 1);
  695. indices.push_back(prevrow + i2 + 1);
  696. indices.push_back(thisrow + i2 + 1);
  697. indices.push_back(thisrow + i2 - 1);
  698. }
  699. x += size.x / (subdivide_w + 1.0);
  700. }
  701. z += size.z / (subdivide_d + 1.0);
  702. prevrow = thisrow;
  703. thisrow = point;
  704. }
  705. p_arr[RS::ARRAY_VERTEX] = points;
  706. p_arr[RS::ARRAY_NORMAL] = normals;
  707. p_arr[RS::ARRAY_TANGENT] = tangents;
  708. p_arr[RS::ARRAY_TEX_UV] = uvs;
  709. if (p_add_uv2) {
  710. p_arr[RS::ARRAY_TEX_UV2] = uv2s;
  711. }
  712. p_arr[RS::ARRAY_INDEX] = indices;
  713. }
  714. void BoxMesh::_bind_methods() {
  715. ClassDB::bind_method(D_METHOD("set_size", "size"), &BoxMesh::set_size);
  716. ClassDB::bind_method(D_METHOD("get_size"), &BoxMesh::get_size);
  717. ClassDB::bind_method(D_METHOD("set_subdivide_width", "subdivide"), &BoxMesh::set_subdivide_width);
  718. ClassDB::bind_method(D_METHOD("get_subdivide_width"), &BoxMesh::get_subdivide_width);
  719. ClassDB::bind_method(D_METHOD("set_subdivide_height", "divisions"), &BoxMesh::set_subdivide_height);
  720. ClassDB::bind_method(D_METHOD("get_subdivide_height"), &BoxMesh::get_subdivide_height);
  721. ClassDB::bind_method(D_METHOD("set_subdivide_depth", "divisions"), &BoxMesh::set_subdivide_depth);
  722. ClassDB::bind_method(D_METHOD("get_subdivide_depth"), &BoxMesh::get_subdivide_depth);
  723. ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "size", PROPERTY_HINT_NONE, "suffix:m"), "set_size", "get_size");
  724. ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_width", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_subdivide_width", "get_subdivide_width");
  725. ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_height", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_subdivide_height", "get_subdivide_height");
  726. ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_depth", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_subdivide_depth", "get_subdivide_depth");
  727. }
  728. void BoxMesh::set_size(const Vector3 &p_size) {
  729. size = p_size;
  730. _update_lightmap_size();
  731. _request_update();
  732. }
  733. Vector3 BoxMesh::get_size() const {
  734. return size;
  735. }
  736. void BoxMesh::set_subdivide_width(const int p_divisions) {
  737. subdivide_w = p_divisions > 0 ? p_divisions : 0;
  738. _request_update();
  739. }
  740. int BoxMesh::get_subdivide_width() const {
  741. return subdivide_w;
  742. }
  743. void BoxMesh::set_subdivide_height(const int p_divisions) {
  744. subdivide_h = p_divisions > 0 ? p_divisions : 0;
  745. _request_update();
  746. }
  747. int BoxMesh::get_subdivide_height() const {
  748. return subdivide_h;
  749. }
  750. void BoxMesh::set_subdivide_depth(const int p_divisions) {
  751. subdivide_d = p_divisions > 0 ? p_divisions : 0;
  752. _request_update();
  753. }
  754. int BoxMesh::get_subdivide_depth() const {
  755. return subdivide_d;
  756. }
  757. BoxMesh::BoxMesh() {}
  758. /**
  759. CylinderMesh
  760. */
  761. void CylinderMesh::_update_lightmap_size() {
  762. if (get_add_uv2()) {
  763. // size must have changed, update lightmap size hint
  764. Size2i _lightmap_size_hint;
  765. float texel_size = get_lightmap_texel_size();
  766. float padding = get_uv2_padding();
  767. float top_circumference = top_radius * Math_PI * 2.0;
  768. float bottom_circumference = bottom_radius * Math_PI * 2.0;
  769. float _width = MAX(top_circumference, bottom_circumference) / texel_size + padding;
  770. _width = MAX(_width, (((top_radius + bottom_radius) / texel_size) + padding) * 2.0); // this is extremely unlikely to be larger, will only happen if padding is larger then our diameter.
  771. _lightmap_size_hint.x = MAX(1.0, _width);
  772. float _height = ((height + (MAX(top_radius, bottom_radius) * 2.0)) / texel_size) + (2.0 * padding);
  773. _lightmap_size_hint.y = MAX(1.0, _height);
  774. set_lightmap_size_hint(_lightmap_size_hint);
  775. }
  776. }
  777. void CylinderMesh::_create_mesh_array(Array &p_arr) const {
  778. bool _add_uv2 = get_add_uv2();
  779. float texel_size = get_lightmap_texel_size();
  780. float _uv2_padding = get_uv2_padding() * texel_size;
  781. create_mesh_array(p_arr, top_radius, bottom_radius, height, radial_segments, rings, cap_top, cap_bottom, _add_uv2, _uv2_padding);
  782. }
  783. void CylinderMesh::create_mesh_array(Array &p_arr, float top_radius, float bottom_radius, float height, int radial_segments, int rings, bool cap_top, bool cap_bottom, bool p_add_uv2, const float p_uv2_padding) {
  784. int i, j, prevrow, thisrow, point;
  785. float x, y, z, u, v, radius, radius_h;
  786. // Only used if we calculate UV2
  787. float top_circumference = top_radius * Math_PI * 2.0;
  788. float bottom_circumference = bottom_radius * Math_PI * 2.0;
  789. float vertical_length = height + MAX(2.0 * top_radius, 2.0 * bottom_radius) + (2.0 * p_uv2_padding);
  790. float height_v = height / vertical_length;
  791. float padding_v = p_uv2_padding / vertical_length;
  792. float horizonal_length = MAX(MAX(2.0 * (top_radius + bottom_radius + p_uv2_padding), top_circumference + p_uv2_padding), bottom_circumference + p_uv2_padding);
  793. float center_h = 0.5 * (horizonal_length - p_uv2_padding) / horizonal_length;
  794. float top_h = top_circumference / horizonal_length;
  795. float bottom_h = bottom_circumference / horizonal_length;
  796. float padding_h = p_uv2_padding / horizonal_length;
  797. Vector<Vector3> points;
  798. Vector<Vector3> normals;
  799. Vector<float> tangents;
  800. Vector<Vector2> uvs;
  801. Vector<Vector2> uv2s;
  802. Vector<int> indices;
  803. point = 0;
  804. #define ADD_TANGENT(m_x, m_y, m_z, m_d) \
  805. tangents.push_back(m_x); \
  806. tangents.push_back(m_y); \
  807. tangents.push_back(m_z); \
  808. tangents.push_back(m_d);
  809. thisrow = 0;
  810. prevrow = 0;
  811. const real_t side_normal_y = (bottom_radius - top_radius) / height;
  812. for (j = 0; j <= (rings + 1); j++) {
  813. v = j;
  814. v /= (rings + 1);
  815. radius = top_radius + ((bottom_radius - top_radius) * v);
  816. radius_h = top_h + ((bottom_h - top_h) * v);
  817. y = height * v;
  818. y = (height * 0.5) - y;
  819. for (i = 0; i <= radial_segments; i++) {
  820. u = i;
  821. u /= radial_segments;
  822. x = sin(u * Math_TAU);
  823. z = cos(u * Math_TAU);
  824. Vector3 p = Vector3(x * radius, y, z * radius);
  825. points.push_back(p);
  826. normals.push_back(Vector3(x, side_normal_y, z).normalized());
  827. ADD_TANGENT(z, 0.0, -x, 1.0)
  828. uvs.push_back(Vector2(u, v * 0.5));
  829. if (p_add_uv2) {
  830. uv2s.push_back(Vector2(center_h + (u - 0.5) * radius_h, v * height_v));
  831. }
  832. point++;
  833. if (i > 0 && j > 0) {
  834. indices.push_back(prevrow + i - 1);
  835. indices.push_back(prevrow + i);
  836. indices.push_back(thisrow + i - 1);
  837. indices.push_back(prevrow + i);
  838. indices.push_back(thisrow + i);
  839. indices.push_back(thisrow + i - 1);
  840. }
  841. }
  842. prevrow = thisrow;
  843. thisrow = point;
  844. }
  845. // Adjust for bottom section, only used if we calculate UV2s.
  846. top_h = top_radius / horizonal_length;
  847. float top_v = top_radius / vertical_length;
  848. bottom_h = bottom_radius / horizonal_length;
  849. float bottom_v = bottom_radius / vertical_length;
  850. // Add top.
  851. if (cap_top && top_radius > 0.0) {
  852. y = height * 0.5;
  853. thisrow = point;
  854. points.push_back(Vector3(0.0, y, 0.0));
  855. normals.push_back(Vector3(0.0, 1.0, 0.0));
  856. ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
  857. uvs.push_back(Vector2(0.25, 0.75));
  858. if (p_add_uv2) {
  859. uv2s.push_back(Vector2(top_h, height_v + padding_v + MAX(top_v, bottom_v)));
  860. }
  861. point++;
  862. for (i = 0; i <= radial_segments; i++) {
  863. float r = i;
  864. r /= radial_segments;
  865. x = sin(r * Math_TAU);
  866. z = cos(r * Math_TAU);
  867. u = ((x + 1.0) * 0.25);
  868. v = 0.5 + ((z + 1.0) * 0.25);
  869. Vector3 p = Vector3(x * top_radius, y, z * top_radius);
  870. points.push_back(p);
  871. normals.push_back(Vector3(0.0, 1.0, 0.0));
  872. ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
  873. uvs.push_back(Vector2(u, v));
  874. if (p_add_uv2) {
  875. uv2s.push_back(Vector2(top_h + (x * top_h), height_v + padding_v + MAX(top_v, bottom_v) + (z * top_v)));
  876. }
  877. point++;
  878. if (i > 0) {
  879. indices.push_back(thisrow);
  880. indices.push_back(point - 1);
  881. indices.push_back(point - 2);
  882. }
  883. }
  884. }
  885. // Add bottom.
  886. if (cap_bottom && bottom_radius > 0.0) {
  887. y = height * -0.5;
  888. thisrow = point;
  889. points.push_back(Vector3(0.0, y, 0.0));
  890. normals.push_back(Vector3(0.0, -1.0, 0.0));
  891. ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
  892. uvs.push_back(Vector2(0.75, 0.75));
  893. if (p_add_uv2) {
  894. uv2s.push_back(Vector2(top_h + top_h + padding_h + bottom_h, height_v + padding_v + MAX(top_v, bottom_v)));
  895. }
  896. point++;
  897. for (i = 0; i <= radial_segments; i++) {
  898. float r = i;
  899. r /= radial_segments;
  900. x = sin(r * Math_TAU);
  901. z = cos(r * Math_TAU);
  902. u = 0.5 + ((x + 1.0) * 0.25);
  903. v = 1.0 - ((z + 1.0) * 0.25);
  904. Vector3 p = Vector3(x * bottom_radius, y, z * bottom_radius);
  905. points.push_back(p);
  906. normals.push_back(Vector3(0.0, -1.0, 0.0));
  907. ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
  908. uvs.push_back(Vector2(u, v));
  909. if (p_add_uv2) {
  910. uv2s.push_back(Vector2(top_h + top_h + padding_h + bottom_h + (x * bottom_h), height_v + padding_v + MAX(top_v, bottom_v) - (z * bottom_v)));
  911. }
  912. point++;
  913. if (i > 0) {
  914. indices.push_back(thisrow);
  915. indices.push_back(point - 2);
  916. indices.push_back(point - 1);
  917. }
  918. }
  919. }
  920. p_arr[RS::ARRAY_VERTEX] = points;
  921. p_arr[RS::ARRAY_NORMAL] = normals;
  922. p_arr[RS::ARRAY_TANGENT] = tangents;
  923. p_arr[RS::ARRAY_TEX_UV] = uvs;
  924. if (p_add_uv2) {
  925. p_arr[RS::ARRAY_TEX_UV2] = uv2s;
  926. }
  927. p_arr[RS::ARRAY_INDEX] = indices;
  928. }
  929. void CylinderMesh::_bind_methods() {
  930. ClassDB::bind_method(D_METHOD("set_top_radius", "radius"), &CylinderMesh::set_top_radius);
  931. ClassDB::bind_method(D_METHOD("get_top_radius"), &CylinderMesh::get_top_radius);
  932. ClassDB::bind_method(D_METHOD("set_bottom_radius", "radius"), &CylinderMesh::set_bottom_radius);
  933. ClassDB::bind_method(D_METHOD("get_bottom_radius"), &CylinderMesh::get_bottom_radius);
  934. ClassDB::bind_method(D_METHOD("set_height", "height"), &CylinderMesh::set_height);
  935. ClassDB::bind_method(D_METHOD("get_height"), &CylinderMesh::get_height);
  936. ClassDB::bind_method(D_METHOD("set_radial_segments", "segments"), &CylinderMesh::set_radial_segments);
  937. ClassDB::bind_method(D_METHOD("get_radial_segments"), &CylinderMesh::get_radial_segments);
  938. ClassDB::bind_method(D_METHOD("set_rings", "rings"), &CylinderMesh::set_rings);
  939. ClassDB::bind_method(D_METHOD("get_rings"), &CylinderMesh::get_rings);
  940. ClassDB::bind_method(D_METHOD("set_cap_top", "cap_top"), &CylinderMesh::set_cap_top);
  941. ClassDB::bind_method(D_METHOD("is_cap_top"), &CylinderMesh::is_cap_top);
  942. ClassDB::bind_method(D_METHOD("set_cap_bottom", "cap_bottom"), &CylinderMesh::set_cap_bottom);
  943. ClassDB::bind_method(D_METHOD("is_cap_bottom"), &CylinderMesh::is_cap_bottom);
  944. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "top_radius", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater,suffix:m"), "set_top_radius", "get_top_radius");
  945. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bottom_radius", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater,suffix:m"), "set_bottom_radius", "get_bottom_radius");
  946. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "height", PROPERTY_HINT_RANGE, "0.001,100,0.001,or_greater,suffix:m"), "set_height", "get_height");
  947. ADD_PROPERTY(PropertyInfo(Variant::INT, "radial_segments", PROPERTY_HINT_RANGE, "1,100,1,or_greater"), "set_radial_segments", "get_radial_segments");
  948. ADD_PROPERTY(PropertyInfo(Variant::INT, "rings", PROPERTY_HINT_RANGE, "1,100,1,or_greater"), "set_rings", "get_rings");
  949. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "cap_top"), "set_cap_top", "is_cap_top");
  950. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "cap_bottom"), "set_cap_bottom", "is_cap_bottom");
  951. }
  952. void CylinderMesh::set_top_radius(const float p_radius) {
  953. top_radius = p_radius;
  954. _update_lightmap_size();
  955. _request_update();
  956. }
  957. float CylinderMesh::get_top_radius() const {
  958. return top_radius;
  959. }
  960. void CylinderMesh::set_bottom_radius(const float p_radius) {
  961. bottom_radius = p_radius;
  962. _update_lightmap_size();
  963. _request_update();
  964. }
  965. float CylinderMesh::get_bottom_radius() const {
  966. return bottom_radius;
  967. }
  968. void CylinderMesh::set_height(const float p_height) {
  969. height = p_height;
  970. _update_lightmap_size();
  971. _request_update();
  972. }
  973. float CylinderMesh::get_height() const {
  974. return height;
  975. }
  976. void CylinderMesh::set_radial_segments(const int p_segments) {
  977. radial_segments = p_segments > 4 ? p_segments : 4;
  978. _request_update();
  979. }
  980. int CylinderMesh::get_radial_segments() const {
  981. return radial_segments;
  982. }
  983. void CylinderMesh::set_rings(const int p_rings) {
  984. rings = p_rings > 0 ? p_rings : 0;
  985. _request_update();
  986. }
  987. int CylinderMesh::get_rings() const {
  988. return rings;
  989. }
  990. void CylinderMesh::set_cap_top(bool p_cap_top) {
  991. cap_top = p_cap_top;
  992. _request_update();
  993. }
  994. bool CylinderMesh::is_cap_top() const {
  995. return cap_top;
  996. }
  997. void CylinderMesh::set_cap_bottom(bool p_cap_bottom) {
  998. cap_bottom = p_cap_bottom;
  999. _request_update();
  1000. }
  1001. bool CylinderMesh::is_cap_bottom() const {
  1002. return cap_bottom;
  1003. }
  1004. CylinderMesh::CylinderMesh() {}
  1005. /**
  1006. PlaneMesh
  1007. */
  1008. void PlaneMesh::_update_lightmap_size() {
  1009. if (get_add_uv2()) {
  1010. // size must have changed, update lightmap size hint
  1011. Size2i _lightmap_size_hint;
  1012. float texel_size = get_lightmap_texel_size();
  1013. float padding = get_uv2_padding();
  1014. _lightmap_size_hint.x = MAX(1.0, (size.x / texel_size) + padding);
  1015. _lightmap_size_hint.y = MAX(1.0, (size.y / texel_size) + padding);
  1016. set_lightmap_size_hint(_lightmap_size_hint);
  1017. }
  1018. }
  1019. void PlaneMesh::_create_mesh_array(Array &p_arr) const {
  1020. int i, j, prevrow, thisrow, point;
  1021. float x, z;
  1022. // Plane mesh can use default UV2 calculation as implemented in Primitive Mesh
  1023. Size2 start_pos = size * -0.5;
  1024. Vector3 normal = Vector3(0.0, 1.0, 0.0);
  1025. if (orientation == FACE_X) {
  1026. normal = Vector3(1.0, 0.0, 0.0);
  1027. } else if (orientation == FACE_Z) {
  1028. normal = Vector3(0.0, 0.0, 1.0);
  1029. }
  1030. Vector<Vector3> points;
  1031. Vector<Vector3> normals;
  1032. Vector<float> tangents;
  1033. Vector<Vector2> uvs;
  1034. Vector<int> indices;
  1035. point = 0;
  1036. #define ADD_TANGENT(m_x, m_y, m_z, m_d) \
  1037. tangents.push_back(m_x); \
  1038. tangents.push_back(m_y); \
  1039. tangents.push_back(m_z); \
  1040. tangents.push_back(m_d);
  1041. /* top + bottom */
  1042. z = start_pos.y;
  1043. thisrow = point;
  1044. prevrow = 0;
  1045. for (j = 0; j <= (subdivide_d + 1); j++) {
  1046. x = start_pos.x;
  1047. for (i = 0; i <= (subdivide_w + 1); i++) {
  1048. float u = i;
  1049. float v = j;
  1050. u /= (subdivide_w + 1.0);
  1051. v /= (subdivide_d + 1.0);
  1052. if (orientation == FACE_X) {
  1053. points.push_back(Vector3(0.0, z, x) + center_offset);
  1054. } else if (orientation == FACE_Y) {
  1055. points.push_back(Vector3(-x, 0.0, -z) + center_offset);
  1056. } else if (orientation == FACE_Z) {
  1057. points.push_back(Vector3(-x, z, 0.0) + center_offset);
  1058. }
  1059. normals.push_back(normal);
  1060. ADD_TANGENT(1.0, 0.0, 0.0, 1.0);
  1061. uvs.push_back(Vector2(1.0 - u, 1.0 - v)); /* 1.0 - uv to match orientation with Quad */
  1062. point++;
  1063. if (i > 0 && j > 0) {
  1064. indices.push_back(prevrow + i - 1);
  1065. indices.push_back(prevrow + i);
  1066. indices.push_back(thisrow + i - 1);
  1067. indices.push_back(prevrow + i);
  1068. indices.push_back(thisrow + i);
  1069. indices.push_back(thisrow + i - 1);
  1070. }
  1071. x += size.x / (subdivide_w + 1.0);
  1072. }
  1073. z += size.y / (subdivide_d + 1.0);
  1074. prevrow = thisrow;
  1075. thisrow = point;
  1076. }
  1077. p_arr[RS::ARRAY_VERTEX] = points;
  1078. p_arr[RS::ARRAY_NORMAL] = normals;
  1079. p_arr[RS::ARRAY_TANGENT] = tangents;
  1080. p_arr[RS::ARRAY_TEX_UV] = uvs;
  1081. p_arr[RS::ARRAY_INDEX] = indices;
  1082. }
  1083. void PlaneMesh::_bind_methods() {
  1084. ClassDB::bind_method(D_METHOD("set_size", "size"), &PlaneMesh::set_size);
  1085. ClassDB::bind_method(D_METHOD("get_size"), &PlaneMesh::get_size);
  1086. ClassDB::bind_method(D_METHOD("set_subdivide_width", "subdivide"), &PlaneMesh::set_subdivide_width);
  1087. ClassDB::bind_method(D_METHOD("get_subdivide_width"), &PlaneMesh::get_subdivide_width);
  1088. ClassDB::bind_method(D_METHOD("set_subdivide_depth", "subdivide"), &PlaneMesh::set_subdivide_depth);
  1089. ClassDB::bind_method(D_METHOD("get_subdivide_depth"), &PlaneMesh::get_subdivide_depth);
  1090. ClassDB::bind_method(D_METHOD("set_center_offset", "offset"), &PlaneMesh::set_center_offset);
  1091. ClassDB::bind_method(D_METHOD("get_center_offset"), &PlaneMesh::get_center_offset);
  1092. ClassDB::bind_method(D_METHOD("set_orientation", "orientation"), &PlaneMesh::set_orientation);
  1093. ClassDB::bind_method(D_METHOD("get_orientation"), &PlaneMesh::get_orientation);
  1094. ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size", PROPERTY_HINT_NONE, "suffix:m"), "set_size", "get_size");
  1095. ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_width", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_subdivide_width", "get_subdivide_width");
  1096. ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_depth", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_subdivide_depth", "get_subdivide_depth");
  1097. ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "center_offset", PROPERTY_HINT_NONE, "suffix:m"), "set_center_offset", "get_center_offset");
  1098. ADD_PROPERTY(PropertyInfo(Variant::INT, "orientation", PROPERTY_HINT_ENUM, "Face X,Face Y,Face Z"), "set_orientation", "get_orientation");
  1099. BIND_ENUM_CONSTANT(FACE_X)
  1100. BIND_ENUM_CONSTANT(FACE_Y)
  1101. BIND_ENUM_CONSTANT(FACE_Z)
  1102. }
  1103. void PlaneMesh::set_size(const Size2 &p_size) {
  1104. size = p_size;
  1105. _update_lightmap_size();
  1106. _request_update();
  1107. }
  1108. Size2 PlaneMesh::get_size() const {
  1109. return size;
  1110. }
  1111. void PlaneMesh::set_subdivide_width(const int p_divisions) {
  1112. subdivide_w = p_divisions > 0 ? p_divisions : 0;
  1113. _request_update();
  1114. }
  1115. int PlaneMesh::get_subdivide_width() const {
  1116. return subdivide_w;
  1117. }
  1118. void PlaneMesh::set_subdivide_depth(const int p_divisions) {
  1119. subdivide_d = p_divisions > 0 ? p_divisions : 0;
  1120. _request_update();
  1121. }
  1122. int PlaneMesh::get_subdivide_depth() const {
  1123. return subdivide_d;
  1124. }
  1125. void PlaneMesh::set_center_offset(const Vector3 p_offset) {
  1126. center_offset = p_offset;
  1127. _request_update();
  1128. }
  1129. Vector3 PlaneMesh::get_center_offset() const {
  1130. return center_offset;
  1131. }
  1132. void PlaneMesh::set_orientation(const Orientation p_orientation) {
  1133. orientation = p_orientation;
  1134. _request_update();
  1135. }
  1136. PlaneMesh::Orientation PlaneMesh::get_orientation() const {
  1137. return orientation;
  1138. }
  1139. PlaneMesh::PlaneMesh() {}
  1140. /**
  1141. PrismMesh
  1142. */
  1143. void PrismMesh::_update_lightmap_size() {
  1144. if (get_add_uv2()) {
  1145. // size must have changed, update lightmap size hint
  1146. Size2i _lightmap_size_hint;
  1147. float texel_size = get_lightmap_texel_size();
  1148. float padding = get_uv2_padding();
  1149. // left_to_right does not effect the surface area of the prism so we ignore that.
  1150. // TODO we could combine the two triangles and save some space but we need to re-align the uv1 and adjust the tangent.
  1151. float width = (size.x + size.z) / texel_size;
  1152. float length = (size.y + size.y + size.z) / texel_size;
  1153. _lightmap_size_hint.x = MAX(1.0, width) + 2.0 * padding;
  1154. _lightmap_size_hint.y = MAX(1.0, length) + 3.0 * padding;
  1155. set_lightmap_size_hint(_lightmap_size_hint);
  1156. }
  1157. }
  1158. void PrismMesh::_create_mesh_array(Array &p_arr) const {
  1159. int i, j, prevrow, thisrow, point;
  1160. float x, y, z;
  1161. float onethird = 1.0 / 3.0;
  1162. float twothirds = 2.0 / 3.0;
  1163. // Only used if we calculate UV2
  1164. bool _add_uv2 = get_add_uv2();
  1165. float texel_size = get_lightmap_texel_size();
  1166. float _uv2_padding = get_uv2_padding() * texel_size;
  1167. float horizontal_total = size.x + size.z + 2.0 * _uv2_padding;
  1168. float width_h = size.x / horizontal_total;
  1169. float depth_h = size.z / horizontal_total;
  1170. float padding_h = _uv2_padding / horizontal_total;
  1171. float vertical_total = (size.y + size.y + size.z) + (3.0 * _uv2_padding);
  1172. float height_v = size.y / vertical_total;
  1173. float depth_v = size.z / vertical_total;
  1174. float padding_v = _uv2_padding / vertical_total;
  1175. // and start building
  1176. Vector3 start_pos = size * -0.5;
  1177. // set our bounding box
  1178. Vector<Vector3> points;
  1179. Vector<Vector3> normals;
  1180. Vector<float> tangents;
  1181. Vector<Vector2> uvs;
  1182. Vector<Vector2> uv2s;
  1183. Vector<int> indices;
  1184. point = 0;
  1185. #define ADD_TANGENT(m_x, m_y, m_z, m_d) \
  1186. tangents.push_back(m_x); \
  1187. tangents.push_back(m_y); \
  1188. tangents.push_back(m_z); \
  1189. tangents.push_back(m_d);
  1190. /* front + back */
  1191. y = start_pos.y;
  1192. thisrow = point;
  1193. prevrow = 0;
  1194. for (j = 0; j <= (subdivide_h + 1); j++) {
  1195. float scale = (y - start_pos.y) / size.y;
  1196. float scaled_size_x = size.x * scale;
  1197. float start_x = start_pos.x + (1.0 - scale) * size.x * left_to_right;
  1198. float offset_front = (1.0 - scale) * onethird * left_to_right;
  1199. float offset_back = (1.0 - scale) * onethird * (1.0 - left_to_right);
  1200. float v = j;
  1201. float v2 = j / (subdivide_h + 1.0);
  1202. v /= (2.0 * (subdivide_h + 1.0));
  1203. x = 0.0;
  1204. for (i = 0; i <= (subdivide_w + 1); i++) {
  1205. float u = i;
  1206. float u2 = i / (subdivide_w + 1.0);
  1207. u /= (3.0 * (subdivide_w + 1.0));
  1208. u *= scale;
  1209. /* front */
  1210. points.push_back(Vector3(start_x + x, -y, -start_pos.z)); // double negative on the Z!
  1211. normals.push_back(Vector3(0.0, 0.0, 1.0));
  1212. ADD_TANGENT(1.0, 0.0, 0.0, 1.0);
  1213. uvs.push_back(Vector2(offset_front + u, v));
  1214. if (_add_uv2) {
  1215. uv2s.push_back(Vector2(u2 * scale * width_h, v2 * height_v));
  1216. }
  1217. point++;
  1218. /* back */
  1219. points.push_back(Vector3(start_x + scaled_size_x - x, -y, start_pos.z));
  1220. normals.push_back(Vector3(0.0, 0.0, -1.0));
  1221. ADD_TANGENT(-1.0, 0.0, 0.0, 1.0);
  1222. uvs.push_back(Vector2(twothirds + offset_back + u, v));
  1223. if (_add_uv2) {
  1224. uv2s.push_back(Vector2(u2 * scale * width_h, height_v + padding_v + v2 * height_v));
  1225. }
  1226. point++;
  1227. if (i > 0 && j == 1) {
  1228. int i2 = i * 2;
  1229. /* front */
  1230. indices.push_back(prevrow + i2);
  1231. indices.push_back(thisrow + i2);
  1232. indices.push_back(thisrow + i2 - 2);
  1233. /* back */
  1234. indices.push_back(prevrow + i2 + 1);
  1235. indices.push_back(thisrow + i2 + 1);
  1236. indices.push_back(thisrow + i2 - 1);
  1237. } else if (i > 0 && j > 0) {
  1238. int i2 = i * 2;
  1239. /* front */
  1240. indices.push_back(prevrow + i2 - 2);
  1241. indices.push_back(prevrow + i2);
  1242. indices.push_back(thisrow + i2 - 2);
  1243. indices.push_back(prevrow + i2);
  1244. indices.push_back(thisrow + i2);
  1245. indices.push_back(thisrow + i2 - 2);
  1246. /* back */
  1247. indices.push_back(prevrow + i2 - 1);
  1248. indices.push_back(prevrow + i2 + 1);
  1249. indices.push_back(thisrow + i2 - 1);
  1250. indices.push_back(prevrow + i2 + 1);
  1251. indices.push_back(thisrow + i2 + 1);
  1252. indices.push_back(thisrow + i2 - 1);
  1253. }
  1254. x += scale * size.x / (subdivide_w + 1.0);
  1255. }
  1256. y += size.y / (subdivide_h + 1.0);
  1257. prevrow = thisrow;
  1258. thisrow = point;
  1259. }
  1260. /* left + right */
  1261. Vector3 normal_left, normal_right;
  1262. normal_left = Vector3(-size.y, size.x * left_to_right, 0.0);
  1263. normal_right = Vector3(size.y, size.x * (1.0 - left_to_right), 0.0);
  1264. normal_left.normalize();
  1265. normal_right.normalize();
  1266. y = start_pos.y;
  1267. thisrow = point;
  1268. prevrow = 0;
  1269. for (j = 0; j <= (subdivide_h + 1); j++) {
  1270. float v = j;
  1271. float v2 = j / (subdivide_h + 1.0);
  1272. v /= (2.0 * (subdivide_h + 1.0));
  1273. float left, right;
  1274. float scale = (y - start_pos.y) / size.y;
  1275. left = start_pos.x + (size.x * (1.0 - scale) * left_to_right);
  1276. right = left + (size.x * scale);
  1277. z = start_pos.z;
  1278. for (i = 0; i <= (subdivide_d + 1); i++) {
  1279. float u = i;
  1280. float u2 = u / (subdivide_d + 1.0);
  1281. u /= (3.0 * (subdivide_d + 1.0));
  1282. /* right */
  1283. points.push_back(Vector3(right, -y, -z));
  1284. normals.push_back(normal_right);
  1285. ADD_TANGENT(0.0, 0.0, -1.0, 1.0);
  1286. uvs.push_back(Vector2(onethird + u, v));
  1287. if (_add_uv2) {
  1288. uv2s.push_back(Vector2(width_h + padding_h + u2 * depth_h, v2 * height_v));
  1289. }
  1290. point++;
  1291. /* left */
  1292. points.push_back(Vector3(left, -y, z));
  1293. normals.push_back(normal_left);
  1294. ADD_TANGENT(0.0, 0.0, 1.0, 1.0);
  1295. uvs.push_back(Vector2(u, 0.5 + v));
  1296. if (_add_uv2) {
  1297. uv2s.push_back(Vector2(width_h + padding_h + u2 * depth_h, height_v + padding_v + v2 * height_v));
  1298. }
  1299. point++;
  1300. if (i > 0 && j > 0) {
  1301. int i2 = i * 2;
  1302. /* right */
  1303. indices.push_back(prevrow + i2 - 2);
  1304. indices.push_back(prevrow + i2);
  1305. indices.push_back(thisrow + i2 - 2);
  1306. indices.push_back(prevrow + i2);
  1307. indices.push_back(thisrow + i2);
  1308. indices.push_back(thisrow + i2 - 2);
  1309. /* left */
  1310. indices.push_back(prevrow + i2 - 1);
  1311. indices.push_back(prevrow + i2 + 1);
  1312. indices.push_back(thisrow + i2 - 1);
  1313. indices.push_back(prevrow + i2 + 1);
  1314. indices.push_back(thisrow + i2 + 1);
  1315. indices.push_back(thisrow + i2 - 1);
  1316. }
  1317. z += size.z / (subdivide_d + 1.0);
  1318. }
  1319. y += size.y / (subdivide_h + 1.0);
  1320. prevrow = thisrow;
  1321. thisrow = point;
  1322. }
  1323. /* bottom */
  1324. z = start_pos.z;
  1325. thisrow = point;
  1326. prevrow = 0;
  1327. for (j = 0; j <= (subdivide_d + 1); j++) {
  1328. float v = j;
  1329. float v2 = v / (subdivide_d + 1.0);
  1330. v /= (2.0 * (subdivide_d + 1.0));
  1331. x = start_pos.x;
  1332. for (i = 0; i <= (subdivide_w + 1); i++) {
  1333. float u = i;
  1334. float u2 = u / (subdivide_w + 1.0);
  1335. u /= (3.0 * (subdivide_w + 1.0));
  1336. /* bottom */
  1337. points.push_back(Vector3(x, start_pos.y, -z));
  1338. normals.push_back(Vector3(0.0, -1.0, 0.0));
  1339. ADD_TANGENT(1.0, 0.0, 0.0, 1.0);
  1340. uvs.push_back(Vector2(twothirds + u, 0.5 + v));
  1341. if (_add_uv2) {
  1342. uv2s.push_back(Vector2(u2 * width_h, 2.0 * (height_v + padding_v) + v2 * depth_v));
  1343. }
  1344. point++;
  1345. if (i > 0 && j > 0) {
  1346. /* bottom */
  1347. indices.push_back(prevrow + i - 1);
  1348. indices.push_back(prevrow + i);
  1349. indices.push_back(thisrow + i - 1);
  1350. indices.push_back(prevrow + i);
  1351. indices.push_back(thisrow + i);
  1352. indices.push_back(thisrow + i - 1);
  1353. }
  1354. x += size.x / (subdivide_w + 1.0);
  1355. }
  1356. z += size.z / (subdivide_d + 1.0);
  1357. prevrow = thisrow;
  1358. thisrow = point;
  1359. }
  1360. p_arr[RS::ARRAY_VERTEX] = points;
  1361. p_arr[RS::ARRAY_NORMAL] = normals;
  1362. p_arr[RS::ARRAY_TANGENT] = tangents;
  1363. p_arr[RS::ARRAY_TEX_UV] = uvs;
  1364. if (_add_uv2) {
  1365. p_arr[RS::ARRAY_TEX_UV2] = uv2s;
  1366. }
  1367. p_arr[RS::ARRAY_INDEX] = indices;
  1368. }
  1369. void PrismMesh::_bind_methods() {
  1370. ClassDB::bind_method(D_METHOD("set_left_to_right", "left_to_right"), &PrismMesh::set_left_to_right);
  1371. ClassDB::bind_method(D_METHOD("get_left_to_right"), &PrismMesh::get_left_to_right);
  1372. ClassDB::bind_method(D_METHOD("set_size", "size"), &PrismMesh::set_size);
  1373. ClassDB::bind_method(D_METHOD("get_size"), &PrismMesh::get_size);
  1374. ClassDB::bind_method(D_METHOD("set_subdivide_width", "segments"), &PrismMesh::set_subdivide_width);
  1375. ClassDB::bind_method(D_METHOD("get_subdivide_width"), &PrismMesh::get_subdivide_width);
  1376. ClassDB::bind_method(D_METHOD("set_subdivide_height", "segments"), &PrismMesh::set_subdivide_height);
  1377. ClassDB::bind_method(D_METHOD("get_subdivide_height"), &PrismMesh::get_subdivide_height);
  1378. ClassDB::bind_method(D_METHOD("set_subdivide_depth", "segments"), &PrismMesh::set_subdivide_depth);
  1379. ClassDB::bind_method(D_METHOD("get_subdivide_depth"), &PrismMesh::get_subdivide_depth);
  1380. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "left_to_right", PROPERTY_HINT_RANGE, "-2.0,2.0,0.1"), "set_left_to_right", "get_left_to_right");
  1381. ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "size", PROPERTY_HINT_NONE, "suffix:m"), "set_size", "get_size");
  1382. ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_width", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_subdivide_width", "get_subdivide_width");
  1383. ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_height", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_subdivide_height", "get_subdivide_height");
  1384. ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_depth", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_subdivide_depth", "get_subdivide_depth");
  1385. }
  1386. void PrismMesh::set_left_to_right(const float p_left_to_right) {
  1387. left_to_right = p_left_to_right;
  1388. _request_update();
  1389. }
  1390. float PrismMesh::get_left_to_right() const {
  1391. return left_to_right;
  1392. }
  1393. void PrismMesh::set_size(const Vector3 &p_size) {
  1394. size = p_size;
  1395. _update_lightmap_size();
  1396. _request_update();
  1397. }
  1398. Vector3 PrismMesh::get_size() const {
  1399. return size;
  1400. }
  1401. void PrismMesh::set_subdivide_width(const int p_divisions) {
  1402. subdivide_w = p_divisions > 0 ? p_divisions : 0;
  1403. _request_update();
  1404. }
  1405. int PrismMesh::get_subdivide_width() const {
  1406. return subdivide_w;
  1407. }
  1408. void PrismMesh::set_subdivide_height(const int p_divisions) {
  1409. subdivide_h = p_divisions > 0 ? p_divisions : 0;
  1410. _request_update();
  1411. }
  1412. int PrismMesh::get_subdivide_height() const {
  1413. return subdivide_h;
  1414. }
  1415. void PrismMesh::set_subdivide_depth(const int p_divisions) {
  1416. subdivide_d = p_divisions > 0 ? p_divisions : 0;
  1417. _request_update();
  1418. }
  1419. int PrismMesh::get_subdivide_depth() const {
  1420. return subdivide_d;
  1421. }
  1422. PrismMesh::PrismMesh() {}
  1423. /**
  1424. SphereMesh
  1425. */
  1426. void SphereMesh::_update_lightmap_size() {
  1427. if (get_add_uv2()) {
  1428. // size must have changed, update lightmap size hint
  1429. Size2i _lightmap_size_hint;
  1430. float texel_size = get_lightmap_texel_size();
  1431. float padding = get_uv2_padding();
  1432. float _width = radius * Math_TAU;
  1433. _lightmap_size_hint.x = MAX(1.0, (_width / texel_size) + padding);
  1434. float _height = (is_hemisphere ? 1.0 : 0.5) * height * Math_PI; // note, with hemisphere height is our radius, while with a full sphere it is the diameter..
  1435. _lightmap_size_hint.y = MAX(1.0, (_height / texel_size) + padding);
  1436. set_lightmap_size_hint(_lightmap_size_hint);
  1437. }
  1438. }
  1439. void SphereMesh::_create_mesh_array(Array &p_arr) const {
  1440. bool _add_uv2 = get_add_uv2();
  1441. float texel_size = get_lightmap_texel_size();
  1442. float _uv2_padding = get_uv2_padding() * texel_size;
  1443. create_mesh_array(p_arr, radius, height, radial_segments, rings, is_hemisphere, _add_uv2, _uv2_padding);
  1444. }
  1445. void SphereMesh::create_mesh_array(Array &p_arr, float radius, float height, int radial_segments, int rings, bool is_hemisphere, bool p_add_uv2, const float p_uv2_padding) {
  1446. int i, j, prevrow, thisrow, point;
  1447. float x, y, z;
  1448. float scale = height * (is_hemisphere ? 1.0 : 0.5);
  1449. // Only used if we calculate UV2
  1450. float circumference = radius * Math_TAU;
  1451. float horizontal_length = circumference + p_uv2_padding;
  1452. float center_h = 0.5 * circumference / horizontal_length;
  1453. float height_v = scale * Math_PI / ((scale * Math_PI) + p_uv2_padding);
  1454. // set our bounding box
  1455. Vector<Vector3> points;
  1456. Vector<Vector3> normals;
  1457. Vector<float> tangents;
  1458. Vector<Vector2> uvs;
  1459. Vector<Vector2> uv2s;
  1460. Vector<int> indices;
  1461. point = 0;
  1462. #define ADD_TANGENT(m_x, m_y, m_z, m_d) \
  1463. tangents.push_back(m_x); \
  1464. tangents.push_back(m_y); \
  1465. tangents.push_back(m_z); \
  1466. tangents.push_back(m_d);
  1467. thisrow = 0;
  1468. prevrow = 0;
  1469. for (j = 0; j <= (rings + 1); j++) {
  1470. float v = j;
  1471. float w;
  1472. v /= (rings + 1);
  1473. w = sin(Math_PI * v);
  1474. y = scale * cos(Math_PI * v);
  1475. for (i = 0; i <= radial_segments; i++) {
  1476. float u = i;
  1477. u /= radial_segments;
  1478. x = sin(u * Math_TAU);
  1479. z = cos(u * Math_TAU);
  1480. if (is_hemisphere && y < 0.0) {
  1481. points.push_back(Vector3(x * radius * w, 0.0, z * radius * w));
  1482. normals.push_back(Vector3(0.0, -1.0, 0.0));
  1483. } else {
  1484. Vector3 p = Vector3(x * radius * w, y, z * radius * w);
  1485. points.push_back(p);
  1486. Vector3 normal = Vector3(x * w * scale, radius * (y / scale), z * w * scale);
  1487. normals.push_back(normal.normalized());
  1488. }
  1489. ADD_TANGENT(z, 0.0, -x, 1.0)
  1490. uvs.push_back(Vector2(u, v));
  1491. if (p_add_uv2) {
  1492. float w_h = w * 2.0 * center_h;
  1493. uv2s.push_back(Vector2(center_h + ((u - 0.5) * w_h), v * height_v));
  1494. }
  1495. point++;
  1496. if (i > 0 && j > 0) {
  1497. indices.push_back(prevrow + i - 1);
  1498. indices.push_back(prevrow + i);
  1499. indices.push_back(thisrow + i - 1);
  1500. indices.push_back(prevrow + i);
  1501. indices.push_back(thisrow + i);
  1502. indices.push_back(thisrow + i - 1);
  1503. }
  1504. }
  1505. prevrow = thisrow;
  1506. thisrow = point;
  1507. }
  1508. p_arr[RS::ARRAY_VERTEX] = points;
  1509. p_arr[RS::ARRAY_NORMAL] = normals;
  1510. p_arr[RS::ARRAY_TANGENT] = tangents;
  1511. p_arr[RS::ARRAY_TEX_UV] = uvs;
  1512. if (p_add_uv2) {
  1513. p_arr[RS::ARRAY_TEX_UV2] = uv2s;
  1514. }
  1515. p_arr[RS::ARRAY_INDEX] = indices;
  1516. }
  1517. void SphereMesh::_bind_methods() {
  1518. ClassDB::bind_method(D_METHOD("set_radius", "radius"), &SphereMesh::set_radius);
  1519. ClassDB::bind_method(D_METHOD("get_radius"), &SphereMesh::get_radius);
  1520. ClassDB::bind_method(D_METHOD("set_height", "height"), &SphereMesh::set_height);
  1521. ClassDB::bind_method(D_METHOD("get_height"), &SphereMesh::get_height);
  1522. ClassDB::bind_method(D_METHOD("set_radial_segments", "radial_segments"), &SphereMesh::set_radial_segments);
  1523. ClassDB::bind_method(D_METHOD("get_radial_segments"), &SphereMesh::get_radial_segments);
  1524. ClassDB::bind_method(D_METHOD("set_rings", "rings"), &SphereMesh::set_rings);
  1525. ClassDB::bind_method(D_METHOD("get_rings"), &SphereMesh::get_rings);
  1526. ClassDB::bind_method(D_METHOD("set_is_hemisphere", "is_hemisphere"), &SphereMesh::set_is_hemisphere);
  1527. ClassDB::bind_method(D_METHOD("get_is_hemisphere"), &SphereMesh::get_is_hemisphere);
  1528. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.001,100.0,0.001,or_greater,suffix:m"), "set_radius", "get_radius");
  1529. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "height", PROPERTY_HINT_RANGE, "0.001,100.0,0.001,or_greater,suffix:m"), "set_height", "get_height");
  1530. ADD_PROPERTY(PropertyInfo(Variant::INT, "radial_segments", PROPERTY_HINT_RANGE, "1,100,1,or_greater"), "set_radial_segments", "get_radial_segments");
  1531. ADD_PROPERTY(PropertyInfo(Variant::INT, "rings", PROPERTY_HINT_RANGE, "1,100,1,or_greater"), "set_rings", "get_rings");
  1532. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "is_hemisphere"), "set_is_hemisphere", "get_is_hemisphere");
  1533. }
  1534. void SphereMesh::set_radius(const float p_radius) {
  1535. radius = p_radius;
  1536. _update_lightmap_size();
  1537. _request_update();
  1538. }
  1539. float SphereMesh::get_radius() const {
  1540. return radius;
  1541. }
  1542. void SphereMesh::set_height(const float p_height) {
  1543. height = p_height;
  1544. _update_lightmap_size();
  1545. _request_update();
  1546. }
  1547. float SphereMesh::get_height() const {
  1548. return height;
  1549. }
  1550. void SphereMesh::set_radial_segments(const int p_radial_segments) {
  1551. radial_segments = p_radial_segments > 4 ? p_radial_segments : 4;
  1552. _request_update();
  1553. }
  1554. int SphereMesh::get_radial_segments() const {
  1555. return radial_segments;
  1556. }
  1557. void SphereMesh::set_rings(const int p_rings) {
  1558. rings = p_rings > 1 ? p_rings : 1;
  1559. _request_update();
  1560. }
  1561. int SphereMesh::get_rings() const {
  1562. return rings;
  1563. }
  1564. void SphereMesh::set_is_hemisphere(const bool p_is_hemisphere) {
  1565. is_hemisphere = p_is_hemisphere;
  1566. _update_lightmap_size();
  1567. _request_update();
  1568. }
  1569. bool SphereMesh::get_is_hemisphere() const {
  1570. return is_hemisphere;
  1571. }
  1572. SphereMesh::SphereMesh() {}
  1573. /**
  1574. TorusMesh
  1575. */
  1576. void TorusMesh::_update_lightmap_size() {
  1577. if (get_add_uv2()) {
  1578. // size must have changed, update lightmap size hint
  1579. Size2i _lightmap_size_hint;
  1580. float texel_size = get_lightmap_texel_size();
  1581. float padding = get_uv2_padding();
  1582. float min_radius = inner_radius;
  1583. float max_radius = outer_radius;
  1584. if (min_radius > max_radius) {
  1585. SWAP(min_radius, max_radius);
  1586. }
  1587. float radius = (max_radius - min_radius) * 0.5;
  1588. float _width = max_radius * Math_TAU;
  1589. _lightmap_size_hint.x = MAX(1.0, (_width / texel_size) + padding);
  1590. float _height = radius * Math_TAU;
  1591. _lightmap_size_hint.y = MAX(1.0, (_height / texel_size) + padding);
  1592. set_lightmap_size_hint(_lightmap_size_hint);
  1593. }
  1594. }
  1595. void TorusMesh::_create_mesh_array(Array &p_arr) const {
  1596. // set our bounding box
  1597. Vector<Vector3> points;
  1598. Vector<Vector3> normals;
  1599. Vector<float> tangents;
  1600. Vector<Vector2> uvs;
  1601. Vector<Vector2> uv2s;
  1602. Vector<int> indices;
  1603. #define ADD_TANGENT(m_x, m_y, m_z, m_d) \
  1604. tangents.push_back(m_x); \
  1605. tangents.push_back(m_y); \
  1606. tangents.push_back(m_z); \
  1607. tangents.push_back(m_d);
  1608. ERR_FAIL_COND_MSG(inner_radius == outer_radius, "Inner radius and outer radius cannot be the same.");
  1609. float min_radius = inner_radius;
  1610. float max_radius = outer_radius;
  1611. if (min_radius > max_radius) {
  1612. SWAP(min_radius, max_radius);
  1613. }
  1614. float radius = (max_radius - min_radius) * 0.5;
  1615. // Only used if we calculate UV2
  1616. bool _add_uv2 = get_add_uv2();
  1617. float texel_size = get_lightmap_texel_size();
  1618. float _uv2_padding = get_uv2_padding() * texel_size;
  1619. float horizontal_total = max_radius * Math_TAU + _uv2_padding;
  1620. float max_h = max_radius * Math_TAU / horizontal_total;
  1621. float delta_h = (max_radius - min_radius) * Math_TAU / horizontal_total;
  1622. float height_v = radius * Math_TAU / (radius * Math_TAU + _uv2_padding);
  1623. for (int i = 0; i <= rings; i++) {
  1624. int prevrow = (i - 1) * (ring_segments + 1);
  1625. int thisrow = i * (ring_segments + 1);
  1626. float inci = float(i) / rings;
  1627. float angi = inci * Math_TAU;
  1628. Vector2 normali = Vector2(-Math::sin(angi), -Math::cos(angi));
  1629. for (int j = 0; j <= ring_segments; j++) {
  1630. float incj = float(j) / ring_segments;
  1631. float angj = incj * Math_TAU;
  1632. Vector2 normalj = Vector2(-Math::cos(angj), Math::sin(angj));
  1633. Vector2 normalk = normalj * radius + Vector2(min_radius + radius, 0);
  1634. float offset_h = 0.5 * (1.0 - normalj.x) * delta_h;
  1635. float adj_h = max_h - offset_h;
  1636. offset_h *= 0.5;
  1637. points.push_back(Vector3(normali.x * normalk.x, normalk.y, normali.y * normalk.x));
  1638. normals.push_back(Vector3(normali.x * normalj.x, normalj.y, normali.y * normalj.x));
  1639. ADD_TANGENT(-Math::cos(angi), 0.0, Math::sin(angi), 1.0);
  1640. uvs.push_back(Vector2(inci, incj));
  1641. if (_add_uv2) {
  1642. uv2s.push_back(Vector2(offset_h + inci * adj_h, incj * height_v));
  1643. }
  1644. if (i > 0 && j > 0) {
  1645. indices.push_back(thisrow + j - 1);
  1646. indices.push_back(prevrow + j);
  1647. indices.push_back(prevrow + j - 1);
  1648. indices.push_back(thisrow + j - 1);
  1649. indices.push_back(thisrow + j);
  1650. indices.push_back(prevrow + j);
  1651. }
  1652. }
  1653. }
  1654. p_arr[RS::ARRAY_VERTEX] = points;
  1655. p_arr[RS::ARRAY_NORMAL] = normals;
  1656. p_arr[RS::ARRAY_TANGENT] = tangents;
  1657. p_arr[RS::ARRAY_TEX_UV] = uvs;
  1658. if (_add_uv2) {
  1659. p_arr[RS::ARRAY_TEX_UV2] = uv2s;
  1660. }
  1661. p_arr[RS::ARRAY_INDEX] = indices;
  1662. }
  1663. void TorusMesh::_bind_methods() {
  1664. ClassDB::bind_method(D_METHOD("set_inner_radius", "radius"), &TorusMesh::set_inner_radius);
  1665. ClassDB::bind_method(D_METHOD("get_inner_radius"), &TorusMesh::get_inner_radius);
  1666. ClassDB::bind_method(D_METHOD("set_outer_radius", "radius"), &TorusMesh::set_outer_radius);
  1667. ClassDB::bind_method(D_METHOD("get_outer_radius"), &TorusMesh::get_outer_radius);
  1668. ClassDB::bind_method(D_METHOD("set_rings", "rings"), &TorusMesh::set_rings);
  1669. ClassDB::bind_method(D_METHOD("get_rings"), &TorusMesh::get_rings);
  1670. ClassDB::bind_method(D_METHOD("set_ring_segments", "rings"), &TorusMesh::set_ring_segments);
  1671. ClassDB::bind_method(D_METHOD("get_ring_segments"), &TorusMesh::get_ring_segments);
  1672. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "inner_radius", PROPERTY_HINT_RANGE, "0.001,1000.0,0.001,or_greater,exp"), "set_inner_radius", "get_inner_radius");
  1673. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "outer_radius", PROPERTY_HINT_RANGE, "0.001,1000.0,0.001,or_greater,exp"), "set_outer_radius", "get_outer_radius");
  1674. ADD_PROPERTY(PropertyInfo(Variant::INT, "rings", PROPERTY_HINT_RANGE, "3,128,1"), "set_rings", "get_rings");
  1675. ADD_PROPERTY(PropertyInfo(Variant::INT, "ring_segments", PROPERTY_HINT_RANGE, "3,64,1"), "set_ring_segments", "get_ring_segments");
  1676. }
  1677. void TorusMesh::set_inner_radius(const float p_inner_radius) {
  1678. inner_radius = p_inner_radius;
  1679. _request_update();
  1680. }
  1681. float TorusMesh::get_inner_radius() const {
  1682. return inner_radius;
  1683. }
  1684. void TorusMesh::set_outer_radius(const float p_outer_radius) {
  1685. outer_radius = p_outer_radius;
  1686. _request_update();
  1687. }
  1688. float TorusMesh::get_outer_radius() const {
  1689. return outer_radius;
  1690. }
  1691. void TorusMesh::set_rings(const int p_rings) {
  1692. ERR_FAIL_COND(p_rings < 3);
  1693. rings = p_rings;
  1694. _request_update();
  1695. }
  1696. int TorusMesh::get_rings() const {
  1697. return rings;
  1698. }
  1699. void TorusMesh::set_ring_segments(const int p_ring_segments) {
  1700. ERR_FAIL_COND(p_ring_segments < 3);
  1701. ring_segments = p_ring_segments;
  1702. _request_update();
  1703. }
  1704. int TorusMesh::get_ring_segments() const {
  1705. return ring_segments;
  1706. }
  1707. TorusMesh::TorusMesh() {}
  1708. /**
  1709. PointMesh
  1710. */
  1711. void PointMesh::_create_mesh_array(Array &p_arr) const {
  1712. Vector<Vector3> faces;
  1713. faces.resize(1);
  1714. faces.set(0, Vector3(0.0, 0.0, 0.0));
  1715. p_arr[RS::ARRAY_VERTEX] = faces;
  1716. }
  1717. PointMesh::PointMesh() {
  1718. primitive_type = PRIMITIVE_POINTS;
  1719. }
  1720. // TUBE TRAIL
  1721. void TubeTrailMesh::set_radius(const float p_radius) {
  1722. radius = p_radius;
  1723. _request_update();
  1724. }
  1725. float TubeTrailMesh::get_radius() const {
  1726. return radius;
  1727. }
  1728. void TubeTrailMesh::set_radial_steps(const int p_radial_steps) {
  1729. ERR_FAIL_COND(p_radial_steps < 3 || p_radial_steps > 128);
  1730. radial_steps = p_radial_steps;
  1731. _request_update();
  1732. }
  1733. int TubeTrailMesh::get_radial_steps() const {
  1734. return radial_steps;
  1735. }
  1736. void TubeTrailMesh::set_sections(const int p_sections) {
  1737. ERR_FAIL_COND(p_sections < 2 || p_sections > 128);
  1738. sections = p_sections;
  1739. _request_update();
  1740. }
  1741. int TubeTrailMesh::get_sections() const {
  1742. return sections;
  1743. }
  1744. void TubeTrailMesh::set_section_length(float p_section_length) {
  1745. section_length = p_section_length;
  1746. _request_update();
  1747. }
  1748. float TubeTrailMesh::get_section_length() const {
  1749. return section_length;
  1750. }
  1751. void TubeTrailMesh::set_section_rings(const int p_section_rings) {
  1752. ERR_FAIL_COND(p_section_rings < 1 || p_section_rings > 1024);
  1753. section_rings = p_section_rings;
  1754. _request_update();
  1755. }
  1756. int TubeTrailMesh::get_section_rings() const {
  1757. return section_rings;
  1758. }
  1759. void TubeTrailMesh::set_cap_top(bool p_cap_top) {
  1760. cap_top = p_cap_top;
  1761. _request_update();
  1762. }
  1763. bool TubeTrailMesh::is_cap_top() const {
  1764. return cap_top;
  1765. }
  1766. void TubeTrailMesh::set_cap_bottom(bool p_cap_bottom) {
  1767. cap_bottom = p_cap_bottom;
  1768. _request_update();
  1769. }
  1770. bool TubeTrailMesh::is_cap_bottom() const {
  1771. return cap_bottom;
  1772. }
  1773. void TubeTrailMesh::set_curve(const Ref<Curve> &p_curve) {
  1774. if (curve == p_curve) {
  1775. return;
  1776. }
  1777. if (curve.is_valid()) {
  1778. curve->disconnect("changed", callable_mp(this, &TubeTrailMesh::_curve_changed));
  1779. }
  1780. curve = p_curve;
  1781. if (curve.is_valid()) {
  1782. curve->connect("changed", callable_mp(this, &TubeTrailMesh::_curve_changed));
  1783. }
  1784. _request_update();
  1785. }
  1786. Ref<Curve> TubeTrailMesh::get_curve() const {
  1787. return curve;
  1788. }
  1789. void TubeTrailMesh::_curve_changed() {
  1790. _request_update();
  1791. }
  1792. int TubeTrailMesh::get_builtin_bind_pose_count() const {
  1793. return sections + 1;
  1794. }
  1795. Transform3D TubeTrailMesh::get_builtin_bind_pose(int p_index) const {
  1796. float depth = section_length * sections;
  1797. Transform3D xform;
  1798. xform.origin.y = depth / 2.0 - section_length * float(p_index);
  1799. xform.origin.y = -xform.origin.y; //bind is an inverse transform, so negate y
  1800. return xform;
  1801. }
  1802. void TubeTrailMesh::_create_mesh_array(Array &p_arr) const {
  1803. // Seeing use case for TubeTrailMesh, no need to do anything more then default UV2 calculation
  1804. PackedVector3Array points;
  1805. PackedVector3Array normals;
  1806. PackedFloat32Array tangents;
  1807. PackedVector2Array uvs;
  1808. PackedInt32Array bone_indices;
  1809. PackedFloat32Array bone_weights;
  1810. PackedInt32Array indices;
  1811. int point = 0;
  1812. #define ADD_TANGENT(m_x, m_y, m_z, m_d) \
  1813. tangents.push_back(m_x); \
  1814. tangents.push_back(m_y); \
  1815. tangents.push_back(m_z); \
  1816. tangents.push_back(m_d);
  1817. int thisrow = 0;
  1818. int prevrow = 0;
  1819. int total_rings = section_rings * sections;
  1820. float depth = section_length * sections;
  1821. for (int j = 0; j <= total_rings; j++) {
  1822. float v = j;
  1823. v /= total_rings;
  1824. float y = depth * v;
  1825. y = (depth * 0.5) - y;
  1826. int bone = j / section_rings;
  1827. float blend = 1.0 - float(j % section_rings) / float(section_rings);
  1828. for (int i = 0; i <= radial_steps; i++) {
  1829. float u = i;
  1830. u /= radial_steps;
  1831. float r = radius;
  1832. if (curve.is_valid() && curve->get_point_count() > 0) {
  1833. r *= curve->sample_baked(v);
  1834. }
  1835. float x = sin(u * Math_TAU);
  1836. float z = cos(u * Math_TAU);
  1837. Vector3 p = Vector3(x * r, y, z * r);
  1838. points.push_back(p);
  1839. normals.push_back(Vector3(x, 0, z));
  1840. ADD_TANGENT(z, 0.0, -x, 1.0)
  1841. uvs.push_back(Vector2(u, v * 0.5));
  1842. point++;
  1843. {
  1844. bone_indices.push_back(bone);
  1845. bone_indices.push_back(MIN(sections, bone + 1));
  1846. bone_indices.push_back(0);
  1847. bone_indices.push_back(0);
  1848. bone_weights.push_back(blend);
  1849. bone_weights.push_back(1.0 - blend);
  1850. bone_weights.push_back(0);
  1851. bone_weights.push_back(0);
  1852. }
  1853. if (i > 0 && j > 0) {
  1854. indices.push_back(prevrow + i - 1);
  1855. indices.push_back(prevrow + i);
  1856. indices.push_back(thisrow + i - 1);
  1857. indices.push_back(prevrow + i);
  1858. indices.push_back(thisrow + i);
  1859. indices.push_back(thisrow + i - 1);
  1860. }
  1861. }
  1862. prevrow = thisrow;
  1863. thisrow = point;
  1864. }
  1865. if (cap_top) {
  1866. // add top
  1867. float scale_pos = 1.0;
  1868. if (curve.is_valid() && curve->get_point_count() > 0) {
  1869. scale_pos = curve->sample_baked(0);
  1870. }
  1871. if (scale_pos > CMP_EPSILON) {
  1872. float y = depth * 0.5;
  1873. thisrow = point;
  1874. points.push_back(Vector3(0.0, y, 0));
  1875. normals.push_back(Vector3(0.0, 1.0, 0.0));
  1876. ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
  1877. uvs.push_back(Vector2(0.25, 0.75));
  1878. point++;
  1879. bone_indices.push_back(0);
  1880. bone_indices.push_back(0);
  1881. bone_indices.push_back(0);
  1882. bone_indices.push_back(0);
  1883. bone_weights.push_back(1.0);
  1884. bone_weights.push_back(0);
  1885. bone_weights.push_back(0);
  1886. bone_weights.push_back(0);
  1887. float rm = radius * scale_pos;
  1888. for (int i = 0; i <= radial_steps; i++) {
  1889. float r = i;
  1890. r /= radial_steps;
  1891. float x = sin(r * Math_TAU);
  1892. float z = cos(r * Math_TAU);
  1893. float u = ((x + 1.0) * 0.25);
  1894. float v = 0.5 + ((z + 1.0) * 0.25);
  1895. Vector3 p = Vector3(x * rm, y, z * rm);
  1896. points.push_back(p);
  1897. normals.push_back(Vector3(0.0, 1.0, 0.0));
  1898. ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
  1899. uvs.push_back(Vector2(u, v));
  1900. point++;
  1901. bone_indices.push_back(0);
  1902. bone_indices.push_back(0);
  1903. bone_indices.push_back(0);
  1904. bone_indices.push_back(0);
  1905. bone_weights.push_back(1.0);
  1906. bone_weights.push_back(0);
  1907. bone_weights.push_back(0);
  1908. bone_weights.push_back(0);
  1909. if (i > 0) {
  1910. indices.push_back(thisrow);
  1911. indices.push_back(point - 1);
  1912. indices.push_back(point - 2);
  1913. }
  1914. }
  1915. }
  1916. }
  1917. if (cap_bottom) {
  1918. float scale_neg = 1.0;
  1919. if (curve.is_valid() && curve->get_point_count() > 0) {
  1920. scale_neg = curve->sample_baked(1.0);
  1921. }
  1922. if (scale_neg > CMP_EPSILON) {
  1923. // add bottom
  1924. float y = depth * -0.5;
  1925. thisrow = point;
  1926. points.push_back(Vector3(0.0, y, 0.0));
  1927. normals.push_back(Vector3(0.0, -1.0, 0.0));
  1928. ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
  1929. uvs.push_back(Vector2(0.75, 0.75));
  1930. point++;
  1931. bone_indices.push_back(sections);
  1932. bone_indices.push_back(0);
  1933. bone_indices.push_back(0);
  1934. bone_indices.push_back(0);
  1935. bone_weights.push_back(1.0);
  1936. bone_weights.push_back(0);
  1937. bone_weights.push_back(0);
  1938. bone_weights.push_back(0);
  1939. float rm = radius * scale_neg;
  1940. for (int i = 0; i <= radial_steps; i++) {
  1941. float r = i;
  1942. r /= radial_steps;
  1943. float x = sin(r * Math_TAU);
  1944. float z = cos(r * Math_TAU);
  1945. float u = 0.5 + ((x + 1.0) * 0.25);
  1946. float v = 1.0 - ((z + 1.0) * 0.25);
  1947. Vector3 p = Vector3(x * rm, y, z * rm);
  1948. points.push_back(p);
  1949. normals.push_back(Vector3(0.0, -1.0, 0.0));
  1950. ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
  1951. uvs.push_back(Vector2(u, v));
  1952. point++;
  1953. bone_indices.push_back(sections);
  1954. bone_indices.push_back(0);
  1955. bone_indices.push_back(0);
  1956. bone_indices.push_back(0);
  1957. bone_weights.push_back(1.0);
  1958. bone_weights.push_back(0);
  1959. bone_weights.push_back(0);
  1960. bone_weights.push_back(0);
  1961. if (i > 0) {
  1962. indices.push_back(thisrow);
  1963. indices.push_back(point - 2);
  1964. indices.push_back(point - 1);
  1965. }
  1966. }
  1967. }
  1968. }
  1969. p_arr[RS::ARRAY_VERTEX] = points;
  1970. p_arr[RS::ARRAY_NORMAL] = normals;
  1971. p_arr[RS::ARRAY_TANGENT] = tangents;
  1972. p_arr[RS::ARRAY_TEX_UV] = uvs;
  1973. p_arr[RS::ARRAY_BONES] = bone_indices;
  1974. p_arr[RS::ARRAY_WEIGHTS] = bone_weights;
  1975. p_arr[RS::ARRAY_INDEX] = indices;
  1976. }
  1977. void TubeTrailMesh::_bind_methods() {
  1978. ClassDB::bind_method(D_METHOD("set_radius", "radius"), &TubeTrailMesh::set_radius);
  1979. ClassDB::bind_method(D_METHOD("get_radius"), &TubeTrailMesh::get_radius);
  1980. ClassDB::bind_method(D_METHOD("set_radial_steps", "radial_steps"), &TubeTrailMesh::set_radial_steps);
  1981. ClassDB::bind_method(D_METHOD("get_radial_steps"), &TubeTrailMesh::get_radial_steps);
  1982. ClassDB::bind_method(D_METHOD("set_sections", "sections"), &TubeTrailMesh::set_sections);
  1983. ClassDB::bind_method(D_METHOD("get_sections"), &TubeTrailMesh::get_sections);
  1984. ClassDB::bind_method(D_METHOD("set_section_length", "section_length"), &TubeTrailMesh::set_section_length);
  1985. ClassDB::bind_method(D_METHOD("get_section_length"), &TubeTrailMesh::get_section_length);
  1986. ClassDB::bind_method(D_METHOD("set_section_rings", "section_rings"), &TubeTrailMesh::set_section_rings);
  1987. ClassDB::bind_method(D_METHOD("get_section_rings"), &TubeTrailMesh::get_section_rings);
  1988. ClassDB::bind_method(D_METHOD("set_cap_top", "cap_top"), &TubeTrailMesh::set_cap_top);
  1989. ClassDB::bind_method(D_METHOD("is_cap_top"), &TubeTrailMesh::is_cap_top);
  1990. ClassDB::bind_method(D_METHOD("set_cap_bottom", "cap_bottom"), &TubeTrailMesh::set_cap_bottom);
  1991. ClassDB::bind_method(D_METHOD("is_cap_bottom"), &TubeTrailMesh::is_cap_bottom);
  1992. ClassDB::bind_method(D_METHOD("set_curve", "curve"), &TubeTrailMesh::set_curve);
  1993. ClassDB::bind_method(D_METHOD("get_curve"), &TubeTrailMesh::get_curve);
  1994. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.001,100.0,0.001,or_greater,suffix:m"), "set_radius", "get_radius");
  1995. ADD_PROPERTY(PropertyInfo(Variant::INT, "radial_steps", PROPERTY_HINT_RANGE, "3,128,1"), "set_radial_steps", "get_radial_steps");
  1996. ADD_PROPERTY(PropertyInfo(Variant::INT, "sections", PROPERTY_HINT_RANGE, "2,128,1"), "set_sections", "get_sections");
  1997. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "section_length", PROPERTY_HINT_RANGE, "0.001,1024.0,0.001,or_greater,suffix:m"), "set_section_length", "get_section_length");
  1998. ADD_PROPERTY(PropertyInfo(Variant::INT, "section_rings", PROPERTY_HINT_RANGE, "1,128,1"), "set_section_rings", "get_section_rings");
  1999. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "cap_top"), "set_cap_top", "is_cap_top");
  2000. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "cap_bottom"), "set_cap_bottom", "is_cap_bottom");
  2001. ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_curve", "get_curve");
  2002. }
  2003. TubeTrailMesh::TubeTrailMesh() {
  2004. }
  2005. // RIBBON TRAIL
  2006. void RibbonTrailMesh::set_shape(Shape p_shape) {
  2007. shape = p_shape;
  2008. _request_update();
  2009. }
  2010. RibbonTrailMesh::Shape RibbonTrailMesh::get_shape() const {
  2011. return shape;
  2012. }
  2013. void RibbonTrailMesh::set_size(const float p_size) {
  2014. size = p_size;
  2015. _request_update();
  2016. }
  2017. float RibbonTrailMesh::get_size() const {
  2018. return size;
  2019. }
  2020. void RibbonTrailMesh::set_sections(const int p_sections) {
  2021. ERR_FAIL_COND(p_sections < 2 || p_sections > 128);
  2022. sections = p_sections;
  2023. _request_update();
  2024. }
  2025. int RibbonTrailMesh::get_sections() const {
  2026. return sections;
  2027. }
  2028. void RibbonTrailMesh::set_section_length(float p_section_length) {
  2029. section_length = p_section_length;
  2030. _request_update();
  2031. }
  2032. float RibbonTrailMesh::get_section_length() const {
  2033. return section_length;
  2034. }
  2035. void RibbonTrailMesh::set_section_segments(const int p_section_segments) {
  2036. ERR_FAIL_COND(p_section_segments < 1 || p_section_segments > 1024);
  2037. section_segments = p_section_segments;
  2038. _request_update();
  2039. }
  2040. int RibbonTrailMesh::get_section_segments() const {
  2041. return section_segments;
  2042. }
  2043. void RibbonTrailMesh::set_curve(const Ref<Curve> &p_curve) {
  2044. if (curve == p_curve) {
  2045. return;
  2046. }
  2047. if (curve.is_valid()) {
  2048. curve->disconnect("changed", callable_mp(this, &RibbonTrailMesh::_curve_changed));
  2049. }
  2050. curve = p_curve;
  2051. if (curve.is_valid()) {
  2052. curve->connect("changed", callable_mp(this, &RibbonTrailMesh::_curve_changed));
  2053. }
  2054. _request_update();
  2055. }
  2056. Ref<Curve> RibbonTrailMesh::get_curve() const {
  2057. return curve;
  2058. }
  2059. void RibbonTrailMesh::_curve_changed() {
  2060. _request_update();
  2061. }
  2062. int RibbonTrailMesh::get_builtin_bind_pose_count() const {
  2063. return sections + 1;
  2064. }
  2065. Transform3D RibbonTrailMesh::get_builtin_bind_pose(int p_index) const {
  2066. float depth = section_length * sections;
  2067. Transform3D xform;
  2068. xform.origin.y = depth / 2.0 - section_length * float(p_index);
  2069. xform.origin.y = -xform.origin.y; //bind is an inverse transform, so negate y
  2070. return xform;
  2071. }
  2072. void RibbonTrailMesh::_create_mesh_array(Array &p_arr) const {
  2073. // Seeing use case of ribbon trail mesh, no need to implement special UV2 calculation
  2074. PackedVector3Array points;
  2075. PackedVector3Array normals;
  2076. PackedFloat32Array tangents;
  2077. PackedVector2Array uvs;
  2078. PackedInt32Array bone_indices;
  2079. PackedFloat32Array bone_weights;
  2080. PackedInt32Array indices;
  2081. #define ADD_TANGENT(m_x, m_y, m_z, m_d) \
  2082. tangents.push_back(m_x); \
  2083. tangents.push_back(m_y); \
  2084. tangents.push_back(m_z); \
  2085. tangents.push_back(m_d);
  2086. int total_segments = section_segments * sections;
  2087. float depth = section_length * sections;
  2088. for (int j = 0; j <= total_segments; j++) {
  2089. float v = j;
  2090. v /= total_segments;
  2091. float y = depth * v;
  2092. y = (depth * 0.5) - y;
  2093. int bone = j / section_segments;
  2094. float blend = 1.0 - float(j % section_segments) / float(section_segments);
  2095. float s = size;
  2096. if (curve.is_valid() && curve->get_point_count() > 0) {
  2097. s *= curve->sample_baked(v);
  2098. }
  2099. points.push_back(Vector3(-s * 0.5, y, 0));
  2100. points.push_back(Vector3(+s * 0.5, y, 0));
  2101. if (shape == SHAPE_CROSS) {
  2102. points.push_back(Vector3(0, y, -s * 0.5));
  2103. points.push_back(Vector3(0, y, +s * 0.5));
  2104. }
  2105. normals.push_back(Vector3(0, 0, 1));
  2106. normals.push_back(Vector3(0, 0, 1));
  2107. if (shape == SHAPE_CROSS) {
  2108. normals.push_back(Vector3(1, 0, 0));
  2109. normals.push_back(Vector3(1, 0, 0));
  2110. }
  2111. uvs.push_back(Vector2(0, v));
  2112. uvs.push_back(Vector2(1, v));
  2113. if (shape == SHAPE_CROSS) {
  2114. uvs.push_back(Vector2(0, v));
  2115. uvs.push_back(Vector2(1, v));
  2116. }
  2117. ADD_TANGENT(0.0, 1.0, 0.0, 1.0)
  2118. ADD_TANGENT(0.0, 1.0, 0.0, 1.0)
  2119. if (shape == SHAPE_CROSS) {
  2120. ADD_TANGENT(0.0, 1.0, 0.0, 1.0)
  2121. ADD_TANGENT(0.0, 1.0, 0.0, 1.0)
  2122. }
  2123. for (int i = 0; i < (shape == SHAPE_CROSS ? 4 : 2); i++) {
  2124. bone_indices.push_back(bone);
  2125. bone_indices.push_back(MIN(sections, bone + 1));
  2126. bone_indices.push_back(0);
  2127. bone_indices.push_back(0);
  2128. bone_weights.push_back(blend);
  2129. bone_weights.push_back(1.0 - blend);
  2130. bone_weights.push_back(0);
  2131. bone_weights.push_back(0);
  2132. }
  2133. if (j > 0) {
  2134. if (shape == SHAPE_CROSS) {
  2135. int base = j * 4 - 4;
  2136. indices.push_back(base + 0);
  2137. indices.push_back(base + 1);
  2138. indices.push_back(base + 4);
  2139. indices.push_back(base + 1);
  2140. indices.push_back(base + 5);
  2141. indices.push_back(base + 4);
  2142. indices.push_back(base + 2);
  2143. indices.push_back(base + 3);
  2144. indices.push_back(base + 6);
  2145. indices.push_back(base + 3);
  2146. indices.push_back(base + 7);
  2147. indices.push_back(base + 6);
  2148. } else {
  2149. int base = j * 2 - 2;
  2150. indices.push_back(base + 0);
  2151. indices.push_back(base + 1);
  2152. indices.push_back(base + 2);
  2153. indices.push_back(base + 1);
  2154. indices.push_back(base + 3);
  2155. indices.push_back(base + 2);
  2156. }
  2157. }
  2158. }
  2159. p_arr[RS::ARRAY_VERTEX] = points;
  2160. p_arr[RS::ARRAY_NORMAL] = normals;
  2161. p_arr[RS::ARRAY_TANGENT] = tangents;
  2162. p_arr[RS::ARRAY_TEX_UV] = uvs;
  2163. p_arr[RS::ARRAY_BONES] = bone_indices;
  2164. p_arr[RS::ARRAY_WEIGHTS] = bone_weights;
  2165. p_arr[RS::ARRAY_INDEX] = indices;
  2166. }
  2167. void RibbonTrailMesh::_bind_methods() {
  2168. ClassDB::bind_method(D_METHOD("set_size", "size"), &RibbonTrailMesh::set_size);
  2169. ClassDB::bind_method(D_METHOD("get_size"), &RibbonTrailMesh::get_size);
  2170. ClassDB::bind_method(D_METHOD("set_sections", "sections"), &RibbonTrailMesh::set_sections);
  2171. ClassDB::bind_method(D_METHOD("get_sections"), &RibbonTrailMesh::get_sections);
  2172. ClassDB::bind_method(D_METHOD("set_section_length", "section_length"), &RibbonTrailMesh::set_section_length);
  2173. ClassDB::bind_method(D_METHOD("get_section_length"), &RibbonTrailMesh::get_section_length);
  2174. ClassDB::bind_method(D_METHOD("set_section_segments", "section_segments"), &RibbonTrailMesh::set_section_segments);
  2175. ClassDB::bind_method(D_METHOD("get_section_segments"), &RibbonTrailMesh::get_section_segments);
  2176. ClassDB::bind_method(D_METHOD("set_curve", "curve"), &RibbonTrailMesh::set_curve);
  2177. ClassDB::bind_method(D_METHOD("get_curve"), &RibbonTrailMesh::get_curve);
  2178. ClassDB::bind_method(D_METHOD("set_shape", "shape"), &RibbonTrailMesh::set_shape);
  2179. ClassDB::bind_method(D_METHOD("get_shape"), &RibbonTrailMesh::get_shape);
  2180. ADD_PROPERTY(PropertyInfo(Variant::INT, "shape", PROPERTY_HINT_ENUM, "Flat,Cross"), "set_shape", "get_shape");
  2181. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "size", PROPERTY_HINT_RANGE, "0.001,100.0,0.001,or_greater,suffix:m"), "set_size", "get_size");
  2182. ADD_PROPERTY(PropertyInfo(Variant::INT, "sections", PROPERTY_HINT_RANGE, "2,128,1"), "set_sections", "get_sections");
  2183. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "section_length", PROPERTY_HINT_RANGE, "0.001,1024.0,0.001,or_greater,suffix:m"), "set_section_length", "get_section_length");
  2184. ADD_PROPERTY(PropertyInfo(Variant::INT, "section_segments", PROPERTY_HINT_RANGE, "1,128,1"), "set_section_segments", "get_section_segments");
  2185. ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_curve", "get_curve");
  2186. BIND_ENUM_CONSTANT(SHAPE_FLAT)
  2187. BIND_ENUM_CONSTANT(SHAPE_CROSS)
  2188. }
  2189. RibbonTrailMesh::RibbonTrailMesh() {
  2190. }
  2191. /*************************************************************************/
  2192. /* TextMesh */
  2193. /*************************************************************************/
  2194. void TextMesh::_generate_glyph_mesh_data(const GlyphMeshKey &p_key, const Glyph &p_gl) const {
  2195. if (cache.has(p_key)) {
  2196. return;
  2197. }
  2198. GlyphMeshData &gl_data = cache[p_key];
  2199. Dictionary d = TS->font_get_glyph_contours(p_gl.font_rid, p_gl.font_size, p_gl.index);
  2200. Vector2 origin = Vector2(p_gl.x_off, p_gl.y_off) * pixel_size;
  2201. PackedVector3Array points = d["points"];
  2202. PackedInt32Array contours = d["contours"];
  2203. bool orientation = d["orientation"];
  2204. if (points.size() < 3 || contours.size() < 1) {
  2205. return; // No full contours, only glyph control points (or nothing), ignore.
  2206. }
  2207. // Approximate Bezier curves as polygons.
  2208. // See https://freetype.org/freetype2/docs/glyphs/glyphs-6.html, for more info.
  2209. for (int i = 0; i < contours.size(); i++) {
  2210. int32_t start = (i == 0) ? 0 : (contours[i - 1] + 1);
  2211. int32_t end = contours[i];
  2212. Vector<ContourPoint> polygon;
  2213. for (int32_t j = start; j <= end; j++) {
  2214. if (points[j].z == TextServer::CONTOUR_CURVE_TAG_ON) {
  2215. // Point on the curve.
  2216. Vector2 p = Vector2(points[j].x, points[j].y) * pixel_size + origin;
  2217. polygon.push_back(ContourPoint(p, true));
  2218. } else if (points[j].z == TextServer::CONTOUR_CURVE_TAG_OFF_CONIC) {
  2219. // Conic Bezier arc.
  2220. int32_t next = (j == end) ? start : (j + 1);
  2221. int32_t prev = (j == start) ? end : (j - 1);
  2222. Vector2 p0;
  2223. Vector2 p1 = Vector2(points[j].x, points[j].y);
  2224. Vector2 p2;
  2225. // For successive conic OFF points add a virtual ON point in the middle.
  2226. if (points[prev].z == TextServer::CONTOUR_CURVE_TAG_OFF_CONIC) {
  2227. p0 = (Vector2(points[prev].x, points[prev].y) + Vector2(points[j].x, points[j].y)) / 2.0;
  2228. } else if (points[prev].z == TextServer::CONTOUR_CURVE_TAG_ON) {
  2229. p0 = Vector2(points[prev].x, points[prev].y);
  2230. } else {
  2231. ERR_FAIL_MSG(vformat("Invalid conic arc point sequence at %d:%d", i, j));
  2232. }
  2233. if (points[next].z == TextServer::CONTOUR_CURVE_TAG_OFF_CONIC) {
  2234. p2 = (Vector2(points[j].x, points[j].y) + Vector2(points[next].x, points[next].y)) / 2.0;
  2235. } else if (points[next].z == TextServer::CONTOUR_CURVE_TAG_ON) {
  2236. p2 = Vector2(points[next].x, points[next].y);
  2237. } else {
  2238. ERR_FAIL_MSG(vformat("Invalid conic arc point sequence at %d:%d", i, j));
  2239. }
  2240. real_t step = CLAMP(curve_step / (p0 - p2).length(), 0.01, 0.5);
  2241. real_t t = step;
  2242. while (t < 1.0) {
  2243. real_t omt = (1.0 - t);
  2244. real_t omt2 = omt * omt;
  2245. real_t t2 = t * t;
  2246. Vector2 point = p1 + omt2 * (p0 - p1) + t2 * (p2 - p1);
  2247. Vector2 p = point * pixel_size + origin;
  2248. polygon.push_back(ContourPoint(p, false));
  2249. t += step;
  2250. }
  2251. } else if (points[j].z == TextServer::CONTOUR_CURVE_TAG_OFF_CUBIC) {
  2252. // Cubic Bezier arc.
  2253. int32_t cur = j;
  2254. int32_t next1 = (j == end) ? start : (j + 1);
  2255. int32_t next2 = (next1 == end) ? start : (next1 + 1);
  2256. int32_t prev = (j == start) ? end : (j - 1);
  2257. // There must be exactly two OFF points and two ON points for each cubic arc.
  2258. if (points[prev].z != TextServer::CONTOUR_CURVE_TAG_ON) {
  2259. cur = (cur == 0) ? end : cur - 1;
  2260. next1 = (next1 == 0) ? end : next1 - 1;
  2261. next2 = (next2 == 0) ? end : next2 - 1;
  2262. prev = (prev == 0) ? end : prev - 1;
  2263. } else {
  2264. j++;
  2265. }
  2266. ERR_FAIL_COND_MSG(points[prev].z != TextServer::CONTOUR_CURVE_TAG_ON, vformat("Invalid cubic arc point sequence at %d:%d", i, prev));
  2267. ERR_FAIL_COND_MSG(points[cur].z != TextServer::CONTOUR_CURVE_TAG_OFF_CUBIC, vformat("Invalid cubic arc point sequence at %d:%d", i, cur));
  2268. ERR_FAIL_COND_MSG(points[next1].z != TextServer::CONTOUR_CURVE_TAG_OFF_CUBIC, vformat("Invalid cubic arc point sequence at %d:%d", i, next1));
  2269. ERR_FAIL_COND_MSG(points[next2].z != TextServer::CONTOUR_CURVE_TAG_ON, vformat("Invalid cubic arc point sequence at %d:%d", i, next2));
  2270. Vector2 p0 = Vector2(points[prev].x, points[prev].y);
  2271. Vector2 p1 = Vector2(points[cur].x, points[cur].y);
  2272. Vector2 p2 = Vector2(points[next1].x, points[next1].y);
  2273. Vector2 p3 = Vector2(points[next2].x, points[next2].y);
  2274. real_t step = CLAMP(curve_step / (p0 - p3).length(), 0.01, 0.5);
  2275. real_t t = step;
  2276. while (t < 1.0) {
  2277. Vector2 point = p0.bezier_interpolate(p1, p2, p3, t);
  2278. Vector2 p = point * pixel_size + origin;
  2279. polygon.push_back(ContourPoint(p, false));
  2280. t += step;
  2281. }
  2282. } else {
  2283. ERR_FAIL_MSG(vformat("Unknown point tag at %d:%d", i, j));
  2284. }
  2285. }
  2286. if (polygon.size() < 3) {
  2287. continue; // Skip glyph control points.
  2288. }
  2289. if (!orientation) {
  2290. polygon.reverse();
  2291. }
  2292. gl_data.contours.push_back(polygon);
  2293. }
  2294. // Calculate bounds.
  2295. List<TPPLPoly> in_poly;
  2296. for (int i = 0; i < gl_data.contours.size(); i++) {
  2297. TPPLPoly inp;
  2298. inp.Init(gl_data.contours[i].size());
  2299. real_t length = 0.0;
  2300. for (int j = 0; j < gl_data.contours[i].size(); j++) {
  2301. int next = (j + 1 == gl_data.contours[i].size()) ? 0 : (j + 1);
  2302. gl_data.min_p.x = MIN(gl_data.min_p.x, gl_data.contours[i][j].point.x);
  2303. gl_data.min_p.y = MIN(gl_data.min_p.y, gl_data.contours[i][j].point.y);
  2304. gl_data.max_p.x = MAX(gl_data.max_p.x, gl_data.contours[i][j].point.x);
  2305. gl_data.max_p.y = MAX(gl_data.max_p.y, gl_data.contours[i][j].point.y);
  2306. length += (gl_data.contours[i][next].point - gl_data.contours[i][j].point).length();
  2307. inp.GetPoint(j) = gl_data.contours[i][j].point;
  2308. }
  2309. TPPLOrientation poly_orient = inp.GetOrientation();
  2310. if (poly_orient == TPPL_ORIENTATION_CW) {
  2311. inp.SetHole(true);
  2312. }
  2313. in_poly.push_back(inp);
  2314. gl_data.contours_info.push_back(ContourInfo(length, poly_orient == TPPL_ORIENTATION_CCW));
  2315. }
  2316. TPPLPartition tpart;
  2317. //Decompose and triangulate.
  2318. List<TPPLPoly> out_poly;
  2319. if (tpart.ConvexPartition_HM(&in_poly, &out_poly) == 0) {
  2320. ERR_FAIL_MSG("Convex decomposing failed. Make sure the font doesn't contain self-intersecting lines, as these are not supported in TextMesh.");
  2321. }
  2322. List<TPPLPoly> out_tris;
  2323. for (List<TPPLPoly>::Element *I = out_poly.front(); I; I = I->next()) {
  2324. if (tpart.Triangulate_OPT(&(I->get()), &out_tris) == 0) {
  2325. ERR_FAIL_MSG("Triangulation failed. Make sure the font doesn't contain self-intersecting lines, as these are not supported in TextMesh.");
  2326. }
  2327. }
  2328. for (List<TPPLPoly>::Element *I = out_tris.front(); I; I = I->next()) {
  2329. TPPLPoly &tp = I->get();
  2330. ERR_FAIL_COND(tp.GetNumPoints() != 3); // Triangles only.
  2331. for (int i = 0; i < 3; i++) {
  2332. gl_data.triangles.push_back(Vector2(tp.GetPoint(i).x, tp.GetPoint(i).y));
  2333. }
  2334. }
  2335. }
  2336. void TextMesh::_create_mesh_array(Array &p_arr) const {
  2337. Ref<Font> font = _get_font_or_default();
  2338. ERR_FAIL_COND(font.is_null());
  2339. if (dirty_cache) {
  2340. cache.clear();
  2341. dirty_cache = false;
  2342. }
  2343. // When a shaped text is invalidated by an external source, we want to reshape it.
  2344. if (!TS->shaped_text_is_ready(text_rid)) {
  2345. dirty_text = true;
  2346. }
  2347. for (const RID &line_rid : lines_rid) {
  2348. if (!TS->shaped_text_is_ready(line_rid)) {
  2349. dirty_lines = true;
  2350. break;
  2351. }
  2352. }
  2353. // Update text buffer.
  2354. if (dirty_text) {
  2355. TS->shaped_text_clear(text_rid);
  2356. TS->shaped_text_set_direction(text_rid, text_direction);
  2357. String txt = (uppercase) ? TS->string_to_upper(xl_text, language) : xl_text;
  2358. TS->shaped_text_add_string(text_rid, txt, font->get_rids(), font_size, font->get_opentype_features(), language);
  2359. for (int i = 0; i < TextServer::SPACING_MAX; i++) {
  2360. TS->shaped_text_set_spacing(text_rid, TextServer::SpacingType(i), font->get_spacing(TextServer::SpacingType(i)));
  2361. }
  2362. TypedArray<Vector3i> stt;
  2363. if (st_parser == TextServer::STRUCTURED_TEXT_CUSTOM) {
  2364. GDVIRTUAL_CALL(_structured_text_parser, st_args, txt, stt);
  2365. } else {
  2366. stt = TS->parse_structured_text(st_parser, st_args, txt);
  2367. }
  2368. TS->shaped_text_set_bidi_override(text_rid, stt);
  2369. dirty_text = false;
  2370. dirty_font = false;
  2371. dirty_lines = true;
  2372. } else if (dirty_font) {
  2373. int spans = TS->shaped_get_span_count(text_rid);
  2374. for (int i = 0; i < spans; i++) {
  2375. TS->shaped_set_span_update_font(text_rid, i, font->get_rids(), font_size, font->get_opentype_features());
  2376. }
  2377. for (int i = 0; i < TextServer::SPACING_MAX; i++) {
  2378. TS->shaped_text_set_spacing(text_rid, TextServer::SpacingType(i), font->get_spacing(TextServer::SpacingType(i)));
  2379. }
  2380. dirty_font = false;
  2381. dirty_lines = true;
  2382. }
  2383. if (dirty_lines) {
  2384. for (int i = 0; i < lines_rid.size(); i++) {
  2385. TS->free_rid(lines_rid[i]);
  2386. }
  2387. lines_rid.clear();
  2388. BitField<TextServer::LineBreakFlag> autowrap_flags = TextServer::BREAK_MANDATORY;
  2389. switch (autowrap_mode) {
  2390. case TextServer::AUTOWRAP_WORD_SMART:
  2391. autowrap_flags = TextServer::BREAK_WORD_BOUND | TextServer::BREAK_ADAPTIVE | TextServer::BREAK_MANDATORY;
  2392. break;
  2393. case TextServer::AUTOWRAP_WORD:
  2394. autowrap_flags = TextServer::BREAK_WORD_BOUND | TextServer::BREAK_MANDATORY;
  2395. break;
  2396. case TextServer::AUTOWRAP_ARBITRARY:
  2397. autowrap_flags = TextServer::BREAK_GRAPHEME_BOUND | TextServer::BREAK_MANDATORY;
  2398. break;
  2399. case TextServer::AUTOWRAP_OFF:
  2400. break;
  2401. }
  2402. PackedInt32Array line_breaks = TS->shaped_text_get_line_breaks(text_rid, width, 0, autowrap_flags);
  2403. float max_line_w = 0.0;
  2404. for (int i = 0; i < line_breaks.size(); i = i + 2) {
  2405. RID line = TS->shaped_text_substr(text_rid, line_breaks[i], line_breaks[i + 1] - line_breaks[i]);
  2406. max_line_w = MAX(max_line_w, TS->shaped_text_get_width(line));
  2407. lines_rid.push_back(line);
  2408. }
  2409. if (horizontal_alignment == HORIZONTAL_ALIGNMENT_FILL) {
  2410. for (int i = 0; i < lines_rid.size() - 1; i++) {
  2411. TS->shaped_text_fit_to_width(lines_rid[i], (width > 0) ? width : max_line_w, TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA);
  2412. }
  2413. }
  2414. dirty_lines = false;
  2415. }
  2416. float total_h = 0.0;
  2417. for (int i = 0; i < lines_rid.size(); i++) {
  2418. total_h += (TS->shaped_text_get_size(lines_rid[i]).y + line_spacing) * pixel_size;
  2419. }
  2420. float vbegin = 0.0;
  2421. switch (vertical_alignment) {
  2422. case VERTICAL_ALIGNMENT_FILL:
  2423. case VERTICAL_ALIGNMENT_TOP: {
  2424. // Nothing.
  2425. } break;
  2426. case VERTICAL_ALIGNMENT_CENTER: {
  2427. vbegin = (total_h - line_spacing * pixel_size) / 2.0;
  2428. } break;
  2429. case VERTICAL_ALIGNMENT_BOTTOM: {
  2430. vbegin = (total_h - line_spacing * pixel_size);
  2431. } break;
  2432. }
  2433. Vector<Vector3> vertices;
  2434. Vector<Vector3> normals;
  2435. Vector<float> tangents;
  2436. Vector<Vector2> uvs;
  2437. Vector<int32_t> indices;
  2438. Vector2 min_p = Vector2(INFINITY, INFINITY);
  2439. Vector2 max_p = Vector2(-INFINITY, -INFINITY);
  2440. int32_t p_size = 0;
  2441. int32_t i_size = 0;
  2442. Vector2 offset = Vector2(0, vbegin + lbl_offset.y * pixel_size);
  2443. for (int i = 0; i < lines_rid.size(); i++) {
  2444. const Glyph *glyphs = TS->shaped_text_get_glyphs(lines_rid[i]);
  2445. int gl_size = TS->shaped_text_get_glyph_count(lines_rid[i]);
  2446. float line_width = TS->shaped_text_get_width(lines_rid[i]) * pixel_size;
  2447. switch (horizontal_alignment) {
  2448. case HORIZONTAL_ALIGNMENT_LEFT:
  2449. offset.x = 0.0;
  2450. break;
  2451. case HORIZONTAL_ALIGNMENT_FILL:
  2452. case HORIZONTAL_ALIGNMENT_CENTER: {
  2453. offset.x = -line_width / 2.0;
  2454. } break;
  2455. case HORIZONTAL_ALIGNMENT_RIGHT: {
  2456. offset.x = -line_width;
  2457. } break;
  2458. }
  2459. offset.x += lbl_offset.x * pixel_size;
  2460. offset.y -= TS->shaped_text_get_ascent(lines_rid[i]) * pixel_size;
  2461. bool has_depth = !Math::is_zero_approx(depth);
  2462. for (int j = 0; j < gl_size; j++) {
  2463. if (glyphs[j].index == 0) {
  2464. offset.x += glyphs[j].advance * pixel_size * glyphs[j].repeat;
  2465. continue;
  2466. }
  2467. if (glyphs[j].font_rid != RID()) {
  2468. GlyphMeshKey key = GlyphMeshKey(glyphs[j].font_rid.get_id(), glyphs[j].index);
  2469. _generate_glyph_mesh_data(key, glyphs[j]);
  2470. GlyphMeshData &gl_data = cache[key];
  2471. p_size += glyphs[j].repeat * gl_data.triangles.size() * ((has_depth) ? 2 : 1);
  2472. i_size += glyphs[j].repeat * gl_data.triangles.size() * ((has_depth) ? 2 : 1);
  2473. if (has_depth) {
  2474. for (int k = 0; k < gl_data.contours.size(); k++) {
  2475. p_size += glyphs[j].repeat * gl_data.contours[k].size() * 4;
  2476. i_size += glyphs[j].repeat * gl_data.contours[k].size() * 6;
  2477. }
  2478. }
  2479. for (int r = 0; r < glyphs[j].repeat; r++) {
  2480. min_p.x = MIN(gl_data.min_p.x + offset.x, min_p.x);
  2481. min_p.y = MIN(gl_data.min_p.y - offset.y, min_p.y);
  2482. max_p.x = MAX(gl_data.max_p.x + offset.x, max_p.x);
  2483. max_p.y = MAX(gl_data.max_p.y - offset.y, max_p.y);
  2484. offset.x += glyphs[j].advance * pixel_size;
  2485. }
  2486. } else {
  2487. p_size += glyphs[j].repeat * 4;
  2488. i_size += glyphs[j].repeat * 6;
  2489. offset.x += glyphs[j].advance * pixel_size * glyphs[j].repeat;
  2490. }
  2491. }
  2492. offset.y -= (TS->shaped_text_get_descent(lines_rid[i]) + line_spacing) * pixel_size;
  2493. }
  2494. vertices.resize(p_size);
  2495. normals.resize(p_size);
  2496. uvs.resize(p_size);
  2497. tangents.resize(p_size * 4);
  2498. indices.resize(i_size);
  2499. Vector3 *vertices_ptr = vertices.ptrw();
  2500. Vector3 *normals_ptr = normals.ptrw();
  2501. float *tangents_ptr = tangents.ptrw();
  2502. Vector2 *uvs_ptr = uvs.ptrw();
  2503. int32_t *indices_ptr = indices.ptrw();
  2504. // Generate mesh.
  2505. int32_t p_idx = 0;
  2506. int32_t i_idx = 0;
  2507. offset = Vector2(0, vbegin + lbl_offset.y * pixel_size);
  2508. for (int i = 0; i < lines_rid.size(); i++) {
  2509. const Glyph *glyphs = TS->shaped_text_get_glyphs(lines_rid[i]);
  2510. int gl_size = TS->shaped_text_get_glyph_count(lines_rid[i]);
  2511. float line_width = TS->shaped_text_get_width(lines_rid[i]) * pixel_size;
  2512. switch (horizontal_alignment) {
  2513. case HORIZONTAL_ALIGNMENT_LEFT:
  2514. offset.x = 0.0;
  2515. break;
  2516. case HORIZONTAL_ALIGNMENT_FILL:
  2517. case HORIZONTAL_ALIGNMENT_CENTER: {
  2518. offset.x = -line_width / 2.0;
  2519. } break;
  2520. case HORIZONTAL_ALIGNMENT_RIGHT: {
  2521. offset.x = -line_width;
  2522. } break;
  2523. }
  2524. offset.x += lbl_offset.x * pixel_size;
  2525. offset.y -= TS->shaped_text_get_ascent(lines_rid[i]) * pixel_size;
  2526. bool has_depth = !Math::is_zero_approx(depth);
  2527. // Generate glyph data, precalculate size of the arrays and mesh bounds for UV.
  2528. for (int j = 0; j < gl_size; j++) {
  2529. if (glyphs[j].index == 0) {
  2530. offset.x += glyphs[j].advance * pixel_size * glyphs[j].repeat;
  2531. continue;
  2532. }
  2533. if (glyphs[j].font_rid != RID()) {
  2534. GlyphMeshKey key = GlyphMeshKey(glyphs[j].font_rid.get_id(), glyphs[j].index);
  2535. _generate_glyph_mesh_data(key, glyphs[j]);
  2536. const GlyphMeshData &gl_data = cache[key];
  2537. int64_t ts = gl_data.triangles.size();
  2538. const Vector2 *ts_ptr = gl_data.triangles.ptr();
  2539. for (int r = 0; r < glyphs[j].repeat; r++) {
  2540. for (int k = 0; k < ts; k += 3) {
  2541. // Add front face.
  2542. for (int l = 0; l < 3; l++) {
  2543. Vector3 point = Vector3(ts_ptr[k + l].x + offset.x, -ts_ptr[k + l].y + offset.y, depth / 2.0);
  2544. vertices_ptr[p_idx] = point;
  2545. normals_ptr[p_idx] = Vector3(0.0, 0.0, 1.0);
  2546. if (has_depth) {
  2547. uvs_ptr[p_idx] = Vector2(Math::remap(point.x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::remap(point.y, -max_p.y, -min_p.y, real_t(0.4), real_t(0.0)));
  2548. } else {
  2549. uvs_ptr[p_idx] = Vector2(Math::remap(point.x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::remap(point.y, -max_p.y, -min_p.y, real_t(1.0), real_t(0.0)));
  2550. }
  2551. tangents_ptr[p_idx * 4 + 0] = 1.0;
  2552. tangents_ptr[p_idx * 4 + 1] = 0.0;
  2553. tangents_ptr[p_idx * 4 + 2] = 0.0;
  2554. tangents_ptr[p_idx * 4 + 3] = 1.0;
  2555. indices_ptr[i_idx++] = p_idx;
  2556. p_idx++;
  2557. }
  2558. if (has_depth) {
  2559. // Add back face.
  2560. for (int l = 2; l >= 0; l--) {
  2561. Vector3 point = Vector3(ts_ptr[k + l].x + offset.x, -ts_ptr[k + l].y + offset.y, -depth / 2.0);
  2562. vertices_ptr[p_idx] = point;
  2563. normals_ptr[p_idx] = Vector3(0.0, 0.0, -1.0);
  2564. uvs_ptr[p_idx] = Vector2(Math::remap(point.x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::remap(point.y, -max_p.y, -min_p.y, real_t(0.8), real_t(0.4)));
  2565. tangents_ptr[p_idx * 4 + 0] = -1.0;
  2566. tangents_ptr[p_idx * 4 + 1] = 0.0;
  2567. tangents_ptr[p_idx * 4 + 2] = 0.0;
  2568. tangents_ptr[p_idx * 4 + 3] = 1.0;
  2569. indices_ptr[i_idx++] = p_idx;
  2570. p_idx++;
  2571. }
  2572. }
  2573. }
  2574. // Add sides.
  2575. if (has_depth) {
  2576. for (int k = 0; k < gl_data.contours.size(); k++) {
  2577. int64_t ps = gl_data.contours[k].size();
  2578. const ContourPoint *ps_ptr = gl_data.contours[k].ptr();
  2579. const ContourInfo &ps_info = gl_data.contours_info[k];
  2580. real_t length = 0.0;
  2581. for (int l = 0; l < ps; l++) {
  2582. int prev = (l == 0) ? (ps - 1) : (l - 1);
  2583. int next = (l + 1 == ps) ? 0 : (l + 1);
  2584. Vector2 d1;
  2585. Vector2 d2 = (ps_ptr[next].point - ps_ptr[l].point).normalized();
  2586. if (ps_ptr[l].sharp) {
  2587. d1 = d2;
  2588. } else {
  2589. d1 = (ps_ptr[l].point - ps_ptr[prev].point).normalized();
  2590. }
  2591. real_t seg_len = (ps_ptr[next].point - ps_ptr[l].point).length();
  2592. Vector3 quad_faces[4] = {
  2593. Vector3(ps_ptr[l].point.x + offset.x, -ps_ptr[l].point.y + offset.y, -depth / 2.0),
  2594. Vector3(ps_ptr[next].point.x + offset.x, -ps_ptr[next].point.y + offset.y, -depth / 2.0),
  2595. Vector3(ps_ptr[l].point.x + offset.x, -ps_ptr[l].point.y + offset.y, depth / 2.0),
  2596. Vector3(ps_ptr[next].point.x + offset.x, -ps_ptr[next].point.y + offset.y, depth / 2.0),
  2597. };
  2598. for (int m = 0; m < 4; m++) {
  2599. const Vector2 &d = ((m % 2) == 0) ? d1 : d2;
  2600. real_t u_pos = ((m % 2) == 0) ? length : length + seg_len;
  2601. vertices_ptr[p_idx + m] = quad_faces[m];
  2602. normals_ptr[p_idx + m] = Vector3(d.y, d.x, 0.0);
  2603. if (m < 2) {
  2604. uvs_ptr[p_idx + m] = Vector2(Math::remap(u_pos, 0, ps_info.length, real_t(0.0), real_t(1.0)), (ps_info.ccw) ? 0.8 : 0.9);
  2605. } else {
  2606. uvs_ptr[p_idx + m] = Vector2(Math::remap(u_pos, 0, ps_info.length, real_t(0.0), real_t(1.0)), (ps_info.ccw) ? 0.9 : 1.0);
  2607. }
  2608. tangents_ptr[(p_idx + m) * 4 + 0] = d.x;
  2609. tangents_ptr[(p_idx + m) * 4 + 1] = -d.y;
  2610. tangents_ptr[(p_idx + m) * 4 + 2] = 0.0;
  2611. tangents_ptr[(p_idx + m) * 4 + 3] = 1.0;
  2612. }
  2613. indices_ptr[i_idx++] = p_idx;
  2614. indices_ptr[i_idx++] = p_idx + 1;
  2615. indices_ptr[i_idx++] = p_idx + 2;
  2616. indices_ptr[i_idx++] = p_idx + 1;
  2617. indices_ptr[i_idx++] = p_idx + 3;
  2618. indices_ptr[i_idx++] = p_idx + 2;
  2619. length += seg_len;
  2620. p_idx += 4;
  2621. }
  2622. }
  2623. }
  2624. offset.x += glyphs[j].advance * pixel_size;
  2625. }
  2626. } else {
  2627. // Add fallback quad for missing glyphs.
  2628. for (int r = 0; r < glyphs[j].repeat; r++) {
  2629. Size2 sz = TS->get_hex_code_box_size(glyphs[j].font_size, glyphs[j].index) * pixel_size;
  2630. Vector3 quad_faces[4] = {
  2631. Vector3(offset.x, offset.y, 0.0),
  2632. Vector3(offset.x, sz.y + offset.y, 0.0),
  2633. Vector3(sz.x + offset.x, sz.y + offset.y, 0.0),
  2634. Vector3(sz.x + offset.x, offset.y, 0.0),
  2635. };
  2636. for (int k = 0; k < 4; k++) {
  2637. vertices_ptr[p_idx + k] = quad_faces[k];
  2638. normals_ptr[p_idx + k] = Vector3(0.0, 0.0, 1.0);
  2639. if (has_depth) {
  2640. uvs_ptr[p_idx + k] = Vector2(Math::remap(quad_faces[k].x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::remap(quad_faces[k].y, -max_p.y, -min_p.y, real_t(0.4), real_t(0.0)));
  2641. } else {
  2642. uvs_ptr[p_idx + k] = Vector2(Math::remap(quad_faces[k].x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::remap(quad_faces[k].y, -max_p.y, -min_p.y, real_t(1.0), real_t(0.0)));
  2643. }
  2644. tangents_ptr[(p_idx + k) * 4 + 0] = 1.0;
  2645. tangents_ptr[(p_idx + k) * 4 + 1] = 0.0;
  2646. tangents_ptr[(p_idx + k) * 4 + 2] = 0.0;
  2647. tangents_ptr[(p_idx + k) * 4 + 3] = 1.0;
  2648. }
  2649. indices_ptr[i_idx++] = p_idx;
  2650. indices_ptr[i_idx++] = p_idx + 1;
  2651. indices_ptr[i_idx++] = p_idx + 2;
  2652. indices_ptr[i_idx++] = p_idx + 0;
  2653. indices_ptr[i_idx++] = p_idx + 2;
  2654. indices_ptr[i_idx++] = p_idx + 3;
  2655. p_idx += 4;
  2656. offset.x += glyphs[j].advance * pixel_size;
  2657. }
  2658. }
  2659. }
  2660. offset.y -= (TS->shaped_text_get_descent(lines_rid[i]) + line_spacing) * pixel_size;
  2661. }
  2662. if (indices.is_empty()) {
  2663. // If empty, add single triangle to suppress errors.
  2664. vertices.push_back(Vector3());
  2665. normals.push_back(Vector3());
  2666. uvs.push_back(Vector2());
  2667. tangents.push_back(1.0);
  2668. tangents.push_back(0.0);
  2669. tangents.push_back(0.0);
  2670. tangents.push_back(1.0);
  2671. indices.push_back(0);
  2672. indices.push_back(0);
  2673. indices.push_back(0);
  2674. }
  2675. p_arr[RS::ARRAY_VERTEX] = vertices;
  2676. p_arr[RS::ARRAY_NORMAL] = normals;
  2677. p_arr[RS::ARRAY_TANGENT] = tangents;
  2678. p_arr[RS::ARRAY_TEX_UV] = uvs;
  2679. p_arr[RS::ARRAY_INDEX] = indices;
  2680. }
  2681. void TextMesh::_bind_methods() {
  2682. ClassDB::bind_method(D_METHOD("set_horizontal_alignment", "alignment"), &TextMesh::set_horizontal_alignment);
  2683. ClassDB::bind_method(D_METHOD("get_horizontal_alignment"), &TextMesh::get_horizontal_alignment);
  2684. ClassDB::bind_method(D_METHOD("set_vertical_alignment", "alignment"), &TextMesh::set_vertical_alignment);
  2685. ClassDB::bind_method(D_METHOD("get_vertical_alignment"), &TextMesh::get_vertical_alignment);
  2686. ClassDB::bind_method(D_METHOD("set_text", "text"), &TextMesh::set_text);
  2687. ClassDB::bind_method(D_METHOD("get_text"), &TextMesh::get_text);
  2688. ClassDB::bind_method(D_METHOD("set_font", "font"), &TextMesh::set_font);
  2689. ClassDB::bind_method(D_METHOD("get_font"), &TextMesh::get_font);
  2690. ClassDB::bind_method(D_METHOD("set_font_size", "font_size"), &TextMesh::set_font_size);
  2691. ClassDB::bind_method(D_METHOD("get_font_size"), &TextMesh::get_font_size);
  2692. ClassDB::bind_method(D_METHOD("set_line_spacing", "line_spacing"), &TextMesh::set_line_spacing);
  2693. ClassDB::bind_method(D_METHOD("get_line_spacing"), &TextMesh::get_line_spacing);
  2694. ClassDB::bind_method(D_METHOD("set_autowrap_mode", "autowrap_mode"), &TextMesh::set_autowrap_mode);
  2695. ClassDB::bind_method(D_METHOD("get_autowrap_mode"), &TextMesh::get_autowrap_mode);
  2696. ClassDB::bind_method(D_METHOD("set_depth", "depth"), &TextMesh::set_depth);
  2697. ClassDB::bind_method(D_METHOD("get_depth"), &TextMesh::get_depth);
  2698. ClassDB::bind_method(D_METHOD("set_width", "width"), &TextMesh::set_width);
  2699. ClassDB::bind_method(D_METHOD("get_width"), &TextMesh::get_width);
  2700. ClassDB::bind_method(D_METHOD("set_pixel_size", "pixel_size"), &TextMesh::set_pixel_size);
  2701. ClassDB::bind_method(D_METHOD("get_pixel_size"), &TextMesh::get_pixel_size);
  2702. ClassDB::bind_method(D_METHOD("set_offset", "offset"), &TextMesh::set_offset);
  2703. ClassDB::bind_method(D_METHOD("get_offset"), &TextMesh::get_offset);
  2704. ClassDB::bind_method(D_METHOD("set_curve_step", "curve_step"), &TextMesh::set_curve_step);
  2705. ClassDB::bind_method(D_METHOD("get_curve_step"), &TextMesh::get_curve_step);
  2706. ClassDB::bind_method(D_METHOD("set_text_direction", "direction"), &TextMesh::set_text_direction);
  2707. ClassDB::bind_method(D_METHOD("get_text_direction"), &TextMesh::get_text_direction);
  2708. ClassDB::bind_method(D_METHOD("set_language", "language"), &TextMesh::set_language);
  2709. ClassDB::bind_method(D_METHOD("get_language"), &TextMesh::get_language);
  2710. ClassDB::bind_method(D_METHOD("set_structured_text_bidi_override", "parser"), &TextMesh::set_structured_text_bidi_override);
  2711. ClassDB::bind_method(D_METHOD("get_structured_text_bidi_override"), &TextMesh::get_structured_text_bidi_override);
  2712. ClassDB::bind_method(D_METHOD("set_structured_text_bidi_override_options", "args"), &TextMesh::set_structured_text_bidi_override_options);
  2713. ClassDB::bind_method(D_METHOD("get_structured_text_bidi_override_options"), &TextMesh::get_structured_text_bidi_override_options);
  2714. ClassDB::bind_method(D_METHOD("set_uppercase", "enable"), &TextMesh::set_uppercase);
  2715. ClassDB::bind_method(D_METHOD("is_uppercase"), &TextMesh::is_uppercase);
  2716. ClassDB::bind_method(D_METHOD("_font_changed"), &TextMesh::_font_changed);
  2717. ClassDB::bind_method(D_METHOD("_request_update"), &TextMesh::_request_update);
  2718. ADD_GROUP("Text", "");
  2719. ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT, ""), "set_text", "get_text");
  2720. ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "font", PROPERTY_HINT_RESOURCE_TYPE, "Font"), "set_font", "get_font");
  2721. ADD_PROPERTY(PropertyInfo(Variant::INT, "font_size", PROPERTY_HINT_RANGE, "1,256,1,or_greater,suffix:px"), "set_font_size", "get_font_size");
  2722. ADD_PROPERTY(PropertyInfo(Variant::INT, "horizontal_alignment", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), "set_horizontal_alignment", "get_horizontal_alignment");
  2723. ADD_PROPERTY(PropertyInfo(Variant::INT, "vertical_alignment", PROPERTY_HINT_ENUM, "Top,Center,Bottom"), "set_vertical_alignment", "get_vertical_alignment");
  2724. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uppercase"), "set_uppercase", "is_uppercase");
  2725. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "line_spacing", PROPERTY_HINT_NONE, "suffix:px"), "set_line_spacing", "get_line_spacing");
  2726. ADD_PROPERTY(PropertyInfo(Variant::INT, "autowrap_mode", PROPERTY_HINT_ENUM, "Off,Arbitrary,Word,Word (Smart)"), "set_autowrap_mode", "get_autowrap_mode");
  2727. ADD_GROUP("Mesh", "");
  2728. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pixel_size", PROPERTY_HINT_RANGE, "0.0001,128,0.0001,suffix:m"), "set_pixel_size", "get_pixel_size");
  2729. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "curve_step", PROPERTY_HINT_RANGE, "0.1,10,0.1,suffix:px"), "set_curve_step", "get_curve_step");
  2730. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "depth", PROPERTY_HINT_RANGE, "0.0,100.0,0.001,or_greater,suffix:m"), "set_depth", "get_depth");
  2731. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "width", PROPERTY_HINT_NONE, "suffix:px"), "set_width", "get_width");
  2732. ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset", PROPERTY_HINT_NONE, "suffix:px"), "set_offset", "get_offset");
  2733. ADD_GROUP("BiDi", "");
  2734. ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left"), "set_text_direction", "get_text_direction");
  2735. ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language");
  2736. ADD_PROPERTY(PropertyInfo(Variant::INT, "structured_text_bidi_override", PROPERTY_HINT_ENUM, "Default,URI,File,Email,List,None,Custom"), "set_structured_text_bidi_override", "get_structured_text_bidi_override");
  2737. ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "structured_text_bidi_override_options"), "set_structured_text_bidi_override_options", "get_structured_text_bidi_override_options");
  2738. }
  2739. void TextMesh::_notification(int p_what) {
  2740. switch (p_what) {
  2741. case MainLoop::NOTIFICATION_TRANSLATION_CHANGED: {
  2742. String new_text = tr(text);
  2743. if (new_text == xl_text) {
  2744. return; // Nothing new.
  2745. }
  2746. xl_text = new_text;
  2747. dirty_text = true;
  2748. _request_update();
  2749. } break;
  2750. }
  2751. }
  2752. TextMesh::TextMesh() {
  2753. primitive_type = PRIMITIVE_TRIANGLES;
  2754. text_rid = TS->create_shaped_text();
  2755. }
  2756. TextMesh::~TextMesh() {
  2757. for (int i = 0; i < lines_rid.size(); i++) {
  2758. TS->free_rid(lines_rid[i]);
  2759. }
  2760. lines_rid.clear();
  2761. TS->free_rid(text_rid);
  2762. }
  2763. void TextMesh::set_horizontal_alignment(HorizontalAlignment p_alignment) {
  2764. ERR_FAIL_INDEX((int)p_alignment, 4);
  2765. if (horizontal_alignment != p_alignment) {
  2766. if (horizontal_alignment == HORIZONTAL_ALIGNMENT_FILL || p_alignment == HORIZONTAL_ALIGNMENT_FILL) {
  2767. dirty_lines = true;
  2768. }
  2769. horizontal_alignment = p_alignment;
  2770. _request_update();
  2771. }
  2772. }
  2773. HorizontalAlignment TextMesh::get_horizontal_alignment() const {
  2774. return horizontal_alignment;
  2775. }
  2776. void TextMesh::set_vertical_alignment(VerticalAlignment p_alignment) {
  2777. ERR_FAIL_INDEX((int)p_alignment, 4);
  2778. if (vertical_alignment != p_alignment) {
  2779. vertical_alignment = p_alignment;
  2780. _request_update();
  2781. }
  2782. }
  2783. VerticalAlignment TextMesh::get_vertical_alignment() const {
  2784. return vertical_alignment;
  2785. }
  2786. void TextMesh::set_text(const String &p_string) {
  2787. if (text != p_string) {
  2788. text = p_string;
  2789. xl_text = tr(text);
  2790. dirty_text = true;
  2791. _request_update();
  2792. }
  2793. }
  2794. String TextMesh::get_text() const {
  2795. return text;
  2796. }
  2797. void TextMesh::_font_changed() {
  2798. dirty_font = true;
  2799. dirty_cache = true;
  2800. call_deferred(SNAME("_request_update"));
  2801. }
  2802. void TextMesh::set_font(const Ref<Font> &p_font) {
  2803. if (font_override != p_font) {
  2804. if (font_override.is_valid()) {
  2805. font_override->disconnect(CoreStringNames::get_singleton()->changed, Callable(this, "_font_changed"));
  2806. }
  2807. font_override = p_font;
  2808. dirty_font = true;
  2809. dirty_cache = true;
  2810. if (font_override.is_valid()) {
  2811. font_override->connect(CoreStringNames::get_singleton()->changed, Callable(this, "_font_changed"));
  2812. }
  2813. _request_update();
  2814. }
  2815. }
  2816. Ref<Font> TextMesh::get_font() const {
  2817. return font_override;
  2818. }
  2819. Ref<Font> TextMesh::_get_font_or_default() const {
  2820. if (font_override.is_valid()) {
  2821. return font_override;
  2822. }
  2823. // Check the project-defined Theme resource.
  2824. if (ThemeDB::get_singleton()->get_project_theme().is_valid()) {
  2825. List<StringName> theme_types;
  2826. ThemeDB::get_singleton()->get_project_theme()->get_type_dependencies(get_class_name(), StringName(), &theme_types);
  2827. for (const StringName &E : theme_types) {
  2828. if (ThemeDB::get_singleton()->get_project_theme()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) {
  2829. return ThemeDB::get_singleton()->get_project_theme()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E);
  2830. }
  2831. }
  2832. }
  2833. // Lastly, fall back on the items defined in the default Theme, if they exist.
  2834. {
  2835. List<StringName> theme_types;
  2836. ThemeDB::get_singleton()->get_default_theme()->get_type_dependencies(get_class_name(), StringName(), &theme_types);
  2837. for (const StringName &E : theme_types) {
  2838. if (ThemeDB::get_singleton()->get_default_theme()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) {
  2839. return ThemeDB::get_singleton()->get_default_theme()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E);
  2840. }
  2841. }
  2842. }
  2843. // If they don't exist, use any type to return the default/empty value.
  2844. return ThemeDB::get_singleton()->get_default_theme()->get_theme_item(Theme::DATA_TYPE_FONT, "font", StringName());
  2845. }
  2846. void TextMesh::set_font_size(int p_size) {
  2847. if (font_size != p_size) {
  2848. font_size = CLAMP(p_size, 1, 127);
  2849. dirty_font = true;
  2850. dirty_cache = true;
  2851. _request_update();
  2852. }
  2853. }
  2854. int TextMesh::get_font_size() const {
  2855. return font_size;
  2856. }
  2857. void TextMesh::set_line_spacing(float p_line_spacing) {
  2858. if (line_spacing != p_line_spacing) {
  2859. line_spacing = p_line_spacing;
  2860. _request_update();
  2861. }
  2862. }
  2863. float TextMesh::get_line_spacing() const {
  2864. return line_spacing;
  2865. }
  2866. void TextMesh::set_autowrap_mode(TextServer::AutowrapMode p_mode) {
  2867. if (autowrap_mode != p_mode) {
  2868. autowrap_mode = p_mode;
  2869. dirty_lines = true;
  2870. _request_update();
  2871. }
  2872. }
  2873. TextServer::AutowrapMode TextMesh::get_autowrap_mode() const {
  2874. return autowrap_mode;
  2875. }
  2876. void TextMesh::set_depth(real_t p_depth) {
  2877. if (depth != p_depth) {
  2878. depth = MAX(p_depth, 0.0);
  2879. _request_update();
  2880. }
  2881. }
  2882. real_t TextMesh::get_depth() const {
  2883. return depth;
  2884. }
  2885. void TextMesh::set_width(real_t p_width) {
  2886. if (width != p_width) {
  2887. width = p_width;
  2888. dirty_lines = true;
  2889. _request_update();
  2890. }
  2891. }
  2892. real_t TextMesh::get_width() const {
  2893. return width;
  2894. }
  2895. void TextMesh::set_pixel_size(real_t p_amount) {
  2896. if (pixel_size != p_amount) {
  2897. pixel_size = CLAMP(p_amount, 0.0001, 128.0);
  2898. dirty_cache = true;
  2899. _request_update();
  2900. }
  2901. }
  2902. real_t TextMesh::get_pixel_size() const {
  2903. return pixel_size;
  2904. }
  2905. void TextMesh::set_offset(const Point2 &p_offset) {
  2906. if (lbl_offset != p_offset) {
  2907. lbl_offset = p_offset;
  2908. _request_update();
  2909. }
  2910. }
  2911. Point2 TextMesh::get_offset() const {
  2912. return lbl_offset;
  2913. }
  2914. void TextMesh::set_curve_step(real_t p_step) {
  2915. if (curve_step != p_step) {
  2916. curve_step = CLAMP(p_step, 0.1, 10.0);
  2917. dirty_cache = true;
  2918. _request_update();
  2919. }
  2920. }
  2921. real_t TextMesh::get_curve_step() const {
  2922. return curve_step;
  2923. }
  2924. void TextMesh::set_text_direction(TextServer::Direction p_text_direction) {
  2925. ERR_FAIL_COND((int)p_text_direction < -1 || (int)p_text_direction > 3);
  2926. if (text_direction != p_text_direction) {
  2927. text_direction = p_text_direction;
  2928. dirty_text = true;
  2929. _request_update();
  2930. }
  2931. }
  2932. TextServer::Direction TextMesh::get_text_direction() const {
  2933. return text_direction;
  2934. }
  2935. void TextMesh::set_language(const String &p_language) {
  2936. if (language != p_language) {
  2937. language = p_language;
  2938. dirty_text = true;
  2939. _request_update();
  2940. }
  2941. }
  2942. String TextMesh::get_language() const {
  2943. return language;
  2944. }
  2945. void TextMesh::set_structured_text_bidi_override(TextServer::StructuredTextParser p_parser) {
  2946. if (st_parser != p_parser) {
  2947. st_parser = p_parser;
  2948. dirty_text = true;
  2949. _request_update();
  2950. }
  2951. }
  2952. TextServer::StructuredTextParser TextMesh::get_structured_text_bidi_override() const {
  2953. return st_parser;
  2954. }
  2955. void TextMesh::set_structured_text_bidi_override_options(Array p_args) {
  2956. if (st_args != p_args) {
  2957. st_args = p_args;
  2958. dirty_text = true;
  2959. _request_update();
  2960. }
  2961. }
  2962. Array TextMesh::get_structured_text_bidi_override_options() const {
  2963. return st_args;
  2964. }
  2965. void TextMesh::set_uppercase(bool p_uppercase) {
  2966. if (uppercase != p_uppercase) {
  2967. uppercase = p_uppercase;
  2968. dirty_text = true;
  2969. _request_update();
  2970. }
  2971. }
  2972. bool TextMesh::is_uppercase() const {
  2973. return uppercase;
  2974. }