afTerrainPVS.cpp
上传用户:kaiguan
上传日期:2007-10-28
资源大小:1074k
文件大小:5k
源码类别:

其他游戏

开发平台:

Visual C++

  1. #include "afTerrainPVS.h"
  2. #include <assert.h>
  3. #include <math.h>
  4. #include <string.h>
  5. #include <stdio.h>
  6. afTerrainPVS::afTerrainPVS()
  7. {
  8. dataX = dataY = dataZ = 0;
  9. dataDZ = 0;
  10. data = (unsigned char*)0;
  11. }
  12. afTerrainPVS::~afTerrainPVS()
  13. {
  14. if(data)
  15. delete data;
  16. }
  17. void afTerrainPVS::calc(const unsigned char* nMinData,
  18.    const unsigned char* nMaxData,
  19.    unsigned int nX, unsigned int nY, unsigned int nZ, unsigned int nDZ)
  20. {
  21. dataX = nX;
  22. dataY = nY;
  23. dataZ = nZ;
  24. dataDZ = nDZ;
  25. unsigned int numData = dataZ * dataY * dataX * dataY * dataX,
  26. dataCount = 0,
  27. dstX,dstY, srcX,srcY,srcZ,srcZC;
  28. dataSize = (numData+7)/8; // +7 => round upwards
  29. data = new unsigned char[dataSize];
  30. memset(data, 0, dataSize);
  31. for(srcZ=dataDZ-1,srcZC=0; srcZC<dataZ; srcZ+=dataDZ,srcZC++)
  32. for(srcY=0; srcY<dataY; srcY++)
  33. for(srcX=0; srcX<dataX; srcX++)
  34. for(dstY=0; dstY<dataY; dstY++)
  35. for(dstX=0; dstX<dataX; dstX++)
  36. {
  37. if(srcZ>500)
  38. srcZ = srcZ;
  39. unsigned char hMax = nMaxData[dstX + dstY*dataX];
  40. float p, step = 1.0f / (float)sqrt((dstX-srcX)*(dstX-srcX) + (dstY-srcY)*(dstY-srcY)),
  41. dx = (float)dstX-srcX,
  42. dy = (float)dstY-srcY,
  43. dz = (float)hMax-srcZ;
  44. setVisible(srcX,srcY,srcZC, dstX,dstY, true);
  45. for(p=0.0f; p<=1.0f; p+=step)
  46. {
  47. int x = (int)(srcX + dx*p),
  48. y = (int)(srcY + dy*p),
  49. z = (int)(srcZ + dz*p);
  50. if(z < nMinData[x + y*dataX])
  51. {
  52. //vis = 0;
  53. setVisible(srcX,srcY,srcZC, dstX,dstY, false);
  54. break;
  55. }
  56. }
  57. dataCount++;
  58. }
  59. assert(dataCount == numData);
  60. }
  61. void afTerrainPVS::shrink()
  62. {
  63. afTerrainPVS* oldPVS = new afTerrainPVS();
  64. oldPVS->dataX = dataX;
  65. oldPVS->dataY = dataY;
  66. oldPVS->dataZ = dataZ;
  67. oldPVS->dataDZ = dataDZ;
  68. oldPVS->data = data;
  69. oldPVS->dataSize = dataSize;
  70. dataX /= 2;
  71. dataY /= 2;
  72. unsigned int numData = dataZ * dataY * dataX * dataY * dataX;
  73. dataSize = (numData+7)/8; // +7 => round upwards
  74. data = new unsigned char[dataSize];
  75. memset(data, 0, dataSize);
  76. unsigned int srcX,srcY,srcZ,dstX,dstY, xs,ys,xd,yd;
  77. for(srcZ=0; srcZ<dataZ; srcZ++)
  78. for(srcY=0; srcY<dataY; srcY++)
  79. for(srcX=0; srcX<dataX; srcX++)
  80. for(dstY=0; dstY<dataY; dstY++)
  81. for(dstX=0; dstX<dataX; dstX++)
  82. {
  83. for(ys=0; ys<2; ys++)
  84. for(xs=0; xs<2; xs++)
  85. for(yd=0; yd<2; yd++)
  86. for(xd=0; xd<2; xd++)
  87. if(oldPVS->isVisible(2*srcX+xs,2*srcY+ys,srcZ, 2*dstX+xd,2*dstY+yd))
  88. {
  89. setVisible(srcX,srcY,srcZ, dstX,dstY, true);
  90. xs = ys = xd = yd = 2;
  91. }
  92. }
  93. delete oldPVS;
  94. }
  95. bool afTerrainPVS::save(const char* nFileName)
  96. {
  97. if(!data)
  98. return false;
  99. FILE* fp = fopen(nFileName, "wb");
  100. unsigned int size;
  101. if(!fp)
  102. return false;
  103. fwrite("TERPVS", 1, 6, fp);
  104. fputc(dataX, fp);
  105. fputc(dataY, fp);
  106. fputc(dataZ, fp);
  107. fputc(dataDZ, fp);
  108. size = fwrite(data, 1, dataSize, fp);
  109. fclose(fp);
  110. return size==dataSize;
  111. }
  112. bool afTerrainPVS::load(const char* nFileName)
  113. {
  114. FILE* fp = fopen(nFileName, "rb");
  115. unsigned int size;
  116. if(!fp)
  117. return false;
  118. char start[6];
  119. fread(start, 1, 6, fp);
  120. if(strncmp("TERPVS", start, 6))
  121. return false;
  122. dataX = fgetc(fp);
  123. dataY = fgetc(fp);
  124. dataZ = fgetc(fp);
  125. dataDZ = fgetc(fp);
  126. unsigned int numData = dataZ * dataY * dataX * dataY * dataX;
  127. dataSize = (numData+7)/8; // +7 => round upwards
  128. if(data)
  129. delete data;
  130. data = new unsigned char[dataSize];
  131. size = fread(data, 1, dataSize, fp);
  132. fclose(fp);
  133. return size==dataSize;
  134. }
  135. void afTerrainPVS::setVisible(int nX0, int nY0, int nZ0, int nX1, int nY1, bool nValue)
  136. {
  137. unsigned int idx = getIdx(nX0,nY0,nZ0, nX1,nY1);
  138. int midx = idx>>3,
  139. sidx = idx&7;
  140. unsigned char mask = (unsigned char)(1 << sidx);
  141. assert(idx < dataZ * dataY * dataX * dataY * dataX);
  142. if(nValue)
  143. data[midx] |= mask;
  144. else
  145. data[midx] &= ~mask;
  146. }
  147. bool afTerrainPVS::isVisible(int nX0, int nY0, int nZ0, int nX1, int nY1) const
  148. {
  149. //if(dataDZ==0)
  150. // return true;
  151. //nZ0 /= dataDZ;
  152. if(nX0<0 || nX0>=(signed)dataX || nY0<0 || nY0>=(signed)dataY || nZ0<0 || nZ0>=(signed)dataZ ||
  153.    nX1<0 || nX1>=(signed)dataX || nY1<0 || nY1>=(signed)dataX)
  154. return true;
  155. unsigned int idx = getIdx(nX0,nY0,nZ0, nX1,nY1);
  156. int midx = idx>>3,
  157. sidx = idx&7;
  158. unsigned char mask = (unsigned char)(1 << sidx);
  159. return (data[midx] & mask) != 0;
  160. }
  161. unsigned int afTerrainPVS::getIdx(int nX0, int nY0, int nZ0, int nX1, int nY1) const
  162. {
  163. return nZ0 * dataX*dataY*dataX*dataY + nY0 * dataX*dataX*dataY + nX0 * dataX*dataY + nY1 * dataX + nX1;
  164. }