PageRenderTime 72ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/CS/migrated/branches/NEW_SHADERSYS/apps/tools/levtool/levtool.cpp

#
C++ | 2227 lines | 1984 code | 173 blank | 70 comment | 412 complexity | bd701f863df7190e32759955c568f4bb MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, LGPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. Copyright (C) 2002 by Jorrit Tyberghein
  3. This library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Library General Public
  5. License as published by the Free Software Foundation; either
  6. version 2 of the License, or (at your option) any later version.
  7. This library is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. Library General Public License for more details.
  11. You should have received a copy of the GNU Library General Public
  12. License along with this library; if not, write to the Free
  13. Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  14. */
  15. #include <stdarg.h>
  16. #include "cssysdef.h"
  17. #include "levtool.h"
  18. #include "csgeom/math3d.h"
  19. #include "csgeom/plane3.h"
  20. #include "csutil/util.h"
  21. #include "csutil/xmltiny.h"
  22. #include "csutil/csstring.h"
  23. #include "iutil/objreg.h"
  24. #include "iutil/plugin.h"
  25. #include "iutil/vfs.h"
  26. #include "iutil/cmdline.h"
  27. #include "iutil/document.h"
  28. #include "cstool/initapp.h"
  29. #include "ivaria/reporter.h"
  30. //-----------------------------------------------------------------------------
  31. CS_IMPLEMENT_APPLICATION
  32. //-----------------------------------------------------------------------------
  33. #define OP_HELP 0
  34. #define OP_LIST 1
  35. #define OP_DYNAVIS 2
  36. #define OP_VALIDATE 3
  37. #define OP_SPLITUNIT 4
  38. #define OP_SPLITGEOM 5
  39. #define OP_COMPRESS 7
  40. #define OP_ANALYZE 8
  41. #define OP_FLAGCLEAR 10
  42. #define OP_FLAGGOOD 11
  43. #define OP_FLAGBAD 12
  44. #define OP_TRANSLATE 13
  45. #define OP_PLANES 14
  46. //-----------------------------------------------------------------------------
  47. void LevTool::ReportError (const char* description, ...)
  48. {
  49. va_list arg;
  50. va_start (arg, description);
  51. csReportV (object_reg, CS_REPORTER_SEVERITY_ERROR,
  52. "crystalspace.apps.levtool", description, arg);
  53. va_end (arg);
  54. }
  55. void LevTool::Report (int severity, const char* description, ...)
  56. {
  57. va_list arg;
  58. va_start (arg, description);
  59. csReportV (object_reg, severity,
  60. "crystalspace.apps.levtool", description, arg);
  61. va_end (arg);
  62. }
  63. //-----------------------------------------------------------------------------
  64. ltVertex::ltVertex ()
  65. {
  66. polygons = 0;
  67. num_polygons = 0;
  68. max_polygons = 0;
  69. }
  70. ltVertex::ltVertex (const ltVertex& vt) : csVector3 (vt.x, vt.y, vt.z)
  71. {
  72. if (vt.max_polygons > 0)
  73. {
  74. polygons = new int [vt.max_polygons];
  75. num_polygons = vt.num_polygons;
  76. max_polygons = vt.max_polygons;
  77. memcpy (polygons, vt.polygons, sizeof (int)*num_polygons);
  78. }
  79. else
  80. {
  81. max_polygons = num_polygons = 0;
  82. polygons = 0;
  83. }
  84. }
  85. ltVertex::~ltVertex ()
  86. {
  87. delete[] polygons;
  88. }
  89. void ltVertex::AddPolygon (int idx)
  90. {
  91. if (num_polygons >= max_polygons)
  92. {
  93. max_polygons += 4;
  94. int* new_poly = new int [max_polygons];
  95. if (num_polygons > 0)
  96. {
  97. memcpy (new_poly, polygons, sizeof (int) * num_polygons);
  98. }
  99. delete[] polygons;
  100. polygons = new_poly;
  101. }
  102. polygons[num_polygons++] = idx;
  103. }
  104. //-----------------------------------------------------------------------------
  105. ltPolygon::ltPolygon (iDocumentNode* polynode)
  106. {
  107. name = 0;
  108. num_vertices = 0;
  109. max_vertices = 0;
  110. vertices = 0;
  111. ltPolygon::polynode = polynode;
  112. }
  113. ltPolygon::~ltPolygon ()
  114. {
  115. delete[] name;
  116. delete[] vertices;
  117. }
  118. void ltPolygon::AddVertex (int idx)
  119. {
  120. if (num_vertices >= max_vertices)
  121. {
  122. max_vertices += 4;
  123. int* new_verts = new int [max_vertices];
  124. if (num_vertices > 0)
  125. {
  126. memcpy (new_verts, vertices, sizeof (int) * num_vertices);
  127. }
  128. delete[] vertices;
  129. vertices = new_verts;
  130. }
  131. vertices[num_vertices++] = idx;
  132. }
  133. void ltPolygon::SetName (const char* name)
  134. {
  135. delete[] ltPolygon::name;
  136. ltPolygon::name = name ? csStrNew (name) : 0;
  137. }
  138. void ltPolygon::RemoveDuplicateVertices ()
  139. {
  140. int i;
  141. int i1 = num_vertices-1;
  142. for (i = 0 ; i < num_vertices ; )
  143. {
  144. if (vertices[i1] == vertices[i])
  145. {
  146. if (i < num_vertices-1)
  147. memmove (vertices+i, vertices+i+1, (num_vertices-i-1) * sizeof (int));
  148. num_vertices--;
  149. }
  150. else
  151. {
  152. i1 = i;
  153. i++;
  154. }
  155. }
  156. }
  157. //-----------------------------------------------------------------------------
  158. ltThing::ltThing (iDocumentNode* meshnode, iDocumentNode* partnode)
  159. {
  160. name = 0;
  161. vertices = 0;
  162. num_vertices = 0;
  163. max_vertices = 0;
  164. polygons = 0;
  165. num_polygons = 0;
  166. max_polygons = 0;
  167. ltThing::meshnode = meshnode;
  168. ltThing::partnode = partnode;
  169. }
  170. ltThing::~ltThing ()
  171. {
  172. delete[] name;
  173. int i;
  174. for (i = 0 ; i < num_polygons ; i++)
  175. {
  176. delete polygons[i];
  177. }
  178. delete[] polygons;
  179. for (i = 0 ; i < num_vertices ; i++)
  180. {
  181. delete vertices[i];
  182. }
  183. delete[] vertices;
  184. }
  185. void ltThing::AddVertex (const csVector3& vt)
  186. {
  187. if (num_vertices >= max_vertices)
  188. {
  189. if (max_vertices < 10000)
  190. max_vertices += max_vertices+2;
  191. else
  192. max_vertices += 10000;
  193. ltVertex** new_verts = new ltVertex* [max_vertices];
  194. if (num_vertices > 0)
  195. {
  196. memcpy (new_verts, vertices, sizeof (ltVertex*) * num_vertices);
  197. }
  198. delete[] vertices;
  199. vertices = new_verts;
  200. }
  201. vertices[num_vertices] = new ltVertex ();
  202. vertices[num_vertices++]->Set (vt);
  203. }
  204. ltPolygon* ltThing::AddPolygon (iDocumentNode* polynode)
  205. {
  206. if (num_polygons >= max_polygons)
  207. {
  208. if (max_polygons < 1000)
  209. max_polygons += max_polygons+2;
  210. else
  211. max_polygons += 1000;
  212. ltPolygon** new_poly = new ltPolygon* [max_polygons];
  213. if (num_polygons > 0)
  214. {
  215. memcpy (new_poly, polygons, sizeof (ltPolygon*) * num_polygons);
  216. }
  217. delete[] polygons;
  218. polygons = new_poly;
  219. }
  220. ltPolygon* np = new ltPolygon (polynode);
  221. polygons[num_polygons++] = np;
  222. const char* name = polynode->GetAttributeValue ("name");
  223. if (name) np->SetName (name);
  224. return np;
  225. }
  226. void ltThing::SetName (const char* name)
  227. {
  228. delete[] ltThing::name;
  229. ltThing::name = name ? csStrNew (name) : 0;
  230. }
  231. struct CompressVertex
  232. {
  233. int orig_idx;
  234. float x, y, z;
  235. int new_idx;
  236. bool used;
  237. };
  238. static int compare_vt (const void *p1, const void *p2)
  239. {
  240. CompressVertex *sp1 = (CompressVertex *)p1;
  241. CompressVertex *sp2 = (CompressVertex *)p2;
  242. if (sp1->x < sp2->x)
  243. return -1;
  244. else if (sp1->x > sp2->x)
  245. return 1;
  246. if (sp1->y < sp2->y)
  247. return -1;
  248. else if (sp1->y > sp2->y)
  249. return 1;
  250. if (sp1->z < sp2->z)
  251. return -1;
  252. else if (sp1->z > sp2->z)
  253. return 1;
  254. return 0;
  255. }
  256. static int compare_vt_orig (const void *p1, const void *p2)
  257. {
  258. CompressVertex *sp1 = (CompressVertex *)p1;
  259. CompressVertex *sp2 = (CompressVertex *)p2;
  260. if (sp1->orig_idx < sp2->orig_idx)
  261. return -1;
  262. else if (sp1->orig_idx > sp2->orig_idx)
  263. return 1;
  264. return 0;
  265. }
  266. void ltThing::CompressVertices ()
  267. {
  268. if (num_vertices <= 0) return ;
  269. // Copy all the vertices.
  270. CompressVertex *vt = new CompressVertex[num_vertices];
  271. int i, j;
  272. for (i = 0; i < num_vertices; i++)
  273. {
  274. vt[i].orig_idx = i;
  275. vt[i].x = (float)ceil (vertices[i]->x * 1000000);
  276. vt[i].y = (float)ceil (vertices[i]->y * 1000000);
  277. vt[i].z = (float)ceil (vertices[i]->z * 1000000);
  278. }
  279. // First sort so that all (nearly) equal vertices are together.
  280. qsort (vt, num_vertices, sizeof (CompressVertex), compare_vt);
  281. // Count unique values and tag all doubles with the index of the unique one.
  282. // new_idx in the vt table will be the index inside vt to the unique vector.
  283. int count_unique = 1;
  284. int last_unique = 0;
  285. vt[0].new_idx = last_unique;
  286. for (i = 1; i < num_vertices; i++)
  287. {
  288. if (
  289. vt[i].x != vt[last_unique].x ||
  290. vt[i].y != vt[last_unique].y ||
  291. vt[i].z != vt[last_unique].z)
  292. {
  293. last_unique = i;
  294. count_unique++;
  295. }
  296. vt[i].new_idx = last_unique;
  297. }
  298. // If count_unique == num_vertices then there is nothing to do.
  299. if (count_unique == num_vertices)
  300. {
  301. delete[] vt;
  302. return ;
  303. }
  304. // Now allocate and fill new vertex tables.
  305. // After this new_idx in the vt table will be the new index
  306. // of the vector.
  307. ltVertex **new_obj = new ltVertex*[count_unique];
  308. memset (new_obj, 0, sizeof (ltVertex*)*count_unique);
  309. new_obj[0] = new ltVertex (*vertices[vt[0].orig_idx]);
  310. vt[0].new_idx = 0;
  311. j = 1;
  312. for (i = 1; i < num_vertices; i++)
  313. {
  314. if (vt[i].new_idx == i)
  315. {
  316. new_obj[j] = new ltVertex (*vertices[vt[i].orig_idx]);
  317. vt[i].new_idx = j;
  318. j++;
  319. }
  320. else
  321. vt[i].new_idx = j - 1;
  322. }
  323. // Now we sort the table back on orig_idx so that we have
  324. // a mapping from the original indices to the new one (new_idx).
  325. qsort (vt, num_vertices, sizeof (CompressVertex), compare_vt_orig);
  326. // Replace the old vertex tables.
  327. for (i = 0 ; i < num_vertices ; i++)
  328. {
  329. delete vertices[i];
  330. }
  331. delete[] vertices;
  332. vertices = new_obj;
  333. num_vertices = max_vertices = count_unique;
  334. // Now we can remap the vertices in all polygons.
  335. for (i = 0 ; i < num_polygons ; i++)
  336. {
  337. ltPolygon *p = polygons[i];
  338. int *idx = p->GetVertexIndices ();
  339. for (j = 0 ; j < p->GetVertexCount () ; j++)
  340. idx[j] = vt[idx[j]].new_idx;
  341. }
  342. delete[] vt;
  343. }
  344. void ltThing::RemoveUnusedVertices ()
  345. {
  346. if (num_vertices <= 0) return ;
  347. // Copy all the vertices that are actually used by polygons.
  348. bool *used = new bool[num_vertices];
  349. int i, j;
  350. for (i = 0; i < num_vertices; i++) used[i] = false;
  351. // Mark all vertices that are used as used.
  352. for (i = 0 ; i < num_polygons ; i++)
  353. {
  354. ltPolygon *p = polygons[i];
  355. int *idx = p->GetVertexIndices ();
  356. for (j = 0 ; j < p->GetVertexCount () ; j++) used[idx[j]] = true;
  357. }
  358. // Count relevant values.
  359. int count_relevant = 0;
  360. for (i = 0; i < num_vertices; i++)
  361. {
  362. if (used[i]) count_relevant++;
  363. }
  364. // If all vertices are relevant then there is nothing to do.
  365. if (count_relevant == num_vertices)
  366. {
  367. delete[] used;
  368. return ;
  369. }
  370. // Now allocate and fill new vertex tables.
  371. // Also fill the 'relocate' table.
  372. ltVertex **new_obj = new ltVertex*[count_relevant];
  373. memset (new_obj, 0, sizeof (ltVertex*)*count_relevant);
  374. int *relocate = new int[num_vertices];
  375. j = 0;
  376. for (i = 0; i < num_vertices; i++)
  377. {
  378. if (used[i])
  379. {
  380. new_obj[j] = new ltVertex (*vertices[i]);
  381. relocate[i] = j;
  382. j++;
  383. }
  384. else
  385. relocate[i] = -1;
  386. }
  387. // Replace the old vertex tables.
  388. for (i = 0 ; i < num_vertices ; i++)
  389. {
  390. delete vertices[i];
  391. }
  392. delete[] vertices;
  393. vertices = new_obj;
  394. num_vertices = max_vertices = count_relevant;
  395. // Now we can remap the vertices in all polygons.
  396. for (i = 0 ; i < num_polygons ; i++)
  397. {
  398. ltPolygon *p = polygons[i];
  399. int *idx = p->GetVertexIndices ();
  400. for (j = 0 ; j < p->GetVertexCount () ; j++) idx[j] = relocate[idx[j]];
  401. }
  402. delete[] relocate;
  403. delete[] used;
  404. }
  405. void ltThing::RemoveDuplicateVertices ()
  406. {
  407. int i;
  408. for (i = 0 ; i < num_polygons ; i++)
  409. {
  410. ltPolygon* p = polygons[i];
  411. p->RemoveDuplicateVertices ();
  412. }
  413. }
  414. void ltThing::CreateBoundingBox ()
  415. {
  416. if (num_vertices <= 0) return;
  417. int i;
  418. bbox.Set (*vertices[0], *vertices[0]);
  419. for (i = 1 ; i < num_vertices ; i++)
  420. bbox.AddBoundingVertexSmart (*vertices[i]);
  421. }
  422. void ltThing::CreateVertexInfo ()
  423. {
  424. int i, j;
  425. for (i = 0 ; i < num_polygons ; i++)
  426. {
  427. ltPolygon* p = polygons[i];
  428. for (j = 0 ; j < p->GetVertexCount () ; j++)
  429. {
  430. ltVertex* v = vertices[p->GetVertex (j)];
  431. v->AddPolygon (i);
  432. }
  433. }
  434. }
  435. void ltThing::PaintConnectedPolygons (ltPolygon* sweep, int obj_number)
  436. {
  437. if (sweep->GetObjectNumber () != -1)
  438. {
  439. CS_ASSERT (sweep->GetObjectNumber () == obj_number);
  440. return;
  441. }
  442. sweep->SetObjectNumber (obj_number);
  443. int i;
  444. for (i = 0 ; i < sweep->GetVertexCount () ; i++)
  445. {
  446. int vtidx = sweep->GetVertex (i);
  447. ltVertex& vt = GetVertex (vtidx);
  448. if (vt.GetObjectNumber () == -1)
  449. {
  450. vt.SetObjectNumber (obj_number);
  451. }
  452. CS_ASSERT (vt.GetObjectNumber () == obj_number);
  453. int j;
  454. for (j = 0 ; j < vt.GetPolygonCount () ; j++)
  455. {
  456. int ptidx = vt.GetPolygon (j);
  457. ltPolygon* p = GetPolygon (ptidx);
  458. PaintConnectedPolygons (p, obj_number);
  459. }
  460. }
  461. }
  462. void ltThing::SplitThingInCenter ()
  463. {
  464. const csVector3& center = bbox.GetCenter ();
  465. max_obj_number = 7;
  466. int i, j;
  467. for (i = 0 ; i < num_polygons ; i++)
  468. {
  469. ltPolygon* p = polygons[i];
  470. int where = 0;
  471. for (j = 0 ; j < p->GetVertexCount () ; j++)
  472. {
  473. ltVertex* vt = vertices[p->GetVertex (j)];
  474. if (vt->x < center.x) where |= 1;
  475. if (vt->y < center.y) where |= 2;
  476. if (vt->z < center.z) where |= 4;
  477. }
  478. p->SetObjectNumber (where);
  479. for (j = 0 ; j < p->GetVertexCount () ; j++)
  480. {
  481. ltVertex* vt = vertices[p->GetVertex (j)];
  482. vt->SetObjectNumber (where);
  483. }
  484. }
  485. }
  486. void ltThing::SplitThingSeparateUnits ()
  487. {
  488. max_obj_number = -1;
  489. int i;
  490. for (i = 0 ; i < num_polygons ; i++)
  491. {
  492. ltPolygon* p = polygons[i];
  493. p->SetObjectNumber (-1);
  494. }
  495. for (i = 0 ; i < num_vertices ; i++)
  496. {
  497. vertices[i]->SetObjectNumber (-1);
  498. }
  499. while (true)
  500. {
  501. ltPolygon* sweep = 0;
  502. for (i = 0 ; i < num_polygons ; i++)
  503. {
  504. ltPolygon* p = polygons[i];
  505. if (p->GetObjectNumber () == -1)
  506. {
  507. sweep = p;
  508. break;
  509. }
  510. }
  511. if (!sweep) break;
  512. max_obj_number++;
  513. PaintConnectedPolygons (sweep, max_obj_number);
  514. }
  515. printf ("Found %d sub-objects\n", max_obj_number); fflush (stdout);
  516. }
  517. void ltThing::DoNotSplitThingSeparateUnits ()
  518. {
  519. max_obj_number = 0;
  520. int i;
  521. for (i = 0 ; i < num_polygons ; i++)
  522. {
  523. ltPolygon* p = polygons[i];
  524. p->SetObjectNumber (0);
  525. }
  526. for (i = 0 ; i < num_vertices ; i++)
  527. {
  528. vertices[i]->SetObjectNumber (0);
  529. }
  530. }
  531. int* ltThing::CreateUnitMapping (int obj_number)
  532. {
  533. int* map = new int [num_vertices];
  534. int new_i = 0;
  535. int i;
  536. for (i = 0 ; i < num_vertices ; i++)
  537. {
  538. ltVertex* vt = vertices[i];
  539. if (vt->GetObjectNumber () == obj_number)
  540. {
  541. map[i] = new_i;
  542. new_i++;
  543. }
  544. else
  545. {
  546. map[i] = -1;
  547. }
  548. }
  549. return map;
  550. }
  551. void ltThing::DuplicateSharedVertices ()
  552. {
  553. int i;
  554. int total_vt = 0;
  555. for (i = 0 ; i < num_polygons ; i++)
  556. {
  557. total_vt += polygons[i]->GetVertexCount ();
  558. }
  559. ltVertex** new_vt = new ltVertex* [total_vt];
  560. int vt_idx = 0;
  561. for (i = 0 ; i < num_polygons ; i++)
  562. {
  563. ltPolygon* p = polygons[i];
  564. int* idx = p->GetVertexIndices ();
  565. int j;
  566. for (j = 0 ; j < p->GetVertexCount () ; j++)
  567. {
  568. new_vt[vt_idx] = new ltVertex ();
  569. new_vt[vt_idx]->Set ((const csVector3&) *vertices[idx[j]]);
  570. idx[j] = vt_idx;
  571. vt_idx++;
  572. }
  573. }
  574. CS_ASSERT (total_vt == vt_idx);
  575. delete[] vertices;
  576. vertices = new_vt;
  577. num_vertices = max_vertices = total_vt;
  578. }
  579. //-----------------------------------------------------------------------------
  580. bool LevTool::TestValidXML (iDocument* doc)
  581. {
  582. csRef<iDocumentNode> root = doc->GetRoot ();
  583. csRef<iDocumentNode> worldnode = root->GetNode ("world");
  584. if (!worldnode)
  585. {
  586. ReportError ("The <world> node seems to be missing!");
  587. return false;
  588. }
  589. csRef<iDocumentNode> sector = worldnode->GetNode ("sector");
  590. if (!sector)
  591. {
  592. ReportError ("There appear to be no sectors in this world!");
  593. return false;
  594. }
  595. return true;
  596. }
  597. void LevTool::AnalyzePluginSection (iDocument* doc, bool meshfacts)
  598. {
  599. thing_plugins.Push (new csString ("crystalspace.mesh.loader.thing"));
  600. if (meshfacts)
  601. thing_plugins.Push (
  602. new csString ("crystalspace.mesh.loader.factory.thing"));
  603. plane_plugins.Push (new csString ("crystalspace.mesh.loader.thing.plane"));
  604. csRef<iDocumentNode> root = doc->GetRoot ();
  605. csRef<iDocumentNode> worldnode = root->GetNode ("world");
  606. csRef<iDocumentNode> pluginsnode = worldnode->GetNode ("plugins");
  607. if (pluginsnode)
  608. {
  609. csRef<iDocumentNodeIterator> it = pluginsnode->GetNodes ();
  610. while (it->HasNext ())
  611. {
  612. csRef<iDocumentNode> child = it->Next ();
  613. if (child->GetType () != CS_NODE_ELEMENT) continue;
  614. const char* value = child->GetValue ();
  615. if (!strcmp (value, "plugin"))
  616. {
  617. const char* plugname = child->GetContentsValue ();
  618. if (plugname && !strcmp (plugname, "crystalspace.mesh.loader.thing"))
  619. {
  620. thing_plugins.Push (new csString (child->GetAttributeValue ("name")));
  621. }
  622. else if (meshfacts && plugname &&
  623. !strcmp (plugname, "crystalspace.mesh.loader.factory.thing"))
  624. {
  625. thing_plugins.Push (new csString (child->GetAttributeValue ("name")));
  626. }
  627. else if (plugname &&
  628. !strcmp (plugname, "crystalspace.mesh.loader.thing.plane"))
  629. {
  630. plane_plugins.Push (new csString (child->GetAttributeValue ("name")));
  631. }
  632. }
  633. }
  634. }
  635. }
  636. bool LevTool::IsAddonAPlane (iDocumentNode* addonnode)
  637. {
  638. csRef<iDocumentNode> pluginnode = addonnode->GetNode ("plugin");
  639. if (!pluginnode)
  640. {
  641. // Very weird. Should not happen.
  642. return false;
  643. }
  644. const char* plugname = pluginnode->GetContentsValue ();
  645. if (!plugname)
  646. {
  647. // Very weird. Should not happen.
  648. return false;
  649. }
  650. int i;
  651. for (i = 0 ; i < plane_plugins.Length () ; i++)
  652. {
  653. csString* str = plane_plugins.Get (i);
  654. if (str->Compare (plugname))
  655. return true;
  656. }
  657. return false;
  658. }
  659. bool LevTool::IsMeshAThing (iDocumentNode* meshnode)
  660. {
  661. csRef<iDocumentNode> pluginnode = meshnode->GetNode ("plugin");
  662. if (!pluginnode)
  663. {
  664. // Very weird. Should not happen.
  665. return false;
  666. }
  667. const char* plugname = pluginnode->GetContentsValue ();
  668. if (!plugname)
  669. {
  670. // Very weird. Should not happen.
  671. return false;
  672. }
  673. int i;
  674. for (i = 0 ; i < thing_plugins.Length () ; i++)
  675. {
  676. csString* str = thing_plugins.Get (i);
  677. if (str->Compare (plugname))
  678. return true;
  679. }
  680. return false;
  681. }
  682. bool LevTool::IsMeshMovable (iDocumentNode* meshnode)
  683. {
  684. csRef<iDocumentNode> paramsnode = meshnode->GetNode ("params");
  685. if (!paramsnode) return false;
  686. csRef<iDocumentNode> movnode = paramsnode->GetNode ("moveable");
  687. if (!movnode) return false;
  688. return true;
  689. }
  690. void LevTool::ParsePart (ltThing* thing, iDocumentNode* partnode,
  691. iDocumentNode* meshnode)
  692. {
  693. csRef<iDocumentNodeIterator> it = partnode->GetNodes ();
  694. while (it->HasNext ())
  695. {
  696. csRef<iDocumentNode> child = it->Next ();
  697. if (child->GetType () != CS_NODE_ELEMENT) continue;
  698. const char* value = child->GetValue ();
  699. if (!strcmp (value, "v"))
  700. {
  701. csVector3 v;
  702. v.x = child->GetAttributeValueAsFloat ("x");
  703. v.y = child->GetAttributeValueAsFloat ("y");
  704. v.z = child->GetAttributeValueAsFloat ("z");
  705. thing->AddVertex (v);
  706. }
  707. else if (!strcmp (value, "p"))
  708. {
  709. ltPolygon* p = thing->AddPolygon (child);
  710. csRef<iDocumentNodeIterator> it2 = child->GetNodes ();
  711. while (it2->HasNext ())
  712. {
  713. csRef<iDocumentNode> child2 = it2->Next ();
  714. if (child2->GetType () != CS_NODE_ELEMENT) continue;
  715. const char* value2 = child2->GetValue ();
  716. if (!strcmp (value2, "v"))
  717. {
  718. int vtidx = child2->GetContentsValueAsInt ();
  719. p->AddVertex (vtidx);
  720. }
  721. }
  722. }
  723. else if (!strcmp (value, "part"))
  724. {
  725. ltThing* partthing = new ltThing (meshnode, child);
  726. const char* childname = child->GetAttributeValue ("name");
  727. if (childname)
  728. partthing->SetName (childname);
  729. else
  730. {
  731. csString newname (thing->GetName ());
  732. newname += "_part";
  733. partthing->SetName (newname);
  734. }
  735. things.Push (partthing);
  736. ParsePart (partthing, child, 0);
  737. }
  738. }
  739. }
  740. void LevTool::ParseThing (iDocumentNode* meshnode)
  741. {
  742. csRef<iDocumentNode> paramsnode = meshnode->GetNode ("params");
  743. if (!paramsnode) return; // Very weird!
  744. ltThing* th = new ltThing (meshnode, paramsnode);
  745. const char* name = meshnode->GetAttributeValue ("name");
  746. if (name) th->SetName (name);
  747. things.Push (th);
  748. ltDocNodeWrap* w = new ltDocNodeWrap ();
  749. w->node = meshnode;
  750. thing_nodes.Push (w);
  751. ParsePart (th, paramsnode, meshnode);
  752. }
  753. void LevTool::FindAllPlanes (iDocument* doc)
  754. {
  755. csRef<iDocumentNode> root = doc->GetRoot ();
  756. csRef<iDocumentNode> worldnode = root->GetNode ("world");
  757. csRef<iDocumentNodeIterator> it = worldnode->GetNodes ();
  758. while (it->HasNext ())
  759. {
  760. csRef<iDocumentNode> child = it->Next ();
  761. if (child->GetType () != CS_NODE_ELEMENT) continue;
  762. const char* value = child->GetValue ();
  763. if (!strcmp (value, "addon") && IsAddonAPlane (child))
  764. {
  765. csRef<iDocumentNode> params = child->GetNode ("params");
  766. ltPlane* pl = new ltPlane;
  767. csRef<iDocumentNode> name = params->GetNode ("name");
  768. if (name)
  769. {
  770. const char* plname = name->GetContentsValue ();
  771. pl->name = csStrNew (plname);
  772. }
  773. csVector3 v;
  774. csRef<iDocumentNode> orig = params->GetNode ("orig");
  775. if (orig)
  776. {
  777. v.x = orig->GetAttributeValueAsFloat ("x");
  778. v.y = orig->GetAttributeValueAsFloat ("y");
  779. v.z = orig->GetAttributeValueAsFloat ("z");
  780. pl->orig = v;
  781. }
  782. csRef<iDocumentNode> first = params->GetNode ("first");
  783. if (first)
  784. {
  785. v.x = first->GetAttributeValueAsFloat ("x");
  786. v.y = first->GetAttributeValueAsFloat ("y");
  787. v.z = first->GetAttributeValueAsFloat ("z");
  788. pl->first = v;
  789. }
  790. csRef<iDocumentNode> second = params->GetNode ("second");
  791. if (second)
  792. {
  793. v.x = second->GetAttributeValueAsFloat ("x");
  794. v.y = second->GetAttributeValueAsFloat ("y");
  795. v.z = second->GetAttributeValueAsFloat ("z");
  796. pl->second = v;
  797. }
  798. csRef<iDocumentNode> firstlen = params->GetNode ("firstlen");
  799. if (firstlen)
  800. pl->firstlen = firstlen->GetContentsValueAsFloat ();
  801. csRef<iDocumentNode> secondlen = params->GetNode ("secondlen");
  802. if (secondlen)
  803. pl->secondlen = secondlen->GetContentsValueAsFloat ();
  804. planes.Push (pl);
  805. }
  806. }
  807. }
  808. void LevTool::FindAllThings (iDocument* doc, bool meshfacts, bool movable)
  809. {
  810. csRef<iDocumentNode> root = doc->GetRoot ();
  811. csRef<iDocumentNode> worldnode = root->GetNode ("world");
  812. csRef<iDocumentNodeIterator> it = worldnode->GetNodes ();
  813. while (it->HasNext ())
  814. {
  815. csRef<iDocumentNode> child = it->Next ();
  816. if (child->GetType () != CS_NODE_ELEMENT) continue;
  817. const char* value = child->GetValue ();
  818. if (!strcmp (value, "sector"))
  819. {
  820. csRef<iDocumentNodeIterator> it2 = child->GetNodes ();
  821. while (it2->HasNext ())
  822. {
  823. csRef<iDocumentNode> child2 = it2->Next ();
  824. if (child2->GetType () != CS_NODE_ELEMENT) continue;
  825. const char* value2 = child2->GetValue ();
  826. if (!strcmp (value2, "meshobj") && IsMeshAThing (child2)
  827. && (movable || !IsMeshMovable (child2)))
  828. {
  829. ParseThing (child2);
  830. }
  831. }
  832. }
  833. else if (meshfacts && !strcmp (value, "meshfact") && IsMeshAThing (child))
  834. {
  835. ParseThing (child);
  836. }
  837. }
  838. }
  839. void LevTool::WriteOutPolygon (iDocumentNode* poly_node, ltPolygon* p,
  840. int* mapping)
  841. {
  842. csRef<iDocumentNodeIterator> it = p->GetNode ()->GetNodes ();
  843. bool write_vertices = true;
  844. while (it->HasNext ())
  845. {
  846. csRef<iDocumentNode> child = it->Next ();
  847. const char* value = child->GetValue ();
  848. if (child->GetType () == CS_NODE_ELEMENT && !strcmp (value, "v"))
  849. {
  850. if (write_vertices)
  851. {
  852. write_vertices = false;
  853. int i;
  854. for (i = 0 ; i < p->GetVertexCount () ; i++)
  855. {
  856. csRef<iDocumentNode> newchild = poly_node->CreateNodeBefore (
  857. CS_NODE_ELEMENT);
  858. newchild->SetValue ("v");
  859. csRef<iDocumentNode> text = newchild->CreateNodeBefore (
  860. CS_NODE_TEXT);
  861. int newvtidx = mapping[p->GetVertex (i)];
  862. CS_ASSERT (newvtidx != -1);
  863. text->SetValueAsInt (newvtidx);
  864. }
  865. }
  866. }
  867. else
  868. {
  869. csRef<iDocumentNode> newchild = poly_node->CreateNodeBefore (
  870. CS_NODE_ELEMENT);
  871. CloneNode (child, newchild);
  872. }
  873. }
  874. }
  875. void LevTool::WriteOutThing (iDocumentNode* params_node, ltThing* th,
  876. int obj_number)
  877. {
  878. int* mapping = th->CreateUnitMapping (obj_number);
  879. csRef<iDocumentNodeIterator> it = th->GetPartNode ()->GetNodes ();
  880. bool write_vertices = true;
  881. while (it->HasNext ())
  882. {
  883. csRef<iDocumentNode> child = it->Next ();
  884. const char* value = child->GetValue ();
  885. if (child->GetType () == CS_NODE_ELEMENT && !strcmp (value, "v"))
  886. {
  887. if (write_vertices)
  888. {
  889. write_vertices = false;
  890. int i;
  891. for (i = 0 ; i < th->GetVertexCount () ; i++)
  892. {
  893. const ltVertex& vt = th->GetVertex (i);
  894. if (vt.GetObjectNumber () == obj_number)
  895. {
  896. csRef<iDocumentNode> newchild = params_node->CreateNodeBefore (
  897. CS_NODE_ELEMENT);
  898. newchild->SetValue ("v");
  899. newchild->SetAttributeAsFloat ("x", vt.x);
  900. newchild->SetAttributeAsFloat ("y", vt.y);
  901. newchild->SetAttributeAsFloat ("z", vt.z);
  902. }
  903. }
  904. }
  905. }
  906. else if (child->GetType () == CS_NODE_ELEMENT && !strcmp (value, "p"))
  907. {
  908. int i;
  909. for (i = 0 ; i < th->GetPolygonCount () ; i++)
  910. {
  911. ltPolygon* p = th->GetPolygon (i);
  912. if (p->GetNode ()->Equals (child))
  913. {
  914. if (p->GetObjectNumber () == obj_number)
  915. {
  916. csRef<iDocumentNode> newchild = params_node->CreateNodeBefore (
  917. CS_NODE_ELEMENT);
  918. newchild->SetValue ("p");
  919. if (p->GetName ())
  920. newchild->SetAttribute ("name", p->GetName ());
  921. WriteOutPolygon (newchild, p, mapping);
  922. }
  923. break;
  924. }
  925. }
  926. }
  927. else if (child->GetType () == CS_NODE_ELEMENT && !strcmp (value, "part"))
  928. {
  929. }
  930. else if (child->GetType () == CS_NODE_ELEMENT && !strcmp (value,
  931. "vistree"))
  932. {
  933. }
  934. else
  935. {
  936. csRef<iDocumentNode> newchild = params_node->CreateNodeBefore (
  937. CS_NODE_ELEMENT);
  938. CloneNode (child, newchild);
  939. }
  940. }
  941. delete[] mapping;
  942. }
  943. void LevTool::SplitThing (iDocumentNode* meshnode, iDocumentNode* parentnode)
  944. {
  945. int i;
  946. for (i = 0 ; i < things.Length () ; i++)
  947. {
  948. ltThing* th = things.Get (i);
  949. if (th->GetMeshNode ()->Equals (meshnode))
  950. {
  951. if (th->GetPolygonCount () == 0) continue;
  952. int j;
  953. for (j = 0 ; j <= th->GetMaxObjectNumber () ; j++)
  954. {
  955. csRef<iDocumentNode> newmesh = parentnode->CreateNodeBefore (
  956. CS_NODE_ELEMENT);
  957. newmesh->SetValue (meshnode->GetValue ());
  958. csRef<iDocumentAttributeIterator> atit = meshnode->GetAttributes ();
  959. while (atit->HasNext ())
  960. {
  961. csRef<iDocumentAttribute> attr = atit->Next ();
  962. newmesh->SetAttribute (attr->GetName (), attr->GetValue ());
  963. }
  964. if (j == 0)
  965. {
  966. newmesh->SetAttribute ("name", th->GetName ());
  967. printf ("Processing '%s' ...\n", th->GetName ()); fflush (stdout);
  968. }
  969. else
  970. {
  971. char newname[512];
  972. sprintf (newname, "%s_%d", th->GetName (), j);
  973. newmesh->SetAttribute ("name", newname);
  974. printf ("Processing '%s' ...\n", newname); fflush (stdout);
  975. }
  976. csRef<iDocumentNodeIterator> it = meshnode->GetNodes ();
  977. while (it->HasNext ())
  978. {
  979. csRef<iDocumentNode> child = it->Next ();
  980. const char* value = child->GetValue ();
  981. if (child->GetType () == CS_NODE_ELEMENT &&
  982. (!strcmp (value, "params")))
  983. {
  984. csRef<iDocumentNode> params_clone = newmesh->CreateNodeBefore (
  985. child->GetType ());
  986. params_clone->SetValue ("params");
  987. WriteOutThing (params_clone, th, j);
  988. }
  989. else if (child->GetType () == CS_NODE_ELEMENT &&
  990. (!strcmp (value, "zfill")))
  991. {
  992. csRef<iDocumentNode> child_clone = newmesh->CreateNodeBefore (
  993. child->GetType ());
  994. CloneNode (child, child_clone);
  995. child_clone->SetValue ("zuse");
  996. }
  997. else
  998. {
  999. csRef<iDocumentNode> child_clone = newmesh->CreateNodeBefore (
  1000. child->GetType ());
  1001. CloneNode (child, child_clone);
  1002. }
  1003. }
  1004. }
  1005. }
  1006. }
  1007. }
  1008. void LevTool::CloneAndSplitDynavis (iDocumentNode* node, iDocumentNode* newnode,
  1009. bool is_dynavis)
  1010. {
  1011. const char* parentvalue = node->GetValue ();
  1012. bool is_world = !strcmp (parentvalue, "world");
  1013. bool is_sector = !strcmp (parentvalue, "sector");
  1014. bool is_root = !strcmp (parentvalue, "");
  1015. if (!is_root && !is_sector && !is_world)
  1016. {
  1017. CloneNode (node, newnode);
  1018. return;
  1019. }
  1020. // First copy the world or sector name and attributes.
  1021. newnode->SetValue (node->GetValue ());
  1022. csRef<iDocumentAttributeIterator> atit = node->GetAttributes ();
  1023. while (atit->HasNext ())
  1024. {
  1025. csRef<iDocumentAttribute> attr = atit->Next ();
  1026. newnode->SetAttribute (attr->GetName (), attr->GetValue ());
  1027. }
  1028. csRef<iDocumentNode> settingsnode;
  1029. csRef<iDocumentNodeIterator> it = node->GetNodes ();
  1030. while (it->HasNext ())
  1031. {
  1032. csRef<iDocumentNode> child = it->Next ();
  1033. const char* value = child->GetValue ();
  1034. if (is_sector && child->GetType () == CS_NODE_ELEMENT &&
  1035. (!strcmp (value, "meshobj")) && IsMeshAThing (child) &&
  1036. !IsMeshMovable (child))
  1037. {
  1038. SplitThing (child, newnode);
  1039. }
  1040. else if (is_dynavis && is_sector && child->GetType () == CS_NODE_ELEMENT &&
  1041. (!strcmp (value, "culler")))
  1042. {
  1043. csRef<iDocumentNode> newchild = newnode->CreateNodeBefore (
  1044. child->GetType ());
  1045. newchild->SetValue ("cullerp");
  1046. csRef<iDocumentNode> text = newchild->CreateNodeBefore (
  1047. CS_NODE_TEXT);
  1048. text->SetValue ("crystalspace.culling.dynavis");
  1049. }
  1050. else if (is_root && !strcmp (value, "world"))
  1051. {
  1052. csRef<iDocumentNode> newchild = newnode->CreateNodeBefore (
  1053. child->GetType ());
  1054. CloneAndSplitDynavis (child, newchild, is_dynavis);
  1055. }
  1056. else if (is_world && !strcmp (value, "sector"))
  1057. {
  1058. csRef<iDocumentNode> newchild = newnode->CreateNodeBefore (
  1059. child->GetType ());
  1060. CloneAndSplitDynavis (child, newchild, is_dynavis);
  1061. }
  1062. else
  1063. {
  1064. csRef<iDocumentNode> newchild = newnode->CreateNodeBefore (
  1065. child->GetType ());
  1066. CloneNode (child, newchild);
  1067. if (is_world && !strcmp (value, "settings"))
  1068. settingsnode = newchild;
  1069. }
  1070. }
  1071. if (is_dynavis && is_world)
  1072. {
  1073. if (settingsnode == 0)
  1074. {
  1075. settingsnode = newnode->CreateNodeBefore (CS_NODE_ELEMENT);
  1076. settingsnode->SetValue ("settings");
  1077. }
  1078. bool found = false;
  1079. csRef<iDocumentNodeIterator> it = settingsnode->GetNodes ();
  1080. while (it->HasNext ())
  1081. {
  1082. csRef<iDocumentNode> child = it->Next ();
  1083. const char* value = child->GetValue ();
  1084. if (child->GetType () == CS_NODE_ELEMENT && !strcmp (value, "clearzbuf"))
  1085. {
  1086. found = true;
  1087. }
  1088. }
  1089. if (!found)
  1090. {
  1091. csRef<iDocumentNode> newchild = settingsnode->CreateNodeBefore (
  1092. CS_NODE_ELEMENT);
  1093. newchild->SetValue ("clearzbuf");
  1094. csRef<iDocumentNode> text = newchild->CreateNodeBefore (
  1095. CS_NODE_TEXT);
  1096. text->SetValue ("yes");
  1097. }
  1098. }
  1099. }
  1100. void LevTool::CloneAndSplitDynavis (iDocument* doc, iDocument* newdoc,
  1101. bool is_dynavis)
  1102. {
  1103. csRef<iDocumentNode> root = doc->GetRoot ();
  1104. csRef<iDocumentNode> newroot = newdoc->CreateRoot ();
  1105. CloneAndSplitDynavis (root, newroot, is_dynavis);
  1106. }
  1107. void LevTool::CloneAndMovePlanes (iDocumentNode* node, iDocumentNode* newnode)
  1108. {
  1109. const char* parentvalue = node->GetValue ();
  1110. bool is_addon = !strcmp (parentvalue, "addon");
  1111. if (is_addon && IsAddonAPlane (node)) return; // Discard.
  1112. bool is_meshfact = !strcmp (parentvalue, "meshfact");
  1113. if (is_meshfact && !IsMeshAThing (node))
  1114. {
  1115. CloneNode (node, newnode);
  1116. return;
  1117. }
  1118. bool is_meshobj = !strcmp (parentvalue, "meshobj");
  1119. if (is_meshobj && !IsMeshAThing (node))
  1120. {
  1121. CloneNode (node, newnode);
  1122. return;
  1123. }
  1124. bool is_world = !strcmp (parentvalue, "world");
  1125. bool is_sector = !strcmp (parentvalue, "sector");
  1126. bool is_plugins = !strcmp (parentvalue, "plugins");
  1127. bool is_p = !strcmp (parentvalue, "p");
  1128. bool is_params = !strcmp (parentvalue, "params");
  1129. bool is_part = !strcmp (parentvalue, "part");
  1130. bool is_texmap = !strcmp (parentvalue, "texmap");
  1131. bool is_root = !strcmp (parentvalue, "");
  1132. if (!is_root && !is_sector && !is_world && !is_meshfact && !is_meshobj
  1133. && !is_p && !is_params && !is_part && !is_texmap && !is_plugins)
  1134. {
  1135. CloneNode (node, newnode);
  1136. return;
  1137. }
  1138. // First copy the name and attributes.
  1139. newnode->SetValue (node->GetValue ());
  1140. csRef<iDocumentAttributeIterator> atit = node->GetAttributes ();
  1141. while (atit->HasNext ())
  1142. {
  1143. csRef<iDocumentAttribute> attr = atit->Next ();
  1144. newnode->SetAttribute (attr->GetName (), attr->GetValue ());
  1145. }
  1146. if (is_texmap)
  1147. {
  1148. csRef<iDocumentNodeIterator> it = node->GetNodes ();
  1149. while (it->HasNext ())
  1150. {
  1151. csRef<iDocumentNode> child = it->Next ();
  1152. const char* value = child->GetValue ();
  1153. if (child->GetType () == CS_NODE_ELEMENT && (!strcmp (value, "plane")))
  1154. {
  1155. const char* planename = child->GetContentsValue ();
  1156. int i;
  1157. for (i = 0 ; i < planes.Length () ; i++)
  1158. {
  1159. ltPlane* pl = planes[i];
  1160. if (strcmp (pl->name, planename) == 0)
  1161. {
  1162. csRef<iDocumentNode> orig = newnode->CreateNodeBefore (
  1163. child->GetType ());
  1164. orig->SetValue ("orig");
  1165. orig->SetAttributeAsFloat ("x", pl->orig.x);
  1166. orig->SetAttributeAsFloat ("y", pl->orig.y);
  1167. orig->SetAttributeAsFloat ("z", pl->orig.z);
  1168. csRef<iDocumentNode> first = newnode->CreateNodeBefore (
  1169. child->GetType ());
  1170. first->SetValue ("first");
  1171. first->SetAttributeAsFloat ("x", pl->first.x);
  1172. first->SetAttributeAsFloat ("y", pl->first.y);
  1173. first->SetAttributeAsFloat ("z", pl->first.z);
  1174. csRef<iDocumentNode> firstlen = newnode->CreateNodeBefore (
  1175. child->GetType ());
  1176. firstlen->SetValue ("firstlen");
  1177. csRef<iDocumentNode> firstlen_text = firstlen->CreateNodeBefore (
  1178. CS_NODE_TEXT);
  1179. firstlen_text->SetValueAsFloat (pl->firstlen);
  1180. csRef<iDocumentNode> second = newnode->CreateNodeBefore (
  1181. child->GetType ());
  1182. second->SetValue ("second");
  1183. second->SetAttributeAsFloat ("x", pl->second.x);
  1184. second->SetAttributeAsFloat ("y", pl->second.y);
  1185. second->SetAttributeAsFloat ("z", pl->second.z);
  1186. csRef<iDocumentNode> secondlen = newnode->CreateNodeBefore (
  1187. child->GetType ());
  1188. secondlen->SetValue ("secondlen");
  1189. csRef<iDocumentNode> secondlen_text = secondlen->CreateNodeBefore (
  1190. CS_NODE_TEXT);
  1191. secondlen_text->SetValueAsFloat (pl->secondlen);
  1192. break;
  1193. }
  1194. }
  1195. }
  1196. else
  1197. {
  1198. csRef<iDocumentNode> newchild = newnode->CreateNodeBefore (
  1199. child->GetType ());
  1200. CloneNode (child, newchild);
  1201. }
  1202. }
  1203. }
  1204. else if (is_plugins)
  1205. {
  1206. csRef<iDocumentNodeIterator> it = node->GetNodes ();
  1207. while (it->HasNext ())
  1208. {
  1209. csRef<iDocumentNode> child = it->Next ();
  1210. const char* value = child->GetValue ();
  1211. if (child->GetType () == CS_NODE_ELEMENT && !strcmp (value, "plugin"))
  1212. {
  1213. const char* plugname = child->GetContentsValue ();
  1214. if (!strcmp (plugname, "crystalspace.mesh.loader.thing.plane"))
  1215. {
  1216. // Drop.
  1217. continue;
  1218. }
  1219. }
  1220. csRef<iDocumentNode> newchild = newnode->CreateNodeBefore (
  1221. child->GetType ());
  1222. CloneNode (child, newchild);
  1223. }
  1224. }
  1225. else
  1226. {
  1227. csRef<iDocumentNodeIterator> it = node->GetNodes ();
  1228. while (it->HasNext ())
  1229. {
  1230. csRef<iDocumentNode> child = it->Next ();
  1231. const char* value = child->GetValue ();
  1232. if (strcmp (value, "addon") == 0 && IsAddonAPlane (child))
  1233. {
  1234. continue; // Skip.
  1235. }
  1236. csRef<iDocumentNode> newchild = newnode->CreateNodeBefore (
  1237. child->GetType ());
  1238. CloneAndMovePlanes (child, newchild);
  1239. }
  1240. }
  1241. }
  1242. void LevTool::CloneAndMovePlanes (iDocument* doc, iDocument* newdoc)
  1243. {
  1244. csRef<iDocumentNode> root = doc->GetRoot ();
  1245. csRef<iDocumentNode> newroot = newdoc->CreateRoot ();
  1246. CloneAndMovePlanes (root, newroot);
  1247. }
  1248. static int cnt;
  1249. void LevTool::CloneAndChangeFlags (iDocumentNode* node, iDocumentNode* newnode,
  1250. int op, int minsize, int maxsize, int minpoly, int maxpoly,
  1251. float global_area)
  1252. {
  1253. const char* parentvalue = node->GetValue ();
  1254. bool is_world = !strcmp (parentvalue, "world");
  1255. bool is_sector = !strcmp (parentvalue, "sector");
  1256. bool is_meshobj = !strcmp (parentvalue, "meshobj");
  1257. bool is_root = !strcmp (parentvalue, "");
  1258. if (!is_root && !is_sector && !is_world && !is_meshobj)
  1259. {
  1260. CloneNode (node, newnode);
  1261. return;
  1262. }
  1263. // First copy the world or sector name and attributes.
  1264. newnode->SetValue (node->GetValue ());
  1265. csRef<iDocumentAttributeIterator> atit = node->GetAttributes ();
  1266. while (atit->HasNext ())
  1267. {
  1268. csRef<iDocumentAttribute> attr = atit->Next ();
  1269. newnode->SetAttribute (attr->GetName (), attr->GetValue ());
  1270. }
  1271. bool is_thing = is_meshobj && IsMeshAThing (node);
  1272. csRef<iDocumentNodeIterator> it = node->GetNodes ();
  1273. while (it->HasNext ())
  1274. {
  1275. csRef<iDocumentNode> child = it->Next ();
  1276. const char* value = child->GetValue ();
  1277. if (op != OP_FLAGBAD && is_thing && child->GetType () == CS_NODE_ELEMENT &&
  1278. !strcmp (value, "goodoccluder"))
  1279. {
  1280. }
  1281. else if (op != OP_FLAGGOOD && is_thing
  1282. && child->GetType () == CS_NODE_ELEMENT &&
  1283. !strcmp (value, "badoccluder"))
  1284. {
  1285. }
  1286. else if (child->GetType () == CS_NODE_ELEMENT &&
  1287. ((is_sector && !strcmp (value, "meshobj")) ||
  1288. (is_root && !strcmp (value, "world")) ||
  1289. (is_world && !strcmp (value, "sector"))))
  1290. {
  1291. csRef<iDocumentNode> newchild = newnode->CreateNodeBefore (
  1292. child->GetType ());
  1293. CloneAndChangeFlags (child, newchild, op, minsize, maxsize,
  1294. minpoly, maxpoly, global_area);
  1295. }
  1296. else
  1297. {
  1298. csRef<iDocumentNode> newchild = newnode->CreateNodeBefore (
  1299. child->GetType ());
  1300. CloneNode (child, newchild);
  1301. }
  1302. }
  1303. if (is_thing)
  1304. {
  1305. ltThing* th = 0;
  1306. int i;
  1307. for (i = 0 ; i < things.Length () ; i++)
  1308. {
  1309. th = things.Get (i);
  1310. if (th->GetMeshNode ()->Equals (node)) break;
  1311. }
  1312. if (th->GetPolygonCount () < minpoly || th->GetPolygonCount () > maxpoly)
  1313. return;
  1314. const csBox3& b = th->GetBoundingBox ();
  1315. float area = (b.MaxX () - b.MinX ()) *
  1316. (b.MaxY () - b.MinY ()) *
  1317. (b.MaxZ () - b.MinZ ());
  1318. area = pow (area, 1.0f/3.0f);
  1319. int where = int (100 * (area / global_area));
  1320. if (where < minsize || where > maxsize)
  1321. return;
  1322. if (op == OP_FLAGGOOD)
  1323. {
  1324. csRef<iDocumentNode> newchild = newnode->CreateNodeBefore (
  1325. CS_NODE_ELEMENT);
  1326. newchild->SetValue ("goodoccluder");
  1327. cnt++;
  1328. }
  1329. else if (op == OP_FLAGBAD)
  1330. {
  1331. csRef<iDocumentNode> newchild = newnode->CreateNodeBefore (
  1332. CS_NODE_ELEMENT);
  1333. newchild->SetValue ("badoccluder");
  1334. cnt++;
  1335. }
  1336. }
  1337. }
  1338. void LevTool::CloneAndChangeFlags (iDocument* doc, iDocument* newdoc,
  1339. int op, int minsize, int maxsize, int minpoly, int maxpoly,
  1340. float global_area)
  1341. {
  1342. csRef<iDocumentNode> root = doc->GetRoot ();
  1343. csRef<iDocumentNode> newroot = newdoc->CreateRoot ();
  1344. CloneAndChangeFlags (root, newroot, op, minsize, maxsize, minpoly, maxpoly,
  1345. global_area);
  1346. }
  1347. void LevTool::CloneNode (iDocumentNode* from, iDocumentNode* to)
  1348. {
  1349. to->SetValue (from->GetValue ());
  1350. csRef<iDocumentNodeIterator> it = from->GetNodes ();
  1351. while (it->HasNext ())
  1352. {
  1353. csRef<iDocumentNode> child = it->Next ();
  1354. csRef<iDocumentNode> child_clone = to->CreateNodeBefore (
  1355. child->GetType (), 0);
  1356. CloneNode (child, child_clone);
  1357. }
  1358. csRef<iDocumentAttributeIterator> atit = from->GetAttributes ();
  1359. while (atit->HasNext ())
  1360. {
  1361. csRef<iDocumentAttribute> attr = atit->Next ();
  1362. to->SetAttribute (attr->GetName (), attr->GetValue ());
  1363. }
  1364. }
  1365. //-----------------------------------------------------------------------------
  1366. void LevTool::ListMeshPart (iDocumentNode* meshpart, int level)
  1367. {
  1368. char indent[1024];
  1369. int i; for (i = 0 ; i < level ; i++) indent[i] = ' '; indent[level] = 0;
  1370. const char* name = meshpart->GetAttributeValue ("name");
  1371. printf ("%spart(%s)\n", indent, name);
  1372. }
  1373. void LevTool::ListMeshObject (iDocumentNode* mesh, int level)
  1374. {
  1375. char indent[1024];
  1376. int i; for (i = 0 ; i < level ; i++) indent[i] = ' '; indent[level] = 0;
  1377. const char* name = mesh->GetAttributeValue ("name");
  1378. csRef<iDocumentNode> pluginnode = mesh->GetNode ("plugin");
  1379. const char* plugin = pluginnode->GetContentsValue ();
  1380. printf ("%smeshobj(%s,%s)\n", indent, name, plugin);
  1381. if (IsMeshAThing (mesh))
  1382. {
  1383. csRef<iDocumentNode> paramsnode = mesh->GetNode ("params");
  1384. if (!paramsnode) return;
  1385. csRef<iDocumentNodeIterator> it = paramsnode->GetNodes ();
  1386. while (it->HasNext ())
  1387. {
  1388. csRef<iDocumentNode> child = it->Next ();
  1389. if (child->GetType () != CS_NODE_ELEMENT) continue;
  1390. const char* value = child->GetValue ();
  1391. if (!strcmp (value, "part"))
  1392. {
  1393. ListMeshPart (child, level+1);
  1394. }
  1395. }
  1396. }
  1397. }
  1398. void LevTool::ListFactory (iDocumentNode* factory, int level)
  1399. {
  1400. char indent[1024];
  1401. int i; for (i = 0 ; i < level ; i++) indent[i] = ' '; indent[level] = 0;
  1402. const char* name = factory->GetAttributeValue ("name");
  1403. csRef<iDocumentNode> pluginnode = factory->GetNode ("plugin");
  1404. const char* plugin = pluginnode->GetContentsValue ();
  1405. printf ("%smeshfact(%s,%s)\n", indent, name, plugin);
  1406. if (IsMeshAThing (factory))
  1407. {
  1408. csRef<iDocumentNode> paramsnode = factory->GetNode ("params");
  1409. if (!paramsnode) return;
  1410. csRef<iDocumentNodeIterator> it = paramsnode->GetNodes ();
  1411. while (it->HasNext ())
  1412. {
  1413. csRef<iDocumentNode> child = it->Next ();
  1414. if (child->GetType () != CS_NODE_ELEMENT) continue;
  1415. const char* value = child->GetValue ();
  1416. if (!strcmp (value, "part"))
  1417. {
  1418. ListMeshPart (child, level+1);
  1419. }
  1420. }
  1421. }
  1422. }
  1423. void LevTool::ListSector (iDocumentNode* sector, int level)
  1424. {
  1425. char indent[1024];
  1426. int i; for (i = 0 ; i < level ; i++) indent[i] = ' '; indent[level] = 0;
  1427. const char* name = sector->GetAttributeValue ("name");
  1428. printf ("%ssector(%s)\n", indent, name);
  1429. csRef<iDocumentNodeIterator> it = sector->GetNodes ();
  1430. while (it->HasNext ())
  1431. {
  1432. csRef<iDocumentNode> child = it->Next ();
  1433. if (child->GetType () != CS_NODE_ELEMENT) continue;
  1434. const char* value = child->GetValue ();
  1435. if (!strcmp (value, "meshobj"))
  1436. {
  1437. ListMeshObject (child, level+1);
  1438. }
  1439. }
  1440. }
  1441. void LevTool::ListContents (iDocumentNode* world)
  1442. {
  1443. printf ("world\n");
  1444. csRef<iDocumentNode> worldnode = world->GetNode ("world");
  1445. csRef<iDocumentNodeIterator> it = worldnode->GetNodes ();
  1446. while (it->HasNext ())
  1447. {
  1448. csRef<iDocumentNode> child = it->Next ();
  1449. if (child->GetType () != CS_NODE_ELEMENT) continue;
  1450. const char* value = child->GetValue ();
  1451. if (!strcmp (value, "sector"))
  1452. {
  1453. ListSector (child, 1);
  1454. }
  1455. else if (!strcmp (value, "meshfact"))
  1456. {
  1457. ListFactory (child, 1);
  1458. }
  1459. }
  1460. fflush (stdout);
  1461. }
  1462. //-----------------------------------------------------------------------------
  1463. void LevTool::ValidateContents (ltThing* thing)
  1464. {
  1465. int i, j;
  1466. for (i = 0 ; i < thing->GetPolygonCount () ; i++)
  1467. {
  1468. ltPolygon* pol = thing->GetPolygon (i);
  1469. if (pol->GetVertexCount () > 3)
  1470. {
  1471. csPlane3 plane (
  1472. thing->GetVertex (pol->GetVertex (0)),
  1473. thing->GetVertex (pol->GetVertex (1)),
  1474. thing->GetVertex (pol->GetVertex (2)));
  1475. for (j = 3 ; j < pol->GetVertexCount () ; j++)
  1476. {
  1477. float d = plane.Distance (thing->GetVertex (pol->GetVertex (j)));
  1478. if (d > 0.01)
  1479. {
  1480. printf ("WARNING! polygon '%s' in thing/part '%s' seems to be non-coplanar with distance %g\n",
  1481. pol->GetName (), thing->GetName (), d);
  1482. }
  1483. }
  1484. }
  1485. }
  1486. }
  1487. void LevTool::ValidateContents ()
  1488. {
  1489. int i;
  1490. for (i = 0 ; i < things.Length () ; i++)
  1491. {
  1492. ltThing* th = things.Get (i);
  1493. ValidateContents (th);
  1494. }
  1495. }
  1496. //-----------------------------------------------------------------------------
  1497. LevTool::LevTool ()
  1498. {
  1499. object_reg = 0;
  1500. }
  1501. LevTool::~LevTool ()
  1502. {
  1503. }
  1504. //----------------------------------------------------------------------------
  1505. // @@@ TODO: support hardmove!
  1506. void LevTool::Main ()
  1507. {
  1508. cmdline = CS_QUERY_REGISTRY (object_reg, iCommandLineParser);
  1509. vfs = CS_QUERY_REGISTRY (object_reg, iVFS);
  1510. csRef<iPluginManager> plugin_mgr =
  1511. CS_QUERY_REGISTRY (object_reg, iPluginManager);
  1512. int op = OP_HELP;
  1513. if (cmdline->GetOption ("inds") || cmdline->GetOption ("outds"))
  1514. op = OP_TRANSLATE;
  1515. if (cmdline->GetOption ("dynavis")) op = OP_DYNAVIS;
  1516. if (cmdline->GetOption ("list")) op = OP_LIST;
  1517. if (cmdline->GetOption ("analyze")) op = OP_ANALYZE;
  1518. if (cmdline->GetOption ("validate")) op = OP_VALIDATE;
  1519. if (cmdline->GetOption ("splitunit")) op = OP_SPLITUNIT;
  1520. if (cmdline->GetOption ("splitgeom")) op = OP_SPLITGEOM;
  1521. if (cmdline->GetOption ("compress")) op = OP_COMPRESS;
  1522. if (cmdline->GetOption ("flagclear")) op = OP_FLAGCLEAR;
  1523. if (cmdline->GetOption ("flaggood")) op = OP_FLAGGOOD;
  1524. if (cmdline->GetOption ("flagbad")) op = OP_FLAGBAD;
  1525. if (cmdline->GetOption ("planes")) op = OP_PLANES;
  1526. if (cmdline->GetOption ("help")) op = OP_HELP;
  1527. if (op == OP_HELP)
  1528. {
  1529. printf ("levtool <options> <zipfile>\n");
  1530. printf (" -list:\n");
  1531. printf (" List world contents.\n");
  1532. printf (" -analyze:\n");
  1533. printf (" Analyze all things and show the distribution of size.\n");
  1534. printf (" You can use this to decide on the 'minsize' parameter.\n");
  1535. printf (" -validate:\n");
  1536. printf (" Validate world contents. This will currently check\n");
  1537. printf (" only for non-coplanar polygons.\n");
  1538. printf (" -compress:\n");
  1539. printf (" Compress all vertices and remove duplicate and unused vertices.\n");
  1540. printf (" Unless you specify -nocompress, -dynavis does this by default.\n");
  1541. printf (" -dynavis:\n");
  1542. printf (" Convert to Dynavis. This takes a level that uses\n");
  1543. printf (" old style octree culler and convert it to Dynavis.\n");
  1544. printf (" All objects will be split in their logical parts.\n");
  1545. printf (" -splitunit:\n");
  1546. printf (" Split large things into separate units. A separate unit\n");
  1547. printf (" is defined as a collection of connected polygons that doesn't\n");
  1548. printf (" connect with any other polygon from the thing.\n");
  1549. printf (" This option will first do -compress.\n");
  1550. printf (" -minsize=<percent>: Only split objects larger than the given\n");
  1551. printf (" percentage. Default 20%%.\n");
  1552. printf (" -splitgeom:\n");
  1553. printf (" Split large things geometrically. After doing this you\n");
  1554. printf (" should run levtool with -compress option for efficiency.\n");
  1555. printf (" -minsize=<percent>: Only split objects larger than the given\n");
  1556. printf (" percentage. Default 20%%.\n");
  1557. printf (" -flagclear:\n");
  1558. printf (" Clear all goodoccluder/badoccluder flags.\n");
  1559. printf (" -flaggood:\n");
  1560. printf (" Add goodoccluder flag for all things that satisfy\n");
  1561. printf (" conditions defined by the following flags:\n");
  1562. printf (" -minsize=<percent>: min object size (default 10%%).\n");
  1563. printf (" -maxsize=<percent>: max object size (default 100%%).\n");
  1564. printf (" -minpoly=<number>: min number of polygons (default 1).\n");
  1565. printf (" -maxpoly=<number>: max number of polygons (default 50).\n");
  1566. printf (" -flagbad:\n");
  1567. printf (" Add badoccluder flag for all things that satisfy\n");
  1568. printf (" conditions defined by the following flags:\n");
  1569. printf (" -minsize=<percent>: mim object size (default 0%%).\n");
  1570. printf (" -maxsize=<percent>: max object size (default 3%%).\n");
  1571. printf (" -minpoly=<number>: min number of polygons (default 6).\n");
  1572. printf (" -maxpoly=<number>: max number of polygons (default 1000000000).\n");
  1573. printf (" -planes:\n");
  1574. printf (" Move all 'addon' planes to the polygons that use them.\n");
  1575. printf (" -inds=<plugin>:\n");
  1576. printf (" Document system plugin for reading world.\n");
  1577. printf (" -outds=<plugin>:\n");
  1578. printf (" Document system plugin for writing world.\n");
  1579. return;
  1580. }
  1581. int minsize, maxsize;
  1582. int minpoly, maxpoly;
  1583. switch (op)
  1584. {
  1585. case OP_FLAGGOOD:
  1586. minsize = 10;
  1587. maxsize = 120;
  1588. minpoly = 1;
  1589. maxpoly = 50;
  1590. break;
  1591. case OP_FLAGBAD:
  1592. minsize = 0;
  1593. maxsize = 3;
  1594. minpoly = 6;
  1595. maxpoly = 1000000000;
  1596. break;
  1597. default:
  1598. minsize = 20;
  1599. maxsize = 120;
  1600. minpoly = 0;
  1601. maxpoly = 1000000000;
  1602. break;
  1603. }
  1604. {
  1605. const char* minsize_arg = cmdline->GetOption ("minsize");
  1606. if (minsize_arg != 0) sscanf (minsize_arg, "%d", &minsize);
  1607. const char* maxsize_arg = cmdline->GetOption ("maxsize");
  1608. if (maxsize_arg != 0) sscanf (maxsize_arg, "%d", &maxsize);
  1609. const char* minpoly_arg = cmdline->GetOption ("minpoly");
  1610. if (minpoly_arg != 0) sscanf (minpoly_arg, "%d", &minpoly);
  1611. const char* maxpoly_arg = cmdline->GetOption ("maxpoly");
  1612. if (maxpoly_arg != 0) sscanf (maxpoly_arg, "%d", &maxpoly);
  1613. }
  1614. csRef<iDocumentSystem> inputDS;
  1615. csRef<iDocumentSystem> outputDS;
  1616. {
  1617. const char *inds = cmdline->GetOption ("inds");
  1618. if (inds)
  1619. {
  1620. /* inputDS = csPtr<iDocumentSystem> (CS_LOAD_PLUGIN (plugin_mgr,
  1621. inds, iDocumentSystem));
  1622. if (!inputDS)*/
  1623. {
  1624. inputDS = csPtr<iDocumentSystem> (CS_LOAD_PLUGIN (plugin_mgr,
  1625. csString().Format ("crystalspace.documentsystem.%s", inds),
  1626. iDocumentSystem));
  1627. }
  1628. if (!inputDS)
  1629. {
  1630. Report (CS_REPORTER_SEVERITY_ERROR,
  1631. "Unable to load input document system '%s'!",
  1632. inds);
  1633. return;
  1634. }
  1635. }
  1636. const char *outds = cmdline->GetOption ("outds");
  1637. if (outds)
  1638. {
  1639. /* outputDS = csPtr<iDocumentSystem> (CS_LOAD_PLUGIN (plugin_mgr,
  1640. outds, iDocumentSystem));
  1641. if (!outputDS)*/

Large files files are truncated, but you can click here to view the full file