source: Revenant/geoworld/src/PNGDEM.cpp@ 8125274

port/mars-tycoon
Last change on this file since 8125274 was 80a6a52, checked in by Jonathan Neufeld <support@…>, 3 years ago

Get to a compile state for terrain procedural generation

  • Property mode set to 100644
File size: 6.0 KB
Line 
1#include "PNGDEM.h"
2
3#include <limits>
4#include <lodepng.h>
5#include <lodepng.cpp>
6
7namespace geoworld
8{
9 PNGDEM::PNGDEM()
10 : _fmt(RGBMultiples), _nCrossIdx(0) {}
11
12 mars::Range< GeoHeightMap::Precision > PNGDEM::getRange( const GeoHeightMap::Precision * pnData, const unsigned short nWidth, const unsigned short nHeight ) const
13 {
14 size_t nLen = nWidth * nHeight;
15 GeoHeightMap::Precision
16 nMin = std::numeric_limits< GeoHeightMap::Precision > ::max(),
17 nMax = std::numeric_limits< GeoHeightMap::Precision > ::lowest();
18
19 while (nLen--)
20 {
21 if (pnData[nLen] > nMax)
22 nMax = pnData[nLen];
23 if (pnData[nLen] < nMin)
24 nMin = pnData[nLen];
25 }
26
27 return mars::Range< GeoHeightMap::Precision > (nMin, nMax);
28 }
29
30 GeoHeightMap::Precision PNGDEM::convertPixelComponentsToElevation( const unsigned char b, const unsigned char g, const unsigned char r ) const
31 {
32 return
33 static_cast< GeoHeightMap::Precision > (
34 static_cast< unsigned long > (b) * (1 << 2) +
35 static_cast< unsigned long > (g) * (1 << 1) +
36 static_cast< unsigned long > (r) * (1 << 0)
37 );
38 }
39
40 unsigned char PNGDEM::convertElevationToPixelComponent( const GeoHeightMap::Precision val, const unsigned bit ) const
41 {
42 const unsigned
43 nMask = 1 << bit,
44 nMult = val / 256;
45
46 return ((256 - 1) - (val % 256)) * ((nMult & nMask) >> bit) + (val % 256) * (((nMult + 1) & nMask) >> bit);
47 }
48
49 void PNGDEM::addCrosshairPoint( const unsigned short x, const unsigned short y, int idx /*= -1*/, const float fAlpha /*= 1.0f*/ )
50 {
51 if (idx < 0)
52 idx = _nCrossIdx++;
53
54 const float
55 r = (idx % 3) / 2.0f,
56 g = ((idx + 1) % 3) / 2.0f,
57 b = ((idx + 2) % 3) / 2.0f;
58
59 assert(fAlpha <= 1.0f && fAlpha >= 0.0f);
60 addCrosshairPoint(x, y, r, g, b, fAlpha);
61 }
62
63 void PNGDEM::addCrosshairPoint( const unsigned short x, const unsigned short y, const float fRed, const float fGreen, const float fBlue, const float fAlpha /*= 1.0f*/ )
64 {
65 _crosshairs.push_back(CrosshairPoint(x, y, fRed, fGreen, fBlue, fAlpha));
66 }
67
68 void PNGDEM::operator << ( std::ifstream & input )
69 {
70 std::streamsize nSize = 0;
71
72 if (input.seekg(0, std::ios::end).good())
73 nSize = input.tellg();
74 if (input.seekg(0, std::ios::beg).good())
75 nSize -= input.tellg();
76
77 assert(nSize <= std::numeric_limits< unsigned int >::max());
78
79 std::vector<unsigned char> rgbaData (nSize);
80
81 if (nSize > 0)
82 input.read(reinterpret_cast< char * > (&rgbaData[0]), nSize);
83
84 unsigned int width, height;
85
86 lodepng::decode(_inbuff, width, height, rgbaData);
87
88 _nWidth = width;
89 _nHeight = height;
90 }
91
92 std::ostream & PNGDEM::operator >> ( std::ostream & output )
93 {
94 std::vector <unsigned char> raw;
95
96 flushCrosshairs();
97 lodepng::encode(raw, _inbuff, _nWidth, _nHeight);
98 output.write(reinterpret_cast< char * > (&raw[0]), raw.size());
99
100 return output;
101 }
102
103 mars::ptr< GeoHeightMap > PNGDEM::createHeightMap(const float fScale /*= 1.0f*/) const
104 {
105 mars::ptr< GeoHeightMap > phm = new GeoHeightMap(_nWidth, _nHeight);
106 GeoHeightMap & hm = *phm;
107 unsigned int c = 0;
108
109 for (std::vector< unsigned char >::const_iterator i = _inbuff.begin(); i != _inbuff.end(); ++i)
110 {
111 const unsigned int
112 nX = c % _nWidth,
113 nY = c / _nWidth;
114
115 switch (_fmt)
116 {
117 case Grayscale:
118 hm(nX, nY) = static_cast< GeoHeightMap::Precision > (static_cast< float > (*i++ + *i++ + *i++) / 3.0f * fScale);
119 break;
120 case RGBMultiples:
121 hm(nX, nY) = static_cast< GeoHeightMap::Precision > (static_cast< float > (convertPixelComponentsToElevation(*i++, *i++, *i++)) * fScale);
122 break;
123 }
124
125 ++c;
126 }
127
128 return phm;
129 }
130
131 void PNGDEM::retrieveLine( GeoHeightMap::Precision * pnData, const unsigned short nY, const float fScale /*= 1.0f*/ ) const
132 {
133 const unsigned int nLen = (nY + 1) * _nWidth;
134 for (unsigned int c = nY * _nWidth, i = 0; c < nLen; ++c, ++i)
135 {
136 switch (_fmt)
137 {
138 case Grayscale:
139 pnData[i] = static_cast< GeoHeightMap::Precision > (static_cast< float > (_inbuff[c++] + _inbuff[c++] + _inbuff[c++]) / 3.0f * fScale);
140 break;
141 case RGBMultiples:
142 pnData[i] = static_cast< GeoHeightMap::Precision > (static_cast< float > (convertPixelComponentsToElevation(_inbuff[c++], _inbuff[c++], _inbuff[c++])) * fScale);
143 break;
144 }
145 }
146 }
147
148 void PNGDEM::flushCrosshairs()
149 {
150 for (Crosshairs::const_iterator i = _crosshairs.begin(); i != _crosshairs.end(); ++i)
151 {
152 if (i->x > 0 && i->y > 0 && i->x - 1 < _nWidth && i->y - 1 < _nHeight)
153 {
154 const unsigned char
155 cRed = static_cast< unsigned char > (i->red * 255.0f),
156 cGreen = static_cast< unsigned char > (i->green * 255.0f),
157 cBlue = static_cast< unsigned char > (i->blue * 255.0f),
158 cAlpha = static_cast< unsigned char > (i->alpha * 255.0f);
159
160 _inbuff[i->y * _nWidth * 4 + i->x * 4 + 0] = cRed;
161 _inbuff[i->y * _nWidth * 4 + i->x * 4 + 1] = cGreen;
162 _inbuff[i->y * _nWidth * 4 + i->x * 4 + 2] = cBlue;
163 _inbuff[i->y * _nWidth * 4 + i->x * 4 + 3] = cAlpha;
164
165 if (i->y > 0)
166 {
167 _inbuff[(i->y - 1) * _nWidth * 4 + i->x * 4 + 0] = cRed;
168 _inbuff[(i->y - 1) * _nWidth * 4 + i->x * 4 + 1] = cGreen;
169 _inbuff[(i->y - 1) * _nWidth * 4 + i->x * 4 + 2] = cBlue;
170 _inbuff[(i->y - 1) * _nWidth * 4 + i->x * 4 + 3] = cAlpha;
171 }
172 if (i->y < _nHeight - 1)
173 {
174 _inbuff[(i->y + 1) * _nWidth * 4 + i->x * 4 + 0] = cRed;
175 _inbuff[(i->y + 1) * _nWidth * 4 + i->x * 4 + 1] = cGreen;
176 _inbuff[(i->y + 1) * _nWidth * 4 + i->x * 4 + 2] = cBlue;
177 _inbuff[(i->y + 1) * _nWidth * 4 + i->x * 4 + 3] = cAlpha;
178 }
179 if (i->x > 0)
180 {
181 _inbuff[i->y * _nWidth * 4 + (i->x - 1) * 4 + 0] = cRed;
182 _inbuff[i->y * _nWidth * 4 + (i->x - 1) * 4 + 1] = cGreen;
183 _inbuff[i->y * _nWidth * 4 + (i->x - 1) * 4 + 2] = cBlue;
184 _inbuff[i->y * _nWidth * 4 + (i->x - 1) * 4 + 3] = cAlpha;
185 }
186 if (i->x < _nWidth - 1)
187 {
188 _inbuff[i->y * _nWidth * 4 + (i->x + 1) * 4 + 0] = cRed;
189 _inbuff[i->y * _nWidth * 4 + (i->x + 1) * 4 + 1] = cGreen;
190 _inbuff[i->y * _nWidth * 4 + (i->x + 1) * 4 + 2] = cBlue;
191 _inbuff[i->y * _nWidth * 4 + (i->x + 1) * 4 + 3] = cAlpha;
192 }
193 }
194 }
195 }
196
197}
Note: See TracBrowser for help on using the repository browser.