ClothMeshBuilder.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717
  1. #include "common.h"
  2. #include "../common_h/FileService.h"
  3. #include "PhysicsService.h"
  4. #include "PhysicsScene.h"
  5. #include "NxCooking.h"
  6. #include "ClothMeshBuilder.h"
  7. #include "CookedBinaries/CookBinManager.h"
  8. #include <cmath>
  9. // внутренности ClothMeshBuilder
  10. struct ClothMeshBuilder::Data
  11. {
  12. Data() : buildBuffer_(__FILE__, __LINE__),
  13. vbCombined_(__FILE__, __LINE__),
  14. ibCombined_(__FILE__, __LINE__),
  15. mesh_(NULL), sdk_(NULL),
  16. uScale(1.0f), vScale(1.0f), uOffset(0.0f), vOffset(0.0f) {}
  17. ~Data() { if (mesh_ && sdk_) sdk_->releaseClothMesh(*mesh_); }
  18. // кусок ткани
  19. struct Piece
  20. {
  21. Piece() : vb(__FILE__, __LINE__, 16),
  22. ib(__FILE__, __LINE__, 64) {}
  23. array<Vertex> vb;
  24. array<unsigned short> ib;
  25. };
  26. array<Piece> buildBuffer_; // буфер для хранения кусков ткани
  27. NxClothMesh* mesh_; // скуканый меш
  28. NxPhysicsSDK* sdk_; //
  29. bool tearable_; // флаг разрывности
  30. array<Vertex> vbCombined_;
  31. array<unsigned short> ibCombined_;
  32. float uScale; // скейл U-координаты
  33. float vScale; // скейл V-координаты
  34. float uOffset; // смещение U-координаты
  35. float vOffset; // смещение V-координаты
  36. void BuildCombinedBuffers()
  37. {
  38. vbCombined_.DelAll();
  39. ibCombined_.DelAll();
  40. for (unsigned int i = 0; i < buildBuffer_.Size(); ++i)
  41. {
  42. unsigned int vtxCount = buildBuffer_[i].vb.Size();
  43. unsigned int indCount = buildBuffer_[i].ib.Size();
  44. unsigned int ibOffset = vbCombined_.Size();
  45. vbCombined_.SetAddElements(vtxCount);
  46. for (unsigned int j = 0; j < vtxCount; ++j)
  47. vbCombined_.Add(buildBuffer_[i].vb[j]);
  48. ibCombined_.SetAddElements(indCount);
  49. for (unsigned int j = 0; j < indCount; ++j)
  50. ibCombined_.Add(buildBuffer_[i].ib[j] + ibOffset);
  51. }
  52. }
  53. };
  54. ClothMeshBuilder::ClothMeshBuilder(NxPhysicsSDK* sdk) :
  55. internal_(NEW Data())
  56. {
  57. Assert(internal_);
  58. internal_->sdk_ = sdk;
  59. iRefCount = 1;
  60. }
  61. ClothMeshBuilder::~ClothMeshBuilder()
  62. {
  63. delete internal_;
  64. }
  65. void ClothMeshBuilder::AddRef()
  66. {
  67. iRefCount++;
  68. }
  69. bool ClothMeshBuilder::Release()
  70. {
  71. iRefCount--;
  72. if (iRefCount > 0) return false;
  73. ForceRelease();
  74. return true;
  75. }
  76. void ClothMeshBuilder::ForceRelease()
  77. {
  78. delete this;
  79. }
  80. // установить scale для генерации текстурных координат
  81. void ClothMeshBuilder::SetTexCoordScale(float uScale, float vScale)
  82. {
  83. internal_->uScale = uScale;
  84. internal_->vScale = vScale;
  85. }
  86. // установить offset для генерации текстурных координат
  87. void ClothMeshBuilder::SetTexCoordOffset(float uOffset, float vOffset)
  88. {
  89. internal_->uOffset = uOffset;
  90. internal_->vOffset = vOffset;
  91. }
  92. // создана ли ткань разрываемой
  93. bool ClothMeshBuilder::IsTearable() const
  94. {
  95. Assert(internal_->mesh_);
  96. return internal_->tearable_;
  97. }
  98. // готова ли сетка для PhysX
  99. bool ClothMeshBuilder::IsReady() const
  100. {
  101. return internal_->mesh_ != NULL;
  102. }
  103. // отдать сетку
  104. NxClothMesh& ClothMeshBuilder::GetMesh() const
  105. {
  106. Assert(internal_->mesh_);
  107. return *(internal_->mesh_);
  108. }
  109. inline float lerp(float a, float b, float t)
  110. {
  111. return a + (b-a)*t;
  112. }
  113. float smoothSquare(float a)
  114. {
  115. if (a > 1.0f) a = 1.0f;
  116. if (a < 0.0f) a = 0.0f;
  117. return -(2.0f*a-1.0f)*(2.0f*a-1.0f)+1.0f;
  118. }
  119. inline float smoothSin(float a) { return sinf(PI*a); }
  120. unsigned int ClothMeshBuilder::AddSail(const Vector vtx[4], unsigned int wDensity, unsigned int hDensity,
  121. float windCurvature, float bottomCurvature)
  122. {
  123. Vector pos, t1,t2;
  124. float cw, ch;
  125. Vertex v;
  126. float width = 0.0f;
  127. float height = 0.0f;
  128. float minY = 1e38f;
  129. float minX = 1e38f;
  130. for (unsigned int i = 0; i < 4; ++i)
  131. {
  132. if (minY > vtx[i].y)
  133. minY = vtx[i].y;
  134. if (minX > vtx[i].x)
  135. minX = vtx[i].x;
  136. if (abs(vtx[i].y - vtx[0].y) > height)
  137. height = abs(vtx[i].y - vtx[0].y);
  138. if (abs(vtx[i].x - vtx[0].x) > width)
  139. width = abs(vtx[i].x - vtx[0].x);
  140. }
  141. internal_->buildBuffer_.Add();
  142. array<Vertex>& vb = internal_->buildBuffer_[internal_->buildBuffer_.Last()].vb;
  143. array<unsigned short>& ib = internal_->buildBuffer_[internal_->buildBuffer_.Last()].ib;
  144. Vector vNormal = (vtx[1]-vtx[0]) ^ (vtx[2]-vtx[0]);
  145. vNormal.Normalize();
  146. for (unsigned int i = 0; i < hDensity; ++i)
  147. for (unsigned int j = 0; j < wDensity; ++j)
  148. {
  149. cw = j/(wDensity-1.0f);
  150. ch = i/(hDensity-1.0f);
  151. t1 = (vtx[3] - vtx[0])*ch + vtx[0];
  152. t2 = (vtx[2] - vtx[1])*ch + vtx[1];
  153. Vector vtmp = (t2 - t1)*cw + t1;
  154. //MOD: sail cooking tweak
  155. ////////////////////////////
  156. vtmp.y -= (minY + height);
  157. vtmp.y *= lerp(1.0f, bottomCurvature, smoothSquare((0.5f*width-abs(vtmp.x))/width));
  158. vtmp.y += (minY + height);
  159. //vtmp += vNormal * windCurvature*smoothSquare(abs((v.pos.y-minY))/height)*smoothSquare(abs((v.pos.x-minX))/width);
  160. vtmp += vNormal * windCurvature*smoothSquare(abs((vtmp.y-minY))/height)*smoothSquare(cw);
  161. //v.pos.z += windCurvature*smoothSquare(abs((v.pos.y-minY))/height)*smoothSquare(abs((v.pos.x-minX))/width);
  162. //v.pos.z += windCurvature*(smoothSin(abs((v.pos.y-minY))/height)*smoothSin(abs((v.pos.x-minX))/width));
  163. ////////////////////////////
  164. v.pos = vtmp;
  165. v.tu = internal_->uOffset + cw*internal_->uScale;
  166. v.tv = internal_->vOffset + ch*internal_->vScale;
  167. vb.Add(v);
  168. }
  169. for (unsigned int i = 0; i < hDensity-1; ++i)
  170. for (unsigned int j = 0; j < wDensity-1; ++j)
  171. {
  172. ib.Add(i*wDensity + j);
  173. ib.Add(i*wDensity + j + wDensity);
  174. ib.Add(i*wDensity + j + wDensity + 1);
  175. ib.Add(i*wDensity + j );
  176. ib.Add(i*wDensity + j + wDensity + 1);
  177. ib.Add(i*wDensity + j + 1);
  178. }
  179. return internal_->buildBuffer_.Last();
  180. }
  181. unsigned int ClothMeshBuilder::AddRope(const Vector& begin, const Vector& end, float thickness)
  182. {
  183. internal_->buildBuffer_.Add();
  184. array<Vertex>& vb = internal_->buildBuffer_[internal_->buildBuffer_.Last()].vb;
  185. array<unsigned short>& ib = internal_->buildBuffer_[internal_->buildBuffer_.Last()].ib;
  186. Matrix mtx;
  187. Vertex v;
  188. float ch,cw;
  189. Vector dir = (end-begin);
  190. float length = dir.Normalize();
  191. mtx.BuildOriented(begin, end, Vector(0,1,0));
  192. const unsigned int wDensity = 4;
  193. const unsigned int hDensity = 8;
  194. for (unsigned int i = 0; i < hDensity; ++i)
  195. for (unsigned int j = 0; j < wDensity; ++j)
  196. {
  197. cw = j/(float)(wDensity);
  198. ch = i/(float)(hDensity-1.0f);
  199. v.pos = Vector( 0.5f*thickness*cosf(2*PI*cw), 0.5f*thickness*sinf(2*PI*cw), length*ch);
  200. v.pos = mtx.MulVertex(v.pos);
  201. v.tu = internal_->uOffset + cw*internal_->uScale;
  202. v.tv = internal_->vOffset + ch*internal_->vScale;
  203. vb.Add(v);
  204. }
  205. for (unsigned int i = 0; i < hDensity-1; ++i)
  206. {
  207. for (unsigned int j = 0; j < wDensity-1; ++j)
  208. {
  209. ib.Add(i*wDensity + j);
  210. ib.Add(i*wDensity + j + wDensity);
  211. ib.Add(i*wDensity + j + wDensity + 1);
  212. ib.Add(i*wDensity + j );
  213. ib.Add(i*wDensity + j + wDensity + 1);
  214. ib.Add(i*wDensity + j + 1);
  215. }
  216. ib.Add(i*wDensity + wDensity-1 );
  217. ib.Add((i+1)*wDensity + wDensity-1);
  218. ib.Add((i+1)*wDensity);
  219. ib.Add(i*wDensity + wDensity-1 );
  220. ib.Add((i+1)*wDensity);
  221. ib.Add(i*wDensity);
  222. }
  223. // дополнительная наружная прошивка
  224. for (unsigned int i = 0; i < hDensity-1; ++i)
  225. {
  226. for (unsigned int j = 0; j < wDensity-1; ++j)
  227. {
  228. ib.Add(i*wDensity + j);
  229. ib.Add(i*wDensity + j + 1);
  230. ib.Add(i*wDensity + j + wDensity);
  231. ib.Add(i*wDensity + j + wDensity);
  232. ib.Add(i*wDensity + j + 1);
  233. ib.Add(i*wDensity + j + wDensity + 1);
  234. }
  235. ib.Add(i*wDensity + wDensity-1 );
  236. ib.Add(i*wDensity);
  237. ib.Add((i+1)*wDensity + wDensity-1);
  238. ib.Add(i*wDensity + wDensity-1 );
  239. ib.Add(i*wDensity);
  240. ib.Add((i+1)*wDensity);
  241. }
  242. return internal_->buildBuffer_.Last();
  243. }
  244. // добавить выпуклый 4-хугольник
  245. unsigned int ClothMeshBuilder::AddConvexQuadrangle(const Vector vtx[4], unsigned int wDensity, unsigned int hDensity)
  246. {
  247. Vector pos, t1,t2;
  248. float cw, ch;
  249. Vertex v;
  250. internal_->buildBuffer_.Add();
  251. array<Vertex>& vb = internal_->buildBuffer_[internal_->buildBuffer_.Last()].vb;
  252. array<unsigned short>& ib = internal_->buildBuffer_[internal_->buildBuffer_.Last()].ib;
  253. for (unsigned int i = 0; i < hDensity; ++i)
  254. for (unsigned int j = 0; j < wDensity; ++j)
  255. {
  256. cw = j/(wDensity-1.0f);
  257. ch = i/(hDensity-1.0f);
  258. t1 = (vtx[3] - vtx[0])*ch + vtx[0];
  259. t2 = (vtx[2] - vtx[1])*ch + vtx[1];
  260. v.pos = (t2 - t1)*cw + t1;
  261. v.tu = internal_->uOffset + cw*internal_->uScale;
  262. v.tv = internal_->vOffset + ch*internal_->vScale;
  263. vb.Add(v);
  264. }
  265. for (unsigned int i = 0; i < hDensity-1; ++i)
  266. for (unsigned int j = 0; j < wDensity-1; ++j)
  267. {
  268. ib.Add(i*wDensity + j);
  269. ib.Add(i*wDensity + j + wDensity);
  270. ib.Add(i*wDensity + j + wDensity + 1);
  271. ib.Add(i*wDensity + j );
  272. ib.Add(i*wDensity + j + wDensity + 1);
  273. ib.Add(i*wDensity + j + 1);
  274. }
  275. return internal_->buildBuffer_.Last();
  276. }
  277. // добавить 3-угольник
  278. unsigned int ClothMeshBuilder::AddTriangle(const Vector vtx[3], unsigned int density)
  279. {
  280. Vector pos, t1,t2;
  281. float cw, ch;
  282. Vertex v;
  283. internal_->buildBuffer_.Add();
  284. array<Vertex>& vb = internal_->buildBuffer_[internal_->buildBuffer_.Last()].vb;
  285. array<unsigned short>& ib = internal_->buildBuffer_[internal_->buildBuffer_.Last()].ib;
  286. for (unsigned int i = 0; i < density; ++i)
  287. for (unsigned int j = 0; j < i+1; ++j)
  288. {
  289. cw = 0.0f;
  290. if (i)
  291. cw = j/(float)i;
  292. ch = i/(density-1.0f);
  293. t1 = (vtx[2] - vtx[0])*ch + vtx[0];
  294. t2 = (vtx[1] - vtx[0])*ch + vtx[0];
  295. v.pos = (t2 - t1)*cw + t1;
  296. v.tu = internal_->uOffset + j/(density-1.0f)*internal_->uScale;
  297. v.tv = internal_->vOffset + ch*internal_->vScale;
  298. vb.Add(v);
  299. }
  300. unsigned int startIndex = 0;
  301. for (unsigned int i = 0; i < density-1; ++i)
  302. {
  303. for (unsigned int j = 0; j < 2*i+1; ++j)
  304. {
  305. if (j & 0x01)
  306. {
  307. ib.Add(startIndex + j/2);
  308. ib.Add(startIndex + j/2 + i + 2);
  309. ib.Add(startIndex + j/2 + 1);
  310. }
  311. else
  312. {
  313. ib.Add(startIndex + j/2);
  314. ib.Add(startIndex + j/2 + i + 1);
  315. ib.Add(startIndex + j/2 + i + 2);
  316. }
  317. }
  318. startIndex += i+1;
  319. }
  320. return internal_->buildBuffer_.Last();
  321. }
  322. // добавить прямоугольник
  323. unsigned int ClothMeshBuilder::AddRect(float width, float height, unsigned int wDensity, unsigned int hDensity, const Matrix& mtx)
  324. {
  325. Vector vtx[4] = { Vector(-width/2, -height/2, 0.0f),
  326. Vector(width/2, -height/2, 0.0f),
  327. Vector(width/2, height/2, 0.0f),
  328. Vector(-width/2, height/2, 0.0f) };
  329. for (unsigned int i = 0; i < sizeof(vtx)/sizeof(vtx[0]); ++i)
  330. vtx[i] = mtx.MulVertex(vtx[i]);
  331. return AddConvexQuadrangle(vtx, wDensity, hDensity);
  332. }
  333. // добавить окружность
  334. unsigned int ClothMeshBuilder::AddCircle(const Matrix& mtx, float radius, unsigned int rDensity, unsigned int aDensity)
  335. {
  336. Assert(!"Not implemented");
  337. return 0xFFFFFFFF;
  338. }
  339. // добавить цилиндр
  340. unsigned int ClothMeshBuilder::AddCylinder(float height, float radius, unsigned int wDensity, unsigned int hDensity, const Matrix& mtx)
  341. {
  342. Vector pos;
  343. float cw, ch;
  344. Vertex v;
  345. internal_->buildBuffer_.Add();
  346. array<Vertex>& vb = internal_->buildBuffer_[internal_->buildBuffer_.Last()].vb;
  347. array<unsigned short>& ib = internal_->buildBuffer_[internal_->buildBuffer_.Last()].ib;
  348. for (unsigned int i = 0; i < hDensity; ++i)
  349. for (unsigned int j = 0; j < wDensity; ++j)
  350. {
  351. cw = j/(float)(wDensity);
  352. ch = i/(float)(hDensity-1.0f);
  353. v.pos = Vector( radius*cosf(2*PI*cw), height*ch, radius*sinf(2*PI*cw));
  354. v.pos = mtx.MulVertex(v.pos);
  355. v.tu = internal_->uOffset + cw*internal_->uScale;
  356. v.tv = internal_->vOffset + ch*internal_->vScale;
  357. vb.Add(v);
  358. }
  359. for (unsigned int i = 0; i < hDensity-1; ++i)
  360. {
  361. for (unsigned int j = 0; j < wDensity-1; ++j)
  362. {
  363. ib.Add(i*wDensity + j);
  364. ib.Add(i*wDensity + j + wDensity);
  365. ib.Add(i*wDensity + j + wDensity + 1);
  366. ib.Add(i*wDensity + j );
  367. ib.Add(i*wDensity + j + wDensity + 1);
  368. ib.Add(i*wDensity + j + 1);
  369. }
  370. ib.Add(i*wDensity + wDensity-1 );
  371. ib.Add((i+1)*wDensity + wDensity-1);
  372. ib.Add((i+1)*wDensity);
  373. ib.Add(i*wDensity + wDensity-1 );
  374. ib.Add((i+1)*wDensity);
  375. ib.Add(i*wDensity);
  376. }
  377. return internal_->buildBuffer_.Last();
  378. }
  379. // добавить произвольную сетку
  380. unsigned int ClothMeshBuilder::AddMesh(const array<Vector>& vb, const array<unsigned short>& ib, const Matrix& mtx)
  381. {
  382. Assert(!"Not implemented");
  383. return 0xFFFFFFFF;
  384. }
  385. // создать соединение между кусками
  386. unsigned int ClothMeshBuilder::Connect(unsigned int index1, unsigned int index2, const Vector& pos)
  387. {
  388. Assert(index1 < internal_->buildBuffer_.Size());
  389. Assert(index2 < internal_->buildBuffer_.Size());
  390. // 1) ищем по 2 ближайшие к pos вершины в каждой сетке
  391. float minDist = FLT_MAX;
  392. float dist;
  393. unsigned int minIndex11 = 0, minIndex12 = 0; // индексы 2-х ближайших вершин 1-й сетки
  394. for (unsigned int i = 0; i < internal_->buildBuffer_[index1].vb.Size(); ++i)
  395. {
  396. dist = (pos-internal_->buildBuffer_[index1].vb[i].pos).GetLength();
  397. if ( minDist > dist )
  398. {
  399. minDist = dist;
  400. minIndex11 = i;
  401. }
  402. }
  403. minDist = FLT_MAX;
  404. for (unsigned int i = 0; i < internal_->buildBuffer_[index1].vb.Size(); ++i)
  405. {
  406. dist = (pos-internal_->buildBuffer_[index1].vb[i].pos).GetLength();
  407. if ( minDist > dist && i != minIndex11)
  408. {
  409. minDist = dist;
  410. minIndex12 = i;
  411. }
  412. }
  413. minDist = FLT_MAX;
  414. unsigned int minIndex21 = 0, minIndex22 = 0; // индексы 2-х ближайших вершин 2-й сетки
  415. for (unsigned int i = 0; i < internal_->buildBuffer_[index2].vb.Size(); ++i)
  416. {
  417. dist = (pos-internal_->buildBuffer_[index2].vb[i].pos).GetLength();
  418. if ( minDist > dist )
  419. {
  420. minDist = dist;
  421. minIndex21 = i;
  422. }
  423. }
  424. minDist = FLT_MAX;
  425. for (unsigned int i = 0; i < internal_->buildBuffer_[index2].vb.Size(); ++i)
  426. {
  427. dist = (pos-internal_->buildBuffer_[index2].vb[i].pos).GetLength();
  428. if ( minDist > dist && i != minIndex21)
  429. {
  430. minDist = dist;
  431. minIndex22 = i;
  432. }
  433. }
  434. // 2) сливаем сетки в одну
  435. internal_->buildBuffer_.Add();
  436. array<Vertex>& vb = internal_->buildBuffer_[internal_->buildBuffer_.Last()].vb;
  437. array<unsigned short>& ib = internal_->buildBuffer_[internal_->buildBuffer_.Last()].ib;
  438. vb = internal_->buildBuffer_[index1].vb;
  439. ib = internal_->buildBuffer_[index1].ib;
  440. unsigned int offset = vb.Size();
  441. for (unsigned int i = 0; i < internal_->buildBuffer_[index2].vb.Size(); ++i)
  442. vb.Add(internal_->buildBuffer_[index2].vb[i]);
  443. for (unsigned int i = 0; i < internal_->buildBuffer_[index2].ib.Size(); ++i)
  444. ib.Add(internal_->buildBuffer_[index2].ib[i] + offset);
  445. // 3) добавляем в новую сетку квад, соединяющий части
  446. ib.Add(minIndex11);
  447. ib.Add(minIndex12);
  448. ib.Add(minIndex21 + offset);
  449. ib.Add(minIndex12);
  450. ib.Add(minIndex21 + offset);
  451. ib.Add(minIndex22 + offset);
  452. // 4) чистим старые сетки
  453. internal_->buildBuffer_[index1].vb.DelAll();
  454. internal_->buildBuffer_[index1].ib.DelAll();
  455. internal_->buildBuffer_[index2].vb.DelAll();
  456. internal_->buildBuffer_[index2].ib.DelAll();
  457. // 5) даем индекс новой сетки
  458. return internal_->buildBuffer_.Last();
  459. }
  460. bool Cook(NxClothMeshDesc& desc, NxPlatform target, PhysicsService::MemoryWriteStream& wb)
  461. {
  462. NxCookingParams params;
  463. params.targetPlatform = target;
  464. NxSetCookingParams(params);
  465. if (!NxCookClothMesh(desc, wb))
  466. return false;
  467. return true;
  468. }
  469. // построить сетку для PhysX
  470. bool ClothMeshBuilder::Build(IPhysicsScene& scene, bool isTearable, IMission* mission, const char* fileName)
  471. {
  472. internal_->tearable_ = isTearable;
  473. if ( internal_->mesh_ )
  474. {
  475. internal_->sdk_->releaseClothMesh(*(internal_->mesh_));
  476. internal_->mesh_ = NULL;
  477. }
  478. NxClothMeshDesc desc;
  479. desc.flags = 0;
  480. if (isTearable)
  481. desc.flags |= NX_CLOTH_MESH_TEARABLE;
  482. internal_->BuildCombinedBuffers();
  483. desc.numTriangles = internal_->ibCombined_.Size()/3;
  484. desc.numVertices = internal_->vbCombined_.Size();
  485. desc.points = &internal_->vbCombined_[0];
  486. desc.pointStrideBytes = sizeof(internal_->vbCombined_[0]);
  487. desc.triangles = &internal_->ibCombined_[0];
  488. desc.triangleStrideBytes = sizeof(internal_->ibCombined_[0])*3;
  489. desc.flags |= NX_MF_16_BIT_INDICES;
  490. desc.vertexFlags = 0;
  491. desc.vertexMasses = 0;
  492. desc.vertexMassStrideBytes = 0;
  493. Assert(sizeof(internal_->ibCombined_[0]) == 2);
  494. PhysicsService::MemoryWriteStream wbPC;
  495. PhysicsService::MemoryWriteStream wbXBOX;
  496. MOSafePointerType<CookBinManager> binMgr;
  497. //CookBinManager* binMgr = NULL;
  498. static const ConstString objName("CookBinManager");
  499. if (mission)
  500. (CookBinManager*)mission->CreateObject(binMgr.GetSPObject(), "CookBinManager", objName);
  501. #ifndef _XBOX
  502. bool bSuccessCook = true;
  503. if( Cook(desc, PLATFORM_PC, wbPC) )
  504. {
  505. if (binMgr.Validate())
  506. binMgr.Ptr()->SaveCookedMesh(fileName, wbPC.Pointer(), wbPC.Size());
  507. }
  508. else
  509. {
  510. bSuccessCook = false;
  511. api->Trace("ClothMeshBuilder::Build() Error! Cook for PC failed!");
  512. }
  513. if( Cook(desc, PLATFORM_XENON, wbXBOX) )
  514. {
  515. if (binMgr.Validate())
  516. binMgr.Ptr()->SaveCookedMesh(string("x360_")+fileName, wbXBOX.Pointer(), wbXBOX.Size());
  517. }
  518. else
  519. {
  520. bSuccessCook = false;
  521. api->Trace("ClothMeshBuilder::Build() Error! Cook for XBox failed!");
  522. }
  523. if( bSuccessCook )
  524. {
  525. PhysicsService::MemoryReadStream rb(wbPC.Pointer(), wbPC.Size());
  526. internal_->mesh_ = internal_->sdk_->createClothMesh(rb);
  527. }
  528. /*#else // на XBox не бум ничего сами строить - должны быть скукенные уже.
  529. Cook(desc, PLATFORM_XENON, wbXBOX);
  530. PhysicsService::MemoryReadStream rb(wbXBOX.Pointer(), wbXBOX.Size());
  531. internal_->mesh_ = internal_->sdk_->createClothMesh(rb);*/
  532. #endif
  533. return internal_->mesh_ != NULL;
  534. }
  535. // построить сетку для PhysX из бинарного файла
  536. bool ClothMeshBuilder::Load(IPhysicsScene& scene, IMission& mission, const char* fileName)
  537. {
  538. internal_->BuildCombinedBuffers();
  539. IFileService * fileSrv = (IFileService *)api->GetService("FileService");
  540. dword fileSize = 0;
  541. MOSafePointerType<CookBinManager> binMgr;
  542. static const ConstString objName("CookBinManager");
  543. mission.CreateObject(binMgr.GetSPObject(), "CookBinManager", objName);
  544. const void * pData = NULL;
  545. #ifdef _XBOX
  546. if (binMgr.Validate())
  547. binMgr.Ptr()->LoadCookedMesh(string("x360_") + fileName, pData, fileSize);
  548. #else
  549. if (binMgr.Validate())
  550. binMgr.Ptr()->LoadCookedMesh(fileName, pData, fileSize);
  551. #endif
  552. if(!pData) return false;
  553. PhysicsService::MemoryReadStream rb(pData, fileSize);
  554. internal_->mesh_ = internal_->sdk_->createClothMesh(rb);
  555. return internal_->mesh_ != NULL;
  556. }
  557. // вернуть скомбинированные буферы индексов и вершин
  558. void ClothMeshBuilder::GetCombinedBuffers(const Vertex*& vb, const unsigned short*& ib, unsigned int& vCount, unsigned int& iCount) const
  559. {
  560. vb = &internal_->vbCombined_[0];
  561. ib = &internal_->ibCombined_[0];
  562. vCount = internal_->vbCombined_.Size();
  563. iCount = internal_->ibCombined_.Size();
  564. }
  565. // почистить временные данные (оставить только скуканый меш)
  566. void ClothMeshBuilder::FreeBuildData()
  567. {
  568. internal_->buildBuffer_.DelAll();
  569. internal_->vbCombined_.DelAll();
  570. internal_->ibCombined_.DelAll();
  571. }
  572. // очистить внутреннее состояние
  573. void ClothMeshBuilder::Reset()
  574. {
  575. if (internal_)
  576. delete internal_, internal_ = NULL;
  577. internal_ = NEW Data();
  578. }