PageRenderTime 28ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/legacy_one/trunk/hardware/hw_trick.c

#
C | 1018 lines | 674 code | 142 blank | 202 comment | 177 complexity | 75d0d49f7beed2404ed84b1f327793fd MD5 | raw file
Possible License(s): GPL-2.0
  1. // Emacs style mode select -*- C++ -*-
  2. //-----------------------------------------------------------------------------
  3. //
  4. // $Id: hw_trick.c 823 2011-03-17 18:53:01Z smite-meister $
  5. //
  6. // Copyright (C) 1998-2001 by DooM Legacy Team.
  7. //
  8. // This program is free software; you can redistribute it and/or
  9. // modify it under the terms of the GNU General Public License
  10. // as published by the Free Software Foundation; either version 2
  11. // of the License, or (at your option) any later version.
  12. //
  13. // This program is distributed in the hope that it will be useful,
  14. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. // GNU General Public License for more details.
  17. //
  18. //
  19. // $Log: hw_trick.c,v $
  20. // Revision 1.10 2002/07/26 15:22:44 hurdler
  21. // near RC release
  22. //
  23. // Revision 1.9 2001/12/26 17:24:47 hurdler
  24. // Update Linux version
  25. //
  26. // Revision 1.8 2001/05/14 19:02:58 metzgermeister
  27. // * Fixed floor not moving up with player on E3M1
  28. // * Fixed crash due to oversized string in screen message ... bad bug!
  29. // * Corrected some typos
  30. // * fixed sound bug in SDL
  31. //
  32. // Revision 1.7 2001/05/07 15:55:05 hurdler
  33. // temporary "fix" for heretic
  34. //
  35. // Revision 1.6 2001/04/11 21:14:11 metzgermeister
  36. // *** empty log message ***
  37. //
  38. // Revision 1.5 2001/04/10 18:39:39 metzgermeister
  39. // fixed a (possible?) crash bug
  40. //
  41. // Revision 1.4 2001/04/09 23:26:06 hurdler
  42. // clean up
  43. //
  44. // Revision 1.3 2001/04/09 20:23:12 metzgermeister
  45. // more conservative trick treatment
  46. //
  47. // Revision 1.2 2001/03/26 19:47:56 metzgermeister
  48. // more tricky things
  49. //
  50. // Revision 1.1 2001/03/25 18:11:24 metzgermeister
  51. // * SDL sound bug with swapped stereo channels fixed
  52. // * separate hw_trick.c now for HW_correctSWTrick(.)
  53. //
  54. //
  55. //
  56. // DESCRIPTION:
  57. // special trick routines to make some SW tricks look OK with
  58. // HW rendering. This includes:
  59. // - deepwatereffect (e.g. tnt/map02)
  60. // - invisible staircase (e.g. eternal/map02)
  61. // - floating ceilings (e.g. eternal/map03)
  62. //
  63. // It is not guaranteed that it looks identical to the SW mode,
  64. // but it looks in most of the cases far better than having
  65. // holes in the architecture, HOM, etc.
  66. //
  67. // It fixes as well missing textures, which are replaced by either
  68. // a default texture or the midtexture.
  69. //
  70. // words of notice:
  71. // pseudosectors, as mentioned in this file, are sectors where both
  72. // sidedefs point to the same sector. This expression is also used
  73. // for sectors which are enclosed by another sector but have no
  74. // correct sidedefs at all
  75. //
  76. // if a vertex is inside a poly is determined by the angles between
  77. // this vertex and all angles on the linedefs (imagine walking along
  78. // a circle always facing a certain point inside/outside the circle;
  79. // if inside, angle have taken all values [0..\pi), otherwise the
  80. // range was < \pi/2
  81. //
  82. //
  83. //-----------------------------------------------------------------------------
  84. #include <math.h>
  85. #include "hw_glob.h"
  86. #include "../r_local.h"
  87. #include "../i_system.h"
  88. //
  89. // add a line to a sectors list of lines
  90. //
  91. static void addLineToChain(sector_t *sector, line_t *line)
  92. {
  93. linechain_t *thisElem, *nextElem;
  94. if(NULL == sector)
  95. return;
  96. thisElem = NULL;
  97. nextElem = sector->sectorLines;
  98. while(NULL != nextElem) // walk through chain
  99. {
  100. thisElem = nextElem;
  101. nextElem = thisElem->next;
  102. }
  103. // add a new element into the chain
  104. if(thisElem)
  105. {
  106. thisElem->next = malloc(sizeof(linechain_t));
  107. if(thisElem->next)
  108. {
  109. thisElem->next->line = line;
  110. thisElem->next->next = NULL;
  111. }
  112. else
  113. {
  114. I_Error("Out of memory in addLineToChain(.)\n");
  115. }
  116. }
  117. else // first element in chain
  118. {
  119. sector->sectorLines = malloc(sizeof(linechain_t));
  120. if(sector->sectorLines)
  121. {
  122. sector->sectorLines->line = line;
  123. sector->sectorLines->next = NULL;
  124. }
  125. else
  126. {
  127. I_Error("Out of memory in addLineToChain(.)\n");
  128. }
  129. }
  130. }
  131. //
  132. // We don´t want a memory hole, do we? ;-)
  133. //
  134. static void releaseLineChains(void)
  135. {
  136. linechain_t *thisElem, *nextElem;
  137. sector_t *sector;
  138. int i;
  139. for(i=0; i<numsectors; i++)
  140. {
  141. sector = &sectors[i];
  142. nextElem = sector->sectorLines;
  143. while(NULL != nextElem)
  144. {
  145. thisElem = nextElem;
  146. nextElem = thisElem->next;
  147. free(thisElem);
  148. }
  149. sector->sectorLines = NULL;
  150. }
  151. }
  152. //
  153. // check if a pseudo sector is valid by checking all it´s linedefs
  154. //
  155. static boolean isPSectorValid(sector_t *sector)
  156. {
  157. linechain_t *thisElem, *nextElem;
  158. if(!sector->pseudoSector) // check only pseudosectors, others don´t care
  159. {
  160. #ifdef PARANOIA
  161. CONS_Printf("Alert! non-pseudosector fed to isPSectorClosed()\n");
  162. #endif
  163. return false;
  164. }
  165. nextElem = sector->sectorLines;
  166. while(NULL != nextElem)
  167. {
  168. thisElem = nextElem;
  169. nextElem = thisElem->next;
  170. if(thisElem->line->frontsector != thisElem->line->backsector)
  171. return false;
  172. }
  173. return true;
  174. }
  175. //
  176. // angles are always phiMax-phiMin [0...2\pi)
  177. //
  178. static double phiDiff(double phiMin, double phiMax)
  179. {
  180. double result;
  181. result = phiMax-phiMin;
  182. if(result < 0.0)
  183. result += 2.0*PI;
  184. return result;
  185. }
  186. //
  187. // sort phi's so that enclosed angle < \pi
  188. //
  189. static void sortPhi(double phi1, double phi2, double *phiMin, double *phiMax)
  190. {
  191. if(phiDiff(phi1, phi2) < PI)
  192. {
  193. *phiMin = phi1;
  194. *phiMax = phi2;
  195. }
  196. else
  197. {
  198. *phiMin = phi2;
  199. *phiMax = phi1;
  200. }
  201. }
  202. //
  203. // return if angle(phi1, phi2) is bigger than \pi
  204. // if so, the vertex lies inside the poly
  205. //
  206. static boolean biggerThanPi(double phi1, double phi2)
  207. {
  208. if(phiDiff(phi1, phi2) > PI)
  209. return true;
  210. return false;
  211. }
  212. #define DELTAPHI (PI/100.0) // some small phi << \pi
  213. //
  214. // calculate bounds for minimum angle
  215. //
  216. void phiBounds(double phi1, double phi2, double *phiMin, double *phiMax)
  217. {
  218. double phi1Tmp, phi2Tmp;
  219. double psi1, psi2, psi3, psi4, psi5, psi6, psi7; // for optimization
  220. sortPhi(phi1, phi2, &phi1Tmp, &phi2Tmp);
  221. phi1 = phi1Tmp;
  222. phi2 = phi2Tmp;
  223. // check start condition
  224. if(*phiMin > PI || *phiMax > PI)
  225. {
  226. *phiMin = phi1;
  227. *phiMax = phi2;
  228. return;
  229. }
  230. // 6 cases:
  231. // new angles inbetween phiMin, phiMax -> forget it
  232. // new angles enclose phiMin -> set phiMin
  233. // new angles enclose phiMax -> set phiMax
  234. // new angles completely outside phiMin, phiMax -> leave largest area free
  235. // new angles close the range completely!
  236. // new angles enlarges range on both sides
  237. psi1 = phiDiff(*phiMin, phi1);
  238. psi2 = phiDiff(*phiMin, phi2);
  239. psi3 = phiDiff(*phiMax, phi1);
  240. psi4 = phiDiff(*phiMax, phi2);
  241. psi5 = phiDiff(*phiMin, *phiMax);
  242. psi6 = 2.0*PI - psi5; // phiDiff(*phiMax, *phiMin);
  243. psi7 = 2.0*PI - psi2; // phiDiff(phi2, *phiMin);
  244. // case 1 & 5!
  245. if((psi1 <= psi5) && (psi2 <= psi5))
  246. {
  247. if(psi1 <= psi2) // case 1
  248. {
  249. return;
  250. }
  251. else // case 5
  252. {
  253. // create some artificial interval here not to get into numerical trouble
  254. // in fact we know now the sector is completely enclosed -> base for computational optimization
  255. *phiMax = 0.0;
  256. *phiMin = DELTAPHI;
  257. return;
  258. }
  259. }
  260. // case 2
  261. if((psi1 >= psi5) && (psi2 <= psi5))
  262. {
  263. *phiMin = phi1;
  264. return;
  265. }
  266. // case 3
  267. if((psi3 >= psi6) && (psi4 <= psi6))
  268. {
  269. *phiMax = phi2;
  270. return;
  271. }
  272. // case 4 & 6
  273. #ifdef PARANOIA
  274. if((psi3 <= psi6) && (psi4 <= psi6)) // FIXME: isn't this case implicitly true anyway??
  275. #endif
  276. {
  277. if(psi3 <= psi4) //case 4
  278. {
  279. if(psi3 >= psi7)
  280. {
  281. *phiMin = phi1;
  282. return;
  283. }
  284. else
  285. {
  286. *phiMax = phi2;
  287. return;
  288. }
  289. }
  290. else // case 6
  291. {
  292. *phiMin = phi1;
  293. *phiMax = phi2;
  294. return;
  295. }
  296. }
  297. I_OutputMsg("phiMin = %f, phiMax = %f, phi1 = %f, phi2 = %f\n", *phiMin, *phiMax, phi1, phi2);
  298. I_Error("Holy shit, phiBounds() freaked out\n");
  299. }
  300. //
  301. // Check if a vertex lies inside a sector
  302. // This works for "well-behaved" convex polygons
  303. // If we need it mathematically correct, we need to sort the
  304. // linedefs first so we have them in a row, then walk along the linedefs,
  305. // but this is a bit overdone
  306. //
  307. boolean isVertexInside(vertex_t *vertex, sector_t *sector)
  308. {
  309. double xa, ya, xe, ye;
  310. linechain_t *chain;
  311. double phiMin, phiMax;
  312. double phi1, phi2;
  313. chain = sector->sectorLines;
  314. phiMin = phiMax = 10.0*PI; // some value > \pi
  315. while(chain)
  316. {
  317. // start and end vertex
  318. xa = (double)chain->line->v1->x - (double)vertex->x;
  319. ya = (double)chain->line->v1->y - (double)vertex->y;
  320. xe = (double)chain->line->v2->x - (double)vertex->x;
  321. ye = (double)chain->line->v2->y - (double)vertex->y;
  322. // angle phi of connection between the vertices and the x-axis
  323. phi1 = atan2(ya, xa);
  324. phi2 = atan2(ye, xe);
  325. // if we have just started, we can have to create start bounds for phi
  326. phiBounds(phi1, phi2, &phiMin, &phiMax);
  327. chain = chain->next;
  328. }
  329. return biggerThanPi(phiMin, phiMax);
  330. }
  331. #define MAXSTACK 256 // Not more than 256 polys in each other?
  332. //
  333. // generate a list of sectors which enclose the given sector
  334. //
  335. static void generateStacklist(sector_t *thisSector)
  336. {
  337. int i;
  338. int stackCnt;
  339. sector_t *locStacklist[MAXSTACK];
  340. sector_t *checkSector;
  341. stackCnt = 0;
  342. for(i=0; i<numsectors; i++)
  343. {
  344. checkSector = &sectors[i];
  345. if(checkSector == thisSector) // don´t check self
  346. continue;
  347. // buggy sector?
  348. if(NULL == thisSector->sectorLines)
  349. continue;
  350. // check if an arbitrary vertex of thisSector lies inside the checkSector
  351. if(isVertexInside(thisSector->sectorLines->line->v1, checkSector))
  352. {
  353. // if so, the thisSector lies inside the checkSector
  354. locStacklist[stackCnt] = checkSector;
  355. stackCnt++;
  356. if(MAXSTACK-1 == stackCnt) // beware of the SIGSEGV! and consider terminating NULL!
  357. break;
  358. }
  359. }
  360. thisSector->stackList = malloc(sizeof(sector_t*) * (stackCnt+1));
  361. if(NULL == thisSector->stackList)
  362. {
  363. I_Error("Out of memory error in generateStacklist()");
  364. }
  365. locStacklist[stackCnt] = NULL; // terminating NULL
  366. memcpy(thisSector->stackList, locStacklist, sizeof(sector_t*) * (stackCnt+1));
  367. }
  368. //
  369. // Bubble sort the stacklist with rising lineoutlengths
  370. //
  371. static void sortStacklist(sector_t *sector)
  372. {
  373. sector_t **list;
  374. sector_t *sec1, *sec2;
  375. boolean finished;
  376. int i;
  377. list = sector->stackList;
  378. finished = false;
  379. if(NULL == *list)
  380. return; // nothing to sort
  381. while(!finished)
  382. {
  383. i=0;
  384. finished = true;
  385. while(NULL != *(list+i+1))
  386. {
  387. sec1 = *(list+i);
  388. sec2 = *(list+i+1);
  389. if(sec1->lineoutLength > sec2->lineoutLength)
  390. {
  391. *(list+i) = sec2;
  392. *(list+i+1) = sec1;
  393. finished = false;
  394. }
  395. i++;
  396. }
  397. }
  398. }
  399. //
  400. // length of a line in euclidian sense
  401. //
  402. static double lineLength(line_t *line)
  403. {
  404. double dx, dy, length;
  405. dx = (double) line->v1->x - (double) line->v2->x;
  406. dy = (double) line->v1->y - (double) line->v2->y;
  407. length = sqrt(dx*dx + dy*dy);
  408. return length;
  409. }
  410. //
  411. // length of the sector lineout
  412. //
  413. static double calcLineoutLength(sector_t *sector)
  414. {
  415. linechain_t *chain;
  416. double length;
  417. length = 0.0;
  418. chain = sector->sectorLines;
  419. while(NULL != chain) // sum up lengths of all lines
  420. {
  421. length += lineLength(chain->line);
  422. chain = chain->next;
  423. }
  424. return length;
  425. }
  426. //
  427. // Calculate length of the sectors lineout
  428. //
  429. static void calcLineouts(sector_t *sector)
  430. {
  431. sector_t *encSector;
  432. int secCount;
  433. secCount = 0;
  434. encSector = *(sector->stackList);
  435. while(NULL != encSector)
  436. {
  437. if(encSector->lineoutLength < 0.0) // if length has not yet been calculated
  438. {
  439. encSector->lineoutLength = calcLineoutLength(encSector);
  440. }
  441. secCount++;
  442. encSector = *((sector->stackList) + secCount);
  443. }
  444. }
  445. //
  446. // Free Stacklists of all sectors
  447. //
  448. static void freeStacklists(void)
  449. {
  450. int i;
  451. for(i=0; i<numsectors; i++)
  452. {
  453. if(sectors[i].stackList)
  454. {
  455. free(sectors[i].stackList);
  456. sectors[i].stackList = NULL;
  457. }
  458. }
  459. }
  460. //
  461. // if more than half of the toptextures are missing
  462. //
  463. static boolean areToptexturesMissing(sector_t *thisSector)
  464. {
  465. linechain_t *thisElem, *nextElem;
  466. sector_t *frontSector, *backSector;
  467. int nomiss;
  468. side_t *sdl, *sdr;
  469. thisElem = NULL;
  470. nextElem = thisSector->sectorLines;
  471. nomiss = 0;
  472. while(NULL != nextElem) // walk through chain
  473. {
  474. thisElem = nextElem;
  475. nextElem = thisElem->next;
  476. frontSector = thisElem->line->frontsector;
  477. backSector = thisElem->line->backsector;
  478. if(frontSector == backSector) // skip damn renderer tricks here
  479. {
  480. continue;
  481. }
  482. if(frontSector == NULL || backSector == NULL)
  483. {
  484. continue;
  485. }
  486. sdr = &sides[thisElem->line->sidenum[0]];
  487. sdl = &sides[thisElem->line->sidenum[1]];
  488. if(backSector->ceilingheight < frontSector->ceilingheight)
  489. {
  490. // texture num are either 0=no-texture, or valid
  491. if(sdr->toptexture != 0)
  492. {
  493. nomiss++;
  494. break; // we can stop here if decision criterium is ==0
  495. }
  496. }
  497. else if(backSector->ceilingheight > frontSector->ceilingheight)
  498. {
  499. // texture num are either 0=no-texture, or valid
  500. if(sdl->toptexture != 0)
  501. {
  502. nomiss++;
  503. break; // we can stop here if decision criterium is ==0
  504. }
  505. }
  506. }
  507. return nomiss == 0;
  508. }
  509. //
  510. // are more textures missing than present?
  511. //
  512. static boolean areBottomtexturesMissing(sector_t *thisSector)
  513. {
  514. linechain_t *thisElem, *nextElem;
  515. sector_t *frontSector, *backSector;
  516. int nomiss;
  517. side_t *sdl, *sdr;
  518. thisElem = NULL;
  519. nextElem = thisSector->sectorLines;
  520. nomiss = 0;
  521. while(NULL != nextElem) // walk through chain
  522. {
  523. thisElem = nextElem;
  524. nextElem = thisElem->next;
  525. frontSector = thisElem->line->frontsector;
  526. backSector = thisElem->line->backsector;
  527. if(frontSector == backSector) // skip damn renderer tricks here
  528. {
  529. continue;
  530. }
  531. if(frontSector == NULL || backSector == NULL)
  532. {
  533. continue;
  534. }
  535. sdr = &sides[thisElem->line->sidenum[0]];
  536. sdl = &sides[thisElem->line->sidenum[1]];
  537. if(backSector->floorheight > frontSector->floorheight)
  538. {
  539. // texture num are either 0=no-texture, or valid
  540. if(sdr->bottomtexture != 0)
  541. {
  542. nomiss++;
  543. break; // we can stop here if decision criterium is ==0
  544. }
  545. }
  546. else if(backSector->floorheight < frontSector->floorheight)
  547. {
  548. // texture num are either 0=no-texture, or valid
  549. if(sdl->bottomtexture != 0)
  550. {
  551. nomiss++;
  552. break; // we can stop here if decision criterium is ==0
  553. }
  554. }
  555. }
  556. // return missing >= nomiss;
  557. return nomiss == 0;
  558. }
  559. //
  560. // check if no adjacent sector has same ceiling height
  561. //
  562. static boolean isCeilingFloating(sector_t *thisSector)
  563. {
  564. sector_t *adjSector, *refSector, *frontSector, *backSector;
  565. boolean floating = true;
  566. linechain_t *thisElem, *nextElem;
  567. if(NULL == thisSector)
  568. return false;
  569. refSector = NULL;
  570. thisElem = NULL;
  571. nextElem = thisSector->sectorLines;
  572. while(NULL != nextElem) // walk through chain
  573. {
  574. thisElem = nextElem;
  575. nextElem = thisElem->next;
  576. frontSector = thisElem->line->frontsector;
  577. backSector = thisElem->line->backsector;
  578. if(frontSector == thisSector)
  579. adjSector = backSector;
  580. else
  581. adjSector = frontSector;
  582. if(NULL == adjSector) // assume floating sectors have surrounding sectors
  583. {
  584. floating = false;
  585. break;
  586. }
  587. if(NULL == refSector)
  588. {
  589. refSector = adjSector;
  590. continue;
  591. }
  592. // if adjacent sector has same height or more than one adjacent sector exists -> stop
  593. if(thisSector->ceilingheight == adjSector->ceilingheight ||
  594. refSector != adjSector)
  595. {
  596. floating = false;
  597. break;
  598. }
  599. }
  600. // now check for walltextures
  601. if(floating)
  602. {
  603. if(!areToptexturesMissing(thisSector))
  604. {
  605. floating = false;
  606. }
  607. }
  608. return floating;
  609. }
  610. //
  611. // check if no adjacent sector has same ceiling height
  612. // FIXME: throw that together with isCeilingFloating??
  613. //
  614. static boolean isFloorFloating(sector_t *thisSector)
  615. {
  616. sector_t *adjSector, *refSector, *frontSector, *backSector;
  617. boolean floating = true;
  618. linechain_t *thisElem, *nextElem;
  619. if(NULL == thisSector)
  620. return false;
  621. refSector = NULL;
  622. thisElem = NULL;
  623. nextElem = thisSector->sectorLines;
  624. while(NULL != nextElem) // walk through chain
  625. {
  626. thisElem = nextElem;
  627. nextElem = thisElem->next;
  628. frontSector = thisElem->line->frontsector;
  629. backSector = thisElem->line->backsector;
  630. if(frontSector == thisSector)
  631. adjSector = backSector;
  632. else
  633. adjSector = frontSector;
  634. if(NULL == adjSector) // assume floating sectors have surrounding sectors
  635. {
  636. floating = false;
  637. break;
  638. }
  639. if(NULL == refSector)
  640. {
  641. refSector = adjSector;
  642. continue;
  643. }
  644. // if adjacent sector has same height or more than one adjacent sector exists -> stop
  645. if(thisSector->floorheight == adjSector->floorheight ||
  646. refSector != adjSector)
  647. {
  648. floating = false;
  649. break;
  650. }
  651. }
  652. // now check for walltextures
  653. if(floating)
  654. {
  655. if(!areBottomtexturesMissing(thisSector))
  656. {
  657. floating = false;
  658. }
  659. }
  660. return floating;
  661. }
  662. //
  663. // estimate ceilingheight according to height of adjacent sector
  664. //
  665. static fixed_t estimateCeilHeight(sector_t *thisSector)
  666. {
  667. sector_t *adjSector;
  668. if(NULL == thisSector ||
  669. NULL == thisSector->sectorLines ||
  670. NULL == thisSector->sectorLines->line)
  671. return 0;
  672. adjSector = thisSector->sectorLines->line->frontsector;
  673. if(adjSector == thisSector)
  674. adjSector = thisSector->sectorLines->line->backsector;
  675. if(NULL == adjSector)
  676. return 0;
  677. return adjSector->ceilingheight;
  678. }
  679. //
  680. // estimate ceilingheight according to height of adjacent sector
  681. //
  682. static fixed_t estimateFloorHeight(sector_t *thisSector)
  683. {
  684. sector_t *adjSector;
  685. if(NULL == thisSector ||
  686. NULL == thisSector->sectorLines ||
  687. NULL == thisSector->sectorLines->line)
  688. return 0;
  689. adjSector = thisSector->sectorLines->line->frontsector;
  690. if(adjSector == thisSector)
  691. adjSector = thisSector->sectorLines->line->backsector;
  692. if(NULL == adjSector)
  693. return 0;
  694. return adjSector->floorheight;
  695. }
  696. #define CORRECT_FLOAT_EXPERIMENTAL
  697. extern boolean raven; // true with heretic and hexen
  698. // --------------------------------------------------------------------------
  699. // Some levels have missing sidedefs, which produces HOM, so let´s try to compensate for that
  700. // and some levels have deep water trick, invisible staircases etc.
  701. // --------------------------------------------------------------------------
  702. // FIXME: put some nice default texture in legacy.dat and use it
  703. // Called from P_SetupLevel
  704. void HWR_CorrectSWTricks(void)
  705. {
  706. int i, k;
  707. line_t *ld;
  708. side_t *sdl = NULL, *sdr;
  709. sector_t *secl, *secr;
  710. sector_t **sectorList;
  711. sector_t *outSector;
  712. if ( (0 == cv_grcorrecttricks.value) || raven )
  713. return;
  714. // determine lines for sectors
  715. for(i=0; i<numlines; i++)
  716. {
  717. ld = &lines[i];
  718. secr = ld->frontsector;
  719. secl = ld->backsector;
  720. if(secr == secl)
  721. {
  722. secr->pseudoSector = true; // special renderer trick?
  723. addLineToChain(secr, ld);
  724. }
  725. else
  726. {
  727. addLineToChain(secr, ld);
  728. addLineToChain(secl, ld);
  729. }
  730. }
  731. // preprocessing
  732. for(i=0; i<numsectors; i++)
  733. {
  734. sector_t *checkSector;
  735. checkSector = &sectors[i];
  736. // identify real pseudosectors first
  737. if(checkSector->pseudoSector)
  738. {
  739. if(!isPSectorValid(checkSector)) // drop invalid pseudo sectors
  740. {
  741. checkSector->pseudoSector = false;
  742. }
  743. }
  744. // determine enclosing sectors for pseudosectors ... used later
  745. if(checkSector->pseudoSector)
  746. {
  747. generateStacklist(checkSector);
  748. calcLineouts(checkSector);
  749. sortStacklist(checkSector);
  750. }
  751. }
  752. // set virtual floor heights for pseudo sectors
  753. // required for deep water effect e.g.
  754. for(i=0; i<numsectors; i++)
  755. {
  756. if(sectors[i].pseudoSector)
  757. {
  758. sectorList = sectors[i].stackList;
  759. k = 0;
  760. while(*(sectorList+k))
  761. {
  762. outSector = *(sectorList+k);
  763. if(!outSector->pseudoSector)
  764. {
  765. sectors[i].virtualFloorheight = outSector->floorheight;
  766. sectors[i].virtualCeilingheight = outSector->ceilingheight;
  767. break;
  768. }
  769. k++;
  770. }
  771. if(*(sectorList+k) == NULL) // sorry, did not work :(
  772. {
  773. sectors[i].virtualFloorheight = sectors[i].floorheight;
  774. sectors[i].virtualCeilingheight = sectors[i].ceilingheight;
  775. }
  776. }
  777. }
  778. #ifdef CORRECT_FLOAT_EXPERIMENTAL
  779. // correct ceiling/floor heights of totally floating sectors
  780. for(i=0; i<numsectors; i++)
  781. {
  782. sector_t *floatSector;
  783. floatSector = &sectors[i];
  784. // correct height of floating sectors
  785. if(isCeilingFloating(floatSector))
  786. {
  787. fixed_t corrheight;
  788. corrheight = estimateCeilHeight(floatSector);
  789. floatSector->virtualCeilingheight = corrheight;
  790. floatSector->virtualCeiling = true;
  791. }
  792. if(isFloorFloating(floatSector))
  793. {
  794. fixed_t corrheight;
  795. corrheight = estimateFloorHeight(floatSector);
  796. floatSector->virtualFloorheight = corrheight;
  797. floatSector->virtualFloor = true;
  798. }
  799. }
  800. #endif
  801. // now for the missing textures
  802. for(i=0; i<numlines; i++)
  803. {
  804. ld = &lines[i];
  805. sdr = &sides[ld->sidenum[0]];
  806. if (ld->sidenum[1] != NULL_INDEX)
  807. {
  808. sdl = &sides[ld->sidenum[1]];
  809. }
  810. secr = ld->frontsector;
  811. secl = ld->backsector;
  812. if(secr == secl) // special renderer trick
  813. continue; // we can´t correct missing textures here
  814. if(NULL != secl) // only if there is a backsector
  815. {
  816. if(secr->pseudoSector || secl->pseudoSector)
  817. continue;
  818. if(!secr->virtualFloor && !secl->virtualFloor)
  819. {
  820. if(secl->floorheight > secr->floorheight)
  821. {
  822. // now check if r-sidedef is correct
  823. // texture num are either 0=no-texture, or valid
  824. if(sdr->bottomtexture == 0)
  825. {
  826. if(sdr->midtexture == 0)
  827. sdr->bottomtexture = R_TextureNumForName("STONE2");
  828. else
  829. sdr->bottomtexture = sdr->midtexture;
  830. }
  831. }
  832. else if(secl->floorheight < secr->floorheight)
  833. {
  834. // now check if l-sidedef is correct
  835. // texture num are either 0=no-texture, or valid
  836. if(sdl->bottomtexture == 0)
  837. {
  838. if(sdl->midtexture == 0)
  839. sdl->bottomtexture = R_TextureNumForName("STONE2");
  840. else
  841. sdl->bottomtexture = sdl->midtexture;
  842. }
  843. }
  844. }
  845. if(!secr->virtualCeiling && !secl->virtualCeiling)
  846. {
  847. if(secl->ceilingheight < secr->ceilingheight)
  848. {
  849. // now check if r-sidedef is correct
  850. // texture num are either 0=no-texture, or valid
  851. if(sdr->toptexture == 0)
  852. {
  853. if(sdr->midtexture == 0)
  854. sdr->toptexture = R_TextureNumForName("STONE2");
  855. else
  856. sdr->toptexture = sdr->midtexture;
  857. }
  858. }
  859. else if(secl->ceilingheight > secr->ceilingheight)
  860. {
  861. // now check if l-sidedef is correct
  862. if(sdl->toptexture == 0)
  863. {
  864. if(sdl->midtexture == 0)
  865. sdl->toptexture = R_TextureNumForName("STONE2");
  866. else
  867. sdl->toptexture = sdl->midtexture;
  868. }
  869. }
  870. }
  871. } // if(NULL != secl)
  872. } // for(i=0; i<numlines; i++)
  873. // release all linechains
  874. releaseLineChains();
  875. freeStacklists();
  876. }