aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs')
-rw-r--r--OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs241
1 files changed, 188 insertions, 53 deletions
diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
index 6d9e31b..f072268 100644
--- a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
+++ b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
@@ -31,21 +31,25 @@ using System.Drawing;
31using System.Drawing.Imaging; 31using System.Drawing.Imaging;
32using System.IO; 32using System.IO;
33using System.Reflection; 33using System.Reflection;
34
34using CSJ2K; 35using CSJ2K;
35using Nini.Config; 36using Nini.Config;
36using log4net; 37using log4net;
37using Rednettle.Warp3D; 38using Rednettle.Warp3D;
38using Mono.Addins; 39using Mono.Addins;
39using OpenMetaverse; 40
40using OpenMetaverse.Imaging;
41using OpenMetaverse.Rendering;
42using OpenMetaverse.StructuredData;
43using OpenSim.Framework; 41using OpenSim.Framework;
44using OpenSim.Region.Framework.Interfaces; 42using OpenSim.Region.Framework.Interfaces;
45using OpenSim.Region.Framework.Scenes; 43using OpenSim.Region.Framework.Scenes;
46using OpenSim.Region.Physics.Manager; 44using OpenSim.Region.Physics.Manager;
47using OpenSim.Services.Interfaces; 45using OpenSim.Services.Interfaces;
48 46
47using OpenMetaverse;
48using OpenMetaverse.Assets;
49using OpenMetaverse.Imaging;
50using OpenMetaverse.Rendering;
51using OpenMetaverse.StructuredData;
52
49using WarpRenderer = global::Warp3D.Warp3D; 53using WarpRenderer = global::Warp3D.Warp3D;
50 54
51namespace OpenSim.Region.CoreModules.World.Warp3DMap 55namespace OpenSim.Region.CoreModules.World.Warp3DMap
@@ -57,12 +61,20 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
57 private static readonly Color4 WATER_COLOR = new Color4(29, 72, 96, 216); 61 private static readonly Color4 WATER_COLOR = new Color4(29, 72, 96, 216);
58 62
59 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 63 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
64 private static string LogHeader = "[WARP 3D IMAGE MODULE]";
60 65
61 private Scene m_scene; 66 private Scene m_scene;
62 private IRendering m_primMesher; 67 private IRendering m_primMesher;
63 private IConfigSource m_config;
64 private Dictionary<UUID, Color4> m_colors = new Dictionary<UUID, Color4>(); 68 private Dictionary<UUID, Color4> m_colors = new Dictionary<UUID, Color4>();
65 private bool m_useAntiAliasing = false; // TODO: Make this a config option 69
70 private IConfigSource m_config;
71 private bool m_drawPrimVolume = true; // true if should render the prims on the tile
72 private bool m_textureTerrain = true; // true if to create terrain splatting texture
73 private bool m_texturePrims = true; // true if should texture the rendered prims
74 private float m_texturePrimSize = 48f; // size of prim before we consider texturing it
75 private bool m_renderMeshes = false; // true if to render meshes rather than just bounding boxes
76 private bool m_useAntiAliasing = false; // true if to anti-alias the rendered image
77
66 private bool m_Enabled = false; 78 private bool m_Enabled = false;
67 79
68 #region Region Module interface 80 #region Region Module interface
@@ -71,11 +83,27 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
71 { 83 {
72 m_config = source; 84 m_config = source;
73 85
86 string[] configSections = new string[] { "Map", "Startup" };
87
74 if (Util.GetConfigVarFromSections<string>( 88 if (Util.GetConfigVarFromSections<string>(
75 m_config, "MapImageModule", new string[] { "Startup", "Map" }, "MapImageModule") != "Warp3DImageModule") 89 m_config, "MapImageModule", configSections, "MapImageModule") != "Warp3DImageModule")
76 return; 90 return;
77 91
78 m_Enabled = true; 92 m_Enabled = true;
93
94 m_drawPrimVolume
95 = Util.GetConfigVarFromSections<bool>(m_config, "DrawPrimOnMapTile", configSections, m_drawPrimVolume);
96 m_textureTerrain
97 = Util.GetConfigVarFromSections<bool>(m_config, "TextureOnMapTile", configSections, m_textureTerrain);
98 m_texturePrims
99 = Util.GetConfigVarFromSections<bool>(m_config, "TexturePrims", configSections, m_texturePrims);
100 m_texturePrimSize
101 = Util.GetConfigVarFromSections<float>(m_config, "TexturePrimSize", configSections, m_texturePrimSize);
102 m_renderMeshes
103 = Util.GetConfigVarFromSections<bool>(m_config, "RenderMeshes", configSections, m_renderMeshes);
104 m_useAntiAliasing
105 = Util.GetConfigVarFromSections<bool>(m_config, "UseAntiAliasing", configSections, m_useAntiAliasing);
106
79 } 107 }
80 108
81 public void AddRegion(Scene scene) 109 public void AddRegion(Scene scene)
@@ -127,31 +155,28 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
127 155
128 public Bitmap CreateMapTile() 156 public Bitmap CreateMapTile()
129 { 157 {
130 Vector3 camPos = new Vector3(127.5f, 127.5f, 221.7025033688163f); 158 // Vector3 camPos = new Vector3(127.5f, 127.5f, 221.7025033688163f);
159 // Camera above the middle of the region
160 Vector3 camPos = new Vector3(
161 m_scene.RegionInfo.RegionSizeX/2 - 0.5f,
162 m_scene.RegionInfo.RegionSizeY/2 - 0.5f,
163 221.7025033688163f);
164 // Viewport viewing down onto the region
131 Viewport viewport = new Viewport(camPos, -Vector3.UnitZ, 1024f, 0.1f, 165 Viewport viewport = new Viewport(camPos, -Vector3.UnitZ, 1024f, 0.1f,
132 (int)Constants.RegionSize, (int)Constants.RegionSize, 166 (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY,
133 (float)Constants.RegionSize, (float)Constants.RegionSize); 167 (float)m_scene.RegionInfo.RegionSizeX, (float)m_scene.RegionInfo.RegionSizeY );
168 // Fill the viewport and return the image
134 return CreateMapTile(viewport, false); 169 return CreateMapTile(viewport, false);
135 } 170 }
136 171
137 public Bitmap CreateViewImage(Vector3 camPos, Vector3 camDir, float fov, int width, int height, bool useTextures) 172 public Bitmap CreateViewImage(Vector3 camPos, Vector3 camDir, float fov, int width, int height, bool useTextures)
138 { 173 {
139 Viewport viewport = new Viewport(camPos, camDir, fov, (float)Constants.RegionSize, 0.1f, width, height); 174 Viewport viewport = new Viewport(camPos, camDir, fov, Constants.RegionSize, 0.1f, width, height);
140 return CreateMapTile(viewport, useTextures); 175 return CreateMapTile(viewport, useTextures);
141 } 176 }
142 177
143 public Bitmap CreateMapTile(Viewport viewport, bool useTextures) 178 public Bitmap CreateMapTile(Viewport viewport, bool useTextures)
144 { 179 {
145 bool drawPrimVolume = true;
146 bool textureTerrain = true;
147
148 string[] configSections = new string[] { "Map", "Startup" };
149
150 drawPrimVolume
151 = Util.GetConfigVarFromSections<bool>(m_config, "DrawPrimOnMapTile", configSections, drawPrimVolume);
152 textureTerrain
153 = Util.GetConfigVarFromSections<bool>(m_config, "TextureOnMapTile", configSections, textureTerrain);
154
155 m_colors.Clear(); 180 m_colors.Clear();
156 181
157 int width = viewport.Width; 182 int width = viewport.Width;
@@ -195,8 +220,8 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
195 renderer.Scene.addLight("Light2", new warp_Light(new warp_Vector(-1f, -1f, 1f), 0xffffff, 0, 100, 40)); 220 renderer.Scene.addLight("Light2", new warp_Light(new warp_Vector(-1f, -1f, 1f), 0xffffff, 0, 100, 40));
196 221
197 CreateWater(renderer); 222 CreateWater(renderer);
198 CreateTerrain(renderer, textureTerrain); 223 CreateTerrain(renderer, m_textureTerrain);
199 if (drawPrimVolume) 224 if (m_drawPrimVolume)
200 CreateAllPrims(renderer, useTextures); 225 CreateAllPrims(renderer, useTextures);
201 226
202 renderer.Render(); 227 renderer.Render();
@@ -212,6 +237,16 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
212 // afterwards. It's generally regarded as a bad idea to manually GC. If Warp3D is using lots of memory 237 // afterwards. It's generally regarded as a bad idea to manually GC. If Warp3D is using lots of memory
213 // then this may be some issue with the Warp3D code itself, though it's also quite possible that generating 238 // then this may be some issue with the Warp3D code itself, though it's also quite possible that generating
214 // this map tile simply takes a lot of memory. 239 // this map tile simply takes a lot of memory.
240 foreach (var o in renderer.Scene.objectData.Values)
241 {
242 warp_Object obj = (warp_Object)o;
243 obj.vertexData = null;
244 obj.triangleData = null;
245 }
246 renderer.Scene.removeAllObjects();
247 renderer = null;
248 viewport = null;
249 m_colors.Clear();
215 GC.Collect(); 250 GC.Collect();
216 m_log.Debug("[WARP 3D IMAGE MODULE]: GC.Collect()"); 251 m_log.Debug("[WARP 3D IMAGE MODULE]: GC.Collect()");
217 252
@@ -238,61 +273,74 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
238 273
239 #region Rendering Methods 274 #region Rendering Methods
240 275
276 // Add a water plane to the renderer.
241 private void CreateWater(WarpRenderer renderer) 277 private void CreateWater(WarpRenderer renderer)
242 { 278 {
243 float waterHeight = (float)m_scene.RegionInfo.RegionSettings.WaterHeight; 279 float waterHeight = (float)m_scene.RegionInfo.RegionSettings.WaterHeight;
244 280
245 renderer.AddPlane("Water", 256f * 0.5f); 281 renderer.AddPlane("Water", m_scene.RegionInfo.RegionSizeX * 0.5f);
246 renderer.Scene.sceneobject("Water").setPos(127.5f, waterHeight, 127.5f); 282 renderer.Scene.sceneobject("Water").setPos(m_scene.RegionInfo.RegionSizeX/2 - 0.5f,
283 waterHeight,
284 m_scene.RegionInfo.RegionSizeY/2 - 0.5f );
247 285
248 renderer.AddMaterial("WaterColor", ConvertColor(WATER_COLOR)); 286 warp_Material waterColorMaterial = new warp_Material(ConvertColor(WATER_COLOR));
249 renderer.Scene.material("WaterColor").setReflectivity(0); // match water color with standard map module thanks lkalif 287 waterColorMaterial.setReflectivity(0); // match water color with standard map module thanks lkalif
250 renderer.Scene.material("WaterColor").setTransparency((byte)((1f - WATER_COLOR.A) * 255f)); 288 waterColorMaterial.setTransparency((byte)((1f - WATER_COLOR.A) * 255f));
289 renderer.Scene.addMaterial("WaterColor", waterColorMaterial);
251 renderer.SetObjectMaterial("Water", "WaterColor"); 290 renderer.SetObjectMaterial("Water", "WaterColor");
252 } 291 }
253 292
293 // Add a terrain to the renderer.
294 // Note that we create a 'low resolution' 256x256 vertex terrain rather than trying for
295 // full resolution. This saves a lot of memory especially for very large regions.
254 private void CreateTerrain(WarpRenderer renderer, bool textureTerrain) 296 private void CreateTerrain(WarpRenderer renderer, bool textureTerrain)
255 { 297 {
256 ITerrainChannel terrain = m_scene.Heightmap; 298 ITerrainChannel terrain = m_scene.Heightmap;
257 float[] heightmap = terrain.GetFloatsSerialised(); 299
300 // 'diff' is the difference in scale between the real region size and the size of terrain we're buiding
301 float diff = (float)m_scene.RegionInfo.RegionSizeX / 256f;
258 302
259 warp_Object obj = new warp_Object(256 * 256, 255 * 255 * 2); 303 warp_Object obj = new warp_Object(256 * 256, 255 * 255 * 2);
260 304
261 for (int y = 0; y < 256; y++) 305 // Create all the vertices for the terrain
306 for (float y = 0; y < m_scene.RegionInfo.RegionSizeY; y += diff)
262 { 307 {
263 for (int x = 0; x < 256; x++) 308 for (float x = 0; x < m_scene.RegionInfo.RegionSizeX; x += diff)
264 { 309 {
265 int v = y * 256 + x; 310 warp_Vector pos = ConvertVector(x, y, (float)terrain[(int)x, (int)y]);
266 float height = heightmap[v]; 311 obj.addVertex(new warp_Vertex(pos,
267 312 x / (float)m_scene.RegionInfo.RegionSizeX,
268 warp_Vector pos = ConvertVector(new Vector3(x, y, height)); 313 (((float)m_scene.RegionInfo.RegionSizeY) - y) / m_scene.RegionInfo.RegionSizeY) );
269 obj.addVertex(new warp_Vertex(pos, (float)x / 255f, (float)(255 - y) / 255f));
270 } 314 }
271 } 315 }
272 316
273 for (int y = 0; y < 256; y++) 317 // Now that we have all the vertices, make another pass and create
318 // the normals for each of the surface triangles and
319 // create the list of triangle indices.
320 for (float y = 0; y < m_scene.RegionInfo.RegionSizeY; y += diff)
274 { 321 {
275 for (int x = 0; x < 256; x++) 322 for (float x = 0; x < m_scene.RegionInfo.RegionSizeX; x += diff)
276 { 323 {
277 if (x < 255 && y < 255) 324 float newX = x / diff;
325 float newY = y / diff;
326 if (newX < 255 && newY < 255)
278 { 327 {
279 int v = y * 256 + x; 328 int v = (int)newY * 256 + (int)newX;
280 329
281 // Normal 330 // Normal for a triangle made up of three adjacent vertices
282 Vector3 v1 = new Vector3(x, y, heightmap[y * 256 + x]); 331 Vector3 v1 = new Vector3(newX, newY, (float)terrain[(int)x, (int)y]);
283 Vector3 v2 = new Vector3(x + 1, y, heightmap[y * 256 + x + 1]); 332 Vector3 v2 = new Vector3(newX + 1, newY, (float)terrain[(int)(x + 1), (int)y]);
284 Vector3 v3 = new Vector3(x, y + 1, heightmap[(y + 1) * 256 + x]); 333 Vector3 v3 = new Vector3(newX, newY + 1, (float)terrain[(int)x, ((int)(y + 1))]);
285 warp_Vector norm = ConvertVector(SurfaceNormal(v1, v2, v3)); 334 warp_Vector norm = ConvertVector(SurfaceNormal(v1, v2, v3));
286 norm = norm.reverse(); 335 norm = norm.reverse();
287 obj.vertex(v).n = norm; 336 obj.vertex(v).n = norm;
288 337
289 // Triangle 1 338 // Make two triangles for each of the squares in the grid of vertices
290 obj.addTriangle( 339 obj.addTriangle(
291 v, 340 v,
292 v + 1, 341 v + 1,
293 v + 256); 342 v + 256);
294 343
295 // Triangle 2
296 obj.addTriangle( 344 obj.addTriangle(
297 v + 256 + 1, 345 v + 256 + 1,
298 v + 256, 346 v + 256,
@@ -307,7 +355,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
307 float[] startHeights = new float[4]; 355 float[] startHeights = new float[4];
308 float[] heightRanges = new float[4]; 356 float[] heightRanges = new float[4];
309 357
310 RegionSettings regionInfo = m_scene.RegionInfo.RegionSettings; 358 OpenSim.Framework.RegionSettings regionInfo = m_scene.RegionInfo.RegionSettings;
311 359
312 textureIDs[0] = regionInfo.TerrainTexture1; 360 textureIDs[0] = regionInfo.TerrainTexture1;
313 textureIDs[1] = regionInfo.TerrainTexture2; 361 textureIDs[1] = regionInfo.TerrainTexture2;
@@ -325,16 +373,18 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
325 heightRanges[3] = (float)regionInfo.Elevation2NE; 373 heightRanges[3] = (float)regionInfo.Elevation2NE;
326 374
327 uint globalX, globalY; 375 uint globalX, globalY;
328 Utils.LongToUInts(m_scene.RegionInfo.RegionHandle, out globalX, out globalY); 376 Util.RegionHandleToWorldLoc(m_scene.RegionInfo.RegionHandle, out globalX, out globalY);
329 377
330 warp_Texture texture; 378 warp_Texture texture;
331
332 using ( 379 using (
333 Bitmap image 380 Bitmap image
334 = TerrainSplat.Splat( 381 = TerrainSplat.Splat(terrain, textureIDs, startHeights, heightRanges,
335 heightmap, textureIDs, startHeights, heightRanges,
336 new Vector3d(globalX, globalY, 0.0), m_scene.AssetService, textureTerrain)) 382 new Vector3d(globalX, globalY, 0.0), m_scene.AssetService, textureTerrain))
337 { 383 {
384 image.Save( // DEBUG DEBUG
385 String.Format("maptiles/splat-{0}-{1}-{2}.jpg", m_scene.RegionInfo.RegionName,
386 m_scene.RegionInfo.RegionLocX, m_scene.RegionInfo.RegionLocY),
387 ImageFormat.Jpeg);
338 texture = new warp_Texture(image); 388 texture = new warp_Texture(image);
339 } 389 }
340 390
@@ -370,8 +420,48 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
370 if (prim.Scale.LengthSquared() < MIN_SIZE * MIN_SIZE) 420 if (prim.Scale.LengthSquared() < MIN_SIZE * MIN_SIZE)
371 return; 421 return;
372 422
423 FacetedMesh renderMesh = null;
373 Primitive omvPrim = prim.Shape.ToOmvPrimitive(prim.OffsetPosition, prim.RotationOffset); 424 Primitive omvPrim = prim.Shape.ToOmvPrimitive(prim.OffsetPosition, prim.RotationOffset);
374 FacetedMesh renderMesh = m_primMesher.GenerateFacetedMesh(omvPrim, DetailLevel.Medium); 425
426 if (m_renderMeshes)
427 {
428 if (omvPrim.Sculpt != null && omvPrim.Sculpt.SculptTexture != UUID.Zero)
429 {
430 // Try fetchinng the asset
431 byte[] sculptAsset = m_scene.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString());
432 if (sculptAsset != null)
433 {
434 // Is it a mesh?
435 if (omvPrim.Sculpt.Type == SculptType.Mesh)
436 {
437 AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset);
438 FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, DetailLevel.Highest, out renderMesh);
439 meshAsset = null;
440 }
441 else // It's sculptie
442 {
443 IJ2KDecoder imgDecoder = m_scene.RequestModuleInterface<IJ2KDecoder>();
444 if (imgDecoder != null)
445 {
446 Image sculpt = imgDecoder.DecodeToImage(sculptAsset);
447 if (sculpt != null)
448 {
449 renderMesh = m_primMesher.GenerateFacetedSculptMesh(omvPrim, (Bitmap)sculpt,
450 DetailLevel.Medium);
451 sculpt.Dispose();
452 }
453 }
454 }
455 }
456 }
457 }
458
459 // If not a mesh or sculptie, try the regular mesher
460 if (renderMesh == null)
461 {
462 renderMesh = m_primMesher.GenerateFacetedMesh(omvPrim, DetailLevel.Medium);
463 }
464
375 if (renderMesh == null) 465 if (renderMesh == null)
376 return; 466 return;
377 467
@@ -430,7 +520,11 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
430 520
431 Primitive.TextureEntryFace teFace = prim.Shape.Textures.GetFace((uint)i); 521 Primitive.TextureEntryFace teFace = prim.Shape.Textures.GetFace((uint)i);
432 Color4 faceColor = GetFaceColor(teFace); 522 Color4 faceColor = GetFaceColor(teFace);
433 string materialName = GetOrCreateMaterial(renderer, faceColor); 523 string materialName = String.Empty;
524 if (m_texturePrims && prim.Scale.LengthSquared() > m_texturePrimSize*m_texturePrimSize)
525 materialName = GetOrCreateMaterial(renderer, faceColor, teFace.TextureID);
526 else
527 materialName = GetOrCreateMaterial(renderer, faceColor);
434 528
435 faceObj.transform(m); 529 faceObj.transform(m);
436 faceObj.setPos(primPos); 530 faceObj.setPos(primPos);
@@ -519,10 +613,51 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
519 return name; 613 return name;
520 } 614 }
521 615
616 public string GetOrCreateMaterial(WarpRenderer renderer, Color4 faceColor, UUID textureID)
617 {
618 string materialName = "Color-" + faceColor.ToString() + "-Texture-" + textureID.ToString();
619
620 if (renderer.Scene.material(materialName) == null)
621 {
622 renderer.AddMaterial(materialName, ConvertColor(faceColor));
623 if (faceColor.A < 1f)
624 {
625 renderer.Scene.material(materialName).setTransparency((byte) ((1f - faceColor.A)*255f));
626 }
627 warp_Texture texture = GetTexture(textureID);
628 if (texture != null)
629 renderer.Scene.material(materialName).setTexture(texture);
630 }
631
632 return materialName;
633 }
634
635 private warp_Texture GetTexture(UUID id)
636 {
637 warp_Texture ret = null;
638 byte[] asset = m_scene.AssetService.GetData(id.ToString());
639 if (asset != null)
640 {
641 IJ2KDecoder imgDecoder = m_scene.RequestModuleInterface<IJ2KDecoder>();
642 Bitmap img = (Bitmap) imgDecoder.DecodeToImage(asset);
643 if (img != null)
644 {
645 return new warp_Texture(img);
646 }
647 }
648 return ret;
649 }
650
522 #endregion Rendering Methods 651 #endregion Rendering Methods
523 652
524 #region Static Helpers 653 #region Static Helpers
525 654
655 // Note: axis change.
656 private static warp_Vector ConvertVector(float x, float y, float z)
657 {
658 return new warp_Vector(x, z, y);
659 }
660
526 private static warp_Vector ConvertVector(Vector3 vector) 661 private static warp_Vector ConvertVector(Vector3 vector)
527 { 662 {
528 return new warp_Vector(vector.X, vector.Z, vector.Y); 663 return new warp_Vector(vector.X, vector.Z, vector.Y);