cm_terrainmap.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. #include "../server/exe_headers.h"
  2. #include "cm_local.h"
  3. #include "cm_patch.h"
  4. #include "cm_landscape.h"
  5. #include "../game/genericparser2.h"
  6. //#include "image.h"
  7. //#include "../qcommon/q_imath.h"
  8. #include "cm_terrainmap.h"
  9. #include "cm_draw.h"
  10. #include "../png/png.h"
  11. static CTerrainMap *TerrainMap = 0;
  12. void R_CreateAutomapImage( const char *name, const byte *pic, int width, int height,
  13. qboolean mipmap, qboolean allowPicmip, qboolean allowTC, int glWrapClampMode );
  14. // simple function for getting a proper color for a side
  15. inline CPixel32 SideColor(int side)
  16. {
  17. CPixel32 col(255,255,255);
  18. switch (side)
  19. {
  20. default:
  21. break;
  22. case SIDE_BLUE:
  23. col = CPixel32(0,0,192);
  24. break;
  25. case SIDE_RED:
  26. col = CPixel32(192,0,0);
  27. break;
  28. }
  29. return col;
  30. }
  31. CTerrainMap::CTerrainMap(CCMLandScape *landscape) :
  32. mLandscape(landscape)
  33. {
  34. ApplyBackground();
  35. ApplyHeightmap();
  36. CDraw32 draw;
  37. draw.SetBuffer((CPixel32*) mImage);
  38. draw.SetBufferSize(TM_WIDTH,TM_HEIGHT,TM_WIDTH);
  39. // create version with paths and water shown
  40. int x,y;
  41. int water;
  42. int land;
  43. for (y=0; y<TM_HEIGHT; y++)
  44. for (x=0; x<TM_WIDTH; x++)
  45. {
  46. CPixel32 cp = ((CPixel32*)mBufImage)[PIXPOS(x,y,TM_WIDTH)];
  47. land = CLAMP(((255 - cp.a)*2)/3,0,255);
  48. water = CLAMP((landscape->GetBaseWaterHeight() - cp.a)*4, 0, 255);
  49. cp.a = 255;
  50. if (x > TM_BORDER && x < (TM_WIDTH-TM_BORDER) &&
  51. y > TM_BORDER && y < (TM_WIDTH-TM_BORDER))
  52. {
  53. cp = ALPHA_PIX (CPixel32(0,0,0), cp, land, 256-land);
  54. if (water > 0)
  55. cp = ALPHA_PIX (CPixel32(0,0,255), cp, water, 256-water);
  56. }
  57. draw.PutPix(x, y, cp);
  58. }
  59. // Load icons for symbols on map
  60. GLenum format;
  61. #ifdef _XBOX
  62. int mipcount;
  63. R_LoadImage("gfx/menus/rmg/start", (byte**)&mSymStart, &mSymStartWidth, &mSymStartHeight, &mipcount, &format);
  64. R_LoadImage("gfx/menus/rmg/end", (byte**)&mSymEnd, &mSymEndWidth, &mSymEndHeight, &mipcount, &format);
  65. R_LoadImage("gfx/menus/rmg/objective", (byte**)&mSymObjective, &mSymObjectiveWidth, &mSymObjectiveHeight, &mipcount, &format);
  66. R_LoadImage("gfx/menus/rmg/building", (byte**)&mSymBld, &mSymBldWidth, &mSymBldHeight, &mipcount, &format);
  67. #else
  68. R_LoadImage("gfx/menus/rmg/start", (byte**)&mSymStart, &mSymStartWidth, &mSymStartHeight, &format);
  69. R_LoadImage("gfx/menus/rmg/end", (byte**)&mSymEnd, &mSymEndWidth, &mSymEndHeight, &format);
  70. R_LoadImage("gfx/menus/rmg/objective", (byte**)&mSymObjective, &mSymObjectiveWidth, &mSymObjectiveHeight, &format);
  71. R_LoadImage("gfx/menus/rmg/building", (byte**)&mSymBld, &mSymBldWidth, &mSymBldHeight, &format);
  72. #endif
  73. }
  74. CTerrainMap::~CTerrainMap()
  75. {
  76. if (mSymStart)
  77. {
  78. Z_Free(mSymStart);
  79. mSymStart = NULL;
  80. }
  81. if (mSymEnd)
  82. {
  83. Z_Free(mSymEnd);
  84. mSymEnd = NULL;
  85. }
  86. if (mSymBld)
  87. {
  88. Z_Free(mSymBld);
  89. mSymBld = NULL;
  90. }
  91. if (mSymObjective)
  92. {
  93. Z_Free(mSymObjective);
  94. mSymObjective = NULL;
  95. }
  96. CDraw32::CleanUp();
  97. }
  98. void CTerrainMap::ApplyBackground(void)
  99. {
  100. int x, y;
  101. byte *outPos;
  102. float xRel, yRel, xInc, yInc;
  103. byte *backgroundImage;
  104. int backgroundWidth, backgroundHeight, backgroundDepth;
  105. int pos;
  106. GLenum format;
  107. memset(mImage, 255, sizeof(mBufImage));
  108. // R_LoadImage("textures\\kamchatka\\ice", &backgroundImage, &backgroundWidth, &backgroundHeight, &format);0
  109. backgroundDepth = 4;
  110. #ifdef _XBOX
  111. int mipcount;
  112. R_LoadImage("gfx\\menus\\rmg\\01_bg", &backgroundImage, &backgroundWidth, &backgroundHeight, &mipcount, &format);
  113. #else
  114. R_LoadImage("gfx\\menus\\rmg\\01_bg", &backgroundImage, &backgroundWidth, &backgroundHeight, &format);
  115. #endif
  116. if (backgroundImage)
  117. {
  118. outPos = (byte *)mBufImage;
  119. xInc = (float)backgroundWidth / (float)TM_WIDTH;
  120. yInc = (float)backgroundHeight / (float)TM_HEIGHT;
  121. yRel = 0.0;
  122. for(y=0;y<TM_HEIGHT;y++)
  123. {
  124. xRel = 0.0;
  125. for(x=0;x<TM_WIDTH;x++)
  126. {
  127. pos = ((((int)yRel)*backgroundWidth) + ((int)xRel)) * 4;
  128. *outPos = backgroundImage[pos++];
  129. outPos++;
  130. *outPos = backgroundImage[pos++];
  131. outPos++;
  132. *outPos = backgroundImage[pos];
  133. outPos+=2;
  134. xRel += xInc;
  135. }
  136. yRel += yInc;
  137. }
  138. Z_Free(backgroundImage);
  139. }
  140. }
  141. void CTerrainMap::ApplyHeightmap(void)
  142. {
  143. int x, y;
  144. byte *inPos = mLandscape->GetHeightMap();
  145. int width = mLandscape->GetRealWidth();
  146. int height = mLandscape->GetRealHeight();
  147. byte *outPos;
  148. unsigned tempColor;
  149. float xRel, yRel, xInc, yInc;
  150. int count;
  151. outPos = (byte *)mBufImage;
  152. outPos += (((TM_BORDER * TM_WIDTH) + TM_BORDER) * 4);
  153. xInc = (float)width / (float)(TM_REAL_WIDTH);
  154. yInc = (float)height / (float)(TM_REAL_HEIGHT);
  155. // add in height map as alpha
  156. yRel = 0.0;
  157. for(y=0;y<TM_REAL_HEIGHT;y++)
  158. {
  159. // x is flipped!
  160. xRel = width;
  161. for(x=0;x<TM_REAL_WIDTH;x++)
  162. {
  163. count = 1;
  164. tempColor = inPos[(((int)yRel)*width) + ((int)xRel)];
  165. if (yRel >= 1.0)
  166. {
  167. tempColor += inPos[(((int)(yRel-0.5))*width) + ((int)xRel)];
  168. count++;
  169. }
  170. if (yRel <= height-2)
  171. {
  172. tempColor += inPos[(((int)(yRel+0.5))*width) + ((int)xRel)];
  173. count++;
  174. }
  175. if (xRel >= 1.0)
  176. {
  177. tempColor += inPos[(((int)(yRel))*width) + ((int)(xRel-0.5))];
  178. count++;
  179. }
  180. if (xRel <= width-2)
  181. {
  182. tempColor += inPos[(((int)(yRel))*width) + ((int)(xRel+0.5))];
  183. count++;
  184. }
  185. tempColor /= count;
  186. outPos[3] = tempColor;
  187. outPos += 4;
  188. // x is flipped!
  189. xRel -= xInc;
  190. }
  191. outPos += TM_BORDER * 4 * 2;
  192. yRel += yInc;
  193. }
  194. }
  195. // Convert position in game coords to automap coords
  196. void CTerrainMap::ConvertPos(int& x, int& y)
  197. {
  198. x = ((x - mLandscape->GetMins()[0]) / mLandscape->GetSize()[0]) * TM_REAL_WIDTH;
  199. y = ((y - mLandscape->GetMins()[1]) / mLandscape->GetSize()[1]) * TM_REAL_HEIGHT;
  200. // x is flipped!
  201. x = TM_REAL_WIDTH - x - 1;
  202. // border
  203. x += TM_BORDER;
  204. y += TM_BORDER;
  205. }
  206. void CTerrainMap::AddStart(int x, int y, int side)
  207. {
  208. ConvertPos(x, y);
  209. CDraw32 draw;
  210. draw.BlitColor(x-mSymStartWidth/2, y-mSymStartHeight/2, mSymStartWidth, mSymStartHeight,
  211. (CPixel32*)mSymStart, 0, 0, mSymStartWidth, SideColor(side));
  212. }
  213. void CTerrainMap::AddEnd(int x, int y, int side)
  214. {
  215. ConvertPos(x, y);
  216. CDraw32 draw;
  217. draw.BlitColor(x-mSymEndWidth/2, y-mSymEndHeight/2, mSymEndWidth, mSymEndHeight,
  218. (CPixel32*)mSymEnd, 0, 0, mSymEndWidth, SideColor(side));
  219. }
  220. void CTerrainMap::AddObjective(int x, int y, int side)
  221. {
  222. ConvertPos(x, y);
  223. CDraw32 draw;
  224. draw.BlitColor(x-mSymObjectiveWidth/2, y-mSymObjectiveHeight/2, mSymObjectiveWidth, mSymObjectiveHeight,
  225. (CPixel32*)mSymObjective, 0, 0, mSymObjectiveWidth, SideColor(side));
  226. }
  227. void CTerrainMap::AddBuilding(int x, int y, int side)
  228. {
  229. ConvertPos(x, y);
  230. CDraw32 draw;
  231. draw.BlitColor(x-mSymBldWidth/2, y-mSymBldHeight/2, mSymBldWidth, mSymBldHeight,
  232. (CPixel32*)mSymBld, 0, 0, mSymBldWidth, SideColor(side));
  233. }
  234. void CTerrainMap::AddNPC(int x, int y, bool friendly)
  235. {
  236. ConvertPos(x, y);
  237. CDraw32 draw;
  238. if (friendly)
  239. draw.DrawCircle(x,y,3, CPixel32(0,192,0), CPixel32(0,0,0,0));
  240. else
  241. draw.DrawCircle(x,y,3, CPixel32(192,0,0), CPixel32(0,0,0,0));
  242. }
  243. void CTerrainMap::AddNode(int x, int y)
  244. {
  245. ConvertPos(x, y);
  246. CDraw32 draw;
  247. draw.DrawCircle(x,y,20, CPixel32(255,255,255), CPixel32(0,0,0,0));
  248. }
  249. void CTerrainMap::AddWallRect(int x, int y, int side)
  250. {
  251. ConvertPos(x, y);
  252. CDraw32 draw;
  253. switch (side)
  254. {
  255. default:
  256. draw.DrawBox(x-1,y-1,3,3,CPixel32(192,192,192,128));
  257. break;
  258. case SIDE_BLUE:
  259. draw.DrawBox(x-1,y-1,3,3,CPixel32(0,0,192,128));
  260. break;
  261. case SIDE_RED:
  262. draw.DrawBox(x-1,y-1,3,3,CPixel32(192,0,0,128));
  263. break;
  264. }
  265. }
  266. void CTerrainMap::AddPlayer(vec3_t origin, vec3_t angles)
  267. {
  268. // draw player start on automap
  269. CDraw32 draw;
  270. vec3_t up;
  271. vec3_t pt[4] = {{0,0,0},{-5,-5,0},{10,0,0},{-5,5,0}};
  272. vec3_t p;
  273. int x,y,i;
  274. float facing;
  275. POINT poly[4];
  276. facing = angles[1];
  277. up[0] = 0;
  278. up[1] = 0;
  279. up[2] = 1;
  280. x = (int)origin[0];
  281. y = (int)origin[1];
  282. ConvertPos(x, y);
  283. x++; y++;
  284. for (i=0; i<4; i++)
  285. {
  286. RotatePointAroundVector( p, up, pt[i], facing );
  287. poly[i].x = (int)(-p[0] + x);
  288. poly[i].y = (int)(p[1] + y);
  289. }
  290. // draw arrowhead shadow
  291. draw.DrawPolygon(4, poly, CPixel32(0,0,0,128), CPixel32(0,0,0,128));
  292. // draw arrowhead
  293. for (i=0; i<4; i++)
  294. {
  295. poly[i].x--;
  296. poly[i].y--;
  297. }
  298. draw.DrawPolygon(4, poly, CPixel32(255,255,255), CPixel32(255,255,255));
  299. }
  300. void CTerrainMap::Upload(vec3_t player_origin, vec3_t player_angles)
  301. {
  302. CDraw32 draw;
  303. // copy completed map to mBufImage
  304. draw.SetBuffer((CPixel32*) mBufImage);
  305. draw.SetBufferSize(TM_WIDTH,TM_HEIGHT,TM_WIDTH);
  306. draw.Blit(0, 0, TM_WIDTH, TM_HEIGHT,
  307. (CPixel32*)mImage, 0, 0, TM_WIDTH);
  308. // now draw player's location on map
  309. if (player_origin)
  310. {
  311. AddPlayer(player_origin, player_angles);
  312. }
  313. draw.SetAlphaBuffer(255);
  314. R_CreateAutomapImage("*automap", (unsigned char *)draw.buffer, TM_WIDTH, TM_HEIGHT, qfalse, qfalse, qtrue, qfalse);
  315. draw.SetBuffer((CPixel32*) mImage);
  316. }
  317. void CTerrainMap::SaveImageToDisk(const char * terrainName, const char * missionName, const char * seed)
  318. {
  319. //ri.COM_SavePNG(va("save/%s_%s_%s.png", terrainName, missionName, seed),
  320. // (unsigned char *)mImage, TM_WIDTH, TM_HEIGHT, 4);
  321. //rww - Use JPG here? This function seems to be only for debugging anyway.
  322. // PNG_Save(va("save/%s_%s_%s.png", terrainName, missionName, seed),
  323. // (unsigned char *)mImage, TM_WIDTH, TM_HEIGHT, 4);
  324. }
  325. void CM_TM_Create(CCMLandScape *landscape)
  326. {
  327. if (TerrainMap)
  328. {
  329. CM_TM_Free();
  330. }
  331. TerrainMap = new CTerrainMap(landscape);
  332. }
  333. void CM_TM_Free(void)
  334. {
  335. if (TerrainMap)
  336. {
  337. delete TerrainMap;
  338. TerrainMap = 0;
  339. }
  340. }
  341. void CM_TM_AddStart(int x, int y, int side)
  342. {
  343. if (TerrainMap)
  344. {
  345. TerrainMap->AddStart(x, y, side);
  346. }
  347. }
  348. void CM_TM_AddEnd(int x, int y, int side)
  349. {
  350. if (TerrainMap)
  351. {
  352. TerrainMap->AddEnd(x, y, side);
  353. }
  354. }
  355. void CM_TM_AddObjective(int x, int y, int side)
  356. {
  357. if (TerrainMap)
  358. {
  359. TerrainMap->AddObjective(x, y, side);
  360. }
  361. }
  362. void CM_TM_AddNPC(int x, int y, bool friendly)
  363. {
  364. if (TerrainMap)
  365. {
  366. TerrainMap->AddNPC(x, y, friendly);
  367. }
  368. }
  369. void CM_TM_AddNode(int x, int y)
  370. {
  371. if (TerrainMap)
  372. {
  373. TerrainMap->AddNode(x, y);
  374. }
  375. }
  376. void CM_TM_AddBuilding(int x, int y, int side)
  377. {
  378. if (TerrainMap)
  379. {
  380. TerrainMap->AddBuilding(x, y, side);
  381. }
  382. }
  383. void CM_TM_AddWallRect(int x, int y, int side)
  384. {
  385. if (TerrainMap)
  386. {
  387. TerrainMap->AddWallRect(x, y, side);
  388. }
  389. }
  390. void CM_TM_Upload(vec3_t player_origin, vec3_t player_angles)
  391. {
  392. if (TerrainMap)
  393. {
  394. TerrainMap->Upload(player_origin, player_angles);
  395. }
  396. }
  397. void CM_TM_SaveImageToDisk(const char * terrainName, const char * missionName, const char * seed)
  398. {
  399. if (TerrainMap)
  400. { // write out automap
  401. TerrainMap->SaveImageToDisk(terrainName, missionName, seed);
  402. }
  403. }
  404. void CM_TM_ConvertPosition(int &x, int &y, int Width, int Height)
  405. {
  406. if (TerrainMap)
  407. {
  408. TerrainMap->ConvertPos(x, y);
  409. x = x * Width / TM_WIDTH;
  410. y = y * Height / TM_HEIGHT;
  411. }
  412. }