OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
MapImageModule.cs
Go to the documentation of this file.
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 OpenSimulator 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 
28 using System;
29 using System.Collections.Generic;
30 using System.Drawing;
31 using System.Reflection;
32 using log4net;
33 using Mono.Addins;
34 using Nini.Config;
35 using OpenMetaverse;
36 using OpenMetaverse.Imaging;
37 using OpenSim.Framework;
38 using OpenSim.Region.Framework.Interfaces;
39 using OpenSim.Region.Framework.Scenes;
40 
41 namespace OpenSim.Region.CoreModules.World.LegacyMap
42 {
43  public enum DrawRoutine
44  {
45  Rectangle,
46  Polygon,
47  Ellipse
48  }
49 
50  public struct face
51  {
52  public Point[] pts;
53  }
54 
55  public struct DrawStruct
56  {
57  public DrawRoutine dr;
58 // public Rectangle rect;
59  public SolidBrush brush;
60  public face[] trns;
61  }
62 
63  [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MapImageModule")]
65  {
66  private static readonly ILog m_log =
67  LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
68 
69  private Scene m_scene;
70  private IConfigSource m_config;
71  private IMapTileTerrainRenderer terrainRenderer;
72  private bool m_Enabled = false;
73 
74  #region IMapImageGenerator Members
75 
76  public Bitmap CreateMapTile()
77  {
78  bool drawPrimVolume = true;
79  bool textureTerrain = false;
80  bool generateMaptiles = true;
81  Bitmap mapbmp;
82 
83  string[] configSections = new string[] { "Map", "Startup" };
84 
85  drawPrimVolume
86  = Util.GetConfigVarFromSections<bool>(m_config, "DrawPrimOnMapTile", configSections, drawPrimVolume);
87  textureTerrain
88  = Util.GetConfigVarFromSections<bool>(m_config, "TextureOnMapTile", configSections, textureTerrain);
89  generateMaptiles
90  = Util.GetConfigVarFromSections<bool>(m_config, "GenerateMaptiles", configSections, generateMaptiles);
91 
92  if (generateMaptiles)
93  {
94  if (String.IsNullOrEmpty(m_scene.RegionInfo.MaptileStaticFile))
95  {
96  if (textureTerrain)
97  {
98  terrainRenderer = new TexturedMapTileRenderer();
99  }
100  else
101  {
102  terrainRenderer = new ShadedMapTileRenderer();
103  }
104 
105  terrainRenderer.Initialise(m_scene, m_config);
106 
107  mapbmp = new Bitmap((int)m_scene.Heightmap.Width, (int)m_scene.Heightmap.Height,
108  System.Drawing.Imaging.PixelFormat.Format24bppRgb);
109  //long t = System.Environment.TickCount;
110  //for (int i = 0; i < 10; ++i) {
111  terrainRenderer.TerrainToBitmap(mapbmp);
112  //}
113  //t = System.Environment.TickCount - t;
114  //m_log.InfoFormat("[MAPTILE] generation of 10 maptiles needed {0} ms", t);
115  if (drawPrimVolume)
116  {
117  DrawObjectVolume(m_scene, mapbmp);
118  }
119  }
120  else
121  {
122  try
123  {
124  mapbmp = new Bitmap(m_scene.RegionInfo.MaptileStaticFile);
125  }
126  catch (Exception)
127  {
128  m_log.ErrorFormat(
129  "[MAPTILE]: Failed to load Static map image texture file: {0} for {1}",
130  m_scene.RegionInfo.MaptileStaticFile, m_scene.Name);
131  //mapbmp = new Bitmap((int)m_scene.Heightmap.Width, (int)m_scene.Heightmap.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
132  mapbmp = null;
133  }
134 
135  if (mapbmp != null)
136  m_log.DebugFormat(
137  "[MAPTILE]: Static map image texture file {0} found for {1}",
138  m_scene.RegionInfo.MaptileStaticFile, m_scene.Name);
139  }
140  }
141  else
142  {
143  mapbmp = FetchTexture(m_scene.RegionInfo.RegionSettings.TerrainImageID);
144  }
145 
146  return mapbmp;
147  }
148 
149  public byte[] WriteJpeg2000Image()
150  {
151  try
152  {
153  using (Bitmap mapbmp = CreateMapTile())
154  {
155  if (mapbmp != null)
156  return OpenJPEG.EncodeFromImage(mapbmp, true);
157  }
158  }
159  catch (Exception e) // LEGIT: Catching problems caused by OpenJPEG p/invoke
160  {
161  m_log.Error("Failed generating terrain map: " + e);
162  }
163 
164  return null;
165  }
166 
167  #endregion
168 
169  #region Region Module interface
170 
171  public void Initialise(IConfigSource source)
172  {
173  m_config = source;
174 
175  if (Util.GetConfigVarFromSections<string>(
176  m_config, "MapImageModule", new string[] { "Startup", "Map" }, "MapImageModule") != "MapImageModule")
177  return;
178 
179  m_Enabled = true;
180  }
181 
182  public void AddRegion(Scene scene)
183  {
184  if (!m_Enabled)
185  return;
186 
187  m_scene = scene;
188 
189  m_scene.RegisterModuleInterface<IMapImageGenerator>(this);
190  }
191 
192  public void RegionLoaded(Scene scene)
193  {
194  }
195 
196  public void RemoveRegion(Scene scene)
197  {
198  }
199 
200  public void Close()
201  {
202  }
203 
204  public string Name
205  {
206  get { return "MapImageModule"; }
207  }
208 
209  public Type ReplaceableInterface
210  {
211  get { return null; }
212  }
213 
214  #endregion
215 
216 // TODO: unused:
217 // private void ShadeBuildings(Bitmap map)
218 // {
219 // lock (map)
220 // {
221 // lock (m_scene.Entities)
222 // {
223 // foreach (EntityBase entity in m_scene.Entities.Values)
224 // {
225 // if (entity is SceneObjectGroup)
226 // {
227 // SceneObjectGroup sog = (SceneObjectGroup) entity;
228 //
229 // foreach (SceneObjectPart primitive in sog.Children.Values)
230 // {
231 // int x = (int) (primitive.AbsolutePosition.X - (primitive.Scale.X / 2));
232 // int y = (int) (primitive.AbsolutePosition.Y - (primitive.Scale.Y / 2));
233 // int w = (int) primitive.Scale.X;
234 // int h = (int) primitive.Scale.Y;
235 //
236 // int dx;
237 // for (dx = x; dx < x + w; dx++)
238 // {
239 // int dy;
240 // for (dy = y; dy < y + h; dy++)
241 // {
242 // if (x < 0 || y < 0)
243 // continue;
244 // if (x >= map.Width || y >= map.Height)
245 // continue;
246 //
247 // map.SetPixel(dx, dy, Color.DarkGray);
248 // }
249 // }
250 // }
251 // }
252 // }
253 // }
254 // }
255 // }
256 
257  private Bitmap FetchTexture(UUID id)
258  {
259  AssetBase asset = m_scene.AssetService.Get(id.ToString());
260 
261  if (asset != null)
262  {
263  m_log.DebugFormat("[MAPTILE]: Static map image texture {0} found for {1}", id, m_scene.Name);
264  }
265  else
266  {
267  m_log.WarnFormat("[MAPTILE]: Static map image texture {0} not found for {1}", id, m_scene.Name);
268  return null;
269  }
270 
271  ManagedImage managedImage;
272  Image image;
273 
274  try
275  {
276  if (OpenJPEG.DecodeToImage(asset.Data, out managedImage, out image))
277  return new Bitmap(image);
278  else
279  return null;
280  }
281  catch (DllNotFoundException)
282  {
283  m_log.ErrorFormat("[MAPTILE]: OpenJpeg is not installed correctly on this system. Asset Data is empty for {0}", id);
284 
285  }
286  catch (IndexOutOfRangeException)
287  {
288  m_log.ErrorFormat("[MAPTILE]: OpenJpeg was unable to decode this. Asset Data is empty for {0}", id);
289 
290  }
291  catch (Exception)
292  {
293  m_log.ErrorFormat("[MAPTILE]: OpenJpeg was unable to decode this. Asset Data is empty for {0}", id);
294 
295  }
296  return null;
297 
298  }
299 
300  private Bitmap DrawObjectVolume(Scene whichScene, Bitmap mapbmp)
301  {
302  int tc = 0;
303  ITerrainChannel hm = whichScene.Heightmap;
304  tc = Environment.TickCount;
305  m_log.Debug("[MAPTILE]: Generating Maptile Step 2: Object Volume Profile");
306  EntityBase[] objs = whichScene.GetEntities();
307  List<float> z_sortheights = new List<float>();
308  List<uint> z_localIDs = new List<uint>();
309  Dictionary<uint, DrawStruct> z_sort = new Dictionary<uint, DrawStruct>();
310 
311  try
312  {
313  lock (objs)
314  {
315  foreach (EntityBase obj in objs)
316  {
317  // Only draw the contents of SceneObjectGroup
318  if (obj is SceneObjectGroup)
319  {
320  SceneObjectGroup mapdot = (SceneObjectGroup)obj;
321  Color mapdotspot = Color.Gray; // Default color when prim color is white
322  // Loop over prim in group
323  foreach (SceneObjectPart part in mapdot.Parts)
324  {
325  if (part == null)
326  continue;
327 
328  // Draw if the object is at least 1 meter wide in any direction
329  if (part.Scale.X > 1f || part.Scale.Y > 1f || part.Scale.Z > 1f)
330  {
331  // Try to get the RGBA of the default texture entry..
332  //
333  try
334  {
335  // get the null checks out of the way
336  // skip the ones that break
337  if (part == null)
338  continue;
339 
340  if (part.Shape == null)
341  continue;
342 
343  if (part.Shape.PCode == (byte)PCode.Tree || part.Shape.PCode == (byte)PCode.NewTree || part.Shape.PCode == (byte)PCode.Grass)
344  continue; // eliminates trees from this since we don't really have a good tree representation
345  // if you want tree blocks on the map comment the above line and uncomment the below line
346  //mapdotspot = Color.PaleGreen;
347 
348  Primitive.TextureEntry textureEntry = part.Shape.Textures;
349 
350  if (textureEntry == null || textureEntry.DefaultTexture == null)
351  continue;
352 
353  Color4 texcolor = textureEntry.DefaultTexture.RGBA;
354 
355  // Not sure why some of these are null, oh well.
356 
357  int colorr = 255 - (int)(texcolor.R * 255f);
358  int colorg = 255 - (int)(texcolor.G * 255f);
359  int colorb = 255 - (int)(texcolor.B * 255f);
360 
361  if (!(colorr == 255 && colorg == 255 && colorb == 255))
362  {
363  //Try to set the map spot color
364  try
365  {
366  // If the color gets goofy somehow, skip it *shakes fist at Color4
367  mapdotspot = Color.FromArgb(colorr, colorg, colorb);
368  }
369  catch (ArgumentException)
370  {
371  }
372  }
373  }
374  catch (IndexOutOfRangeException)
375  {
376  // Windows Array
377  }
378  catch (ArgumentOutOfRangeException)
379  {
380  // Mono Array
381  }
382 
383  Vector3 pos = part.GetWorldPosition();
384 
385  // skip prim outside of retion
386  if (!m_scene.PositionIsInCurrentRegion(pos))
387  continue;
388 
389  // skip prim in non-finite position
390  if (Single.IsNaN(pos.X) || Single.IsNaN(pos.Y) ||
391  Single.IsInfinity(pos.X) || Single.IsInfinity(pos.Y))
392  continue;
393 
394  // Figure out if object is under 256m above the height of the terrain
395  bool isBelow256AboveTerrain = false;
396 
397  try
398  {
399  isBelow256AboveTerrain = (pos.Z < ((float)hm[(int)pos.X, (int)pos.Y] + 256f));
400  }
401  catch (Exception)
402  {
403  }
404 
405  if (isBelow256AboveTerrain)
406  {
407  // Translate scale by rotation so scale is represented properly when object is rotated
408  Vector3 lscale = new Vector3(part.Shape.Scale.X, part.Shape.Scale.Y, part.Shape.Scale.Z);
409  Vector3 scale = new Vector3();
410  Vector3 tScale = new Vector3();
411  Vector3 axPos = new Vector3(pos.X, pos.Y, pos.Z);
412 
413  Quaternion llrot = part.GetWorldRotation();
414  Quaternion rot = new Quaternion(llrot.W, llrot.X, llrot.Y, llrot.Z);
415  scale = lscale * rot;
416 
417  // negative scales don't work in this situation
418  scale.X = Math.Abs(scale.X);
419  scale.Y = Math.Abs(scale.Y);
420  scale.Z = Math.Abs(scale.Z);
421 
422  // This scaling isn't very accurate and doesn't take into account the face rotation :P
423  int mapdrawstartX = (int)(pos.X - scale.X);
424  int mapdrawstartY = (int)(pos.Y - scale.Y);
425  int mapdrawendX = (int)(pos.X + scale.X);
426  int mapdrawendY = (int)(pos.Y + scale.Y);
427 
428  // If object is beyond the edge of the map, don't draw it to avoid errors
429  if (mapdrawstartX < 0
430  || mapdrawstartX > (hm.Width - 1)
431  || mapdrawendX < 0
432  || mapdrawendX > (hm.Width - 1)
433  || mapdrawstartY < 0
434  || mapdrawstartY > (hm.Height - 1)
435  || mapdrawendY < 0
436  || mapdrawendY > (hm.Height - 1))
437  continue;
438 
439  #region obb face reconstruction part duex
440  Vector3[] vertexes = new Vector3[8];
441 
442  // float[] distance = new float[6];
443  Vector3[] FaceA = new Vector3[6]; // vertex A for Facei
444  Vector3[] FaceB = new Vector3[6]; // vertex B for Facei
445  Vector3[] FaceC = new Vector3[6]; // vertex C for Facei
446  Vector3[] FaceD = new Vector3[6]; // vertex D for Facei
447 
448  tScale = new Vector3(lscale.X, -lscale.Y, lscale.Z);
449  scale = ((tScale * rot));
450  vertexes[0] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
451  // vertexes[0].x = pos.X + vertexes[0].x;
452  //vertexes[0].y = pos.Y + vertexes[0].y;
453  //vertexes[0].z = pos.Z + vertexes[0].z;
454 
455  FaceA[0] = vertexes[0];
456  FaceB[3] = vertexes[0];
457  FaceA[4] = vertexes[0];
458 
459  tScale = lscale;
460  scale = ((tScale * rot));
461  vertexes[1] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
462 
463  // vertexes[1].x = pos.X + vertexes[1].x;
464  // vertexes[1].y = pos.Y + vertexes[1].y;
465  //vertexes[1].z = pos.Z + vertexes[1].z;
466 
467  FaceB[0] = vertexes[1];
468  FaceA[1] = vertexes[1];
469  FaceC[4] = vertexes[1];
470 
471  tScale = new Vector3(lscale.X, -lscale.Y, -lscale.Z);
472  scale = ((tScale * rot));
473 
474  vertexes[2] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
475 
476  //vertexes[2].x = pos.X + vertexes[2].x;
477  //vertexes[2].y = pos.Y + vertexes[2].y;
478  //vertexes[2].z = pos.Z + vertexes[2].z;
479 
480  FaceC[0] = vertexes[2];
481  FaceD[3] = vertexes[2];
482  FaceC[5] = vertexes[2];
483 
484  tScale = new Vector3(lscale.X, lscale.Y, -lscale.Z);
485  scale = ((tScale * rot));
486  vertexes[3] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
487 
488  //vertexes[3].x = pos.X + vertexes[3].x;
489  // vertexes[3].y = pos.Y + vertexes[3].y;
490  // vertexes[3].z = pos.Z + vertexes[3].z;
491 
492  FaceD[0] = vertexes[3];
493  FaceC[1] = vertexes[3];
494  FaceA[5] = vertexes[3];
495 
496  tScale = new Vector3(-lscale.X, lscale.Y, lscale.Z);
497  scale = ((tScale * rot));
498  vertexes[4] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
499 
500  // vertexes[4].x = pos.X + vertexes[4].x;
501  // vertexes[4].y = pos.Y + vertexes[4].y;
502  // vertexes[4].z = pos.Z + vertexes[4].z;
503 
504  FaceB[1] = vertexes[4];
505  FaceA[2] = vertexes[4];
506  FaceD[4] = vertexes[4];
507 
508  tScale = new Vector3(-lscale.X, lscale.Y, -lscale.Z);
509  scale = ((tScale * rot));
510  vertexes[5] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
511 
512  // vertexes[5].x = pos.X + vertexes[5].x;
513  // vertexes[5].y = pos.Y + vertexes[5].y;
514  // vertexes[5].z = pos.Z + vertexes[5].z;
515 
516  FaceD[1] = vertexes[5];
517  FaceC[2] = vertexes[5];
518  FaceB[5] = vertexes[5];
519 
520  tScale = new Vector3(-lscale.X, -lscale.Y, lscale.Z);
521  scale = ((tScale * rot));
522  vertexes[6] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
523 
524  // vertexes[6].x = pos.X + vertexes[6].x;
525  // vertexes[6].y = pos.Y + vertexes[6].y;
526  // vertexes[6].z = pos.Z + vertexes[6].z;
527 
528  FaceB[2] = vertexes[6];
529  FaceA[3] = vertexes[6];
530  FaceB[4] = vertexes[6];
531 
532  tScale = new Vector3(-lscale.X, -lscale.Y, -lscale.Z);
533  scale = ((tScale * rot));
534  vertexes[7] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
535 
536  // vertexes[7].x = pos.X + vertexes[7].x;
537  // vertexes[7].y = pos.Y + vertexes[7].y;
538  // vertexes[7].z = pos.Z + vertexes[7].z;
539 
540  FaceD[2] = vertexes[7];
541  FaceC[3] = vertexes[7];
542  FaceD[5] = vertexes[7];
543  #endregion
544 
545  //int wy = 0;
546 
547  //bool breakYN = false; // If we run into an error drawing, break out of the
548  // loop so we don't lag to death on error handling
549  DrawStruct ds = new DrawStruct();
550  ds.brush = new SolidBrush(mapdotspot);
551  //ds.rect = new Rectangle(mapdrawstartX, (255 - mapdrawstartY), mapdrawendX - mapdrawstartX, mapdrawendY - mapdrawstartY);
552 
553  ds.trns = new face[FaceA.Length];
554 
555  for (int i = 0; i < FaceA.Length; i++)
556  {
557  Point[] working = new Point[5];
558  working[0] = project(hm, FaceA[i], axPos);
559  working[1] = project(hm, FaceB[i], axPos);
560  working[2] = project(hm, FaceD[i], axPos);
561  working[3] = project(hm, FaceC[i], axPos);
562  working[4] = project(hm, FaceA[i], axPos);
563 
564  face workingface = new face();
565  workingface.pts = working;
566 
567  ds.trns[i] = workingface;
568  }
569 
570  z_sort.Add(part.LocalId, ds);
571  z_localIDs.Add(part.LocalId);
572  z_sortheights.Add(pos.Z);
573 
574  // for (int wx = mapdrawstartX; wx < mapdrawendX; wx++)
575  // {
576  // for (wy = mapdrawstartY; wy < mapdrawendY; wy++)
577  // {
578  // m_log.InfoFormat("[MAPDEBUG]: {0},{1}({2})", wx, (255 - wy),wy);
579  // try
580  // {
581  // // Remember, flip the y!
582  // mapbmp.SetPixel(wx, (255 - wy), mapdotspot);
583  // }
584  // catch (ArgumentException)
585  // {
586  // breakYN = true;
587  // }
588  // }
589  // if (breakYN)
590  // break;
591  // }
592  // }
593  //}
594  } // Object is within 256m Z of terrain
595  } // object is at least a meter wide
596  } // loop over group children
597  } // entitybase is sceneobject group
598  } // foreach loop over entities
599 
600  float[] sortedZHeights = z_sortheights.ToArray();
601  uint[] sortedlocalIds = z_localIDs.ToArray();
602 
603  // Sort prim by Z position
604  Array.Sort(sortedZHeights, sortedlocalIds);
605 
606  using (Graphics g = Graphics.FromImage(mapbmp))
607  {
608  for (int s = 0; s < sortedZHeights.Length; s++)
609  {
610  if (z_sort.ContainsKey(sortedlocalIds[s]))
611  {
612  DrawStruct rectDrawStruct = z_sort[sortedlocalIds[s]];
613  for (int r = 0; r < rectDrawStruct.trns.Length; r++)
614  {
615  g.FillPolygon(rectDrawStruct.brush,rectDrawStruct.trns[r].pts);
616  }
617  //g.FillRectangle(rectDrawStruct.brush , rectDrawStruct.rect);
618  }
619  }
620  }
621  } // lock entities objs
622 
623  }
624  finally
625  {
626  foreach (DrawStruct ds in z_sort.Values)
627  ds.brush.Dispose();
628  }
629 
630  m_log.Debug("[MAPTILE]: Generating Maptile Step 2: Done in " + (Environment.TickCount - tc) + " ms");
631 
632  return mapbmp;
633  }
634 
635  private Point project(ITerrainChannel hm, Vector3 point3d, Vector3 originpos)
636  {
637  Point returnpt = new Point();
638  //originpos = point3d;
639  //int d = (int)(256f / 1.5f);
640 
641  //Vector3 topos = new Vector3(0, 0, 0);
642  // float z = -point3d.z - topos.z;
643 
644  returnpt.X = (int)point3d.X;//(int)((topos.x - point3d.x) / z * d);
645  returnpt.Y = (int)((hm.Width - 1) - point3d.Y);//(int)(255 - (((topos.y - point3d.y) / z * d)));
646 
647  return returnpt;
648  }
649 
650  public Bitmap CreateViewImage(Vector3 camPos, Vector3 camDir, float fov, int width, int height, bool useTextures)
651  {
652  return null;
653  }
654  }
655 }
Bitmap CreateViewImage(Vector3 camPos, Vector3 camDir, float fov, int width, int height, bool useTextures)
void RemoveRegion(Scene scene)
This is called whenever a Scene is removed. For shared modules, this can happen several times...
A scene object group is conceptually an object in the scene. The object is constituted of SceneObject...
void AddRegion(Scene scene)
This is called whenever a Scene is added. For shared modules, this can happen several times...
Asset class. All Assets are reference by this class or a class derived from this class ...
Definition: AssetBase.cs:49
void Close()
This is the inverse to Initialise. After a Close(), this instance won't be usable anymore...
Vector3 Scale
Change the scale of this part.
void Initialise(IConfigSource source)
This is called to initialize the region module. For shared modules, this is called exactly once...
void RegionLoaded(Scene scene)
This will be called once for every scene loaded. In a shared module this will be multiple times in on...