OpenClonk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
C4FoWAmbient.cpp
Go to the documentation of this file.
1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 2014-2016, The OpenClonk Team and contributors
5  *
6  * Distributed under the terms of the ISC license; see accompanying file
7  * "COPYING" for details.
8  *
9  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
10  * See accompanying file "TRADEMARK" for details.
11  *
12  * To redistribute this file separately, substitute the full license texts
13  * for the above references.
14  */
15 
16 #include "C4Include.h"
19 #include "landscape/fow/C4FoW.h"
20 #include "graphics/C4Draw.h"
21 
22 namespace
23 {
24 
25 template<typename LightMap>
26 double AmbientForPix(int x0, int y0, double R, const LightMap& light_map)
27 {
28  double d = 0.;
29 
30  const int Ri = static_cast<int>(R);
31  for(int y = 1; y <= Ri; ++y)
32  {
33  // quarter circle
34  int max_x = static_cast<int>(sqrt(R * R - y * y));
35  for(int x = 1; x <= max_x; ++x)
36  {
37  const double l = sqrt(x*x + y*y);
38  assert(l <= R);
39 
40  if(light_map(x0 + x, y0 + y)) d += 1. / l;
41  if(light_map(x0 + x, y0 - y)) d += 1. / l;
42  if(light_map(x0 - x, y0 - y)) d += 1. / l;
43  if(light_map(x0 - x, y0 + y)) d += 1. / l;
44  }
45 
46  // Vertical/Horizontal lines
47  const double l = static_cast<double>(y);
48  if(light_map(x0 + y, y0)) d += 1. / l;
49  if(light_map(x0 - y, y0)) d += 1. / l;
50  if(light_map(x0, y0 + y)) d += 1. / l;
51  if(light_map(x0, y0 - y)) d += 1. / l;
52  }
53 
54  // Central pix
55  if(light_map(x0, y0)) d += 2 * sqrt(M_PI); // int_0^2pi int_0^1/sqrt(pi) 1/r dr r dphi
56 
57  return d;
58 }
59 
60 // Everything is illuminated, independent of the landscape
61 // This is used to obtain the normalization factor
62 struct LightMapFull {
63  LightMapFull() {}
64  bool operator()(int x, int y) const { return true; }
65 };
66 
67 struct LightMapZoom {
68  LightMapZoom(const C4Landscape& landscape, double sx, double sy):
69  Landscape(landscape), sx(sx), sy(sy) {}
70 
71  // Returns whether zoomed coordinate is LightMap or not
72  bool operator()(int x, int y) const
73  {
74  // Landscape coordinates
75  const int lx = Clamp(static_cast<int>((x + 0.5) * sx), 0, Landscape.GetWidth() - 1);
76  const int ly = Clamp(static_cast<int>((y + 0.5) * sy), 0, Landscape.GetHeight() - 1);
77  // LightMap check
79  }
80 
81  const C4Landscape& Landscape;
82  const double sx;
83  const double sy;
84 };
85 
86 } // anonymous namespace
87 
89 #ifndef USE_CONSOLE
90  Tex(0),
91 #endif
92  Resolution(0.), Radius(0.), FullCoverage(0.),
93  SizeX(0), LandscapeX(0), SizeY(0), LandscapeY(0),
94  Brightness(1.)
95 {
96 }
97 
99 {
100  Clear();
101 }
102 
104 {
105 #ifndef USE_CONSOLE
106  if(Tex != 0) glDeleteTextures(1, &Tex);
107  Tex = 0;
108 #endif
109  Resolution = Radius = FullCoverage = 0.;
110  SizeX = SizeY = 0;
111  LandscapeX = LandscapeY = 0;
112  Brightness = 1.;
113 }
114 
115 void C4FoWAmbient::CreateFromLandscape(const C4Landscape& landscape, double resolution, double radius, double full_coverage)
116 {
117  assert(resolution >= 1.);
118  assert(radius >= 1.);
119  assert(full_coverage > 0 && full_coverage <= 1.);
120 
121  // Clear old map
122  Clear();
123 
124  Resolution = resolution;
125  Radius = radius;
126  FullCoverage = full_coverage;
127 
128  // Number of zoomed pixels
129  LandscapeX = Landscape.GetWidth();
130  LandscapeY = Landscape.GetHeight();
131  SizeX = std::min<unsigned int>(static_cast<unsigned int>(ceil(LandscapeX / resolution)), pDraw->MaxTexSize);
132  SizeY = std::min<unsigned int>(static_cast<unsigned int>(ceil(LandscapeY / resolution)), pDraw->MaxTexSize);
133 
134 #ifndef USE_CONSOLE
135  glGenTextures(1, &Tex);
136  glBindTexture(GL_TEXTURE_2D, Tex);
137  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
138  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
139  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
140  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
141  glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, SizeX, SizeY, 0, GL_RED, GL_FLOAT, nullptr);
142 
145  uint32_t dt = C4TimeMilliseconds::Now() - begin;
146  LogF("Created %ux%u ambient map in %g secs", SizeX, SizeY, dt / 1000.);
147 #endif
148 }
149 
150 void C4FoWAmbient::UpdateFromLandscape(const C4Landscape& landscape, const C4Rect& update)
151 {
152 #ifndef USE_CONSOLE
153  // Nothing to do?
154  if(update.Wdt == 0 || update.Hgt == 0) return;
155 
156  assert(Tex != 0);
157 
158  // Factor to go from zoomed to landscape coordinates
159  const double zoom_x = static_cast<double>(Landscape.GetWidth()) / SizeX;
160  const double zoom_y = static_cast<double>(Landscape.GetHeight()) / SizeY;
161  // Update region in zoomed coordinates
162  const unsigned int left = std::max(static_cast<int>( (update.x - Radius) / zoom_x), 0);
163  const unsigned int right = std::min(static_cast<unsigned int>( (update.x + update.Wdt + Radius) / zoom_x), SizeX - 1) + 1;
164  const unsigned int top = std::max(static_cast<int>( (update.y - Radius) / zoom_y), 0);
165  const unsigned int bottom = std::min(static_cast<unsigned int>( (update.y + update.Hgt + Radius) / zoom_y), SizeY - 1) + 1;
166  assert(right > left);
167  assert(bottom > top);
168  // Zoomed radius
169  const double R = Radius / sqrt(zoom_x * zoom_y);
170  // Normalization factor with the full circle
171  // The analytic result is 2*R*M_PI, and this number is typically close to it
172  const double norm = AmbientForPix(0, 0, R, LightMapFull()) * FullCoverage;
173  // Create the ambient map
174  LightMapZoom light_mapZoom(landscape, zoom_x, zoom_y);
175  float* ambient = new float[(right - left) * (bottom - top)];
176  for(unsigned int y = top; y < bottom; ++y)
177  {
178  for(unsigned int x = left; x < right; ++x)
179  {
180  ambient[(y - top) * (right - left) + (x - left)] = std::min(AmbientForPix(x, y, R, light_mapZoom) / norm, 1.0);
181  }
182  }
183 
184 #if 0
185  CSurface8 debug(SizeX, SizeY);
186  for(unsigned int y = 0; y < SizeY; ++y)
187  {
188  for(unsigned int x = 0; x < SizeX; ++x)
189  {
190  debug.SetPix(x, y, int(ambient[y * SizeX + x] * 255. + 0.5));
191  }
192  }
193 
194  CStdPalette pal;
195  for(int i = 0; i < 256; ++i)
196  pal.Colors[i] = i + (i << 8) + (i << 16);
197  debug.Save("Ambient.bmp", &pal);
198 #endif
199 
200  // Update the texture
201  glBindTexture(GL_TEXTURE_2D, Tex);
202  glTexSubImage2D(GL_TEXTURE_2D, 0, left, top, (right - left), (bottom - top), GL_RED, GL_FLOAT, ambient);
203  delete[] ambient;
204 #endif
205 }
206 
207 void C4FoWAmbient::GetFragTransform(const FLOAT_RECT& vpRect, const C4Rect& clipRect, const C4Rect& outRect, float ambientTransform[6]) const
208 {
209  C4FragTransform trans;
210  // Invert Y coordinate
211  trans.Scale(1, -1);
212  trans.Translate(0, outRect.Hgt);
213  // Clip offset
214  trans.Translate(-clipRect.x, -clipRect.y);
215  // Clip normalization (0,0 -> 1,1)
216  trans.Scale(1.0f / clipRect.Wdt, 1.0f / clipRect.Hgt);
217  // Viewport normalization
218  trans.Scale(vpRect.right - vpRect.left, vpRect.bottom - vpRect.top);
219  // Viewport offset
220  trans.Translate(vpRect.left, vpRect.top);
221  // Landscape normalization
222  trans.Scale(1.0f / LandscapeX, 1.0f / LandscapeY);
223 
224  // Extract matrix
225  trans.Get2x3(ambientTransform);
226 }
int MaxTexSize
Definition: C4Draw.h:99
void Translate(float dx, float dy)
Definition: C4FoW.h:38
float bottom
Definition: C4Rect.h:27
float right
Definition: C4Rect.h:27
float left
Definition: C4Rect.h:27
void UpdateFromLandscape(const C4Landscape &landscape, const C4Rect &update)
DWORD Colors[256]
Definition: StdColors.h:186
void CreateFromLandscape(const C4Landscape &landscape, double resolution, double radius, double full_coverage)
Definition: C4Rect.h:29
T Clamp(T bval, T lbound, T rbound)
Definition: Standard.h:46
int32_t Wdt
Definition: C4Rect.h:32
void Scale(float sx, float sy)
Definition: C4FoW.h:45
int32_t y
Definition: C4Rect.h:32
C4Landscape Landscape
C4Draw * pDraw
Definition: C4Draw.cpp:45
int32_t x
Definition: C4Rect.h:32
int32_t GetHeight() const
void Get2x3(float transform[6])
Definition: C4FoW.h:54
int32_t Hgt
Definition: C4Rect.h:32
void SetPix(int iX, int iY, BYTE byCol)
Definition: CSurface8.h:37
bool Save(const char *szFilename, CStdPalette *=nullptr)
Definition: CSurface8.cpp:158
bool LogF(const char *strMessage,...)
Definition: C4Log.cpp:253
bool _GetLight(int32_t x, int32_t y)
float top
Definition: C4Rect.h:27
static C4TimeMilliseconds Now()
int32_t GetWidth() const
void GetFragTransform(const struct FLOAT_RECT &vpRect, const C4Rect &clipRect, const C4Rect &outRect, float ambientTransform[6]) const