diff options
author | UbitUmarov | 2018-05-06 17:32:03 +0100 |
---|---|---|
committer | UbitUmarov | 2018-05-06 17:32:03 +0100 |
commit | dffa6289666382166dd038e250cad94d24b88c6c (patch) | |
tree | 52e9b0ec61fb4f4b8a5486c9df6988b805e99215 /OpenSim | |
parent | fix warp3d textures UV (diff) | |
download | opensim-SC-dffa6289666382166dd038e250cad94d24b88c6c.zip opensim-SC-dffa6289666382166dd038e250cad94d24b88c6c.tar.gz opensim-SC-dffa6289666382166dd038e250cad94d24b88c6c.tar.bz2 opensim-SC-dffa6289666382166dd038e250cad94d24b88c6c.tar.xz |
break nap a bit more, add options ExportMapAddScale, ExportMapAddRegionName and (warp3d) AverageTextureColorOnMapTile
Diffstat (limited to 'OpenSim')
4 files changed, 318 insertions, 235 deletions
diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs index 226b330..ba6ebfc 100644 --- a/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs +++ b/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs | |||
@@ -56,7 +56,9 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
56 | 56 | ||
57 | private static readonly Color[] DEFAULT_TERRAIN_COLOR = new Color[] | 57 | private static readonly Color[] DEFAULT_TERRAIN_COLOR = new Color[] |
58 | { | 58 | { |
59 | Color.FromArgb(255, 164, 136, 117), | 59 | // Color.FromArgb(255, 164, 136, 117), |
60 | Color.FromArgb(255, 255, 136, 117), | ||
61 | |||
60 | Color.FromArgb(255, 65, 87, 47), | 62 | Color.FromArgb(255, 65, 87, 47), |
61 | Color.FromArgb(255, 157, 145, 131), | 63 | Color.FromArgb(255, 157, 145, 131), |
62 | Color.FromArgb(255, 125, 128, 130) | 64 | Color.FromArgb(255, 125, 128, 130) |
@@ -82,7 +84,8 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
82 | 84 | ||
83 | public static Bitmap Splat(ITerrainChannel terrain, | 85 | public static Bitmap Splat(ITerrainChannel terrain, |
84 | UUID[] textureIDs, float[] startHeights, float[] heightRanges, | 86 | UUID[] textureIDs, float[] startHeights, float[] heightRanges, |
85 | Vector3d regionPosition, IAssetService assetService, bool textureTerrain) | 87 | uint regionPositionX,uint regionPositionY, |
88 | IAssetService assetService, bool textureTerrain, bool averagetextureTerrain) | ||
86 | { | 89 | { |
87 | Debug.Assert(textureIDs.Length == 4); | 90 | Debug.Assert(textureIDs.Length == 4); |
88 | Debug.Assert(startHeights.Length == 4); | 91 | Debug.Assert(startHeights.Length == 4); |
@@ -90,70 +93,81 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
90 | 93 | ||
91 | Bitmap[] detailTexture = new Bitmap[4]; | 94 | Bitmap[] detailTexture = new Bitmap[4]; |
92 | 95 | ||
96 | byte[] mapColorsRed = new byte[4]; | ||
97 | byte[] mapColorsGreen = new byte[4]; | ||
98 | byte[] mapColorsBlue = new byte[4]; | ||
99 | |||
100 | bool usecolors = false; | ||
101 | |||
93 | if (textureTerrain) | 102 | if (textureTerrain) |
94 | { | 103 | { |
95 | // Swap empty terrain textureIDs with default IDs | 104 | // Swap empty terrain textureIDs with default IDs |
96 | for (int i = 0; i < textureIDs.Length; i++) | 105 | for(int i = 0; i < textureIDs.Length; i++) |
97 | { | 106 | { |
98 | if (textureIDs[i] == UUID.Zero) | 107 | if(textureIDs[i] == UUID.Zero) |
99 | textureIDs[i] = DEFAULT_TERRAIN_DETAIL[i]; | 108 | textureIDs[i] = DEFAULT_TERRAIN_DETAIL[i]; |
100 | } | 109 | } |
101 | 110 | ||
102 | #region Texture Fetching | 111 | #region Texture Fetching |
103 | 112 | ||
104 | if (assetService != null) | 113 | if(assetService != null) |
105 | { | 114 | { |
106 | for (int i = 0; i < 4; i++) | 115 | for(int i = 0; i < 4; i++) |
107 | { | 116 | { |
108 | AssetBase asset; | 117 | AssetBase asset = null; |
109 | UUID cacheID = UUID.Combine(TERRAIN_CACHE_MAGIC, textureIDs[i]); | 118 | UUID cacheID = UUID.Combine(TERRAIN_CACHE_MAGIC, textureIDs[i]); |
110 | 119 | ||
111 | // Try to fetch a cached copy of the decoded/resized version of this texture | 120 | // Try to fetch a cached copy of the decoded/resized version of this texture |
112 | asset = assetService.GetCached(cacheID.ToString()); | 121 | // asset = assetService.GetCached(cacheID.ToString()); |
113 | if (asset != null) | 122 | if(asset != null) |
114 | { | 123 | { |
115 | try | 124 | try |
116 | { | 125 | { |
117 | using (System.IO.MemoryStream stream = new System.IO.MemoryStream(asset.Data)) | 126 | using(System.IO.MemoryStream stream = new System.IO.MemoryStream(asset.Data)) |
118 | detailTexture[i] = (Bitmap)Image.FromStream(stream); | 127 | detailTexture[i] = (Bitmap)Image.FromStream(stream); |
119 | } | 128 | } |
120 | catch (Exception ex) | 129 | catch(Exception ex) |
121 | { | 130 | { |
122 | m_log.Warn("Failed to decode cached terrain texture " + cacheID + | 131 | m_log.Warn("Failed to decode cached terrain texture " + cacheID + |
123 | " (textureID: " + textureIDs[i] + "): " + ex.Message); | 132 | " (textureID: " + textureIDs[i] + "): " + ex.Message); |
124 | } | 133 | } |
134 | if(detailTexture[i].PixelFormat != PixelFormat.Format24bppRgb || | ||
135 | detailTexture[i].Width != 16 || detailTexture[i].Height != 16) | ||
136 | { | ||
137 | detailTexture[i].Dispose(); | ||
138 | detailTexture[i] = null; | ||
139 | } | ||
125 | } | 140 | } |
126 | 141 | ||
127 | if (detailTexture[i] == null) | 142 | if(detailTexture[i] == null) |
128 | { | 143 | { |
129 | // Try to fetch the original JPEG2000 texture, resize if needed, and cache as PNG | 144 | // Try to fetch the original JPEG2000 texture, resize if needed, and cache as PNG |
130 | asset = assetService.Get(textureIDs[i].ToString()); | 145 | asset = assetService.Get(textureIDs[i].ToString()); |
131 | if (asset != null) | 146 | if(asset != null) |
132 | { | 147 | { |
133 | // m_log.DebugFormat( | 148 | // m_log.DebugFormat( |
134 | // "[TERRAIN SPLAT]: Got cached original JPEG2000 terrain texture {0} {1}", i, asset.ID); | 149 | // "[TERRAIN SPLAT]: Got cached original JPEG2000 terrain texture {0} {1}", i, asset.ID); |
135 | 150 | ||
136 | try { detailTexture[i] = (Bitmap)CSJ2K.J2kImage.FromBytes(asset.Data); } | 151 | try |
137 | catch (Exception ex) | 152 | { |
153 | detailTexture[i] = (Bitmap)CSJ2K.J2kImage.FromBytes(asset.Data); | ||
154 | } | ||
155 | catch(Exception ex) | ||
138 | { | 156 | { |
139 | m_log.Warn("Failed to decode terrain texture " + asset.ID + ": " + ex.Message); | 157 | m_log.Warn("Failed to decode terrain texture " + asset.ID + ": " + ex.Message); |
140 | } | 158 | } |
141 | } | 159 | } |
142 | 160 | ||
143 | if (detailTexture[i] != null) | 161 | if(detailTexture[i] != null) |
144 | { | 162 | { |
145 | // Make sure this texture is the correct size, otherwise resize | 163 | if(detailTexture[i].PixelFormat != PixelFormat.Format24bppRgb || |
146 | if (detailTexture[i].Width != 256 || detailTexture[i].Height != 256) | 164 | detailTexture[i].Width != 16 || detailTexture[i].Height != 16) |
147 | { | 165 | using(Bitmap origBitmap = detailTexture[i]) |
148 | using (Bitmap origBitmap = detailTexture[i]) | 166 | detailTexture[i] = ImageUtils.ResizeImageSolid(origBitmap, 16, 16); |
149 | { | ||
150 | detailTexture[i] = ImageUtils.ResizeImage(origBitmap, 256, 256); | ||
151 | } | ||
152 | } | ||
153 | 167 | ||
154 | // Save the decoded and resized texture to the cache | 168 | // Save the decoded and resized texture to the cache |
155 | byte[] data; | 169 | byte[] data; |
156 | using (System.IO.MemoryStream stream = new System.IO.MemoryStream()) | 170 | using(System.IO.MemoryStream stream = new System.IO.MemoryStream()) |
157 | { | 171 | { |
158 | detailTexture[i].Save(stream, ImageFormat.Png); | 172 | detailTexture[i].Save(stream, ImageFormat.Png); |
159 | data = stream.ToArray(); | 173 | data = stream.ToArray(); |
@@ -180,91 +194,97 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
180 | } | 194 | } |
181 | 195 | ||
182 | #endregion Texture Fetching | 196 | #endregion Texture Fetching |
183 | } | 197 | if(averagetextureTerrain) |
184 | |||
185 | // Fill in any missing textures with a solid color | ||
186 | for (int i = 0; i < 4; i++) | ||
187 | { | ||
188 | if (detailTexture[i] == null) | ||
189 | { | 198 | { |
190 | m_log.DebugFormat("{0} Missing terrain texture for layer {1}. Filling with solid default color", | 199 | for(int t = 0; t < 4; t++) |
191 | LogHeader, i); | ||
192 | // Create a solid color texture for this layer | ||
193 | detailTexture[i] = new Bitmap(256, 256, PixelFormat.Format24bppRgb); | ||
194 | using (Graphics gfx = Graphics.FromImage(detailTexture[i])) | ||
195 | { | 200 | { |
196 | using (SolidBrush brush = new SolidBrush(DEFAULT_TERRAIN_COLOR[i])) | 201 | usecolors = true; |
197 | gfx.FillRectangle(brush, 0, 0, 256, 256); | 202 | if(detailTexture[t] == null) |
203 | { | ||
204 | mapColorsRed[t] = DEFAULT_TERRAIN_COLOR[t].R; | ||
205 | mapColorsGreen[t] = DEFAULT_TERRAIN_COLOR[t].G; | ||
206 | mapColorsBlue[t] = DEFAULT_TERRAIN_COLOR[t].B; | ||
207 | continue; | ||
208 | } | ||
209 | |||
210 | int npixeis = 0; | ||
211 | int cR = 0; | ||
212 | int cG = 0; | ||
213 | int cB = 0; | ||
214 | |||
215 | BitmapData bmdata = detailTexture[t].LockBits(new Rectangle(0, 0, 16, 16), | ||
216 | ImageLockMode.ReadOnly, detailTexture[t].PixelFormat); | ||
217 | |||
218 | npixeis = bmdata.Height * bmdata.Width; | ||
219 | int ylen = bmdata.Height * bmdata.Stride; | ||
220 | |||
221 | unsafe | ||
222 | { | ||
223 | for(int y = 0; y < ylen; y += bmdata.Stride) | ||
224 | { | ||
225 | byte* ptrc = (byte*)bmdata.Scan0 + y; | ||
226 | for(int x = 0 ; x < bmdata.Width; ++x) | ||
227 | { | ||
228 | cR += *(ptrc++); | ||
229 | cG += *(ptrc++); | ||
230 | cB += *(ptrc++); | ||
231 | } | ||
232 | } | ||
233 | |||
234 | } | ||
235 | detailTexture[t].UnlockBits(bmdata); | ||
236 | detailTexture[t].Dispose(); | ||
237 | |||
238 | mapColorsRed[t] = (byte)Util.Clamp(cR / npixeis, 0 , 255); | ||
239 | mapColorsGreen[t] = (byte)Util.Clamp(cG / npixeis, 0 , 255); | ||
240 | mapColorsBlue[t] = (byte)Util.Clamp(cB / npixeis, 0 , 255); | ||
198 | } | 241 | } |
199 | } | 242 | } |
200 | else | 243 | else |
201 | { | 244 | { |
202 | if (detailTexture[i].Width != 256 || detailTexture[i].Height != 256) | 245 | // Fill in any missing textures with a solid color |
246 | for(int i = 0; i < 4; i++) | ||
203 | { | 247 | { |
204 | detailTexture[i] = ResizeBitmap(detailTexture[i], 256, 256); | 248 | if(detailTexture[i] == null) |
249 | { | ||
250 | m_log.DebugFormat("{0} Missing terrain texture for layer {1}. Filling with solid default color", LogHeader, i); | ||
251 | |||
252 | // Create a solid color texture for this layer | ||
253 | detailTexture[i] = new Bitmap(16, 16, PixelFormat.Format24bppRgb); | ||
254 | using(Graphics gfx = Graphics.FromImage(detailTexture[i])) | ||
255 | { | ||
256 | using(SolidBrush brush = new SolidBrush(DEFAULT_TERRAIN_COLOR[i])) | ||
257 | gfx.FillRectangle(brush, 0, 0, 16, 16); | ||
258 | } | ||
259 | } | ||
260 | else | ||
261 | { | ||
262 | if(detailTexture[i].Width != 16 || detailTexture[i].Height != 16) | ||
263 | { | ||
264 | using(Bitmap origBitmap = detailTexture[i]) | ||
265 | detailTexture[i] = ImageUtils.ResizeImageSolid(origBitmap, 16, 16); | ||
266 | } | ||
267 | } | ||
205 | } | 268 | } |
206 | } | 269 | } |
207 | } | 270 | } |
208 | 271 | else | |
209 | #region Layer Map | ||
210 | |||
211 | float[,] layermap = new float[256, 256]; | ||
212 | |||
213 | // Scale difference between actual region size and the 256 texture being created | ||
214 | int xFactor = terrain.Width / 256; | ||
215 | int yFactor = terrain.Height / 256; | ||
216 | |||
217 | // Create 'layermap' where each value is the fractional layer number to place | ||
218 | // at that point. For instance, a value of 1.345 gives the blending of | ||
219 | // layer 1 and layer 2 for that point. | ||
220 | for (int y = 0; y < 256; y++) | ||
221 | { | 272 | { |
222 | for (int x = 0; x < 256; x++) | 273 | usecolors = true; |
274 | for(int t = 0; t < 4; t++) | ||
223 | { | 275 | { |
224 | float height = (float)terrain[x * xFactor, y * yFactor]; | 276 | mapColorsRed[t] = DEFAULT_TERRAIN_COLOR[t].R; |
225 | 277 | mapColorsGreen[t] = DEFAULT_TERRAIN_COLOR[t].G; | |
226 | float pctX = (float)x / 255f; | 278 | mapColorsBlue[t] = DEFAULT_TERRAIN_COLOR[t].B; |
227 | float pctY = (float)y / 255f; | ||
228 | |||
229 | // Use bilinear interpolation between the four corners of start height and | ||
230 | // height range to select the current values at this position | ||
231 | float startHeight = ImageUtils.Bilinear( | ||
232 | startHeights[0], | ||
233 | startHeights[2], | ||
234 | startHeights[1], | ||
235 | startHeights[3], | ||
236 | pctX, pctY); | ||
237 | startHeight = Utils.Clamp(startHeight, 0f, 255f); | ||
238 | |||
239 | float heightRange = ImageUtils.Bilinear( | ||
240 | heightRanges[0], | ||
241 | heightRanges[2], | ||
242 | heightRanges[1], | ||
243 | heightRanges[3], | ||
244 | pctX, pctY); | ||
245 | heightRange = Utils.Clamp(heightRange, 0f, 255f); | ||
246 | |||
247 | // Generate two frequencies of perlin noise based on our global position | ||
248 | // The magic values were taken from http://opensimulator.org/wiki/Terrain_Splatting | ||
249 | Vector3 vec = new Vector3 | ||
250 | ( | ||
251 | ((float)regionPosition.X + (x * xFactor)) * 0.20319f, | ||
252 | ((float)regionPosition.Y + (y * yFactor)) * 0.20319f, | ||
253 | height * 0.25f | ||
254 | ); | ||
255 | |||
256 | float lowFreq = Perlin.noise2(vec.X * 0.222222f, vec.Y * 0.222222f) * 6.5f; | ||
257 | float highFreq = Perlin.turbulence2(vec.X, vec.Y, 2f) * 2.25f; | ||
258 | float noise = (lowFreq + highFreq) * 2f; | ||
259 | |||
260 | // Combine the current height, generated noise, start height, and height range parameters, then scale all of it | ||
261 | float layer = ((height + noise - startHeight) / heightRange) * 4f; | ||
262 | if (Single.IsNaN(layer)) | ||
263 | layer = 0f; | ||
264 | layermap[x, y] = Utils.Clamp(layer, 0f, 3f); | ||
265 | } | 279 | } |
266 | } | 280 | } |
267 | 281 | ||
282 | #region Layer Map | ||
283 | |||
284 | // Scale difference between actual region size and the 256 texture being created | ||
285 | float xFactor = terrain.Width / 256f; | ||
286 | float yFactor = terrain.Height / 256f; | ||
287 | |||
268 | #endregion Layer Map | 288 | #endregion Layer Map |
269 | 289 | ||
270 | #region Texture Compositing | 290 | #region Texture Compositing |
@@ -274,115 +294,152 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
274 | 294 | ||
275 | // Unsafe work as we lock down the source textures for quicker access and access the | 295 | // Unsafe work as we lock down the source textures for quicker access and access the |
276 | // pixel data directly | 296 | // pixel data directly |
277 | unsafe | 297 | if(usecolors) |
278 | { | 298 | { |
279 | // Get handles to all of the texture data arrays | 299 | unsafe |
280 | BitmapData[] datas = new BitmapData[] | ||
281 | { | ||
282 | detailTexture[0].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[0].PixelFormat), | ||
283 | detailTexture[1].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[1].PixelFormat), | ||
284 | detailTexture[2].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[2].PixelFormat), | ||
285 | detailTexture[3].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[3].PixelFormat) | ||
286 | }; | ||
287 | |||
288 | // Compute size of each pixel data (used to address into the pixel data array) | ||
289 | int[] comps = new int[] | ||
290 | { | ||
291 | (datas[0].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3, | ||
292 | (datas[1].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3, | ||
293 | (datas[2].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3, | ||
294 | (datas[3].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3 | ||
295 | }; | ||
296 | |||
297 | for (int y = 0; y < 256; y++) | ||
298 | { | 300 | { |
299 | for (int x = 0; x < 256; x++) | 301 | for(int y = 0; y < 256; ++y) |
300 | { | 302 | { |
301 | float layer = layermap[x, y]; | 303 | int ty = (int)((255 - y) * yFactor); |
304 | byte* ptrO = (byte*)outputData.Scan0 + y * outputData.Stride; | ||
302 | 305 | ||
303 | // Select two textures | 306 | for(int x = 0; x < 256; ++x) |
304 | int l0 = (int)Math.Floor(layer); | 307 | { |
305 | int l1 = Math.Min(l0 + 1, 3); | 308 | int tx = (int)(x * xFactor); |
309 | float height = (float)terrain[tx, ty]; | ||
310 | float layer = getLayerTex(height, x, (255 - y), | ||
311 | (uint)tx + regionPositionX, (uint)ty + regionPositionY, | ||
312 | startHeights, heightRanges); | ||
306 | 313 | ||
307 | byte* ptrA = (byte*)datas[l0].Scan0 + y * datas[l0].Stride + x * comps[l0]; | 314 | // Select two textures |
308 | byte* ptrB = (byte*)datas[l1].Scan0 + y * datas[l1].Stride + x * comps[l1]; | 315 | int l0 = (int)layer; |
309 | byte* ptrO = (byte*)outputData.Scan0 + y * outputData.Stride + x * 3; | 316 | int l1 = Math.Min(l0 + 1, 3); |
310 | 317 | ||
311 | float aB = *(ptrA + 0); | 318 | float layerDiff = layer - l0; |
312 | float aG = *(ptrA + 1); | ||
313 | float aR = *(ptrA + 2); | ||
314 | 319 | ||
315 | float bB = *(ptrB + 0); | 320 | float a = mapColorsRed[l0]; |
316 | float bG = *(ptrB + 1); | 321 | float b = mapColorsRed[l1]; |
317 | float bR = *(ptrB + 2); | 322 | *(ptrO++) = (byte)(a + layerDiff * (b - a)); |
318 | 323 | ||
319 | float layerDiff = layer - l0; | 324 | a = mapColorsGreen[l0]; |
325 | b = mapColorsGreen[l1]; | ||
326 | *(ptrO++) = (byte)(a + layerDiff * (b - a)); | ||
320 | 327 | ||
321 | // Interpolate between the two selected textures | 328 | a = mapColorsBlue[l0]; |
322 | *(ptrO + 0) = (byte)Math.Floor(aB + layerDiff * (bB - aB)); | 329 | b = mapColorsBlue[l1]; |
323 | *(ptrO + 1) = (byte)Math.Floor(aG + layerDiff * (bG - aG)); | 330 | *(ptrO++) = (byte)(a + layerDiff * (b - a)); |
324 | *(ptrO + 2) = (byte)Math.Floor(aR + layerDiff * (bR - aR)); | 331 | } |
325 | } | 332 | } |
326 | } | 333 | } |
327 | |||
328 | for (int i = 0; i < detailTexture.Length; i++) | ||
329 | detailTexture[i].UnlockBits(datas[i]); | ||
330 | } | 334 | } |
335 | else | ||
336 | { | ||
337 | unsafe | ||
338 | { | ||
339 | // Get handles to all of the texture data arrays | ||
340 | BitmapData[] datas = new BitmapData[] | ||
341 | { | ||
342 | detailTexture[0].LockBits(new Rectangle(0, 0, 16, 16), ImageLockMode.ReadOnly, detailTexture[0].PixelFormat), | ||
343 | detailTexture[1].LockBits(new Rectangle(0, 0, 16, 16), ImageLockMode.ReadOnly, detailTexture[1].PixelFormat), | ||
344 | detailTexture[2].LockBits(new Rectangle(0, 0, 16, 16), ImageLockMode.ReadOnly, detailTexture[2].PixelFormat), | ||
345 | detailTexture[3].LockBits(new Rectangle(0, 0, 16, 16), ImageLockMode.ReadOnly, detailTexture[3].PixelFormat) | ||
346 | }; | ||
347 | |||
348 | for(int y = 0; y < 256; y++) | ||
349 | { | ||
350 | int ty = (int)((255 - y) * yFactor); | ||
351 | int ypatch = ((int)(y * yFactor) & 0x0f) * datas[0].Stride; | ||
352 | |||
353 | for(int x = 0; x < 256; x++) | ||
354 | { | ||
355 | int tx = (int)(x * xFactor); | ||
356 | float height = (float)terrain[tx, ty]; | ||
357 | float layer = getLayerTex(height, x, (255 - y), | ||
358 | (uint)tx + regionPositionX, (uint)ty + regionPositionY, | ||
359 | startHeights, heightRanges); | ||
360 | |||
361 | // Select two textures | ||
362 | int l0 = (int)layer; | ||
363 | int l1 = Math.Min(l0 + 1, 3); | ||
364 | |||
365 | int patchOffset = (tx & 0x0f) * 3 + ypatch; | ||
366 | byte* ptrA = (byte*)datas[l0].Scan0 + patchOffset; | ||
367 | byte* ptrB = (byte*)datas[l1].Scan0 + patchOffset; | ||
368 | byte* ptrO = (byte*)outputData.Scan0 + y * outputData.Stride + x * 3; | ||
369 | |||
370 | float aB = *(ptrA + 0); | ||
371 | float aG = *(ptrA + 1); | ||
372 | float aR = *(ptrA + 2); | ||
373 | |||
374 | float bB = *(ptrB + 0); | ||
375 | float bG = *(ptrB + 1); | ||
376 | float bR = *(ptrB + 2); | ||
377 | |||
378 | float layerDiff = layer - l0; | ||
379 | |||
380 | // Interpolate between the two selected textures | ||
381 | *(ptrO + 0) = (byte)(aB + layerDiff * (bB - aB)); | ||
382 | *(ptrO + 1) = (byte)(aG + layerDiff * (bG - aG)); | ||
383 | *(ptrO + 2) = (byte)(aR + layerDiff * (bR - aR)); | ||
384 | } | ||
385 | } | ||
386 | |||
387 | for(int i = 0; i < detailTexture.Length; i++) | ||
388 | detailTexture[i].UnlockBits(datas[i]); | ||
389 | } | ||
331 | 390 | ||
332 | for (int i = 0; i < detailTexture.Length; i++) | 391 | for(int i = 0; i < detailTexture.Length; i++) |
333 | if (detailTexture[i] != null) | 392 | if(detailTexture[i] != null) |
334 | detailTexture[i].Dispose(); | 393 | detailTexture[i].Dispose(); |
394 | } | ||
335 | 395 | ||
336 | output.UnlockBits(outputData); | 396 | output.UnlockBits(outputData); |
337 | 397 | ||
338 | // We generated the texture upside down, so flip it | 398 | output.Save("terr.png",ImageFormat.Png); |
339 | output.RotateFlip(RotateFlipType.RotateNoneFlipY); | ||
340 | 399 | ||
341 | #endregion Texture Compositing | 400 | #endregion Texture Compositing |
342 | 401 | ||
343 | return output; | 402 | return output; |
344 | } | 403 | } |
345 | 404 | ||
346 | public static Bitmap ResizeBitmap(Bitmap b, int nWidth, int nHeight) | 405 | [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] |
347 | { | 406 | private static float getLayerTex(float height, int x, int y, uint sourceX, uint sourceY, |
348 | m_log.DebugFormat("{0} ResizeBitmap. From <{1},{2}> to <{3},{4}>", | 407 | float[] startHeights, float[] heightRanges) |
349 | LogHeader, b.Width, b.Height, nWidth, nHeight); | ||
350 | Bitmap result = new Bitmap(nWidth, nHeight); | ||
351 | using (Graphics g = Graphics.FromImage(result)) | ||
352 | g.DrawImage(b, 0, 0, nWidth, nHeight); | ||
353 | b.Dispose(); | ||
354 | return result; | ||
355 | } | ||
356 | public static Bitmap SplatSimple(float[] heightmap) | ||
357 | { | 408 | { |
358 | const float BASE_HSV_H = 93f / 360f; | 409 | float pctX = (float)x / 255f; |
359 | const float BASE_HSV_S = 44f / 100f; | 410 | float pctY = (float)y / 255f; |
360 | const float BASE_HSV_V = 34f / 100f; | 411 | |
361 | 412 | // Use bilinear interpolation between the four corners of start height and | |
362 | Bitmap img = new Bitmap(256, 256); | 413 | // height range to select the current values at this position |
363 | BitmapData bitmapData = img.LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb); | 414 | float startHeight = ImageUtils.Bilinear( |
364 | 415 | startHeights[0], startHeights[2], | |
365 | unsafe | 416 | startHeights[1], startHeights[3], |
366 | { | 417 | pctX, pctY); |
367 | for (int y = 255; y >= 0; y--) | 418 | startHeight = Utils.Clamp(startHeight, 0f, 255f); |
368 | { | 419 | |
369 | for (int x = 0; x < 256; x++) | 420 | float heightRange = ImageUtils.Bilinear( |
370 | { | 421 | heightRanges[0], heightRanges[2], |
371 | float normHeight = heightmap[y * 256 + x] / 255f; | 422 | heightRanges[1], heightRanges[3], |
372 | normHeight = Utils.Clamp(normHeight, BASE_HSV_V, 1.0f); | 423 | pctX, pctY); |
373 | 424 | heightRange = Utils.Clamp(heightRange, 0f, 255f); | |
374 | Color4 color = Color4.FromHSV(BASE_HSV_H, BASE_HSV_S, normHeight); | 425 | |
375 | 426 | // Generate two frequencies of perlin noise based on our global position | |
376 | byte* ptr = (byte*)bitmapData.Scan0 + y * bitmapData.Stride + x * 3; | 427 | // The magic values were taken from http://opensimulator.org/wiki/Terrain_Splatting |
377 | *(ptr + 0) = (byte)(color.B * 255f); | 428 | Vector3 vec = new Vector3 |
378 | *(ptr + 1) = (byte)(color.G * 255f); | 429 | ( |
379 | *(ptr + 2) = (byte)(color.R * 255f); | 430 | sourceX * 0.20319f, |
380 | } | 431 | sourceY * 0.20319f, |
381 | } | 432 | height * 0.25f |
382 | } | 433 | ); |
383 | 434 | ||
384 | img.UnlockBits(bitmapData); | 435 | float noise = Perlin.noise2(vec.X * 0.222222f, vec.Y * 0.222222f) * 13.0f; |
385 | return img; | 436 | noise += Perlin.turbulence2(vec.X, vec.Y, 2f) * 4.5f; |
437 | |||
438 | // Combine the current height, generated noise, start height, and height range parameters, then scale all of it | ||
439 | float layer = ((height + noise - startHeight) / heightRange) * 4f; | ||
440 | if(Single.IsNaN(layer)) | ||
441 | return 0; | ||
442 | return Utils.Clamp(layer, 0f, 3f); | ||
386 | } | 443 | } |
387 | } | 444 | } |
388 | } | 445 | } |
diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/Viewport.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/Viewport.cs index 472f86e..5ea4d29 100644 --- a/OpenSim/Region/CoreModules/World/Warp3DMap/Viewport.cs +++ b/OpenSim/Region/CoreModules/World/Warp3DMap/Viewport.cs | |||
@@ -57,6 +57,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
57 | NearPlaneDistance = nearPlaneDist; | 57 | NearPlaneDistance = nearPlaneDist; |
58 | Width = width; | 58 | Width = width; |
59 | Height = height; | 59 | Height = height; |
60 | Orthographic = false; | ||
60 | } | 61 | } |
61 | 62 | ||
62 | public Viewport(Vector3 position, Vector3 lookDirection, float farPlaneDist, float nearPlaneDist, int width, int height, float orthoWindowWidth, float orthoWindowHeight) | 63 | public Viewport(Vector3 position, Vector3 lookDirection, float farPlaneDist, float nearPlaneDist, int width, int height, float orthoWindowWidth, float orthoWindowHeight) |
diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs index 387248c..9186fae 100644 --- a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs +++ b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs | |||
@@ -73,6 +73,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
73 | private IConfigSource m_config; | 73 | private IConfigSource m_config; |
74 | private bool m_drawPrimVolume = true; // true if should render the prims on the tile | 74 | private bool m_drawPrimVolume = true; // true if should render the prims on the tile |
75 | private bool m_textureTerrain = true; // true if to create terrain splatting texture | 75 | private bool m_textureTerrain = true; // true if to create terrain splatting texture |
76 | private bool m_textureAvegareTerrain = true; // replace terrain textures by their average color | ||
76 | private bool m_texturePrims = true; // true if should texture the rendered prims | 77 | private bool m_texturePrims = true; // true if should texture the rendered prims |
77 | private float m_texturePrimSize = 48f; // size of prim before we consider texturing it | 78 | private float m_texturePrimSize = 48f; // size of prim before we consider texturing it |
78 | private bool m_renderMeshes = false; // true if to render meshes rather than just bounding boxes | 79 | private bool m_renderMeshes = false; // true if to render meshes rather than just bounding boxes |
@@ -96,16 +97,21 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
96 | 97 | ||
97 | m_Enabled = true; | 98 | m_Enabled = true; |
98 | 99 | ||
99 | m_drawPrimVolume | 100 | m_drawPrimVolume = |
100 | = Util.GetConfigVarFromSections<bool>(m_config, "DrawPrimOnMapTile", configSections, m_drawPrimVolume); | 101 | Util.GetConfigVarFromSections<bool>(m_config, "DrawPrimOnMapTile", configSections, m_drawPrimVolume); |
101 | m_textureTerrain | 102 | m_textureTerrain = |
102 | = Util.GetConfigVarFromSections<bool>(m_config, "TextureOnMapTile", configSections, m_textureTerrain); | 103 | Util.GetConfigVarFromSections<bool>(m_config, "TextureOnMapTile", configSections, m_textureTerrain); |
103 | m_texturePrims | 104 | m_textureAvegareTerrain = |
104 | = Util.GetConfigVarFromSections<bool>(m_config, "TexturePrims", configSections, m_texturePrims); | 105 | Util.GetConfigVarFromSections<bool>(m_config, "AverageTextureColorOnMapTile", configSections, m_textureAvegareTerrain); |
105 | m_texturePrimSize | 106 | if(m_textureAvegareTerrain) |
106 | = Util.GetConfigVarFromSections<float>(m_config, "TexturePrimSize", configSections, m_texturePrimSize); | 107 | m_textureTerrain = true; |
107 | m_renderMeshes | 108 | m_texturePrims = |
108 | = Util.GetConfigVarFromSections<bool>(m_config, "RenderMeshes", configSections, m_renderMeshes); | 109 | Util.GetConfigVarFromSections<bool>(m_config, "TexturePrims", configSections, m_texturePrims); |
110 | m_texturePrimSize = | ||
111 | Util.GetConfigVarFromSections<float>(m_config, "TexturePrimSize", configSections, m_texturePrimSize); | ||
112 | m_renderMeshes = | ||
113 | Util.GetConfigVarFromSections<bool>(m_config, "RenderMeshes", configSections, m_renderMeshes); | ||
114 | |||
109 | } | 115 | } |
110 | 116 | ||
111 | public void AddRegion(Scene scene) | 117 | public void AddRegion(Scene scene) |
@@ -168,13 +174,13 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
168 | Vector3 camPos = new Vector3( | 174 | Vector3 camPos = new Vector3( |
169 | (m_scene.RegionInfo.RegionSizeX) * 0.5f, | 175 | (m_scene.RegionInfo.RegionSizeX) * 0.5f, |
170 | (m_scene.RegionInfo.RegionSizeY) * 0.5f, | 176 | (m_scene.RegionInfo.RegionSizeY) * 0.5f, |
171 | 221.7025033688163f); | 177 | 250f); |
172 | // Viewport viewing down onto the region | 178 | // Viewport viewing down onto the region |
173 | Viewport viewport = new Viewport(camPos, -Vector3.UnitZ, 1024f, 0.1f, | 179 | Viewport viewport = new Viewport(camPos, -Vector3.UnitZ, 1024f, 0.1f, |
174 | (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY, | 180 | (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY, |
175 | (float)m_scene.RegionInfo.RegionSizeX, (float)m_scene.RegionInfo.RegionSizeY); | 181 | (float)m_scene.RegionInfo.RegionSizeX, (float)m_scene.RegionInfo.RegionSizeY); |
176 | 182 | ||
177 | Bitmap tile = CreateMapTile(viewport, false); | 183 | Bitmap tile = CreateMapTile(viewport); |
178 | m_primMesher = null; | 184 | m_primMesher = null; |
179 | return tile; | 185 | return tile; |
180 | /* | 186 | /* |
@@ -187,10 +193,10 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
187 | public Bitmap CreateViewImage(Vector3 camPos, Vector3 camDir, float fov, int width, int height, bool useTextures) | 193 | public Bitmap CreateViewImage(Vector3 camPos, Vector3 camDir, float fov, int width, int height, bool useTextures) |
188 | { | 194 | { |
189 | Viewport viewport = new Viewport(camPos, camDir, fov, Constants.RegionSize, 0.1f, width, height); | 195 | Viewport viewport = new Viewport(camPos, camDir, fov, Constants.RegionSize, 0.1f, width, height); |
190 | return CreateMapTile(viewport, useTextures); | 196 | return CreateMapTile(viewport); |
191 | } | 197 | } |
192 | 198 | ||
193 | public Bitmap CreateMapTile(Viewport viewport, bool useTextures) | 199 | public Bitmap CreateMapTile(Viewport viewport) |
194 | { | 200 | { |
195 | m_colors.Clear(); | 201 | m_colors.Clear(); |
196 | 202 | ||
@@ -207,29 +213,20 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
207 | warp_Vector pos = ConvertVector(viewport.Position); | 213 | warp_Vector pos = ConvertVector(viewport.Position); |
208 | warp_Vector lookat = warp_Vector.add(ConvertVector(viewport.Position), ConvertVector(viewport.LookDirection)); | 214 | warp_Vector lookat = warp_Vector.add(ConvertVector(viewport.Position), ConvertVector(viewport.LookDirection)); |
209 | 215 | ||
216 | |||
217 | renderer.Scene.defaultCamera.setOrthographic(true, viewport.OrthoWindowWidth, viewport.OrthoWindowHeight); | ||
218 | |||
210 | renderer.Scene.defaultCamera.setPos(pos); | 219 | renderer.Scene.defaultCamera.setPos(pos); |
211 | renderer.Scene.defaultCamera.lookAt(lookat); | 220 | renderer.Scene.defaultCamera.lookAt(lookat); |
212 | |||
213 | if (viewport.Orthographic) | ||
214 | { | ||
215 | renderer.Scene.defaultCamera.setOrthographic(true,viewport.OrthoWindowWidth, viewport.OrthoWindowHeight); | ||
216 | } | ||
217 | else | ||
218 | { | ||
219 | float fov = viewport.FieldOfView; | ||
220 | fov *= 1.75f; // FIXME: ??? | ||
221 | renderer.Scene.defaultCamera.setFov(fov); | ||
222 | } | ||
223 | |||
224 | #endregion Camera | 221 | #endregion Camera |
225 | 222 | ||
226 | renderer.Scene.addLight("Light1", new warp_Light(new warp_Vector(1.0f, 0.5f, 1f), 0xffffff, 0, 320, 40)); | 223 | renderer.Scene.addLight("Light1", new warp_Light(new warp_Vector(1.0f, 0.5f, 1f), 0xffffff, 0, 320, 40)); |
227 | renderer.Scene.addLight("Light2", new warp_Light(new warp_Vector(-1f, -1f, 1f), 0xffffff, 0, 100, 40)); | 224 | renderer.Scene.addLight("Light2", new warp_Light(new warp_Vector(-1f, -1f, 1f), 0xffffff, 0, 100, 40)); |
228 | 225 | ||
229 | CreateWater(renderer); | 226 | CreateWater(renderer); |
230 | CreateTerrain(renderer, m_textureTerrain); | 227 | CreateTerrain(renderer); |
231 | if (m_drawPrimVolume) | 228 | if (m_drawPrimVolume) |
232 | CreateAllPrims(renderer, useTextures); | 229 | CreateAllPrims(renderer); |
233 | 230 | ||
234 | renderer.Render(); | 231 | renderer.Render(); |
235 | Bitmap bitmap = renderer.Scene.getImage(); | 232 | Bitmap bitmap = renderer.Scene.getImage(); |
@@ -286,7 +283,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
286 | // Add a terrain to the renderer. | 283 | // Add a terrain to the renderer. |
287 | // Note that we create a 'low resolution' 257x257 vertex terrain rather than trying for | 284 | // Note that we create a 'low resolution' 257x257 vertex terrain rather than trying for |
288 | // full resolution. This saves a lot of memory especially for very large regions. | 285 | // full resolution. This saves a lot of memory especially for very large regions. |
289 | private void CreateTerrain(WarpRenderer renderer, bool textureTerrain) | 286 | private void CreateTerrain(WarpRenderer renderer) |
290 | { | 287 | { |
291 | ITerrainChannel terrain = m_scene.Heightmap; | 288 | ITerrainChannel terrain = m_scene.Heightmap; |
292 | 289 | ||
@@ -296,11 +293,14 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
296 | // 'diff' is the difference in scale between the real region size and the size of terrain we're buiding | 293 | // 'diff' is the difference in scale between the real region size and the size of terrain we're buiding |
297 | float diff = regionsx / 256f; | 294 | float diff = regionsx / 256f; |
298 | 295 | ||
299 | int npointsx = (int)(regionsx / diff) + 1; | 296 | int npointsx = (int)(regionsx / diff); |
300 | int npointsy = (int)(regionsy / diff) + 1; | 297 | int npointsy = (int)(regionsy / diff); |
301 | 298 | ||
302 | float invsx = 1.0f / (npointsx * diff); | 299 | float invsx = 1.0f / (npointsx); |
303 | float invsy = 1.0f / (npointsy * diff); | 300 | float invsy = 1.0f / (npointsy); |
301 | |||
302 | npointsx++; | ||
303 | npointsy++; | ||
304 | 304 | ||
305 | // Create all the vertices for the terrain | 305 | // Create all the vertices for the terrain |
306 | warp_Object obj = new warp_Object(); | 306 | warp_Object obj = new warp_Object(); |
@@ -310,6 +310,10 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
310 | { | 310 | { |
311 | for (x = 0; x < regionsx; x += diff) | 311 | for (x = 0; x < regionsx; x += diff) |
312 | { | 312 | { |
313 | if(x == 48 && y == 36) | ||
314 | { | ||
315 | |||
316 | } | ||
313 | pos = ConvertVector(x , y , (float)terrain[(int)x, (int)y]); | 317 | pos = ConvertVector(x , y , (float)terrain[(int)x, (int)y]); |
314 | obj.addVertex(new warp_Vertex(pos, x * invsx, 1.0f - y * invsy)); | 318 | obj.addVertex(new warp_Vertex(pos, x * invsx, 1.0f - y * invsy)); |
315 | } | 319 | } |
@@ -378,17 +382,18 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
378 | warp_Texture texture; | 382 | warp_Texture texture; |
379 | using (Bitmap image = TerrainSplat.Splat( | 383 | using (Bitmap image = TerrainSplat.Splat( |
380 | terrain, textureIDs, startHeights, heightRanges, | 384 | terrain, textureIDs, startHeights, heightRanges, |
381 | new Vector3d(globalX, globalY, 0.0), m_scene.AssetService, textureTerrain)) | 385 | m_scene.RegionInfo.WorldLocX, m_scene.RegionInfo.WorldLocY, |
386 | m_scene.AssetService, m_textureTerrain, m_textureAvegareTerrain)) | ||
382 | texture = new warp_Texture(image); | 387 | texture = new warp_Texture(image); |
383 | 388 | ||
384 | warp_Material material = new warp_Material(texture); | 389 | warp_Material material = new warp_Material(texture); |
385 | material.setReflectivity(50); | 390 | // material.setReflectivity(50); |
386 | renderer.Scene.addMaterial("TerrainColor", material); | 391 | renderer.Scene.addMaterial("TerrainColor", material); |
387 | renderer.Scene.material("TerrainColor").setReflectivity(0); // reduces tile seams a bit thanks lkalif | 392 | // renderer.Scene.material("TerrainColor").setReflectivity(0); // reduces tile seams a bit thanks lkalif |
388 | renderer.SetObjectMaterial("Terrain", "TerrainColor"); | 393 | renderer.SetObjectMaterial("Terrain", "TerrainColor"); |
389 | } | 394 | } |
390 | 395 | ||
391 | private void CreateAllPrims(WarpRenderer renderer, bool useTextures) | 396 | private void CreateAllPrims(WarpRenderer renderer) |
392 | { | 397 | { |
393 | if (m_primMesher == null) | 398 | if (m_primMesher == null) |
394 | return; | 399 | return; |
@@ -397,13 +402,12 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
397 | delegate(SceneObjectGroup group) | 402 | delegate(SceneObjectGroup group) |
398 | { | 403 | { |
399 | foreach (SceneObjectPart child in group.Parts) | 404 | foreach (SceneObjectPart child in group.Parts) |
400 | CreatePrim(renderer, child, useTextures); | 405 | CreatePrim(renderer, child); |
401 | } | 406 | } |
402 | ); | 407 | ); |
403 | } | 408 | } |
404 | 409 | ||
405 | private void CreatePrim(WarpRenderer renderer, SceneObjectPart prim, | 410 | private void CreatePrim(WarpRenderer renderer, SceneObjectPart prim) |
406 | bool useTextures) | ||
407 | { | 411 | { |
408 | const float MIN_SIZE_SQUARE = 4f; | 412 | const float MIN_SIZE_SQUARE = 4f; |
409 | 413 | ||
@@ -489,19 +493,20 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
489 | } | 493 | } |
490 | 494 | ||
491 | Primitive.TextureEntryFace teFace = prim.Shape.Textures.GetFace((uint)i); | 495 | Primitive.TextureEntryFace teFace = prim.Shape.Textures.GetFace((uint)i); |
492 | Color4 faceColor = GetFaceColor(teFace); | 496 | Color4 faceColor = teFace.RGBA; |
493 | string materialName = String.Empty; | 497 | string materialName = String.Empty; |
494 | if (m_texturePrims && primScaleLenSquared > m_texturePrimSize*m_texturePrimSize) | 498 | if (m_texturePrims && primScaleLenSquared > m_texturePrimSize*m_texturePrimSize) |
495 | materialName = GetOrCreateMaterial(renderer, faceColor, teFace.TextureID); | 499 | materialName = GetOrCreateMaterial(renderer, faceColor, teFace.TextureID); |
496 | else | 500 | else |
497 | materialName = GetOrCreateMaterial(renderer, faceColor); | 501 | materialName = GetOrCreateMaterial(renderer, GetFaceColor(teFace)); |
498 | 502 | ||
499 | faceObj.scaleSelf(prim.Scale.X, prim.Scale.Z, prim.Scale.Y); | 503 | faceObj.scaleSelf(prim.Scale.X, prim.Scale.Z, prim.Scale.Y); |
500 | 504 | ||
501 | warp_Vector primPos = ConvertVector(prim.GetWorldPosition()); | ||
502 | warp_Quaternion primRot = ConvertQuaternion(prim.GetWorldRotation()); | 505 | warp_Quaternion primRot = ConvertQuaternion(prim.GetWorldRotation()); |
503 | warp_Matrix m = warp_Matrix.quaternionMatrix(primRot); | 506 | warp_Matrix m = warp_Matrix.quaternionMatrix(primRot); |
504 | faceObj.transform(m); | 507 | faceObj.transform(m); |
508 | |||
509 | warp_Vector primPos = ConvertVector(prim.GetWorldPosition()); | ||
505 | faceObj.setPos(primPos); | 510 | faceObj.setPos(primPos); |
506 | 511 | ||
507 | renderer.Scene.addObject(meshName, faceObj); | 512 | renderer.Scene.addObject(meshName, faceObj); |
@@ -645,7 +650,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
645 | 650 | ||
646 | private static warp_Quaternion ConvertQuaternion(Quaternion quat) | 651 | private static warp_Quaternion ConvertQuaternion(Quaternion quat) |
647 | { | 652 | { |
648 | return new warp_Quaternion(quat.X, quat.Z, quat.Y, -quat.W); | 653 | return new warp_Quaternion(quat.X, quat.Z, quat.Y, -quat.W); |
649 | } | 654 | } |
650 | 655 | ||
651 | private static int ConvertColor(Color4 color) | 656 | private static int ConvertColor(Color4 color) |
@@ -778,18 +783,21 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
778 | /// <param name="width">New width</param> | 783 | /// <param name="width">New width</param> |
779 | /// <param name="height">New height</param> | 784 | /// <param name="height">New height</param> |
780 | /// <returns>Resized image</returns> | 785 | /// <returns>Resized image</returns> |
781 | public static Bitmap ResizeImage(Image image, int width, int height) | 786 | public static Bitmap ResizeImageSolid(Image image, int width, int height) |
782 | { | 787 | { |
783 | Bitmap result = new Bitmap(width, height); | 788 | Bitmap result = new Bitmap(width, height, PixelFormat.Format24bppRgb); |
784 | 789 | ||
790 | using (ImageAttributes atrib = new ImageAttributes()) | ||
785 | using (Graphics graphics = Graphics.FromImage(result)) | 791 | using (Graphics graphics = Graphics.FromImage(result)) |
786 | { | 792 | { |
793 | atrib.SetWrapMode(System.Drawing.Drawing2D.WrapMode.TileFlipXY); | ||
787 | graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; | 794 | graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; |
788 | graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; | 795 | graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; |
789 | graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; | 796 | graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; |
790 | graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality; | 797 | graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.None; |
791 | 798 | ||
792 | graphics.DrawImage(image, 0, 0, result.Width, result.Height); | 799 | graphics.DrawImage(image,new Rectangle(0,0, result.Width, result.Height), |
800 | 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, atrib); | ||
793 | } | 801 | } |
794 | 802 | ||
795 | return result; | 803 | return result; |
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index 476d90a..4b14c71 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs | |||
@@ -93,6 +93,9 @@ namespace OpenSim.Region.CoreModules.World.WorldMap | |||
93 | private const double expireResponsesTime = 120.0; // 2 minutes ? | 93 | private const double expireResponsesTime = 120.0; // 2 minutes ? |
94 | //private int CacheRegionsDistance = 256; | 94 | //private int CacheRegionsDistance = 256; |
95 | 95 | ||
96 | private bool m_exportPrintScale = false; // prints the scale of map in meters on exported map | ||
97 | private bool m_exportPrintRegionName = false; // prints the region name exported map | ||
98 | |||
96 | #region INonSharedRegionModule Members | 99 | #region INonSharedRegionModule Members |
97 | public virtual void Initialise(IConfigSource config) | 100 | public virtual void Initialise(IConfigSource config) |
98 | { | 101 | { |
@@ -103,6 +106,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap | |||
103 | m_Enabled = true; | 106 | m_Enabled = true; |
104 | 107 | ||
105 | expireBlackListTime = (double)Util.GetConfigVarFromSections<int>(config, "BlacklistTimeout", configSections, 10 * 60); | 108 | expireBlackListTime = (double)Util.GetConfigVarFromSections<int>(config, "BlacklistTimeout", configSections, 10 * 60); |
109 | |||
110 | m_exportPrintScale = | ||
111 | Util.GetConfigVarFromSections<bool>(config, "ExportMapAddScale", configSections, m_exportPrintScale); | ||
112 | m_exportPrintRegionName = | ||
113 | Util.GetConfigVarFromSections<bool>(config, "ExportMapAddRegionName", configSections, m_exportPrintRegionName); | ||
106 | } | 114 | } |
107 | 115 | ||
108 | public virtual void AddRegion(Scene scene) | 116 | public virtual void AddRegion(Scene scene) |
@@ -1418,14 +1426,16 @@ namespace OpenSim.Region.CoreModules.World.WorldMap | |||
1418 | int spanY = endY - startY + 2; | 1426 | int spanY = endY - startY + 2; |
1419 | 1427 | ||
1420 | Bitmap mapTexture = new Bitmap(spanX, spanY); | 1428 | Bitmap mapTexture = new Bitmap(spanX, spanY); |
1429 | ImageAttributes gatrib = new ImageAttributes(); | ||
1421 | Graphics g = Graphics.FromImage(mapTexture); | 1430 | Graphics g = Graphics.FromImage(mapTexture); |
1431 | gatrib.SetWrapMode(System.Drawing.Drawing2D.WrapMode.TileFlipXY); | ||
1422 | g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; | 1432 | g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; |
1423 | g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; | 1433 | g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; |
1424 | g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; | 1434 | g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; |
1425 | g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality; | 1435 | g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.None; |
1426 | 1436 | ||
1427 | SolidBrush sea = new SolidBrush(Color.DarkBlue); | 1437 | SolidBrush sea = new SolidBrush(Color.DarkBlue); |
1428 | g.FillRectangle(sea, 0, 0, spanX - 1, spanY - 1); | 1438 | g.FillRectangle(sea, 0, 0, spanX, spanY); |
1429 | sea.Dispose(); | 1439 | sea.Dispose(); |
1430 | 1440 | ||
1431 | List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, | 1441 | List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, |
@@ -1457,8 +1467,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap | |||
1457 | int y = r.RegionLocY - startY; | 1467 | int y = r.RegionLocY - startY; |
1458 | int sx = r.RegionSizeX; | 1468 | int sx = r.RegionSizeX; |
1459 | int sy = r.RegionSizeY; | 1469 | int sy = r.RegionSizeY; |
1460 | g.DrawImage(image, x, spanY - y - sy, sx, sy); // y origin is top | 1470 | // y origin is top |
1461 | if(r.RegionHandle == m_scene.RegionInfo.RegionHandle) | 1471 | g.DrawImage(image,new Rectangle(x, spanY - y - sy, sx, sy), |
1472 | 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, gatrib); | ||
1473 | |||
1474 | if(m_exportPrintRegionName && r.RegionHandle == m_scene.RegionInfo.RegionHandle) | ||
1462 | { | 1475 | { |
1463 | SizeF stringSize = g.MeasureString(r.RegionName, drawFont); | 1476 | SizeF stringSize = g.MeasureString(r.RegionName, drawFont); |
1464 | g.DrawString(r.RegionName, drawFont, drawBrush, x + 30, spanY - y - 30 - stringSize.Height); | 1477 | g.DrawString(r.RegionName, drawFont, drawBrush, x + 30, spanY - y - 30 - stringSize.Height); |
@@ -1469,13 +1482,17 @@ namespace OpenSim.Region.CoreModules.World.WorldMap | |||
1469 | if(image != null) | 1482 | if(image != null) |
1470 | image.Dispose(); | 1483 | image.Dispose(); |
1471 | 1484 | ||
1472 | String drawString = string.Format("{0}m x {1}m", spanX, spanY); | 1485 | if(m_exportPrintScale) |
1473 | g.DrawString(drawString, drawFont, drawBrush, 30, 30); | 1486 | { |
1487 | String drawString = string.Format("{0}m x {1}m", spanX, spanY); | ||
1488 | g.DrawString(drawString, drawFont, drawBrush, 30, 30); | ||
1489 | } | ||
1474 | 1490 | ||
1475 | drawBrush.Dispose(); | 1491 | drawBrush.Dispose(); |
1476 | drawFont.Dispose(); | 1492 | drawFont.Dispose(); |
1477 | } | 1493 | } |
1478 | 1494 | ||
1495 | gatrib.Dispose(); | ||
1479 | g.Dispose(); | 1496 | g.Dispose(); |
1480 | 1497 | ||
1481 | mapTexture.Save(exportPath, ImageFormat.Jpeg); | 1498 | mapTexture.Save(exportPath, ImageFormat.Jpeg); |