aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/World/WorldMap/ShadedMapTileRenderer.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/CoreModules/World/WorldMap/ShadedMapTileRenderer.cs')
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/ShadedMapTileRenderer.cs249
1 files changed, 249 insertions, 0 deletions
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/ShadedMapTileRenderer.cs b/OpenSim/Region/CoreModules/World/WorldMap/ShadedMapTileRenderer.cs
new file mode 100644
index 0000000..b783d7c
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/WorldMap/ShadedMapTileRenderer.cs
@@ -0,0 +1,249 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Drawing;
32using System.Drawing.Drawing2D;
33using System.Drawing.Imaging;
34using System.Reflection;
35using OpenMetaverse;
36using OpenMetaverse.Imaging;
37using Nini.Config;
38using log4net;
39using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Region.Framework.Scenes;
41
42namespace OpenSim.Region.CoreModules.World.WorldMap
43{
44 public class ShadedMapTileRenderer : IMapTileTerrainRenderer
45 {
46 private static readonly ILog m_log =
47 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48
49 private Scene m_scene;
50 //private IConfigSource m_config; // not used currently
51
52 public void Initialise(Scene scene, IConfigSource config)
53 {
54 m_scene = scene;
55 // m_config = config; // not used currently
56 }
57
58 public void TerrainToBitmap(Bitmap mapbmp)
59 {
60 int tc = System.Environment.TickCount;
61 m_log.Info("[MAPTILE]: Generating Maptile Step 1: Terrain");
62
63 double[,] hm = m_scene.Heightmap.GetDoubles();
64 bool ShadowDebugContinue = true;
65
66 bool terraincorruptedwarningsaid = false;
67
68 float low = 255;
69 float high = 0;
70 for (int x = 0; x < 256; x++)
71 {
72 for (int y = 0; y < 256; y++)
73 {
74 float hmval = (float)hm[x, y];
75 if (hmval < low)
76 low = hmval;
77 if (hmval > high)
78 high = hmval;
79 }
80 }
81
82 float waterHeight = (float)m_scene.RegionInfo.RegionSettings.WaterHeight;
83
84 for (int x = 0; x < 256; x++)
85 {
86 for (int y = 0; y < 256; y++)
87 {
88 // Y flip the cordinates for the bitmap: hf origin is lower left, bm origin is upper left
89 int yr = 255 - y;
90
91 float heightvalue = (float)hm[x, y];
92
93 if (heightvalue > waterHeight)
94 {
95 // scale height value
96 // No, that doesn't scale it:
97 // heightvalue = low + mid * (heightvalue - low) / mid; => low + (heightvalue - low) * mid / mid = low + (heightvalue - low) * 1 = low + heightvalue - low = heightvalue
98
99 if (Single.IsInfinity(heightvalue) || Single.IsNaN(heightvalue))
100 heightvalue = 0;
101 else if (heightvalue > 255f)
102 heightvalue = 255f;
103 else if (heightvalue < 0f)
104 heightvalue = 0f;
105
106 Color color = Color.FromArgb((int)heightvalue, 100, (int)heightvalue);
107
108 mapbmp.SetPixel(x, yr, color);
109
110 try
111 {
112 //X
113 // .
114 //
115 // Shade the terrain for shadows
116 if (x < 255 && yr < 255)
117 {
118 float hfvalue = (float)hm[x, y];
119 float hfvaluecompare = 0f;
120
121 if ((x + 1 < 256) && (y + 1 < 256))
122 {
123 hfvaluecompare = (float)hm[x + 1, y + 1]; // light from north-east => look at land height there
124 }
125 if (Single.IsInfinity(hfvalue) || Single.IsNaN(hfvalue))
126 hfvalue = 0f;
127
128 if (Single.IsInfinity(hfvaluecompare) || Single.IsNaN(hfvaluecompare))
129 hfvaluecompare = 0f;
130
131 float hfdiff = hfvalue - hfvaluecompare; // => positive if NE is lower, negative if here is lower
132
133 int hfdiffi = 0;
134 int hfdiffihighlight = 0;
135 float highlightfactor = 0.18f;
136
137 try
138 {
139 // hfdiffi = Math.Abs((int)((hfdiff * 4) + (hfdiff * 0.5))) + 1;
140 hfdiffi = Math.Abs((int)(hfdiff * 4.5f)) + 1;
141 if (hfdiff % 1f != 0)
142 {
143 // hfdiffi = hfdiffi + Math.Abs((int)(((hfdiff % 1) * 0.5f) * 10f) - 1);
144 hfdiffi = hfdiffi + Math.Abs((int)((hfdiff % 1f) * 5f) - 1);
145 }
146
147 hfdiffihighlight = Math.Abs((int)((hfdiff * highlightfactor) * 4.5f)) + 1;
148 if (hfdiff % 1f != 0)
149 {
150 // hfdiffi = hfdiffi + Math.Abs((int)(((hfdiff % 1) * 0.5f) * 10f) - 1);
151 hfdiffihighlight = hfdiffihighlight + Math.Abs((int)(((hfdiff * highlightfactor) % 1f) * 5f) - 1);
152 }
153 }
154 catch (System.OverflowException)
155 {
156 m_log.Debug("[MAPTILE]: Shadow failed at value: " + hfdiff.ToString());
157 ShadowDebugContinue = false;
158 }
159
160 if (hfdiff > 0.3f)
161 {
162 // NE is lower than here
163 // We have to desaturate and lighten the land at the same time
164 // we use floats, colors use bytes, so shrink are space down to
165 // 0-255
166
167 if (ShadowDebugContinue)
168 {
169 int r = color.R;
170 int g = color.G;
171 int b = color.B;
172 color = Color.FromArgb((r + hfdiffihighlight < 255) ? r + hfdiffihighlight : 255,
173 (g + hfdiffihighlight < 255) ? g + hfdiffihighlight : 255,
174 (b + hfdiffihighlight < 255) ? b + hfdiffihighlight : 255);
175 }
176 }
177 else if (hfdiff < -0.3f)
178 {
179 // here is lower than NE:
180 // We have to desaturate and blacken the land at the same time
181 // we use floats, colors use bytes, so shrink are space down to
182 // 0-255
183
184 if (ShadowDebugContinue)
185 {
186 if ((x - 1 > 0) && (yr + 1 < 256))
187 {
188 color = mapbmp.GetPixel(x - 1, yr + 1);
189 int r = color.R;
190 int g = color.G;
191 int b = color.B;
192 color = Color.FromArgb((r - hfdiffi > 0) ? r - hfdiffi : 0,
193 (g - hfdiffi > 0) ? g - hfdiffi : 0,
194 (b - hfdiffi > 0) ? b - hfdiffi : 0);
195
196 mapbmp.SetPixel(x-1, yr+1, color);
197 }
198 }
199 }
200 }
201 }
202 catch (System.ArgumentException)
203 {
204 if (!terraincorruptedwarningsaid)
205 {
206 m_log.WarnFormat("[MAPIMAGE]: Your terrain is corrupted in region {0}, it might take a few minutes to generate the map image depending on the corruption level", m_scene.RegionInfo.RegionName);
207 terraincorruptedwarningsaid = true;
208 }
209 color = Color.Black;
210 mapbmp.SetPixel(x, yr, color);
211 }
212 }
213 else
214 {
215 // We're under the water level with the terrain, so paint water instead of land
216
217 // Y flip the cordinates
218 heightvalue = waterHeight - heightvalue;
219 if (Single.IsInfinity(heightvalue) || Single.IsNaN(heightvalue))
220 heightvalue = 0f;
221 else if (heightvalue > 19f)
222 heightvalue = 19f;
223 else if (heightvalue < 0f)
224 heightvalue = 0f;
225
226 heightvalue = 100f - (heightvalue * 100f) / 19f;
227
228 try
229 {
230 Color water = Color.FromArgb((int)heightvalue, (int)heightvalue, 255);
231 mapbmp.SetPixel(x, yr, water);
232 }
233 catch (System.ArgumentException)
234 {
235 if (!terraincorruptedwarningsaid)
236 {
237 m_log.WarnFormat("[MAPIMAGE]: Your terrain is corrupted in region {0}, it might take a few minutes to generate the map image depending on the corruption level", m_scene.RegionInfo.RegionName);
238 terraincorruptedwarningsaid = true;
239 }
240 Color black = Color.Black;
241 mapbmp.SetPixel(x, (256 - y) - 1, black);
242 }
243 }
244 }
245 }
246 m_log.Info("[MAPTILE]: Generating Maptile Step 1: Done in " + (System.Environment.TickCount - tc) + " ms");
247 }
248 }
249}