Mesh Base.cpp 56 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. namespace EE{
  4. /******************************************************************************/
  5. UInt EtqFlagSwap(UInt flag)
  6. {
  7. UInt f=(flag&~ETQ_LR);
  8. if(flag&ETQ_L)f|=ETQ_R;
  9. if(flag&ETQ_R)f|=ETQ_L;
  10. return f;
  11. }
  12. /******************************************************************************/
  13. SIDE_TYPE GetSide(C VecI2 &edge, C VecI &tri)
  14. {
  15. Int e0=edge.c[0], e1=edge.c[1];
  16. if((tri.c[0]==e0 && tri.c[1]==e1)
  17. || (tri.c[1]==e0 && tri.c[2]==e1)
  18. || (tri.c[2]==e0 && tri.c[0]==e1))return SIDE_R;
  19. if((tri.c[0]==e1 && tri.c[1]==e0)
  20. || (tri.c[1]==e1 && tri.c[2]==e0)
  21. || (tri.c[2]==e1 && tri.c[0]==e0))return SIDE_L;
  22. return SIDE_NONE;
  23. }
  24. SIDE_TYPE GetSide(C VecI2 &edge, C VecI4 &quad)
  25. {
  26. Int e0=edge.c[0], e1=edge.c[1];
  27. if((quad.c[0]==e0 && quad.c[1]==e1)
  28. || (quad.c[1]==e0 && quad.c[2]==e1)
  29. || (quad.c[2]==e0 && quad.c[3]==e1)
  30. || (quad.c[3]==e0 && quad.c[0]==e1))return SIDE_R;
  31. if((quad.c[0]==e1 && quad.c[1]==e0)
  32. || (quad.c[1]==e1 && quad.c[2]==e0)
  33. || (quad.c[2]==e1 && quad.c[3]==e0)
  34. || (quad.c[3]==e1 && quad.c[0]==e0))return SIDE_L;
  35. return SIDE_NONE;
  36. }
  37. /******************************************************************************/
  38. MeshBase::MeshBase( Int vtxs, Int edges, Int tris, Int quads, UInt flag) : MeshBase() {create(vtxs, edges, tris, quads, flag);}
  39. MeshBase::MeshBase(C MeshBase &src , UInt flag_and ) : MeshBase() {create(src , flag_and);}
  40. MeshBase::MeshBase(C MeshRender &src , UInt flag_and ) : MeshBase() {create(src , flag_and);}
  41. MeshBase::MeshBase(C MeshPart &src , UInt flag_and ) : MeshBase() {create(src , flag_and);}
  42. MeshBase::MeshBase(C MeshLod &src , UInt flag_and ) : MeshBase() {create(src , flag_and);}
  43. MeshBase::MeshBase(C PhysPart &src ) : MeshBase() {create(src);}
  44. /******************************************************************************/
  45. void MeshBase::copyVtxs(C MeshBase &src)
  46. {
  47. Int elms=Min(vtxs(), src.vtxs());
  48. CopyN(vtx.pos (), src.vtx.pos (), elms);
  49. CopyN(vtx.nrm (), src.vtx.nrm (), elms);
  50. CopyN(vtx.tan (), src.vtx.tan (), elms);
  51. CopyN(vtx.bin (), src.vtx.bin (), elms);
  52. CopyN(vtx.hlp (), src.vtx.hlp (), elms);
  53. CopyN(vtx.tex0 (), src.vtx.tex0 (), elms);
  54. CopyN(vtx.tex1 (), src.vtx.tex1 (), elms);
  55. CopyN(vtx.tex2 (), src.vtx.tex2 (), elms);
  56. CopyN(vtx.matrix (), src.vtx.matrix (), elms);
  57. CopyN(vtx.blend (), src.vtx.blend (), elms);
  58. CopyN(vtx.size (), src.vtx.size (), elms);
  59. CopyN(vtx.material(), src.vtx.material(), elms);
  60. CopyN(vtx.color (), src.vtx.color (), elms);
  61. CopyN(vtx.flag (), src.vtx.flag (), elms);
  62. CopyN(vtx.dup (), src.vtx.dup (), elms);
  63. }
  64. void MeshBase::copyVtxs(C MeshBase &src, C MemPtr<Bool> &is)
  65. {
  66. DEBUG_ASSERT(is.elms()<=src.vtxs() && CountIs(is)<=vtxs(), "copyVtxs");
  67. CopyIs(vtx.pos (), src.vtx.pos (), is);
  68. CopyIs(vtx.nrm (), src.vtx.nrm (), is);
  69. CopyIs(vtx.tan (), src.vtx.tan (), is);
  70. CopyIs(vtx.bin (), src.vtx.bin (), is);
  71. CopyIs(vtx.hlp (), src.vtx.hlp (), is);
  72. CopyIs(vtx.tex0 (), src.vtx.tex0 (), is);
  73. CopyIs(vtx.tex1 (), src.vtx.tex1 (), is);
  74. CopyIs(vtx.tex2 (), src.vtx.tex2 (), is);
  75. CopyIs(vtx.matrix (), src.vtx.matrix (), is);
  76. CopyIs(vtx.blend (), src.vtx.blend (), is);
  77. CopyIs(vtx.size (), src.vtx.size (), is);
  78. CopyIs(vtx.material(), src.vtx.material(), is);
  79. CopyIs(vtx.color (), src.vtx.color (), is);
  80. CopyIs(vtx.flag (), src.vtx.flag (), is);
  81. CopyIs(vtx.dup (), src.vtx.dup (), is);
  82. }
  83. void MeshBase::copyEdges(C MeshBase &src)
  84. {
  85. Int elms=Min(edges(), src.edges());
  86. CopyN(edge.ind (), src.edge.ind (), elms);
  87. CopyN(edge.adjFace(), src.edge.adjFace(), elms);
  88. CopyN(edge.nrm (), src.edge.nrm (), elms);
  89. CopyN(edge.flag (), src.edge.flag (), elms);
  90. CopyN(edge.id (), src.edge.id (), elms);
  91. }
  92. void MeshBase::copyEdges(C MeshBase &src, C MemPtr<Bool> &is)
  93. {
  94. DEBUG_ASSERT(is.elms()<=src.edges() && CountIs(is)<=edges(), "copyEdges");
  95. CopyIs(edge.ind (), src.edge.ind (), is);
  96. CopyIs(edge.adjFace(), src.edge.adjFace(), is);
  97. CopyIs(edge.nrm (), src.edge.nrm (), is);
  98. CopyIs(edge.flag (), src.edge.flag (), is);
  99. CopyIs(edge.id (), src.edge.id (), is);
  100. }
  101. void MeshBase::copyTris(C MeshBase &src)
  102. {
  103. Int elms=Min(tris(), src.tris());
  104. CopyN(tri.ind (), src.tri.ind (), elms);
  105. CopyN(tri.adjFace(), src.tri.adjFace(), elms);
  106. CopyN(tri.adjEdge(), src.tri.adjEdge(), elms);
  107. CopyN(tri.nrm (), src.tri.nrm (), elms);
  108. CopyN(tri.flag (), src.tri.flag (), elms);
  109. CopyN(tri.id (), src.tri.id (), elms);
  110. }
  111. void MeshBase::copyTris(C MeshBase &src, C MemPtr<Bool> &is)
  112. {
  113. DEBUG_ASSERT(is.elms()<=src.tris() && CountIs(is)<=tris(), "copyTris");
  114. CopyIs(tri.ind (), src.tri.ind (), is);
  115. CopyIs(tri.adjFace(), src.tri.adjFace(), is);
  116. CopyIs(tri.adjEdge(), src.tri.adjEdge(), is);
  117. CopyIs(tri.nrm (), src.tri.nrm (), is);
  118. CopyIs(tri.flag (), src.tri.flag (), is);
  119. CopyIs(tri.id (), src.tri.id (), is);
  120. }
  121. void MeshBase::copyQuads(C MeshBase &src)
  122. {
  123. Int elms=Min(quads(), src.quads());
  124. CopyN(quad.ind (), src.quad.ind (), elms);
  125. CopyN(quad.adjFace(), src.quad.adjFace(), elms);
  126. CopyN(quad.adjEdge(), src.quad.adjEdge(), elms);
  127. CopyN(quad.nrm (), src.quad.nrm (), elms);
  128. CopyN(quad.flag (), src.quad.flag (), elms);
  129. CopyN(quad.id (), src.quad.id (), elms);
  130. }
  131. void MeshBase::copyQuads(C MeshBase &src, C MemPtr<Bool> &is)
  132. {
  133. DEBUG_ASSERT(is.elms()<=src.quads() && CountIs(is)<=quads(), "copyQuads");
  134. CopyIs(quad.ind (), src.quad.ind (), is);
  135. CopyIs(quad.adjFace(), src.quad.adjFace(), is);
  136. CopyIs(quad.adjEdge(), src.quad.adjEdge(), is);
  137. CopyIs(quad.nrm (), src.quad.nrm (), is);
  138. CopyIs(quad.flag (), src.quad.flag (), is);
  139. CopyIs(quad.id (), src.quad.id (), is);
  140. }
  141. /******************************************************************************/
  142. Int SetVtxDup(MemPtr<VtxDup> vtxs, C Box &box, Flt pos_eps)
  143. {
  144. Int unique=0;
  145. // link box->vtx
  146. Boxes boxes (box , vtxs.elms());
  147. Index box_vtx(boxes.num(), vtxs.elms());
  148. REPA(vtxs)box_vtx.elmGroup(boxes.index(vtxs[i].pos), i); box_vtx.set();
  149. // get duplicates
  150. Int xs=boxes.cells.x,
  151. ys=boxes.cells.y, xys=xs*ys;
  152. // iterate all boxes
  153. FREPD(z, boxes.cells.z)
  154. FREPD(y, boxes.cells.y)
  155. FREPD(x, boxes.cells.x)
  156. {
  157. Int box_tests=0;
  158. IndexGroup *box_test[2+3+9],
  159. *box_cur=&box_vtx.group[x + y*xs + z*xys]; // get current box
  160. // set which neighbor boxes to test
  161. box_test[box_tests++]=box_cur ;
  162. if(x)box_test[box_tests++]=box_cur-1;
  163. if(y)
  164. {
  165. if(x<xs-1)box_test[box_tests++]=box_cur+1-xs;
  166. box_test[box_tests++]=box_cur -xs;
  167. if( x)box_test[box_tests++]=box_cur-1-xs;
  168. }
  169. if(z)
  170. {
  171. if(y<ys-1)
  172. {
  173. if(x<xs-1)box_test[box_tests++]=box_cur+1+xs-xys;
  174. box_test[box_tests++]=box_cur +xs-xys;
  175. if( x)box_test[box_tests++]=box_cur-1+xs-xys;
  176. }
  177. if(x<xs-1)box_test[box_tests++]=box_cur+1 -xys;
  178. box_test[box_tests++]=box_cur -xys;
  179. if( x)box_test[box_tests++]=box_cur-1 -xys;
  180. if(y)
  181. {
  182. if(x<xs-1)box_test[box_tests++]=box_cur+1-xs-xys;
  183. box_test[box_tests++]=box_cur -xs-xys;
  184. if( x)box_test[box_tests++]=box_cur-1-xs-xys;
  185. }
  186. }
  187. FREPA(*box_cur) // iterate all vertexes in this box
  188. {
  189. Int vtx_cur_i= (*box_cur)[i]; // this is i-th vtx in this box
  190. VtxDup &vtx_cur =vtxs[vtx_cur_i];
  191. C Vec &pos_cur =vtx_cur.pos; // this is position of that vertex
  192. REPD(c, box_tests) // iterate all boxes to test
  193. {
  194. IndexGroup *bt=box_test[c];
  195. REPD(m, (box_cur==bt) ? i : bt->num) // iterate all vtxs in the test box (if the test box is the current box, then check only vertexes before the current one)
  196. {
  197. Int vtx_test_i=(*bt)[m]; // this is m-th vtx in the test box
  198. C VtxDup &vtx_test =vtxs[vtx_test_i];
  199. if(vtx_test.dup==vtx_test_i // if this vtx is unique (points to self), this is so that we assign mapping only to uniqe vtxs (and not to vtxs that point to other vtxs)
  200. && Equal(pos_cur, vtx_test.pos, pos_eps)) // if position is the same
  201. {
  202. // found a duplicate
  203. vtx_cur.dup=vtx_test_i; goto next; // set 'dup' index to point to unique 'vtx_test_i'
  204. }
  205. }
  206. }
  207. // haven't found a duplicate, so set as unique
  208. vtx_cur.dup=vtx_cur_i; // set 'dup' index to point to self
  209. unique++; // increase unique counter
  210. next:;
  211. }
  212. }
  213. return unique;
  214. }
  215. Int SetVtxDup(MemPtr<VtxDupNrm> vtxs, C Box &box, Flt pos_eps, Flt nrm_cos)
  216. {
  217. Int unique=0;
  218. // link box->vtx
  219. Boxes boxes (box , vtxs.elms());
  220. Index box_vtx(boxes.num(), vtxs.elms());
  221. REPA(vtxs)box_vtx.elmGroup(boxes.index(vtxs[i].pos), i); box_vtx.set();
  222. // get duplicates
  223. Int xs=boxes.cells.x,
  224. ys=boxes.cells.y, xys=xs*ys;
  225. // iterate all boxes
  226. FREPD(z, boxes.cells.z)
  227. FREPD(y, boxes.cells.y)
  228. FREPD(x, boxes.cells.x)
  229. {
  230. Int box_tests=0;
  231. IndexGroup *box_test[2+3+9],
  232. *box_cur=&box_vtx.group[x + y*xs + z*xys]; // get current box
  233. // set which neighbor boxes to test
  234. box_test[box_tests++]=box_cur ;
  235. if(x)box_test[box_tests++]=box_cur-1;
  236. if(y)
  237. {
  238. if(x<xs-1)box_test[box_tests++]=box_cur+1-xs;
  239. box_test[box_tests++]=box_cur -xs;
  240. if( x)box_test[box_tests++]=box_cur-1-xs;
  241. }
  242. if(z)
  243. {
  244. if(y<ys-1)
  245. {
  246. if(x<xs-1)box_test[box_tests++]=box_cur+1+xs-xys;
  247. box_test[box_tests++]=box_cur +xs-xys;
  248. if( x)box_test[box_tests++]=box_cur-1+xs-xys;
  249. }
  250. if(x<xs-1)box_test[box_tests++]=box_cur+1 -xys;
  251. box_test[box_tests++]=box_cur -xys;
  252. if( x)box_test[box_tests++]=box_cur-1 -xys;
  253. if(y)
  254. {
  255. if(x<xs-1)box_test[box_tests++]=box_cur+1-xs-xys;
  256. box_test[box_tests++]=box_cur -xs-xys;
  257. if( x)box_test[box_tests++]=box_cur-1-xs-xys;
  258. }
  259. }
  260. FREPA(*box_cur) // iterate all vertexes in this box
  261. {
  262. Int vtx_cur_i= (*box_cur)[i]; // this is i-th vtx in this box
  263. VtxDupNrm &vtx_cur =vtxs[vtx_cur_i];
  264. C Vec &pos_cur =vtx_cur.pos; // this is position of that vertex
  265. C Vec &nrm_cur =vtx_cur.nrm; // this is normal of that vertex
  266. REPD(c, box_tests) // iterate all boxes to test
  267. {
  268. IndexGroup *bt=box_test[c];
  269. REPD(m, (box_cur==bt) ? i : bt->num) // iterate all vtxs in the test box (if the test box is the current box, then check only vertexes before the current one)
  270. {
  271. Int vtx_test_i=(*bt)[m]; // this is m-th vtx in the test box
  272. C VtxDupNrm &vtx_test =vtxs[vtx_test_i];
  273. if(vtx_test.dup==vtx_test_i // if this vtx is unique (points to self), this is so that we assign mapping only to uniqe vtxs (and not to vtxs that point to other vtxs)
  274. && Equal(pos_cur, vtx_test.pos, pos_eps) // if position is the same
  275. && Dot (nrm_cur, vtx_test.nrm)>=nrm_cos)
  276. {
  277. // found a duplicate
  278. vtx_cur.dup=vtx_test_i; goto next; // set 'dup' index to point to unique 'vtx_test_i'
  279. }
  280. }
  281. }
  282. // haven't found a duplicate, so set as unique
  283. vtx_cur.dup=vtx_cur_i; // set 'dup' index to point to self
  284. unique++; // increase unique counter
  285. next:;
  286. }
  287. }
  288. return unique;
  289. }
  290. /******************************************************************************/
  291. static Int CompareMatrixWeight(C VecB2 &matrix_weight_a, C VecB2 &matrix_weight_b)
  292. {
  293. if(Int c=Compare(matrix_weight_b.y, matrix_weight_a.y))return c; // first compare by weight, reverse order to list most important first
  294. return Compare(matrix_weight_b.x, matrix_weight_a.x) ; // next compare by matrix, reverse order to list children first, and parents last (especially zero last)
  295. }
  296. void SetSkin(C MemPtrN<IndexWeight, 256> &skin, VecB4 &matrix, VecB4 &blend, C Skeleton *skeleton)
  297. {
  298. const Int max_bone_influence=3; // only 3 bones are supported
  299. MemtN<IndexWeight, 256> temp; temp=skin;
  300. // remove invalid indexes
  301. if(skeleton)
  302. {
  303. const Int max_index=skeleton->bones.elms()+VIRTUAL_ROOT_BONE;
  304. REPA(temp)if(!InRange(temp[i].index, max_index))temp.remove(i);
  305. }
  306. // merge same bones (do this before removing empty references so we can have both positive and negative weights for the same matrix, used by the editor when changing skinning)
  307. REPA(temp)
  308. {
  309. C IndexWeight &a=temp[i]; REPD(j, i)
  310. {
  311. IndexWeight &b=temp[j]; if(a.index==b.index){b.weight+=a.weight; temp.remove(i); break;}
  312. }
  313. }
  314. // remove empty references (do this after merging the same bones)
  315. REPA(temp)if(temp[i].weight<=0)temp.remove(i);
  316. // sort from most to least important
  317. temp.sort(Compare);
  318. // remove those that won't fit
  319. if(skeleton) // if skeleton is provided
  320. for(Int i=temp.elms()-1; i>=max_bone_influence; i--) // iterate all weights that would get removed
  321. {
  322. Int bone=temp[i].index-VIRTUAL_ROOT_BONE,
  323. min_distance=0xFF+1,
  324. closest=0;
  325. REPD(j, i-1) // get all closest bones
  326. {
  327. Int distance =skeleton->hierarchyDistance(bone, temp[j].index-VIRTUAL_ROOT_BONE);
  328. if( distance< min_distance){min_distance=distance; closest=1;}else // if found smaller distance than previous then set it, and set closest bones to 1
  329. if( distance==min_distance){closest++;} // if distance found is equal to min then another bone is close, so increase it by 1
  330. }
  331. if(closest)
  332. {
  333. Flt weight=temp[i].weight/closest; REPD(j, i-1)if(skeleton->hierarchyDistance(bone, temp[j].index-VIRTUAL_ROOT_BONE)==min_distance)temp[j].weight+=weight; // add weight from this bone to all closest bones equally
  334. }
  335. temp.removeLast(); if(closest)temp.sort(Compare); // remove last element and re-sort if any weights were modified
  336. }
  337. if(temp.elms()>max_bone_influence)temp.setNum(max_bone_influence); // this is needed because we're calculating sum below
  338. Flt sum=0; REPA(temp)sum+=temp[i].weight;
  339. if( sum)
  340. {
  341. sum=255/sum; REPAO(temp).weight*=sum; // normalize and scale to 255
  342. switch(temp.elms())
  343. {
  344. case 0: goto zero; // shouldn't really happen
  345. case 1:
  346. {
  347. blend .set(255 , 0, 0, 0); // 'blend.sum' must be exactly equal to 255 !!
  348. matrix.set(temp[0].index, 0, 0, 0);
  349. }break;
  350. case 2:
  351. {
  352. Byte w=RoundPos(temp[0].weight);
  353. blend .set(w , 255-w , 0, 0); // 'blend.sum' must be exactly equal to 255 !!
  354. matrix.set(temp[0].index, temp[1].index, 0, 0);
  355. }break;
  356. case 3:
  357. {
  358. Byte w0= RoundPos(temp[0].weight),
  359. w1=Mid(RoundPos(temp[1].weight), 0, 255-w0); // limit to "255-w0" because we can't have "w0+w1>255"
  360. blend .set(w0 , w1 , 255-w0-w1 , 0); // 'blend.sum' must be exactly equal to 255 !!
  361. matrix.set(temp[0].index, temp[1].index, temp[2].index, 0);
  362. }break;
  363. default: // 4 or more
  364. {
  365. Byte w0= RoundPos(temp[0].weight),
  366. w1=Mid(RoundPos(temp[1].weight), 0, 255-w0 ), // limit to "255-w0 " because we can't have "w0+w1 >255"
  367. w2=Mid(RoundPos(temp[2].weight), 0, 255-w0-w1); // limit to "255-w0-w1" because we can't have "w0+w1+w2>255"
  368. blend .set(w0 , w1 , w2 , 255-w0-w1-w2 ); // 'blend.sum' must be exactly equal to 255 !!
  369. matrix.set(temp[0].index, temp[1].index, temp[2].index, temp[3].index);
  370. }break;
  371. }
  372. REPA(blend)if(!blend.c[i])matrix.c[i]=0; // clear bones to 0 if they have no weight
  373. // sort matrix/weight to list most important first, and in case weights are the same, then sort by matrix index (this is needed because even though 'temp' is already sorted, we need to sort again because weights now in byte format can be the same, and in which case we need to sort by matrix index), we do this, so in the future we can compare 2 matrix weights using fast checks like "matrix0==matrix1 && weight0==weight1" instead of checking each matrix index component separately (for cases where they are listed in different order)
  374. if(temp.elms()>=3) // need to check this only for 3 or more bones, because 1 and 2 will never have this (1 has always 255,0,0,0 weights, and 2 has always w,255-w,0,0 weights, which means they are always different, because Byte w is always different than 255-w)
  375. {
  376. VecB2 matrix_weight[]={VecB2(matrix.x, blend.x), VecB2(matrix.y, blend.y), VecB2(matrix.z, blend.z), VecB2(matrix.w, blend.w)};
  377. Sort( matrix_weight, Elms(matrix_weight), CompareMatrixWeight);
  378. matrix.set(matrix_weight[0].x, matrix_weight[1].x, matrix_weight[2].x, matrix_weight[3].x);
  379. blend .set(matrix_weight[0].y, matrix_weight[1].y, matrix_weight[2].y, matrix_weight[3].y);
  380. }
  381. }else
  382. {
  383. zero:
  384. blend .set(255, 0, 0, 0); // 'blend.sum' must be exactly equal to 255 !!
  385. matrix=0;
  386. }
  387. }
  388. /******************************************************************************/
  389. // VERTEX FULL
  390. /******************************************************************************/
  391. void VtxFull::reset()
  392. {
  393. Zero(T);
  394. color=WHITE;
  395. material.x=255; // 'material.sum' must be exactly equal to 255 !!
  396. blend .x=255; // 'blend.sum' must be exactly equal to 255 !!
  397. }
  398. VtxFull& VtxFull::from(C MeshBase &mshb, Int i)
  399. {
  400. reset();
  401. if(InRange(i, mshb.vtx))
  402. {
  403. if(mshb.vtx.pos ())pos =mshb.vtx.pos (i);
  404. if(mshb.vtx.nrm ())nrm =mshb.vtx.nrm (i);
  405. if(mshb.vtx.tan ())tan =mshb.vtx.tan (i);
  406. if(mshb.vtx.bin ())bin =mshb.vtx.bin (i);
  407. if(mshb.vtx.hlp ())hlp =mshb.vtx.hlp (i);
  408. if(mshb.vtx.tex0 ())tex0 =mshb.vtx.tex0 (i);
  409. if(mshb.vtx.tex1 ())tex1 =mshb.vtx.tex1 (i);
  410. if(mshb.vtx.tex2 ())tex2 =mshb.vtx.tex2 (i);
  411. if(mshb.vtx.color ())color =mshb.vtx.color (i);
  412. if(mshb.vtx.material())material=mshb.vtx.material(i);
  413. if(mshb.vtx.matrix ())matrix =mshb.vtx.matrix (i);
  414. if(mshb.vtx.blend ())blend =mshb.vtx.blend (i);
  415. if(mshb.vtx.size ())size =mshb.vtx.size (i);
  416. }
  417. return T;
  418. }
  419. void VtxFull::to(MeshBase &mshb, Int i)C
  420. {
  421. if(InRange(i, mshb.vtx))
  422. {
  423. if(mshb.vtx.pos ())mshb.vtx.pos (i)=pos;
  424. if(mshb.vtx.nrm ())mshb.vtx.nrm (i)=nrm;
  425. if(mshb.vtx.tan ())mshb.vtx.tan (i)=tan;
  426. if(mshb.vtx.bin ())mshb.vtx.bin (i)=bin;
  427. if(mshb.vtx.hlp ())mshb.vtx.hlp (i)=hlp;
  428. if(mshb.vtx.tex0 ())mshb.vtx.tex0 (i)=tex0;
  429. if(mshb.vtx.tex1 ())mshb.vtx.tex1 (i)=tex1;
  430. if(mshb.vtx.tex2 ())mshb.vtx.tex2 (i)=tex2;
  431. if(mshb.vtx.color ())mshb.vtx.color (i)=color;
  432. if(mshb.vtx.material())mshb.vtx.material(i)=material;
  433. if(mshb.vtx.matrix ())mshb.vtx.matrix (i)=matrix;
  434. if(mshb.vtx.blend ())mshb.vtx.blend (i)=blend;
  435. if(mshb.vtx.size ())mshb.vtx.size (i)=size;
  436. if(mshb.vtx.dup ())mshb.vtx.dup (i)=i;
  437. }
  438. }
  439. VtxFull& VtxFull::avg(C VtxFull &a, C VtxFull &b)
  440. {
  441. pos =Avg (a.pos , b.pos );
  442. nrm = !(a.nrm + b.nrm );
  443. tan = !(a.tan + b.tan );
  444. bin = !(a.bin + b.bin );
  445. hlp =Avg (a.hlp , b.hlp );
  446. tex0 =Avg (a.tex0 , b.tex0 );
  447. tex1 =Avg (a.tex1 , b.tex1 );
  448. tex2 =Avg (a.tex2 , b.tex2 );
  449. size =Avg (a.size , b.size );
  450. color =Avg (a.color , b.color );
  451. material=AvgI(a.material, b.material);
  452. MemtN<IndexWeight, 256> skin;
  453. FREPA(a.matrix)skin.New().set(a.matrix.c[i], a.blend.c[i]);
  454. FREPA(b.matrix)skin.New().set(b.matrix.c[i], b.blend.c[i]);
  455. SetSkin(skin, matrix, blend, null);
  456. return T;
  457. }
  458. VtxFull& VtxFull::lerp(C VtxFull &a, C VtxFull &b, Flt step)
  459. {
  460. Flt step1=1-step;
  461. pos = a.pos *step1 + b.pos *step;
  462. nrm = !(a.nrm *step1 + b.nrm *step);
  463. tan = !(a.tan *step1 + b.tan *step);
  464. bin = !(a.bin *step1 + b.bin *step);
  465. hlp = a.hlp *step1 + b.hlp *step;
  466. tex0 = a.tex0*step1 + b.tex0*step;
  467. tex1 = a.tex1*step1 + b.tex1*step;
  468. tex2 = a.tex2*step1 + b.tex2*step;
  469. size = a.size*step1 + b.size*step;
  470. color =Lerp(a.color , b.color , step);
  471. material=Lerp(a.material, b.material, step);
  472. MemtN<IndexWeight, 256> skin;
  473. FREPA(a.matrix)skin.New().set(a.matrix.c[i], a.blend.c[i]*step1);
  474. FREPA(b.matrix)skin.New().set(b.matrix.c[i], b.blend.c[i]*step );
  475. SetSkin(skin, matrix, blend, null);
  476. return T;
  477. }
  478. VtxFull& VtxFull::lerp(C VtxFull &a, C VtxFull &b, C VtxFull &c, C Vec &blend)
  479. {
  480. Flt ba=blend.c[0],
  481. bb=blend.c[1],
  482. bc=blend.c[2];
  483. T.pos = a.pos *ba + b.pos *bb + c.pos *bc ;
  484. T.nrm =!(a.nrm *ba + b.nrm *bb + c.nrm *bc);
  485. T.tan =!(a.tan *ba + b.tan *bb + c.tan *bc);
  486. T.bin =!(a.bin *ba + b.bin *bb + c.bin *bc);
  487. T.hlp = a.hlp *ba + b.hlp *bb + c.hlp *bc ;
  488. T.tex0 = a.tex0*ba + b.tex0*bb + c.tex0*bc ;
  489. T.tex1 = a.tex1*ba + b.tex1*bb + c.tex1*bc ;
  490. T.tex2 = a.tex2*ba + b.tex2*bb + c.tex2*bc ;
  491. T.size = a.size*ba + b.size*bb + c.size*bc ;
  492. T.color =Lerp(a.color , b.color , c.color , blend);
  493. T.material=Lerp(a.material, b.material, c.material, blend);
  494. MemtN<IndexWeight, 256> skin;
  495. FREPA(a.matrix)skin.New().set(a.matrix.c[i], a.blend.c[i]*ba);
  496. FREPA(b.matrix)skin.New().set(b.matrix.c[i], b.blend.c[i]*bb);
  497. FREPA(c.matrix)skin.New().set(c.matrix.c[i], c.blend.c[i]*bc);
  498. SetSkin(skin, T.matrix, T.blend, null);
  499. return T;
  500. }
  501. VtxFull& VtxFull::mul(C Matrix &matrix, C Matrix3 &matrix3)
  502. {
  503. pos*=matrix ;
  504. hlp*=matrix ;
  505. nrm*=matrix3;
  506. tan*=matrix3;
  507. bin*=matrix3;
  508. return T;
  509. }
  510. /******************************************************************************/
  511. // MESH BASE
  512. /******************************************************************************/
  513. UInt MeshBase::flag()C
  514. {
  515. UInt f=0;
  516. if(vtx.pos ())f|=VTX_POS;
  517. if(vtx.nrm ())f|=VTX_NRM;
  518. if(vtx.tan ())f|=VTX_TAN;
  519. if(vtx.bin ())f|=VTX_BIN;
  520. if(vtx.hlp ())f|=VTX_HLP;
  521. if(vtx.tex0 ())f|=VTX_TEX0;
  522. if(vtx.tex1 ())f|=VTX_TEX1;
  523. if(vtx.tex2 ())f|=VTX_TEX2;
  524. if(vtx.matrix ())f|=VTX_MATRIX;
  525. if(vtx.blend ())f|=VTX_BLEND;
  526. if(vtx.size ())f|=VTX_SIZE;
  527. if(vtx.material())f|=VTX_MATERIAL;
  528. if(vtx.color ())f|=VTX_COLOR;
  529. if(vtx.flag ())f|=VTX_FLAG;
  530. if(vtx.dup ())f|=VTX_DUP;
  531. if(edge.ind ())f|=EDGE_IND;
  532. if(edge.adjFace())f|=EDGE_ADJ_FACE;
  533. if(edge.nrm ())f|=EDGE_NRM;
  534. if(edge.flag ())f|=EDGE_FLAG;
  535. if(edge.id ())f|=EDGE_ID;
  536. if(tri.ind ())f|=TRI_IND;
  537. if(tri.adjFace())f|=TRI_ADJ_FACE;
  538. if(tri.adjEdge())f|=TRI_ADJ_EDGE;
  539. if(tri.nrm ())f|=TRI_NRM;
  540. if(tri.flag ())f|=TRI_FLAG;
  541. if(tri.id ())f|=TRI_ID;
  542. if(quad.ind ())f|=QUAD_IND;
  543. if(quad.adjFace())f|=QUAD_ADJ_FACE;
  544. if(quad.adjEdge())f|=QUAD_ADJ_EDGE;
  545. if(quad.nrm ())f|=QUAD_NRM;
  546. if(quad.flag ())f|=QUAD_FLAG;
  547. if(quad.id ())f|=QUAD_ID;
  548. return f;
  549. }
  550. UInt MeshBase::memUsage()C
  551. {
  552. UInt size=0;
  553. if(Int elms=vtx.elms())
  554. {
  555. UInt s=0;
  556. if(vtx.pos ())s+=SIZE(*vtx.pos ());
  557. if(vtx.nrm ())s+=SIZE(*vtx.nrm ());
  558. if(vtx.tan ())s+=SIZE(*vtx.tan ());
  559. if(vtx.bin ())s+=SIZE(*vtx.bin ());
  560. if(vtx.hlp ())s+=SIZE(*vtx.hlp ());
  561. if(vtx.tex0 ())s+=SIZE(*vtx.tex0 ());
  562. if(vtx.tex1 ())s+=SIZE(*vtx.tex1 ());
  563. if(vtx.tex2 ())s+=SIZE(*vtx.tex2 ());
  564. if(vtx.matrix ())s+=SIZE(*vtx.matrix ());
  565. if(vtx.blend ())s+=SIZE(*vtx.blend ());
  566. if(vtx.size ())s+=SIZE(*vtx.size ());
  567. if(vtx.material())s+=SIZE(*vtx.material());
  568. if(vtx.color ())s+=SIZE(*vtx.color ());
  569. if(vtx.flag ())s+=SIZE(*vtx.flag ());
  570. if(vtx.dup ())s+=SIZE(*vtx.dup ());
  571. size+=s*elms;
  572. }
  573. if(Int elms=edge.elms())
  574. {
  575. UInt s=0;
  576. if(edge.ind ())s+=SIZE(*edge.ind ());
  577. if(edge.adjFace())s+=SIZE(*edge.adjFace());
  578. if(edge.nrm ())s+=SIZE(*edge.nrm ());
  579. if(edge.flag ())s+=SIZE(*edge.flag ());
  580. if(edge.id ())s+=SIZE(*edge.id ());
  581. size+=s*elms;
  582. }
  583. if(Int elms=tri.elms())
  584. {
  585. UInt s=0;
  586. if(tri.ind ())s+=SIZE(*tri.ind ());
  587. if(tri.adjFace())s+=SIZE(*tri.adjFace());
  588. if(tri.adjEdge())s+=SIZE(*tri.adjEdge());
  589. if(tri.nrm ())s+=SIZE(*tri.nrm ());
  590. if(tri.flag ())s+=SIZE(*tri.flag ());
  591. if(tri.id ())s+=SIZE(*tri.id ());
  592. size+=s*elms;
  593. }
  594. if(Int elms=quad.elms())
  595. {
  596. UInt s=0;
  597. if(quad.ind ())s+=SIZE(*quad.ind ());
  598. if(quad.adjFace())s+=SIZE(*quad.adjFace());
  599. if(quad.adjEdge())s+=SIZE(*quad.adjEdge());
  600. if(quad.nrm ())s+=SIZE(*quad.nrm ());
  601. if(quad.flag ())s+=SIZE(*quad.flag ());
  602. if(quad.id ())s+=SIZE(*quad.id ());
  603. size+=s*elms;
  604. }
  605. return size;
  606. }
  607. MeshBase& MeshBase::include(UInt f)
  608. {
  609. if(f&VTX_ALL)
  610. {
  611. Int elms=vtx.elms();
  612. if(f&VTX_POS && !vtx._pos )Alloc(vtx._pos , elms);
  613. if(f&VTX_NRM && !vtx._nrm )Alloc(vtx._nrm , elms);
  614. if(f&VTX_TAN && !vtx._tan )Alloc(vtx._tan , elms);
  615. if(f&VTX_BIN && !vtx._bin )Alloc(vtx._bin , elms);
  616. if(f&VTX_HLP && !vtx._hlp )Alloc(vtx._hlp , elms);
  617. if(f&VTX_TEX0 && !vtx._tex0 )Alloc(vtx._tex0 , elms);
  618. if(f&VTX_TEX1 && !vtx._tex1 )Alloc(vtx._tex1 , elms);
  619. if(f&VTX_TEX2 && !vtx._tex2 )Alloc(vtx._tex2 , elms);
  620. if(f&VTX_MATRIX && !vtx._matrix )Alloc(vtx._matrix , elms);
  621. if(f&VTX_BLEND && !vtx._blend )Alloc(vtx._blend , elms);
  622. if(f&VTX_SIZE && !vtx._size )Alloc(vtx._size , elms);
  623. if(f&VTX_MATERIAL && !vtx._material)Alloc(vtx._material, elms);
  624. if(f&VTX_COLOR && !vtx._color )Alloc(vtx._color , elms);
  625. if(f&VTX_FLAG && !vtx._flag )Alloc(vtx._flag , elms);
  626. if(f&VTX_DUP && !vtx._dup )Alloc(vtx._dup , elms);
  627. }
  628. if(f&EDGE_ALL)
  629. {
  630. Int elms=edge.elms();
  631. if(f&EDGE_IND && !edge._ind )Alloc(edge._ind , elms);
  632. if(f&EDGE_ADJ_FACE && !edge._adj_face)Alloc(edge._adj_face, elms);
  633. if(f&EDGE_NRM && !edge._nrm )Alloc(edge._nrm , elms);
  634. if(f&EDGE_FLAG && !edge._flag )Alloc(edge._flag , elms);
  635. if(f&EDGE_ID && !edge._id )Alloc(edge._id , elms);
  636. }
  637. if(f&TRI_ALL)
  638. {
  639. Int elms=tri.elms();
  640. if(f&TRI_IND && !tri._ind )Alloc(tri._ind , elms);
  641. if(f&TRI_ADJ_FACE && !tri._adj_face)Alloc(tri._adj_face, elms);
  642. if(f&TRI_ADJ_EDGE && !tri._adj_edge)Alloc(tri._adj_edge, elms);
  643. if(f&TRI_NRM && !tri._nrm )Alloc(tri._nrm , elms);
  644. if(f&TRI_FLAG && !tri._flag )Alloc(tri._flag , elms);
  645. if(f&TRI_ID && !tri._id )Alloc(tri._id , elms);
  646. }
  647. if(f&QUAD_ALL)
  648. {
  649. Int elms=quad.elms();
  650. if(f&QUAD_IND && !quad._ind )Alloc(quad._ind , elms);
  651. if(f&QUAD_ADJ_FACE && !quad._adj_face)Alloc(quad._adj_face, elms);
  652. if(f&QUAD_ADJ_EDGE && !quad._adj_edge)Alloc(quad._adj_edge, elms);
  653. if(f&QUAD_NRM && !quad._nrm )Alloc(quad._nrm , elms);
  654. if(f&QUAD_FLAG && !quad._flag )Alloc(quad._flag , elms);
  655. if(f&QUAD_ID && !quad._id )Alloc(quad._id , elms);
  656. }
  657. return T;
  658. }
  659. MeshBase& MeshBase::exclude(UInt f)
  660. {
  661. if(f&VTX_ALL)
  662. {
  663. if(f&VTX_POS )Free(vtx._pos );
  664. if(f&VTX_NRM )Free(vtx._nrm );
  665. if(f&VTX_TAN )Free(vtx._tan );
  666. if(f&VTX_BIN )Free(vtx._bin );
  667. if(f&VTX_HLP )Free(vtx._hlp );
  668. if(f&VTX_TEX0 )Free(vtx._tex0 );
  669. if(f&VTX_TEX1 )Free(vtx._tex1 );
  670. if(f&VTX_TEX2 )Free(vtx._tex2 );
  671. if(f&VTX_MATRIX )Free(vtx._matrix );
  672. if(f&VTX_BLEND )Free(vtx._blend );
  673. if(f&VTX_SIZE )Free(vtx._size );
  674. if(f&VTX_MATERIAL)Free(vtx._material);
  675. if(f&VTX_COLOR )Free(vtx._color );
  676. if(f&VTX_FLAG )Free(vtx._flag );
  677. if(f&VTX_DUP )Free(vtx._dup );
  678. }
  679. if(f&EDGE_ALL)
  680. {
  681. if(f&EDGE_IND )Free(edge._ind );
  682. if(f&EDGE_ADJ_FACE)Free(edge._adj_face);
  683. if(f&EDGE_NRM )Free(edge._nrm );
  684. if(f&EDGE_FLAG )Free(edge._flag );
  685. if(f&EDGE_ID )Free(edge._id );
  686. }
  687. if(f&TRI_ALL)
  688. {
  689. if(f&TRI_IND )Free(tri._ind );
  690. if(f&TRI_ADJ_FACE)Free(tri._adj_face);
  691. if(f&TRI_ADJ_EDGE)Free(tri._adj_edge);
  692. if(f&TRI_NRM )Free(tri._nrm );
  693. if(f&TRI_FLAG )Free(tri._flag );
  694. if(f&TRI_ID )Free(tri._id );
  695. }
  696. if(f&QUAD_ALL)
  697. {
  698. if(f&QUAD_IND )Free(quad._ind );
  699. if(f&QUAD_ADJ_FACE)Free(quad._adj_face);
  700. if(f&QUAD_ADJ_EDGE)Free(quad._adj_edge);
  701. if(f&QUAD_NRM )Free(quad._nrm );
  702. if(f&QUAD_FLAG )Free(quad._flag );
  703. if(f&QUAD_ID )Free(quad._id );
  704. }
  705. f=flag();
  706. if(!(f& VTX_ALL))vtx ._elms=0;
  707. if(!(f&EDGE_ALL))edge._elms=0;
  708. if(!(f& TRI_ALL))tri ._elms=0;
  709. if(!(f&QUAD_ALL))quad._elms=0;
  710. return T;
  711. }
  712. MeshBase& MeshBase::keepOnly(UInt f) {return exclude(~f);}
  713. /******************************************************************************/
  714. MeshBase& MeshBase::del()
  715. {
  716. return keepOnly(0);
  717. }
  718. MeshBase& MeshBase::create(Int vtxs, Int edges, Int tris, Int quads, UInt flag)
  719. {
  720. del();
  721. vtx ._elms=vtxs ;
  722. edge._elms=edges;
  723. tri ._elms=tris ;
  724. quad._elms=quads;
  725. include(flag|VTX_POS|EDGE_IND|FACE_IND);
  726. return T;
  727. }
  728. /******************************************************************************/
  729. #if WINDOWS_OLD
  730. static void SetWeight(VecB4 &weight, Vec4 src) // 'weight.sum' must be always equal to 255 !!
  731. {
  732. if(Flt sum=src.sum())src/=sum; // normalize
  733. if(src.z) // currently there's limit of 3 max bone influences, so ignore src.w and set it to 0
  734. {
  735. Byte w0= RoundPos(src.x*255),
  736. w1=Mid(RoundPos(src.y*255), 0, 255-w0);
  737. weight.set(w0, w1, 255-w0-w1, 0);
  738. }else
  739. if(src.y)
  740. {
  741. Byte w=RoundPos(src.x*255);
  742. weight.set(w, 255-w, 0, 0);
  743. }else
  744. {
  745. weight.set(255, 0, 0, 0);
  746. }
  747. }
  748. static Bool Create(MeshBase &mesh, IDirect3DVertexBuffer9 *vtx_buffer, D3DVERTEXELEMENT9 ve[], Int vtx_size, Int vtx_num, Bool allow_binormal)
  749. {
  750. mesh.exclude(VTX_ALL); if(!vtx_num)return true;
  751. SyncLocker locker(D._lock);
  752. Byte *vtx_buf; if(OK(vtx_buffer->Lock(0, 0, (Ptr*)&vtx_buf, D3DLOCK_READONLY)))
  753. {
  754. // check elements
  755. UInt flag=0;
  756. Bool bin_from_tan=false, bin_from_bin=false;
  757. FREP(MAX_FVF_DECL_SIZE)
  758. {
  759. D3DVERTEXELEMENT9 &v=ve[i];
  760. if(v.Stream==0xFF)break;else switch(v.Usage)
  761. {
  762. case D3DDECLUSAGE_POSITION : if(v.UsageIndex==0)flag|=VTX_POS;else if(v.UsageIndex==1)flag|=VTX_HLP; break;
  763. case D3DDECLUSAGE_BLENDWEIGHT : flag|=VTX_BLEND ; break;
  764. case D3DDECLUSAGE_BLENDINDICES: flag|=VTX_MATRIX; break;
  765. case D3DDECLUSAGE_NORMAL : if(v.Type==D3DDECLTYPE_FLOAT3)flag|=VTX_NRM;else if(v.Type==D3DDECLTYPE_UBYTE4N) flag|=VTX_NRM; break;
  766. case D3DDECLUSAGE_TANGENT : if(v.Type==D3DDECLTYPE_FLOAT3)flag|=VTX_TAN;else if(v.Type==D3DDECLTYPE_UBYTE4N){flag|=VTX_TAN; bin_from_tan=true;} break;
  767. case D3DDECLUSAGE_BINORMAL : if(v.Type==D3DDECLTYPE_FLOAT3)flag|=VTX_BIN; bin_from_bin=true; break;
  768. case D3DDECLUSAGE_PSIZE : flag|=VTX_SIZE; break;
  769. case D3DDECLUSAGE_TEXCOORD : if(v.UsageIndex==0)flag|=VTX_TEX0 ;else if(v.UsageIndex==1)flag|=VTX_TEX1 ;else if(v.UsageIndex==2)flag|=VTX_TEX2; break;
  770. case D3DDECLUSAGE_COLOR : if(v.UsageIndex==0)flag|=VTX_MATERIAL;else if(v.UsageIndex==1)flag|=VTX_COLOR; break;
  771. }
  772. }
  773. // update binormal info
  774. if(bin_from_tan)
  775. {
  776. if(bin_from_bin || !(flag&VTX_NRM) || !allow_binormal)bin_from_tan=false;else flag|=VTX_BIN;
  777. }
  778. // create vertexes
  779. mesh.vtx._elms=vtx_num;
  780. mesh.include(flag);
  781. // copy data
  782. FREP(MAX_FVF_DECL_SIZE)
  783. {
  784. D3DVERTEXELEMENT9 &v=ve[i];
  785. if(v.Stream==0xFF)break;else
  786. {
  787. Byte *vd=vtx_buf+v.Offset; // vtx_data
  788. switch(v.Usage)
  789. {
  790. case D3DDECLUSAGE_POSITION:
  791. if(v.UsageIndex==0)REPA(mesh.vtx)mesh.vtx.pos(i)=*(Vec*)(vd+i*vtx_size);else
  792. if(v.UsageIndex==1)REPA(mesh.vtx)mesh.vtx.hlp(i)=*(Vec*)(vd+i*vtx_size);
  793. break;
  794. case D3DDECLUSAGE_NORMAL:
  795. if(v.Type==D3DDECLTYPE_FLOAT3 )REPA(mesh.vtx)mesh.vtx.nrm(i)= *(Vec *)(vd+i*vtx_size) ;else
  796. if(v.Type==D3DDECLTYPE_UBYTE4N)REPA(mesh.vtx)mesh.vtx.nrm(i)=UByte4ToNrm(*(VecB4*)(vd+i*vtx_size));
  797. break;
  798. case D3DDECLUSAGE_TANGENT:
  799. if(v.Type==D3DDECLTYPE_FLOAT3 )REPA(mesh.vtx)mesh.vtx.tan(i)=*(Vec*)(vd+i*vtx_size);else
  800. if(v.Type==D3DDECLTYPE_UBYTE4N)REPA(mesh.vtx)
  801. {
  802. VecB4 tan=*(VecB4*)(vd+i*vtx_size);
  803. mesh.vtx.tan(i) =UByte4ToNrm(tan);
  804. if(bin_from_tan)mesh.vtx.bin(i).x=((tan.w>=128) ? 1.0f : -1.0f);
  805. }
  806. break;
  807. case D3DDECLUSAGE_BINORMAL:
  808. if(v.Type==D3DDECLTYPE_FLOAT3)REPA(mesh.vtx)mesh.vtx.bin(i)=*(Vec*)(vd+i*vtx_size); break;
  809. break;
  810. case D3DDECLUSAGE_PSIZE : REPA(mesh.vtx)mesh.vtx.size (i)=*(Flt *)(vd+i*vtx_size); break;
  811. case D3DDECLUSAGE_BLENDINDICES: REPA(mesh.vtx)mesh.vtx.matrix(i)=*(VecB4*)(vd+i*vtx_size); break;
  812. case D3DDECLUSAGE_BLENDWEIGHT:
  813. if(v.UsageIndex==0)REPA(mesh.vtx)
  814. {
  815. if(v.Type==D3DDECLTYPE_UBYTE4
  816. || v.Type==D3DDECLTYPE_UBYTE4N){VecB4 v=*(VecB4*)(vd+i*vtx_size); SetWeight(mesh.vtx.blend(i), v );}else
  817. if(v.Type==D3DDECLTYPE_FLOAT1 ){Flt f=*(Flt *)(vd+i*vtx_size); SetWeight(mesh.vtx.blend(i), Vec4(f, 1-f, 0, 0));}else
  818. if(v.Type==D3DDECLTYPE_FLOAT3 ){Vec v=*(Vec *)(vd+i*vtx_size); SetWeight(mesh.vtx.blend(i), Vec4(v , 0));}else
  819. if(v.Type==D3DDECLTYPE_FLOAT4 ){Vec4 v=*(Vec4 *)(vd+i*vtx_size); SetWeight(mesh.vtx.blend(i), v );}
  820. }
  821. break;
  822. case D3DDECLUSAGE_TEXCOORD:
  823. if(v.UsageIndex==0)REPA(mesh.vtx)mesh.vtx.tex0(i)=*(Vec2*)(vd+i*vtx_size);else
  824. if(v.UsageIndex==1)REPA(mesh.vtx)mesh.vtx.tex1(i)=*(Vec2*)(vd+i*vtx_size);else
  825. if(v.UsageIndex==2)REPA(mesh.vtx)mesh.vtx.tex2(i)=*(Vec2*)(vd+i*vtx_size);
  826. break;
  827. case D3DDECLUSAGE_COLOR:
  828. if(v.UsageIndex==0)REPA(mesh.vtx)mesh.vtx.material(i)=*(VecB4*)(vd+i*vtx_size);else
  829. if(v.UsageIndex==1)REPA(mesh.vtx)
  830. {
  831. if(v.Type==D3DDECLTYPE_UBYTE4N ) mesh.vtx.color(i)=*(Color*)(vd+i*vtx_size);else
  832. if(v.Type==D3DDECLTYPE_D3DCOLOR){mesh.vtx.color(i)=*(Color*)(vd+i*vtx_size); Swap(mesh.vtx.color(i).r, mesh.vtx.color(i).b);}
  833. }
  834. break;
  835. }
  836. }
  837. }
  838. // update binormals
  839. if(bin_from_tan)REPA(mesh.vtx)mesh.vtx.bin(i)=mesh.vtx.bin(i).x*Cross(mesh.vtx.nrm(i), mesh.vtx.tan(i));
  840. // add missing vertex blends when only matrix indexes provided
  841. if(mesh.vtx.matrix() && !mesh.vtx.blend())
  842. {
  843. mesh.include(VTX_BLEND);
  844. REPA(mesh.vtx)mesh.vtx.blend(i).set(255, 0, 0, 0);
  845. }
  846. vtx_buffer->Unlock();
  847. return true;
  848. }
  849. return false;
  850. }
  851. static Bool Create(MeshBase &mesh, IDirect3DIndexBuffer9 *ind_buffer, Bool bit16, Int tris)
  852. {
  853. mesh.exclude(FACE_ALL|ADJ_ALL); if(tris<=0)return true;
  854. SyncLocker locker(D._lock);
  855. Ptr ind; if(OK(ind_buffer->Lock(0, 0, &ind, D3DLOCK_READONLY)))
  856. {
  857. mesh.tri._elms=tris;
  858. mesh.include(TRI_IND);
  859. if(bit16)Copy16To32(mesh.tri.ind(), ind, tris*3);
  860. else Copy32To32(mesh.tri.ind(), ind, tris*3);
  861. ind_buffer->Unlock();
  862. return true;
  863. }
  864. return false;
  865. }
  866. #if 0
  867. Bool MeshBase::create(ID3DXMesh *mesh)
  868. {
  869. Bool ok;
  870. del(); if(!mesh)return true;
  871. SyncLocker locker(D._lock);
  872. // create vertexes
  873. D3DVERTEXELEMENT9 ve[MAX_FVF_DECL_SIZE]; if(!OK(mesh->GetDeclaration ( ve )))return false;
  874. IDirect3DVertexBuffer9 *vtx_buf=null; if(!OK(mesh->GetVertexBuffer(&vtx_buf)))return false;
  875. ok=Create(T, vtx_buf, ve, mesh->GetNumBytesPerVertex(), mesh->GetNumVertices(), true); RELEASE(vtx_buf); if(!ok)return false;
  876. // create indexes
  877. IDirect3DIndexBuffer9 *ind_buf=null; if(!OK(mesh->GetIndexBuffer(&ind_buf)))return false;
  878. ok=Create(T, ind_buf, !FlagTest(mesh->GetOptions(), D3DXMESH_32BIT), mesh->GetNumFaces()); RELEASE(ind_buf); if(!ok)return false;
  879. // set attributes
  880. D3DXATTRIBUTERANGE attrib[256];
  881. DWORD elms=Elms(attrib);
  882. if(OK(mesh->GetAttributeTable(attrib, &elms)))
  883. {
  884. if(elms>1 || attrib[0].AttribId!=0) // required by DirectX .X importer
  885. {
  886. include(TRI_ID);
  887. REP(elms)
  888. {
  889. Int id =attrib[i].AttribId ,
  890. start=attrib[i].FaceStart;
  891. REPD(f, attrib[i].FaceCount)tri.id(start+f)=id;
  892. }
  893. }
  894. }
  895. return true;
  896. }
  897. #endif
  898. #endif
  899. /******************************************************************************/
  900. T1(TYPE) static void Set(C Byte* &v, Int i, TYPE *data, UInt flag) {if(data)data[i]=*(TYPE*)v; if(flag)v+=SIZE(TYPE);}
  901. Bool MeshBase::createVtx(C VtxBuf &vb, UInt flag, UInt storage, MeshRender::BoneSplit *bone_split, Int bone_splits, UInt flag_and)
  902. {
  903. exclude(VTX_ALL);
  904. if(!vb._vtx_num)return true;
  905. if(C Byte *v=vb.lockRead())
  906. {
  907. vtx._elms=vb._vtx_num; include(VTX_ALL&flag&flag_and);
  908. if(storage&MSHR_COMPRESS)
  909. {
  910. Bool sign=FlagTest(storage, MSHR_SIGNED);
  911. FREPA(vtx)
  912. {
  913. Set(v, i, vtx.pos (), flag&VTX_POS );
  914. if(vtx.nrm() )vtx.nrm(i)=(sign ? SByte4ToNrm : UByte4ToNrm)(*(VecB4*)v); if(flag&VTX_NRM)v+=SIZE(VecB4);
  915. if(vtx.tan() || vtx.bin())(sign ? SByte4ToTan : UByte4ToTan)(*(VecB4*)v, vtx.tan() ? &vtx.tan(i) : null, vtx.bin() ? &vtx.bin(i) : null, vtx.nrm() ? &vtx.nrm(i) : null); if(flag&VTX_TAN_BIN)v+=SIZE(VecB4);
  916. Set(v, i, vtx.hlp (), flag&VTX_HLP );
  917. Set(v, i, vtx.tex0 (), flag&VTX_TEX0 );
  918. Set(v, i, vtx.tex1 (), flag&VTX_TEX1 );
  919. Set(v, i, vtx.tex2 (), flag&VTX_TEX2 );
  920. Set(v, i, vtx.matrix (), flag&VTX_MATRIX );
  921. Set(v, i, vtx.blend (), flag&VTX_BLEND );
  922. Set(v, i, vtx.size (), flag&VTX_SIZE );
  923. Set(v, i, vtx.material(), flag&VTX_MATERIAL);
  924. Set(v, i, vtx.color (), flag&VTX_COLOR );
  925. }
  926. }else
  927. {
  928. FREPA(vtx)
  929. {
  930. Set(v, i, vtx.pos (), flag&VTX_POS );
  931. Set(v, i, vtx.nrm (), flag&VTX_NRM );
  932. Set(v, i, vtx.tan (), flag&VTX_TAN );
  933. Set(v, i, vtx.bin (), flag&VTX_BIN );
  934. Set(v, i, vtx.hlp (), flag&VTX_HLP );
  935. Set(v, i, vtx.tex0 (), flag&VTX_TEX0 );
  936. Set(v, i, vtx.tex1 (), flag&VTX_TEX1 );
  937. Set(v, i, vtx.tex2 (), flag&VTX_TEX2 );
  938. Set(v, i, vtx.matrix (), flag&VTX_MATRIX );
  939. Set(v, i, vtx.blend (), flag&VTX_BLEND );
  940. Set(v, i, vtx.size (), flag&VTX_SIZE );
  941. Set(v, i, vtx.material(), flag&VTX_MATERIAL);
  942. Set(v, i, vtx.color (), flag&VTX_COLOR );
  943. }
  944. }
  945. vb.unlock();
  946. // restore real bone matrix indexes
  947. if((storage&MSHR_BONE_SPLIT) && bone_split)if(VecB4 *matrix=vtx.matrix())FREP(bone_splits)
  948. {
  949. C MeshRender::BoneSplit &split=bone_split[i];
  950. FREP(split.vtxs)
  951. {
  952. matrix->x=split.split_to_real[matrix->x];
  953. matrix->y=split.split_to_real[matrix->y];
  954. matrix->z=split.split_to_real[matrix->z];
  955. matrix->w=split.split_to_real[matrix->w];
  956. matrix++;
  957. }
  958. }
  959. return true;
  960. }
  961. return false;
  962. }
  963. /******************************************************************************/
  964. Bool MeshBase::createInd(C IndBuf &ib)
  965. {
  966. exclude(FACE_ALL|ADJ_ALL);
  967. if(ib._ind_num/3<=0)return true;
  968. if(CPtr ind=ib.lockRead())
  969. {
  970. tri._elms=ib._ind_num/3;
  971. include(TRI_IND);
  972. if(ib.bit16())Copy16To32(tri.ind(), ind, tri.elms()*3);
  973. else Copy32To32(tri.ind(), ind, tri.elms()*3);
  974. ib.unlock();
  975. return true;
  976. }
  977. return false;
  978. }
  979. /******************************************************************************/
  980. MeshBase& MeshBase::create(C MeshRender &src, UInt flag_and)
  981. {
  982. del();
  983. if(createVtx(src._vb, src.flag(), src._storage, src._bone_split, src._bone_splits, flag_and))
  984. createInd(src._ib);
  985. return T;
  986. }
  987. /******************************************************************************/
  988. MeshBase& MeshBase::createPhys(C MeshLod &src, UInt flag_and, Bool set_face_id_from_part_index, Bool skip_hidden_parts)
  989. {
  990. UInt part_flag=MSHP_NO_PHYS_BODY; if(skip_hidden_parts)part_flag|=MSHP_HIDDEN;
  991. REPA(src)if(src.parts[i].part_flag&part_flag) // if at least one needs to be removed
  992. {
  993. Memt<MeshBase> meshes; REPAD(p, src)if(!(src.parts[p].part_flag&part_flag)) // copy all desired MeshBase into container
  994. {
  995. MeshBase &mesh=meshes.New();
  996. mesh.create(src.parts[p], flag_and);
  997. if(set_face_id_from_part_index)
  998. {
  999. mesh.include(FACE_ID);
  1000. REPA(mesh.tri )mesh.tri .id(i)=p;
  1001. REPA(mesh.quad)mesh.quad.id(i)=p;
  1002. }
  1003. }
  1004. create(meshes.data(), meshes.elms()); // create basing on the container
  1005. return T;
  1006. }
  1007. create(src, flag_and, set_face_id_from_part_index); // create basing on the whole 'MeshLod'
  1008. return T;
  1009. }
  1010. /******************************************************************************/
  1011. #if PHYSX
  1012. Bool MeshBase::create(PxConvexMesh &convex)
  1013. {
  1014. Int tris=0;
  1015. PxHullPolygon poly;
  1016. const PxU8 *ind=convex.getIndexBuffer();
  1017. // calculate number of tris
  1018. REP(convex.getNbPolygons())
  1019. if(convex.getPolygonData(i, poly))tris+=Max(0, poly.mNbVerts-2);
  1020. // create
  1021. create(convex.getNbVertices(), 0, tris, 0);
  1022. // copy vertexes
  1023. CopyN(vtx.pos(), (Vec*)convex.getVertices(), vtxs());
  1024. // setup tris
  1025. tris=0;
  1026. FREP(convex.getNbPolygons())
  1027. if(convex.getPolygonData(i, poly))
  1028. FREP(poly.mNbVerts-2)
  1029. tri.ind(tris++).set(ind[poly.mIndexBase+0], ind[poly.mIndexBase+i+1], ind[poly.mIndexBase+i+2]);
  1030. return true;
  1031. }
  1032. Bool MeshBase::create(PxTriangleMesh &mesh)
  1033. {
  1034. create(mesh.getNbVertices(), 0, mesh.getNbTriangles(), 0);
  1035. CopyN (vtx.pos(), (Vec *)mesh.getVertices (), vtxs() );
  1036. if(mesh.getTriangleMeshFlags()&PxTriangleMeshFlag::e16_BIT_INDICES)Copy16To32(tri.ind(), mesh.getTriangles(), tris()*3);
  1037. else CopyN (tri.ind(), (VecI*)mesh.getTriangles(), tris() );
  1038. return true;
  1039. }
  1040. #else
  1041. Bool MeshBase::create(btConvexHullShape &convex)
  1042. {
  1043. Memt<Vec> points; points.setNum(convex.getNumPoints()); REPA(points)points[i]=Bullet.vec(convex.getScaledPoint(i));
  1044. createConvex(points.data(), points.elms());
  1045. return true;
  1046. }
  1047. Bool MeshBase::create(btBvhTriangleMeshShape &mesh)
  1048. {
  1049. Bool ok=false;
  1050. if(btStridingMeshInterface *smi=mesh.getMeshInterface())
  1051. {
  1052. Vec *pos;
  1053. VecI *ind;
  1054. int vtxs, tris, vtx_stride, ind_stride;
  1055. PHY_ScalarType vtx_type, ind_type;
  1056. smi->getLockedReadOnlyVertexIndexBase((const unsigned char**)&pos, vtxs, vtx_type, vtx_stride, (const unsigned char**)&ind, ind_stride, tris, ind_type);
  1057. if(vtx_type==PHY_FLOAT && ind_type==PHY_INTEGER)
  1058. {
  1059. create(vtxs, 0, tris, 0);
  1060. CopyN (vtx.pos(), pos, vtxs);
  1061. CopyN (tri.ind(), ind, tris);
  1062. ok=true;
  1063. }
  1064. smi->unLockReadOnlyVertexBase(0);
  1065. }
  1066. if(!ok)del(); return ok;
  1067. }
  1068. #endif
  1069. MeshBase& MeshBase::create(C PhysPart &part)
  1070. {
  1071. switch(part.type())
  1072. {
  1073. case PHYS_SHAPE: return create(part.shape, 0, (part.shape.type==SHAPE_BALL) ? 16 : ShapeTypeRound(part.shape.type) ? 32 : -1);
  1074. case PHYS_CONVEX:
  1075. case PHYS_MESH : if(part._pm)
  1076. {
  1077. if(part._pm->_base ){create(*part._pm->_base ); return T;}
  1078. if(part._pm->_convex){create(*part._pm->_convex); return T;}
  1079. if(part._pm->_mesh ){create(*part._pm->_mesh ); return T;}
  1080. }break;
  1081. }
  1082. return del();
  1083. }
  1084. /******************************************************************************/
  1085. MeshBase& MeshBase::create(C MeshBase *src[], Int elms, UInt flag_and, Bool set_face_id_from_part_index)
  1086. {
  1087. if(!src)elms=0;
  1088. UInt flag=0;
  1089. Int vtxs=0, edges=0, tris=0, quads=0;
  1090. MeshBase temp;
  1091. REP(elms)if(C MeshBase *mesh=src[i])
  1092. {
  1093. flag |=mesh->flag ();
  1094. vtxs +=mesh->vtxs ();
  1095. edges+=mesh->edges();
  1096. tris +=mesh->tris ();
  1097. quads+=mesh->quads();
  1098. }
  1099. flag&=flag_and&(~(VTX_DUP|ADJ_ALL)); if(set_face_id_from_part_index)flag|=ID_ALL;
  1100. temp.create(vtxs, edges, tris, quads, flag);
  1101. Vec *vtx_pos =temp.vtx.pos ();
  1102. Vec *vtx_nrm =temp.vtx.nrm ();
  1103. Vec *vtx_tan =temp.vtx.tan ();
  1104. Vec *vtx_bin =temp.vtx.bin ();
  1105. Vec *vtx_hlp =temp.vtx.hlp ();
  1106. Vec2 *vtx_tex0 =temp.vtx.tex0 ();
  1107. Vec2 *vtx_tex1 =temp.vtx.tex1 ();
  1108. Vec2 *vtx_tex2 =temp.vtx.tex2 ();
  1109. VecB4 *vtx_matrix =temp.vtx.matrix ();
  1110. VecB4 *vtx_blend =temp.vtx.blend ();
  1111. Flt *vtx_size =temp.vtx.size ();
  1112. VecB4 *vtx_material=temp.vtx.material();
  1113. Color *vtx_color =temp.vtx.color ();
  1114. Byte *vtx_flag =temp.vtx.flag ();
  1115. VecI2 *edge_ind =temp.edge.ind ();
  1116. Vec *edge_nrm =temp.edge.nrm ();
  1117. Byte *edge_flag=temp.edge.flag();
  1118. Int *edge_id =temp.edge.id ();
  1119. VecI *tri_ind =temp.tri.ind ();
  1120. Vec *tri_nrm =temp.tri.nrm ();
  1121. Byte *tri_flag=temp.tri.flag();
  1122. Int *tri_id =temp.tri.id ();
  1123. VecI4 *quad_ind =temp.quad.ind ();
  1124. Vec *quad_nrm =temp.quad.nrm ();
  1125. Byte *quad_flag=temp.quad.flag();
  1126. Int *quad_id =temp.quad.id ();
  1127. // vertexes
  1128. FREP(elms)if(C MeshBase *mesh=src[i])if(Int vtxs=mesh->vtxs())
  1129. {
  1130. if(vtx_pos ){CopyN(vtx_pos , mesh->vtx.pos (), vtxs); vtx_pos +=vtxs;}
  1131. if(vtx_nrm ){CopyN(vtx_nrm , mesh->vtx.nrm (), vtxs); vtx_nrm +=vtxs;}
  1132. if(vtx_tan ){CopyN(vtx_tan , mesh->vtx.tan (), vtxs); vtx_tan +=vtxs;}
  1133. if(vtx_bin ){CopyN(vtx_bin , mesh->vtx.bin (), vtxs); vtx_bin +=vtxs;}
  1134. if(vtx_hlp ){CopyN(vtx_hlp , mesh->vtx.hlp (), vtxs); vtx_hlp +=vtxs;}
  1135. if(vtx_tex0 ){CopyN(vtx_tex0 , mesh->vtx.tex0 (), vtxs); vtx_tex0 +=vtxs;}
  1136. if(vtx_tex1 ){CopyN(vtx_tex1 , mesh->vtx.tex1 (), vtxs); vtx_tex1 +=vtxs;}
  1137. if(vtx_tex2 ){CopyN(vtx_tex2 , mesh->vtx.tex2 (), vtxs); vtx_tex2 +=vtxs;}
  1138. if(vtx_matrix ){CopyN(vtx_matrix , mesh->vtx.matrix (), vtxs); vtx_matrix +=vtxs;}
  1139. if(vtx_size ){CopyN(vtx_size , mesh->vtx.size (), vtxs); vtx_size +=vtxs;}
  1140. if(vtx_flag ){CopyN(vtx_flag , mesh->vtx.flag (), vtxs); vtx_flag +=vtxs;}
  1141. if(vtx_blend ){if(mesh->vtx.blend ())CopyN(vtx_blend , mesh->vtx.blend (), vtxs);else REP(vtxs)vtx_blend [i].set(255, 0, 0, 0); vtx_blend +=vtxs;}
  1142. if(vtx_material){if(mesh->vtx.material())CopyN(vtx_material, mesh->vtx.material(), vtxs);else REP(vtxs)vtx_material[i].set(255, 0, 0, 0); vtx_material+=vtxs;}
  1143. if(vtx_color ){if(mesh->vtx.color ())CopyN(vtx_color , mesh->vtx.color (), vtxs);else REP(vtxs)vtx_color [i]=WHITE ; vtx_color +=vtxs;}
  1144. }
  1145. // edges, tris, quads
  1146. if(elms==1)
  1147. {
  1148. if(C MeshBase *mesh=src[0])
  1149. {
  1150. if(edge_ind )CopyN(edge_ind , mesh->edge.ind (), edges);
  1151. if(edge_nrm )CopyN(edge_nrm , mesh->edge.nrm (), edges);
  1152. if(edge_flag)CopyN(edge_flag, mesh->edge.flag(), edges);
  1153. if(tri_ind )CopyN(tri_ind , mesh->tri.ind (), tris);
  1154. if(tri_nrm )CopyN(tri_nrm , mesh->tri.nrm (), tris);
  1155. if(tri_flag)CopyN(tri_flag, mesh->tri.flag(), tris);
  1156. if(quad_ind )CopyN(quad_ind , mesh->quad.ind (), quads);
  1157. if(quad_nrm )CopyN(quad_nrm , mesh->quad.nrm (), quads);
  1158. if(quad_flag)CopyN(quad_flag, mesh->quad.flag(), quads);
  1159. if(set_face_id_from_part_index)
  1160. {
  1161. REP(edges)edge_id[i]=0;
  1162. REP(tris ) tri_id[i]=0;
  1163. REP(quads)quad_id[i]=0;
  1164. }else
  1165. {
  1166. if(edge_id)CopyN(edge_id, mesh->edge.id(), edges);
  1167. if( tri_id)CopyN( tri_id, mesh->tri .id(), tris);
  1168. if(quad_id)CopyN(quad_id, mesh->quad.id(), quads);
  1169. }
  1170. }
  1171. }else
  1172. {
  1173. Int vtx_ofs=0; FREPD(m, elms)if(C MeshBase *mesh=src[m])
  1174. {
  1175. if(Int edges=mesh->edges())
  1176. {
  1177. if(edge_ind ){C VecI2 *ind=mesh->edge.ind(); if(!ind){ZeroN(edge_ind, edges); edge_ind+=edges;}else REP(edges)*edge_ind++=(*ind++)+vtx_ofs;}
  1178. if(edge_nrm ){CopyN(edge_nrm , mesh->edge.nrm (), edges); edge_nrm +=edges;}
  1179. if(edge_flag){CopyN(edge_flag, mesh->edge.flag(), edges); edge_flag+=edges;}
  1180. if(set_face_id_from_part_index)REP(edges)*edge_id++=m;else if(edge_id){CopyN(edge_id, mesh->edge.id(), edges); edge_id+=edges;}
  1181. }
  1182. if(Int tris=mesh->tris())
  1183. {
  1184. if(tri_ind ){C VecI *ind=mesh->tri.ind(); if(!ind){ZeroN(tri_ind, tris); tri_ind+=tris;}else REP(tris)*tri_ind++=(*ind++)+vtx_ofs;}
  1185. if(tri_nrm ){CopyN(tri_nrm , mesh->tri.nrm (), tris); tri_nrm +=tris;}
  1186. if(tri_flag){CopyN(tri_flag, mesh->tri.flag(), tris); tri_flag+=tris;}
  1187. if(set_face_id_from_part_index)REP(tris)*tri_id++=m;else if(tri_id){CopyN(tri_id, mesh->tri.id(), tris); tri_id+=tris;}
  1188. }
  1189. if(Int quads=mesh->quads())
  1190. {
  1191. if(quad_ind ){C VecI4 *ind=mesh->quad.ind(); if(!ind){ZeroN(quad_ind, quads); quad_ind+=quads;}else REP(quads)*quad_ind++=(*ind++)+vtx_ofs;}
  1192. if(quad_nrm ){CopyN(quad_nrm , mesh->quad.nrm (), quads); quad_nrm +=quads;}
  1193. if(quad_flag){CopyN(quad_flag, mesh->quad.flag(), quads); quad_flag+=quads;}
  1194. if(set_face_id_from_part_index)REP(quads)*quad_id++=m;else if(quad_id){CopyN(quad_id, mesh->quad.id(), quads); quad_id+=quads;}
  1195. }
  1196. vtx_ofs+=mesh->vtxs();
  1197. }
  1198. }
  1199. Swap(temp, T); return T;
  1200. }
  1201. MeshBase& MeshBase::create(C MeshBase *src, Int elms, UInt flag_and, Bool set_face_id_from_part_index)
  1202. {
  1203. if(!src)elms=0;
  1204. Memt<C MeshBase*, 1024> mesh_ptr; mesh_ptr.setNum(elms); REPAO(mesh_ptr)=&src[i];
  1205. return create(mesh_ptr.data(), mesh_ptr.elms(), flag_and, set_face_id_from_part_index);
  1206. }
  1207. MeshBase& MeshBase::create(C MeshBase &src, UInt flag_and)
  1208. {
  1209. if(this==&src)keepOnly(flag_and);else
  1210. {
  1211. create (src.vtxs(), src.edges(), src.tris(), src.quads(), src.flag()&flag_and);
  1212. copyVtxs (src);
  1213. copyEdges(src);
  1214. copyTris (src);
  1215. copyQuads(src);
  1216. }
  1217. return T;
  1218. }
  1219. MeshBase& MeshBase::create(C MeshLod &src, UInt flag_and, Bool set_face_id_from_part_index)
  1220. {
  1221. Memb< MeshBase > temp ; // use 'Memb' because we're storing pointers to elms
  1222. Memt<C MeshBase*, 1024> mesh_ptr; mesh_ptr.setNum(src.parts.elms());
  1223. REPA(mesh_ptr)
  1224. {
  1225. C MeshPart &part=src.parts[i];
  1226. if(part.render.is() && !part.base.is())mesh_ptr[i]=&temp.New().create(part.render, flag_and); // MeshBase needs to be created
  1227. else mesh_ptr[i]=& part.base; // copy ptr of MeshLod's MeshBase
  1228. }
  1229. return create(mesh_ptr.data(), mesh_ptr.elms(), flag_and, set_face_id_from_part_index);
  1230. }
  1231. MeshBase& MeshBase::create(C MeshPart &src, UInt flag_and)
  1232. {
  1233. if(src.base .is())return create(src.base , flag_and);
  1234. if(src.render.is())return create(src.render, flag_and);
  1235. return del();
  1236. }
  1237. MeshBase& MeshBase::copyFace(MeshBase &dest, C MemPtr<Bool> &edge_is, C MemPtr<Bool> &tri_is, C MemPtr<Bool> &quad_is, UInt flag_and)C
  1238. {
  1239. C Int *p;
  1240. // vtx
  1241. Memt<Bool> vtx_is; vtx_is.setNumZero(vtxs());
  1242. Memt<Int > vtx_remap;
  1243. if(edge_is)FREPA(edge)if(edge_is[i]){p=edge.ind(i).c; REPD(j, 2)vtx_is[p[j]]=true;}
  1244. if( tri_is)FREPA(tri )if( tri_is[i]){p=tri .ind(i).c; REPD(j, 3)vtx_is[p[j]]=true;}
  1245. if(quad_is)FREPA(quad)if(quad_is[i]){p=quad.ind(i).c; REPD(j, 4)vtx_is[p[j]]=true;}
  1246. // create copy
  1247. MeshBase temp(CountIs( vtx_is),
  1248. CountIs(edge_is),
  1249. CountIs( tri_is),
  1250. CountIs(quad_is), flag()&flag_and&(~(VTX_DUP|ADJ_ALL)));
  1251. temp.copyVtxs (T, vtx_is);
  1252. temp.copyEdges(T, edge_is);
  1253. temp.copyTris (T, tri_is);
  1254. temp.copyQuads(T, quad_is);
  1255. SetRemap(vtx_remap, vtx_is , vtxs ());
  1256. IndRemap(vtx_remap, temp.edge.ind(), temp.edges());
  1257. IndRemap(vtx_remap, temp.tri .ind(), temp.tris ());
  1258. IndRemap(vtx_remap, temp.quad.ind(), temp.quads());
  1259. Swap(dest, temp); return dest;
  1260. }
  1261. /******************************************************************************/
  1262. static void CopyId(MeshBase &dest, C MeshBase &src, Int id, Memt<Bool> &edge_is, Memt<Bool> &tri_is, Memt<Bool> &quad_is, UInt flag_and)
  1263. {
  1264. edge_is.setNum(src.edges());
  1265. tri_is.setNum(src.tris ());
  1266. quad_is.setNum(src.quads());
  1267. // select
  1268. C Int *_id;
  1269. _id=src.edge.id(); if(!_id)ZeroN(edge_is.data(), edge_is.elms());else FREPA(edge_is){edge_is[i]=(*_id==id); _id++;}
  1270. _id=src.tri .id(); if(!_id)ZeroN( tri_is.data(), tri_is.elms());else FREPA( tri_is){ tri_is[i]=(*_id==id); _id++;}
  1271. _id=src.quad.id(); if(!_id)ZeroN(quad_is.data(), quad_is.elms());else FREPA(quad_is){quad_is[i]=(*_id==id); _id++;}
  1272. // copy
  1273. src.copyFace(dest, edge_is, tri_is, quad_is, flag_and);
  1274. /*// adjust edge flag
  1275. if(Byte *flag=dest.edge.flag())
  1276. if(VecI2 *e_id=dest.edge.id ())REPA(dest.edge)
  1277. {
  1278. *flag&=~ETQ_LR;
  1279. if(e_id->x==id)*flag|=ETQ_R;
  1280. if(e_id->y==id)*flag|=ETQ_L;
  1281. flag++; e_id++;
  1282. }*/
  1283. }
  1284. void MeshBase::copyId(MeshBase &dest, Int id, UInt flag_and)C
  1285. {
  1286. Memt<Bool> edge_is, tri_is, quad_is;
  1287. CopyId(dest, T, id, edge_is, tri_is, quad_is, flag_and);
  1288. }
  1289. void MeshBase::copyId(MeshLod &dest, UInt flag_and)C
  1290. {
  1291. Memt<Bool> edge_is, tri_is, quad_is;
  1292. dest.create(maxId()+1); REPA(dest)CopyId(dest.parts[i].base, T, i, edge_is, tri_is, quad_is, flag_and);
  1293. }
  1294. void MeshBase::copyId(Mesh &dest, UInt flag_and)C
  1295. {
  1296. dest.del();
  1297. MeshLod &d=dest; copyId(d, flag_and);
  1298. dest.setBox();
  1299. }
  1300. /******************************************************************************/
  1301. }
  1302. /******************************************************************************/