PageRenderTime 26ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/CS/migrated/branches/R0_94/apps/import/map2cs/csector.cpp

#
C++ | 882 lines | 594 code | 124 blank | 164 comment | 81 complexity | e8b948dcfe6d1869f295b6364acc0096 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, LGPL-2.0
  1. /*
  2. Map2cs: a convertor to convert the frequently used MAP format, into
  3. something, that can be directly understood by Crystal Space.
  4. Copyright (C) 1999 Thomas Hieber (thieber@gmx.net)
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. */
  17. #include "cssysdef.h"
  18. #include "mapstd.h"
  19. #include "brush.h"
  20. #include "mpoly.h"
  21. #include "mpolyset.h"
  22. #include "mcurve.h"
  23. #include "iportal.h"
  24. #include "map.h"
  25. #include "texplane.h"
  26. #include "entity.h"
  27. #include "vertbuf.h"
  28. #include "cthing.h"
  29. #include "csector.h"
  30. #include "cworld.h"
  31. static char* BuildMaterialKey (int i, CMapEntity* pEntity)
  32. {
  33. char* key = new char[1024];
  34. char* returnvalue = new char[1024];
  35. sprintf(key,"MaterialName%d",i);
  36. printf(key);
  37. if(!pEntity->GetValueOfKey(key)) return NULL;
  38. sprintf(returnvalue,"KEY(\"defmaterial\",\"%s\")\n",
  39. pEntity->GetValueOfKey(key));
  40. return returnvalue;
  41. }
  42. //Auxiliar funtion to check if the file name is a mdl file
  43. static bool isMdlFile(const char* csmodelfile)
  44. {
  45. int i = 0;
  46. bool dot = false;
  47. char *extension = new char[strlen(csmodelfile)];
  48. for (i = 0; i < (int)strlen(csmodelfile); i++)
  49. {
  50. if(dot) extension[i] = csmodelfile[i];
  51. else if (csmodelfile[i] == '.') dot = true;
  52. }
  53. if(!strcmp(extension,"MDL")) return true;
  54. if(!strcmp(extension,"mdl")) return true;
  55. if(!strcmp(extension,"MDl")) return true;
  56. if(!strcmp(extension,"MdL")) return true;
  57. if(!strcmp(extension,"mDL")) return true;
  58. if(!strcmp(extension,"mdL")) return true;
  59. if(!strcmp(extension,"mDl")) return true;
  60. if(!strcmp(extension,"Mdl")) return true;
  61. return false;
  62. };
  63. //Auxiliar Function to contruct the Factory name of a cs_model
  64. static char* GetFactoryName(const char * csmodelfile)
  65. {
  66. /*
  67. * Searchs for the extension and substitutes ".extension" by "Fact" and
  68. * returns this new string
  69. */
  70. char* aux = new char[1024];
  71. bool found = false;
  72. int slashIndex = 0; //Last '/' in path file
  73. int i;
  74. for( i = 0;i < (int)strlen(csmodelfile); i++)
  75. {
  76. if(csmodelfile[i] == '/') slashIndex = i;
  77. }
  78. i = slashIndex + 1;
  79. while(i < (int)strlen(csmodelfile) && !found)
  80. {
  81. if(csmodelfile[i] == '.')
  82. {
  83. found = true;
  84. }
  85. else
  86. {
  87. aux[i-slashIndex - 1] = csmodelfile[i];
  88. i++;
  89. }
  90. }
  91. aux[i-slashIndex - 1] = 'F';aux[i-slashIndex] = 'a';
  92. aux[i-slashIndex + 1] = 'c';aux[i-slashIndex +2] = 't';
  93. aux[i-slashIndex + 3] = 0;
  94. return aux;
  95. }
  96. CCSSector::CCSSector(CMapBrush* pBrush)
  97. : CISector(pBrush)
  98. {
  99. }
  100. CCSSector::~CCSSector()
  101. {
  102. }
  103. bool CCSSector::Write(CIWorld* pIWorld)
  104. {
  105. assert(pIWorld);
  106. CCSWorld* pWorld = (CCSWorld*) pIWorld;
  107. CMapFile* pMap = pWorld->GetMap();
  108. FILE* fd = pWorld->GetFile();
  109. assert(pMap);
  110. assert(fd);
  111. pWorld->WriteIndent();
  112. fprintf(fd, "SECTOR '%s' (\n", GetName());
  113. pWorld->Indent();
  114. pWorld->WriteIndent();
  115. fprintf(fd, "MESHOBJ 'static'(\n");
  116. pWorld->Indent();
  117. pWorld->WriteIndent();
  118. fprintf(fd, "PLUGIN('thing')\n");
  119. pWorld->WriteIndent();
  120. fprintf(fd, "ZFILL()\n");
  121. pWorld->WriteIndent();
  122. fprintf(fd, "PRIORITY('wall')\n");
  123. CMapEntity* pEntity = m_pOriginalBrush->GetEntity();
  124. CCSWorld::WriteKeys(pWorld, pEntity);
  125. pWorld->WriteIndent();
  126. fprintf(fd, "PARAMS(\n");
  127. pWorld->Indent();
  128. if (pMap->GetConfigInt("Map2CS.General.UseBSP", 0))
  129. {
  130. pWorld->WriteIndent();
  131. fprintf(fd, "VISTREE()\n");
  132. }
  133. if (m_IsDefaultsector && pWorld->NeedSkysector())
  134. {
  135. /*pWorld->WriteIndent();
  136. fprintf(fd, "PART 'p1' (\n");
  137. pWorld->Indent();*/
  138. pWorld->WriteSky();
  139. /*pWorld->Unindent();
  140. pWorld->WriteIndent();
  141. fprintf(fd, ")\n");*/ //PART
  142. }
  143. else
  144. {
  145. if (m_Walls.Length() > 0 ||
  146. m_Portals.Length() > 0)
  147. {
  148. pWorld->WriteIndent();
  149. fprintf(fd, "PART 'p1' (\n");
  150. pWorld->Indent();
  151. int i, j, l;
  152. CVertexBuffer Vb;
  153. Vb.AddVertices(&m_Walls);
  154. Vb.AddVertices(&m_Portals);
  155. Vb.WriteCS(pWorld);
  156. for (i=0; i<m_Walls.Length(); i++)
  157. {
  158. CMapPolygonSet* pPolySet = m_Walls[i];
  159. for (j=0; j<pPolySet->GetPolygonCount(); j++)
  160. {
  161. CMapPolygon* pPolygon = pPolySet->GetPolygon(j);
  162. pWorld->WritePolygon(pPolygon, this, true, Vb);
  163. }
  164. }
  165. for (i=0; i<m_Portals.Length(); i++)
  166. {
  167. CIPortal* pPortal = m_Portals[i];
  168. for (j=0; j<pPortal->GetPolygonCount(); j++)
  169. {
  170. CMapPolygon* pPolygon = pPortal->GetPolygon(j);
  171. const CMapTexturedPlane* pPlane = pPortal->GetBaseplane();
  172. CTextureFile* pTexture = pPlane->GetTexture();
  173. //Because for a sector we draw the _inside_ of the brush, we spit out the
  174. //vertices in reverse order, so they will have proper orientation for
  175. //backface culling in the engine.
  176. pWorld->WriteIndent();
  177. fprintf(fd, "POLYGON '' ( VERTICES (");
  178. for (l=pPolygon->GetVertexCount()-1; l>=0; l--)
  179. {
  180. fprintf(fd, "%d%s", Vb.GetIndex(pPolygon->GetVertex(l)),
  181. ((l==0) ? "" : ","));
  182. }
  183. fprintf(fd, ") "); //End of Vertices
  184. //print textureinfo
  185. fprintf(fd, "MATERIAL('%s') ", pTexture->GetTexturename());
  186. fprintf(fd, "TEXTURE(PLANE ('%s')) ", pPolygon->GetBaseplane()->GetName());
  187. fprintf(fd, "PORTAL ('%s') ", pPortal->GetTargetSector()->GetName());
  188. fprintf(fd, ")\n"); //End of Polygon
  189. }
  190. }
  191. pWorld->Unindent();
  192. pWorld->WriteIndent();
  193. fprintf(fd, ")\n"); //PART
  194. } //if contains any polygons
  195. }
  196. WriteWorldspawn(pWorld);
  197. pWorld->Unindent();
  198. pWorld->WriteIndent();
  199. fprintf(fd, ")\n"); //End of PARAMS
  200. pWorld->Unindent();
  201. pWorld->WriteIndent();
  202. fprintf(fd, ")\n"); //End of MESHOBJ
  203. WriteFog(pWorld);
  204. WriteLights(pWorld);
  205. WriteCurves(pWorld);
  206. WriteThings(pWorld);
  207. WriteSprites(pWorld);
  208. WriteSprites2D(pWorld);
  209. WriteNodes (pWorld);
  210. if (pMap->GetConfigInt("Map2CS.General.UseBSP", 0))
  211. {
  212. pWorld->WriteIndent();
  213. fprintf(fd, "CULLER('static')\n");
  214. }
  215. pWorld->Unindent();
  216. pWorld->WriteIndent();
  217. fprintf(fd, ")\n\n"); //End of SECTOR(
  218. return true;
  219. }
  220. bool CCSSector::WriteWorldspawn(CIWorld* pWorld)
  221. {
  222. int i;
  223. for (i=0; i<m_Things.Length(); i++)
  224. {
  225. if (strcasecmp(m_Things[i]->GetClassname(), "worldspawn")==0)
  226. {
  227. if (!((CCSThing*)m_Things[i])->WriteAsPart(pWorld, this))
  228. {
  229. return false;
  230. }
  231. }
  232. }
  233. return true;
  234. }
  235. bool CCSSector::WriteThings(CIWorld* pWorld)
  236. {
  237. int i;
  238. for (i=0; i<m_Things.Length(); i++)
  239. {
  240. if (strcasecmp(m_Things[i]->GetClassname(), "worldspawn")!=0)
  241. {
  242. if (!m_Things[i]->Write(pWorld, this))
  243. {
  244. return false;
  245. }
  246. }
  247. }
  248. return true;
  249. }
  250. bool CCSSector::WriteLights(CIWorld* pWorld)
  251. {
  252. assert(pWorld);
  253. CMapFile* pMap = pWorld->GetMap();
  254. FILE* fd = pWorld->GetFile();
  255. double ScaleFactor = pWorld->GetScalefactor();
  256. assert(pMap);
  257. assert(fd);
  258. fprintf(fd, "\n");
  259. int i;
  260. //iterate all entities, brushes, polygons and vertices:
  261. for (i=0; i<pMap->GetNumEntities(); i++)
  262. {
  263. CMapEntity* pEntity = pMap->GetEntity(i);
  264. if (strcmp(pEntity->GetClassname(), "light")==0)
  265. {
  266. CdVector3 origin;
  267. if (pEntity->GetOrigin(origin))
  268. {
  269. if (IsInside(origin))
  270. {
  271. //The entity is identified as light and has a valid position.
  272. //There seem to be multiple versions of light formats, so I will
  273. //try out every format I know of.
  274. //I will prefer the "_light" format provided by Half-Life, because
  275. //this will allow colored light. If there is no "_light" statement,
  276. //we will look for a "light" key, which will only contain the radius.
  277. bool LightOk = false;
  278. double r = 255;
  279. double g = 255;
  280. double b = 255;
  281. double radius = 200;
  282. bool dynamic = false;
  283. double halo = 0;
  284. double halointen = 0;
  285. double halocross = 0;
  286. char attenuation[99] = "none";
  287. const char* lightvalue = pEntity->GetValueOfKey("_light");
  288. if (lightvalue)
  289. {
  290. char dummy;
  291. if (sscanf(lightvalue, "%lf %lf %lf %lf%c", &r, &g, &b, &radius, &dummy)==4)
  292. {
  293. LightOk = true;
  294. }
  295. }
  296. if (!LightOk)
  297. {
  298. radius = pEntity->GetNumValueOfKey("light", 100);
  299. r = 255;
  300. g = 255;
  301. b = 255;
  302. }
  303. //dynamic light key
  304. dynamic = pEntity->GetBoolValueOfKey("dynamic", false);
  305. //halo light key
  306. pEntity->GetTripleNumValueOfKey("halo", halo, halointen, halocross);
  307. //attenuation light key
  308. const char* attenuationlightvalue = pEntity->GetValueOfKey("attenuation");
  309. if (attenuationlightvalue)
  310. {
  311. char dummy;
  312. if (sscanf(attenuationlightvalue, "%s%c",attenuation, &dummy) == 1)
  313. {
  314. if (!(strcmp(attenuation,"none") || strcmp(attenuation,"linear") ||
  315. strcmp(attenuation,"inverse") || strcmp(attenuation,"realistic")))
  316. {
  317. strcpy( attenuation , "realistic" );
  318. }
  319. }
  320. else
  321. {
  322. strcpy( attenuation , "realistic" );
  323. }
  324. }
  325. //We have a correct light definition
  326. float lightscale = pWorld->GetMap()->GetConfigFloat(
  327. "Map2CS.General.LightScale", 3);
  328. //Anyway, if we scale light normally they will be far to small.
  329. //It looks like Crystal Space uses a different algo for lights,
  330. //so we will scale them up a bit. (Maybe the factor should be
  331. //configurable in the future)
  332. pWorld->WriteIndent();
  333. fprintf(fd, "LIGHT (");
  334. fprintf(fd, "CENTER (%g,%g,%g) ",
  335. origin.x*ScaleFactor,
  336. origin.z*ScaleFactor,
  337. origin.y*ScaleFactor);
  338. fprintf(fd, "RADIUS (%g) ",radius*ScaleFactor*lightscale);
  339. fprintf(fd, "COLOR (%g,%g,%g) ",
  340. (r/255) * (radius/128),
  341. (g/255) * (radius/128),
  342. (b/255) * (radius/128));
  343. if (dynamic)
  344. {
  345. fprintf(fd, "DYNAMIC () ");
  346. }
  347. fprintf(fd, "HALO (%g,%g,%g) ",
  348. (halo),
  349. (halointen),
  350. (halocross));
  351. fprintf(fd, "ATTENUATION (%s) ",attenuation);
  352. fprintf(fd, ")\n\n");
  353. } //if (light is inside this sector)
  354. } // if (entity had origin)
  355. } //if (classname == "light")
  356. } //for (all entities)
  357. return true;
  358. }
  359. /// Write all nodes inside the sector
  360. bool CCSSector::WriteNodes(CIWorld* pWorld)
  361. {
  362. assert(pWorld);
  363. FILE* fd = pWorld->GetFile();
  364. assert(fd);
  365. double ScaleFactor = pWorld->GetScalefactor();
  366. //iterate all nodes
  367. int i;
  368. for (i=0; i<m_Nodes.Length(); i++)
  369. {
  370. CMapEntity* pEntity = m_Nodes[i];
  371. CdVector3 Origin(0,0,0);
  372. pEntity->GetOrigin(Origin);
  373. if (strcmp(pEntity->GetValueOfKey("classname"),"cs_model")){
  374. pWorld->WriteIndent();
  375. fprintf(fd, "NODE '%s' (\n", pEntity->GetName());
  376. pWorld->Indent();
  377. CCSWorld::WriteKeys(pWorld, pEntity);
  378. pWorld->WriteIndent();
  379. fprintf(fd, "POSITION(%g,%g,%g)\n",
  380. Origin.x*ScaleFactor,
  381. Origin.z*ScaleFactor,
  382. Origin.y*ScaleFactor);
  383. pWorld->Unindent();
  384. pWorld->WriteIndent();
  385. fprintf(fd, ")\n");
  386. }
  387. }
  388. return true;
  389. }
  390. bool CCSSector::WriteCurves(CIWorld* pWorld)
  391. {
  392. assert(pWorld);
  393. CMapFile* pMap = pWorld->GetMap();
  394. FILE* fd = pWorld->GetFile();
  395. assert(pMap);
  396. assert(fd);
  397. int i, curve;
  398. for (i=0; i<pMap->GetNumEntities(); i++)
  399. {
  400. CMapEntity* pEntity = pMap->GetEntity(i);
  401. int const ncurves = pEntity->GetCurveCount();
  402. if (ncurves>0)
  403. {
  404. for (curve=0; curve<ncurves; curve++)
  405. {
  406. CMapCurve* pCurve = pEntity->GetCurve(curve);
  407. CTextureFile* pTexture = pCurve->GetTexture();
  408. if (pTexture->IsVisible())
  409. {
  410. pWorld->WriteIndent();
  411. fprintf(fd, "MESHOBJ '%s_e%d_c%d'(\n",pEntity->GetName(), i, curve);
  412. pWorld->Indent();
  413. pWorld->WriteIndent();
  414. fprintf(fd, "PLUGIN('thing')\n");
  415. pWorld->WriteIndent();
  416. fprintf(fd, "ZUSE()\n");
  417. pWorld->WriteIndent();
  418. fprintf(fd, "PRIORITY('object')\n");
  419. CCSWorld::WriteKeys(pWorld, pEntity);
  420. pWorld->WriteIndent();
  421. fprintf(fd, "PARAMS(\n");
  422. pWorld->Indent();
  423. pWorld->WriteIndent();
  424. fprintf(fd, "FACTORY ('curve_%s') \n", pCurve->GetName());
  425. pWorld->Unindent();
  426. pWorld->WriteIndent();
  427. fprintf(fd, ")\n"); //PARAMS
  428. pWorld->WriteIndent();
  429. fprintf(fd, "MOVE (V (0,0,0))\n");
  430. pWorld->Unindent();
  431. pWorld->WriteIndent();
  432. fprintf(fd, ")\n\n"); //MESHOBJ
  433. }
  434. }
  435. }
  436. }
  437. return true;
  438. }
  439. /// Write all 3D sprites inside the sector
  440. //SPRITE 'testbot'
  441. // (
  442. // TEMPLATE ('tree.mdl', 'base')
  443. // MOVE (V (-3,-3,2) )
  444. // )
  445. //also added MIXMODE for 3Dsprites
  446. //MIXMODE arguments (can be combined)
  447. // COPY () //=SRC
  448. // ADD () //=SRC+DST
  449. // MULTIPLY () //=SRC*DST
  450. // MULTIPLY2 () //=2*SRC*DST
  451. // ALPHA (alpha) //=(1-alpha)*SRC + alpha*DST
  452. // TRANSPARENT () //=DST
  453. // KEYCOLOR () // color 0 is transparent
  454. bool CCSSector::WriteSprites(CIWorld* pWorld)
  455. {
  456. assert(pWorld);
  457. CMapFile* pMap = pWorld->GetMap();
  458. FILE* fd = pWorld->GetFile();
  459. double ScaleFactor = pWorld->GetScalefactor();
  460. //const char* modelscale = "1"; //df added matrix scaler
  461. assert(pMap);
  462. assert(fd);
  463. fprintf(fd, "\n");
  464. int i;
  465. char mdlname[99] = "none";
  466. //char action[99] = "none";
  467. // char alphastr[99] = "none";
  468. //iterate all entities, brushes, polygons and vertices:
  469. for (i=0; i<pMap->GetNumEntities(); i++)
  470. {
  471. CMapEntity* pEntity = pMap->GetEntity(i);
  472. assert(pEntity);
  473. const char* classname = pEntity->GetClassname();
  474. assert(classname);
  475. if (strcmp(classname, "cs_model")==0)
  476. {
  477. const char* csnamevalue = pEntity->GetValueOfKey("cs_name");
  478. const char* csmodelfile = pEntity->GetValueOfKey("ModelFile");
  479. const char* csactionsfile = pEntity->GetValueOfKey("ActionsFile");
  480. const char* csscalefactor = pEntity->GetValueOfKey("ScaleFactor");
  481. const char* csspritematerial =
  482. pEntity->GetValueOfKey("SpriteMaterial");
  483. const char* csfactmaterial =
  484. pEntity->GetValueOfKey("FactoryMaterial");
  485. const char* csstaticmodel = pEntity->GetValueOfKey("StaticModel");
  486. CdVector3 Origin;
  487. pEntity->GetOrigin(Origin);
  488. char* csfactname = GetFactoryName(csmodelfile);
  489. if (csnamevalue)
  490. {
  491. //TEMPLATE ('tree.mdl', 'base')
  492. char dummy;
  493. if (sscanf(csnamevalue, "%s%c",mdlname, &dummy) == 1)
  494. {
  495. pWorld->WriteIndent();
  496. fprintf(fd,"NODE 'SEED_MESH_OBJ' (\n");
  497. // Key/Value pairs writting
  498. pWorld->Indent();
  499. pWorld->WriteIndent();
  500. fprintf(fd,"KEY(\"classname\",\"SEED_MESH_OBJ\")\n");
  501. pWorld->WriteIndent();
  502. fprintf(fd,"KEY(\"cs_name\",\"%s\")\n",csnamevalue);
  503. /*Lets build all material definition
  504. *keys KEY("defmaterial","materialname, texturefile")
  505. * It will declare materials until BuildMateriaKey returns a NULL
  506. */
  507. int mIndex; //material Index
  508. char* key;
  509. for (mIndex = 1; (key = BuildMaterialKey(mIndex,pEntity)); mIndex++)
  510. {
  511. pWorld->WriteIndent();
  512. fprintf(fd,key);
  513. }
  514. pWorld->WriteIndent();
  515. fprintf(fd,"KEY(\"spritematerial\",\"%s\")\n",csspritematerial);
  516. pWorld->WriteIndent();
  517. fprintf(fd,"KEY(\"factory\",\"%s\")\n",csfactname);
  518. pWorld->WriteIndent();
  519. fprintf(fd,"KEY(\"factorymaterial\",\"%s\")\n",csfactmaterial);
  520. pWorld->WriteIndent();
  521. /*
  522. * CAUTION!!! If factory isn't loaded for this sprite
  523. * the material must be loaded already, or, at least in material
  524. * list of this model. Otherwise you will obtain a crash
  525. * (factory without material error)
  526. */
  527. fprintf(fd,"KEY(\"factoryfile\",\"%s\")\n",csmodelfile);
  528. /*
  529. * MDL files have actions defined so if model file is an mdl we
  530. * don't need action file. Here we check for file extension, it
  531. * won't work if you put a non mdl files with mdl extension
  532. */
  533. pWorld->WriteIndent();
  534. if(!isMdlFile(csmodelfile))
  535. fprintf(fd,"KEY(\"actionsfile\",\"%s\")\n",csactionsfile);
  536. else fprintf(fd,"KEY(\"actionfile\",\"NONE\"\n");
  537. pWorld->WriteIndent();
  538. fprintf(fd,"KEY(\"scalefactor\",\"%s\")\n",csscalefactor);
  539. pWorld->WriteIndent();
  540. fprintf(fd,"KEY(\"staticflag\",\"%s\")\n",csstaticmodel);
  541. pWorld->WriteIndent();
  542. fprintf(fd, "POSITION( %g, %g, %g)\n",Origin.x*ScaleFactor,
  543. Origin.z*ScaleFactor, Origin.y*ScaleFactor);
  544. pWorld->Unindent();
  545. pWorld->WriteIndent();
  546. fprintf(fd,")\n\n");
  547. pWorld->Unindent();
  548. pWorld->WriteIndent();
  549. /*
  550. pWorld->WriteIndent();
  551. fprintf(fd, "MESHREF '%s' \n", csnamevalue);
  552. pWorld->WriteIndent();
  553. fprintf(fd, "( \n");
  554. pWorld->Indent();
  555. pWorld->WriteIndent();
  556. fprintf(fd, "FACTORY ('%s')\n ", csnamevaluefact);
  557. fprintf(fd, "PRIORITY ('Object')\n ");
  558. fprintf(fd, "ZUSE( )\n ");
  559. */
  560. /*const char* actionvalue = pEntity->GetValueOfKey("action");
  561. if (sscanf(actionvalue, "%s%c",action, &dummy) == 1)
  562. {
  563. fprintf(fd, "'%s' )\n", action);
  564. }
  565. */
  566. //END OF MODIFIED CODE
  567. }
  568. /*double x, y, z;
  569. if (pEntity->GetTripleNumValueOfKey("origin", x,y,z))
  570. {
  571. //The strings format matched
  572. pWorld->WriteIndent();
  573. fprintf(fd, "MOVE (V ( %g, %g, %g) ",
  574. x*ScaleFactor,
  575. z*ScaleFactor,
  576. y*ScaleFactor);
  577. //TODO: mixmode; add other keys
  578. //const char* alphavalue = pEntity->GetValueOfKey("alpha");
  579. //if (sscanf(alphavalue, "%s%c",alphastr, &dummy) == 1)
  580. //{
  581. //pWorld->WriteIndent();
  582. //fprintf(fd, "MIXMODE (ALPHA (%s))\n", alphastr);
  583. //}
  584. //added single value matrix scaler
  585. //need to also add 9 value matrix for rotation etc
  586. //if (pEntity->GetValueOfKey("uniformscale", modelscale))
  587. //{
  588. //fprintf(fd, " MATRIX ( %s ) )\n", modelscale);
  589. //}
  590. //else
  591. //{
  592. //fprintf(fd, " )\n"); //add newline if no scale value
  593. //}
  594. //
  595. //pWorld->Unindent();
  596. //pWorld->WriteIndent();
  597. //fprintf(fd, ") \n\n");
  598. */
  599. // }
  600. }
  601. }
  602. }
  603. return true;
  604. }
  605. //Write all 2D sprites inside the sector
  606. //SPRITE 'spritename'
  607. // (
  608. // VERTICES (-1,1,1,1,1,-1) //triangular polygon
  609. // UV (0,0,1,0,1,1) //texture coordinates
  610. // TEXNR (texture.gif) //texture name
  611. // MOVE (-3,-3,2) //initial start position
  612. // MIXMODE (ALPHA (.5)) //settings below
  613. // COLORS (1,0,0,0,1,0,0,0,1) //vertex color array
  614. // )
  615. //MIXMODE arguments (can be combined)
  616. // COPY () //=SRC
  617. // ADD () //=SRC+DST
  618. // MULTIPLY () //=SRC*DST
  619. // MULTIPLY2 () //=2*SRC*DST
  620. // ALPHA (alpha) //=(1-alpha)*SRC + alpha*DST
  621. // TRANSPARENT () //=DST
  622. // KEYCOLOR () // color 0 is transparent
  623. bool CCSSector::WriteSprites2D(CIWorld* pWorld)
  624. {
  625. assert(pWorld);
  626. CMapFile* pMap = pWorld->GetMap();
  627. FILE* fd = pWorld->GetFile();
  628. double ScaleFactor = pWorld->GetScalefactor();
  629. assert(pMap);
  630. assert(fd);
  631. fprintf(fd, "\n");
  632. int i;
  633. //iterate all entities, brushes, polygons and vertices:
  634. for (i=0; i<pMap->GetNumEntities(); i++)
  635. {
  636. CMapEntity* pEntity = pMap->GetEntity(i);
  637. assert(pEntity);
  638. char sprname[99] = "none";
  639. char dummy;
  640. const char* classname = pEntity->GetClassname();
  641. assert(classname);
  642. if (strcmp(classname, "cs_sprite")==0)
  643. {
  644. const char* csnamevalue = pEntity->GetValueOfKey("cs_name");
  645. if (csnamevalue)
  646. {
  647. if (sscanf(csnamevalue, "%s%c",sprname, &dummy) == 1)
  648. {
  649. pWorld->WriteIndent();
  650. fprintf(fd, "SPRITE2D '%s' \n", sprname);
  651. pWorld->WriteIndent();
  652. fprintf(fd, "( \n");
  653. //vertices; add square sprite polygon
  654. pWorld->Indent();
  655. pWorld->WriteIndent();
  656. fprintf(fd, "VERTICES (-1,1,1,1,1,-1,-1,-1)\n");
  657. //UV; add square texture coordinates
  658. pWorld->WriteIndent();
  659. fprintf(fd, "UV (0,0,1,0,1,1,0,1)\n");
  660. pWorld->WriteIndent();
  661. const char* spritetexture = pEntity->GetValueOfKey("texture");
  662. fprintf(fd, "MATERIAL (%s)\n", spritetexture);
  663. //initial start position
  664. double x, y, z;
  665. if (pEntity->GetTripleNumValueOfKey("origin", x,y,z))
  666. {
  667. //The strings format matched
  668. pWorld->WriteIndent();
  669. fprintf(fd, "MOVE ( %g, %g, %g )\n ",
  670. x*ScaleFactor,
  671. z*ScaleFactor,
  672. y*ScaleFactor);
  673. }
  674. //mixmode
  675. pWorld->WriteIndent();
  676. fprintf(fd, "MIXMODE ( ");
  677. bool copy = pEntity->GetBoolValueOfKey("copy", false);
  678. if (copy)
  679. {
  680. fprintf(fd, "COPY () ");
  681. }
  682. bool add = pEntity->GetBoolValueOfKey("add", false);
  683. if (add)
  684. {
  685. fprintf(fd, "ADD () ");
  686. }
  687. bool multiply = pEntity->GetBoolValueOfKey("multiply", false);
  688. if (multiply)
  689. {
  690. fprintf(fd, "MULTIPLY ( ) ");
  691. }
  692. bool multiply2 = pEntity->GetBoolValueOfKey("multiply2", false);
  693. if (multiply2)
  694. {
  695. fprintf(fd, "MULTIPLY2 ( ) ");
  696. }
  697. char alphastr[99] = "none";
  698. const char* alphavalue = pEntity->GetValueOfKey("alpha");
  699. if (sscanf(alphavalue, "%s%c",alphastr, &dummy) == 1)
  700. {
  701. fprintf(fd, "ALPHA (%s) ", alphastr);
  702. }
  703. bool transparent = pEntity->GetBoolValueOfKey("transparent", false);
  704. if (transparent)
  705. {
  706. fprintf(fd, "TRANSPARENT ( ) ");
  707. }
  708. bool keycolor = pEntity->GetBoolValueOfKey("keycolor", false);
  709. if (keycolor)
  710. {
  711. fprintf(fd, "KEYCOLOR ( ) ");
  712. }
  713. fprintf(fd, ")\n");
  714. pWorld->Unindent();
  715. pWorld->WriteIndent();
  716. fprintf(fd, ") \n\n");
  717. }
  718. }
  719. }
  720. }
  721. return true;
  722. }
  723. bool CCSSector::WriteFog(CIWorld* pWorld)
  724. {
  725. assert(pWorld);
  726. CMapFile* pMap = pWorld->GetMap();
  727. FILE* fd = pWorld->GetFile();
  728. assert(pMap);
  729. assert(fd);
  730. fprintf(fd, "\n");
  731. double r=255.0;
  732. double g=255.0;
  733. double b=255.0;
  734. //iterate all entities, brushes, polygons and vertices:
  735. int i;
  736. for (i=0; i<pMap->GetNumEntities(); i++)
  737. {
  738. CMapEntity* pEntity = pMap->GetEntity(i);
  739. assert(pEntity);
  740. const char* classname = pEntity->GetClassname();
  741. assert(classname);
  742. if (strcmp(classname, "fog")==0)
  743. {
  744. double fogdensity = pEntity->GetNumValueOfKey("fogdensity", 0.0);
  745. if (fogdensity>0.0)
  746. {
  747. pEntity->GetTripleNumValueOfKey("fogcolor", r, g, b);
  748. pWorld->WriteIndent();
  749. fprintf(fd, "FOG(%g,%g,%g,%g)\n", r/255.0, g/255.0, b/255.0, fogdensity);
  750. }
  751. }
  752. }
  753. return true;
  754. }