1 /*
2  Copyright (c) 2013 yvt
3 
4  This file is part of OpenSpades.
5 
6  OpenSpades is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  OpenSpades is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with OpenSpades.  If not, see <http://www.gnu.org/licenses/>.
18 
19  */
20 
21 #include "GLFlatMapRenderer.h"
22 #include <Client/GameMap.h>
23 #include <Core/Bitmap.h>
24 #include <Core/Debug.h>
25 #include "GLImage.h"
26 #include "GLRenderer.h"
27 
28 namespace spades {
29 	namespace draw {
GLFlatMapRenderer(GLRenderer * r,client::GameMap * m)30 		GLFlatMapRenderer::GLFlatMapRenderer(GLRenderer *r, client::GameMap *m)
31 		    : renderer(r), map(m) {
32 			SPADES_MARK_FUNCTION();
33 
34 			chunkRows = m->Height() >> ChunkBits;
35 			chunkCols = m->Width() >> ChunkBits;
36 			for (int i = 0; i < chunkRows * chunkCols; i++)
37 				chunkInvalid.push_back(false);
38 
39 			Handle<Bitmap> bmp(GenerateBitmap(0, 0, m->Width(), m->Height()), false);
40 			try {
41 				image = static_cast<GLImage *>(renderer->CreateImage(bmp));
42 			} catch (...) {
43 				throw;
44 			}
45 
46 			image->Bind(IGLDevice::Texture2D);
47 			IGLDevice *dev = renderer->GetGLDevice();
48 			dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter,
49 			                  IGLDevice::Nearest);
50 			dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter,
51 			                  IGLDevice::Nearest);
52 		}
53 
~GLFlatMapRenderer()54 		GLFlatMapRenderer::~GLFlatMapRenderer() { image->Release(); }
55 
GenerateBitmap(int mx,int my,int w,int h)56 		Bitmap *GLFlatMapRenderer::GenerateBitmap(int mx, int my, int w, int h) {
57 			SPADES_MARK_FUNCTION();
58 			Handle<Bitmap> bmp(new Bitmap(w, h), false);
59 			try {
60 				uint32_t *pixels = bmp->GetPixels();
61 
62 				for (int y = 0; y < h; y++) {
63 					for (int x = 0; x < w; x++) {
64 						int px = mx + x, py = my + y;
65 						for (int z = 0; z < 64; z++) {
66 							if (map->IsSolid(px, py, z)) {
67 								uint32_t col = map->GetColor(px, py, z);
68 								col |= 0xff000000UL;
69 								*pixels = col;
70 								break;
71 							}
72 						}
73 						pixels++;
74 					}
75 				}
76 			} catch (...) {
77 				throw;
78 			}
79 			return bmp.Unmanage();
80 		}
81 
GameMapChanged(int x,int y,int z,client::GameMap * map)82 		void GLFlatMapRenderer::GameMapChanged(int x, int y, int z, client::GameMap *map) {
83 			if (map != this->map)
84 				return;
85 
86 			SPAssert(x >= 0);
87 			SPAssert(x < map->Width());
88 			SPAssert(y >= 0);
89 			SPAssert(y < map->Height());
90 			SPAssert(z >= 0);
91 			SPAssert(z < map->Depth());
92 
93 			int chunkX = x >> ChunkBits;
94 			int chunkY = y >> ChunkBits;
95 			int chunkId = chunkX + chunkY * chunkCols;
96 			SPAssert(chunkId >= 0);
97 			SPAssert(chunkId < chunkCols * chunkRows);
98 			chunkInvalid[chunkId] = true;
99 		}
100 
Draw(const AABB2 & dest,const AABB2 & src)101 		void GLFlatMapRenderer::Draw(const AABB2 &dest, const AABB2 &src) {
102 			SPADES_MARK_FUNCTION();
103 
104 			// update chunks
105 			for (size_t i = 0; i < chunkInvalid.size(); i++) {
106 				if (!chunkInvalid[i])
107 					continue;
108 				int chunkX = ((int)i) % chunkCols;
109 				int chunkY = ((int)i) / chunkCols;
110 
111 				Handle<Bitmap> bmp(
112 				  GenerateBitmap(chunkX * ChunkSize, chunkY * ChunkSize, ChunkSize, ChunkSize),
113 				  false);
114 				try {
115 					image->SubImage(bmp, chunkX * ChunkSize, chunkY * ChunkSize);
116 				} catch (...) {
117 					throw;
118 				}
119 				chunkInvalid[i] = false;
120 			}
121 
122 			renderer->DrawImage(image, dest, src);
123 		}
124 	}
125 }
126