aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Framework')
-rw-r--r--OpenSim/Framework/Constants.cs9
-rw-r--r--OpenSim/Framework/RegionInfo.cs165
-rw-r--r--OpenSim/Framework/TerrainData.cs260
3 files changed, 392 insertions, 42 deletions
diff --git a/OpenSim/Framework/Constants.cs b/OpenSim/Framework/Constants.cs
index a2eb5ee..d18b32e 100644
--- a/OpenSim/Framework/Constants.cs
+++ b/OpenSim/Framework/Constants.cs
@@ -30,9 +30,16 @@ namespace OpenSim.Framework
30{ 30{
31 public class Constants 31 public class Constants
32 { 32 {
33 // 'RegionSize' captures the legacy region size.
34 // DO NOT USE THIS FOR ANY NEW CODE. Use Scene.RegionSize[XYZ] as a region might not
35 // be the legacy region size.
33 public const uint RegionSize = 256; 36 public const uint RegionSize = 256;
34 public const uint RegionHeight = 4096; 37 public const uint RegionHeight = 4096;
35 public const byte TerrainPatchSize = 16; 38
39 // Since terrain is stored in 16x16 heights, regions must be a multiple of this number and that is the minimum
40 public const int MinRegionSize = 16;
41 public const int TerrainPatchSize = 16;
42
36 public const string DefaultTexture = "89556747-24cb-43ed-920b-47caed15465f"; 43 public const string DefaultTexture = "89556747-24cb-43ed-920b-47caed15465f";
37 44
38 public enum EstateAccessCodex : uint 45 public enum EstateAccessCodex : uint
diff --git a/OpenSim/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs
index 24b9c89..882fe33 100644
--- a/OpenSim/Framework/RegionInfo.cs
+++ b/OpenSim/Framework/RegionInfo.cs
@@ -137,16 +137,20 @@ namespace OpenSim.Framework
137 public bool m_allow_alternate_ports; 137 public bool m_allow_alternate_ports;
138 protected string m_externalHostName; 138 protected string m_externalHostName;
139 protected IPEndPoint m_internalEndPoint; 139 protected IPEndPoint m_internalEndPoint;
140 protected uint? m_regionLocX;
141 protected uint? m_regionLocY;
142 protected uint m_remotingPort; 140 protected uint m_remotingPort;
143 public UUID RegionID = UUID.Zero; 141 public UUID RegionID = UUID.Zero;
144 public string RemotingAddress; 142 public string RemotingAddress;
145 public UUID ScopeID = UUID.Zero; 143 public UUID ScopeID = UUID.Zero;
146 private UUID m_maptileStaticUUID = UUID.Zero; 144 private UUID m_maptileStaticUUID = UUID.Zero;
147 145
148 private Dictionary<String, String> m_otherSettings = new Dictionary<string, string>(); 146 public uint RegionWorldLocX = 0;
147 public uint RegionWorldLocY = 0;
148 public uint RegionWorldLocZ = 0;
149 public uint RegionSizeX = Constants.RegionSize;
150 public uint RegionSizeY = Constants.RegionSize;
151 public uint RegionSizeZ = Constants.RegionHeight;
149 152
153 private Dictionary<String, String> m_otherSettings = new Dictionary<string, string>();
150 154
151 // Apparently, we're applying the same estatesettings regardless of whether it's local or remote. 155 // Apparently, we're applying the same estatesettings regardless of whether it's local or remote.
152 156
@@ -229,11 +233,8 @@ namespace OpenSim.Framework
229 m_serverURI = string.Empty; 233 m_serverURI = string.Empty;
230 } 234 }
231 235
232 public RegionInfo(uint regionLocX, uint regionLocY, IPEndPoint internalEndPoint, string externalUri) 236 public RegionInfo(uint legacyRegionLocX, uint legacyRegionLocY, IPEndPoint internalEndPoint, string externalUri)
233 { 237 {
234 m_regionLocX = regionLocX;
235 m_regionLocY = regionLocY;
236
237 m_internalEndPoint = internalEndPoint; 238 m_internalEndPoint = internalEndPoint;
238 m_externalHostName = externalUri; 239 m_externalHostName = externalUri;
239 m_serverURI = string.Empty; 240 m_serverURI = string.Empty;
@@ -447,25 +448,66 @@ namespace OpenSim.Framework
447 448
448 /// <summary> 449 /// <summary>
449 /// The x co-ordinate of this region in map tiles (e.g. 1000). 450 /// The x co-ordinate of this region in map tiles (e.g. 1000).
451 /// Coordinate is scaled as world coordinates divided by the legacy region size
452 /// and is thus is the number of legacy regions.
453 /// </summary>
454 public uint LegacyRegionLocX
455 {
456 get { return RegionWorldLocX / Constants.RegionSize; }
457 set { RegionWorldLocX = value * Constants.RegionSize; }
458 }
459
460 /// <summary>
461 /// The y co-ordinate of this region in map tiles (e.g. 1000).
462 /// Coordinate is scaled as world coordinates divided by the legacy region size
463 /// and is thus is the number of legacy regions.
464 /// </summary>
465 public uint LegacyRegionLocY
466 {
467 get { return RegionWorldLocY / Constants.RegionSize; }
468 set { RegionWorldLocY = value * Constants.RegionSize; }
469 }
470
471 /// <summary>
472 /// The x co-ordinate of this region in map tiles (e.g. 1000).
473 /// Coordinate is scaled as world coordinates divided by the legacy region size
474 /// and is thus is the number of legacy regions.
475 /// DO NOT USE FOR NEW CODE! This entrypoint exists for downward compatability with external modules.
450 /// </summary> 476 /// </summary>
451 public uint RegionLocX 477 public uint RegionLocX
452 { 478 {
453 get { return m_regionLocX.Value; } 479 get { return LegacyRegionLocX; }
454 set { m_regionLocX = value; } 480 set { LegacyRegionLocX = value; }
455 } 481 }
456 482
457 /// <summary> 483 /// <summary>
458 /// The y co-ordinate of this region in map tiles (e.g. 1000). 484 /// The y co-ordinate of this region in map tiles (e.g. 1000).
485 /// Coordinate is scaled as world coordinates divided by the legacy region size
486 /// and is thus is the number of legacy regions.
487 /// DO NOT USE FOR NEW CODE! This entrypoint exists for downward compatability with external modules.
459 /// </summary> 488 /// </summary>
460 public uint RegionLocY 489 public uint RegionLocY
461 { 490 {
462 get { return m_regionLocY.Value; } 491 get { return LegacyRegionLocY; }
463 set { m_regionLocY = value; } 492 set { LegacyRegionLocY = value; }
493 }
494
495 public void SetDefaultRegionSize()
496 {
497 RegionWorldLocX = 0;
498 RegionWorldLocY = 0;
499 RegionWorldLocZ = 0;
500 RegionSizeX = Constants.RegionSize;
501 RegionSizeY = Constants.RegionSize;
502 RegionSizeZ = Constants.RegionHeight;
464 } 503 }
465 504
505 // A unique region handle is created from the region's world coordinates.
506 // This cannot be changed because some code expects to receive the region handle and then
507 // compute the region coordinates from it.
466 public ulong RegionHandle 508 public ulong RegionHandle
467 { 509 {
468 get { return Util.UIntsToLong((RegionLocX * (uint) Constants.RegionSize), (RegionLocY * (uint) Constants.RegionSize)); } 510 get { return Util.UIntsToLong(RegionWorldLocX, RegionWorldLocY); }
469 } 511 }
470 512
471 public void SetEndPoint(string ipaddr, int port) 513 public void SetEndPoint(string ipaddr, int port)
@@ -572,8 +614,23 @@ namespace OpenSim.Framework
572 614
573 string[] locationElements = location.Split(new char[] {','}); 615 string[] locationElements = location.Split(new char[] {','});
574 616
575 m_regionLocX = Convert.ToUInt32(locationElements[0]); 617 LegacyRegionLocX = Convert.ToUInt32(locationElements[0]);
576 m_regionLocY = Convert.ToUInt32(locationElements[1]); 618 LegacyRegionLocY = Convert.ToUInt32(locationElements[1]);
619
620 // Region size
621 // Default to legacy region size if not specified.
622 allKeys.Remove("SizeX");
623 string configSizeX = config.GetString("SizeX", Constants.RegionSize.ToString());
624 config.Set("SizeX", configSizeX);
625 RegionSizeX = Convert.ToUInt32(configSizeX);
626 allKeys.Remove("SizeY");
627 string configSizeY = config.GetString("SizeY", Constants.RegionSize.ToString());
628 config.Set("SizeY", configSizeX);
629 RegionSizeY = Convert.ToUInt32(configSizeY);
630 allKeys.Remove("SizeZ");
631 string configSizeZ = config.GetString("SizeZ", Constants.RegionHeight.ToString());
632 config.Set("SizeZ", configSizeX);
633 RegionSizeZ = Convert.ToUInt32(configSizeZ);
577 634
578 // InternalAddress 635 // InternalAddress
579 // 636 //
@@ -704,9 +761,16 @@ namespace OpenSim.Framework
704 761
705 config.Set("RegionUUID", RegionID.ToString()); 762 config.Set("RegionUUID", RegionID.ToString());
706 763
707 string location = String.Format("{0},{1}", m_regionLocX, m_regionLocY); 764 string location = String.Format("{0},{1}", LegacyRegionLocX, LegacyRegionLocY);
708 config.Set("Location", location); 765 config.Set("Location", location);
709 766
767 if (RegionSizeX != Constants.RegionSize || RegionSizeY != Constants.RegionSize)
768 {
769 config.Set("SizeX", RegionSizeX);
770 config.Set("SizeY", RegionSizeY);
771 config.Set("SizeZ", RegionSizeZ);
772 }
773
710 config.Set("InternalAddress", m_internalEndPoint.Address.ToString()); 774 config.Set("InternalAddress", m_internalEndPoint.Address.ToString());
711 config.Set("InternalPort", m_internalEndPoint.Port); 775 config.Set("InternalPort", m_internalEndPoint.Port);
712 776
@@ -789,10 +853,18 @@ namespace OpenSim.Framework
789 RegionID.ToString(), true); 853 RegionID.ToString(), true);
790 configMember.addConfigurationOption("sim_name", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, 854 configMember.addConfigurationOption("sim_name", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY,
791 "Region Name", RegionName, true); 855 "Region Name", RegionName, true);
856
792 configMember.addConfigurationOption("sim_location_x", ConfigurationOption.ConfigurationTypes.TYPE_UINT32, 857 configMember.addConfigurationOption("sim_location_x", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
793 "Grid Location (X Axis)", m_regionLocX.ToString(), true); 858 "Grid Location (X Axis)", LegacyRegionLocX.ToString(), true);
794 configMember.addConfigurationOption("sim_location_y", ConfigurationOption.ConfigurationTypes.TYPE_UINT32, 859 configMember.addConfigurationOption("sim_location_y", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
795 "Grid Location (Y Axis)", m_regionLocY.ToString(), true); 860 "Grid Location (Y Axis)", LegacyRegionLocY.ToString(), true);
861 configMember.addConfigurationOption("sim_size_x", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
862 "Size of region in X dimension", RegionSizeX.ToString(), true);
863 configMember.addConfigurationOption("sim_size_y", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
864 "Size of region in Y dimension", RegionSizeY.ToString(), true);
865 configMember.addConfigurationOption("sim_size_z", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
866 "Size of region in Z dimension", RegionSizeZ.ToString(), true);
867
796 //m_configMember.addConfigurationOption("datastore", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, "Filename for local storage", "OpenSim.db", false); 868 //m_configMember.addConfigurationOption("datastore", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, "Filename for local storage", "OpenSim.db", false);
797 configMember.addConfigurationOption("internal_ip_address", 869 configMember.addConfigurationOption("internal_ip_address",
798 ConfigurationOption.ConfigurationTypes.TYPE_IP_ADDRESS, 870 ConfigurationOption.ConfigurationTypes.TYPE_IP_ADDRESS,
@@ -855,10 +927,18 @@ namespace OpenSim.Framework
855 UUID.Random().ToString(), true); 927 UUID.Random().ToString(), true);
856 configMember.addConfigurationOption("sim_name", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, 928 configMember.addConfigurationOption("sim_name", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY,
857 "Region Name", "OpenSim Test", false); 929 "Region Name", "OpenSim Test", false);
930
858 configMember.addConfigurationOption("sim_location_x", ConfigurationOption.ConfigurationTypes.TYPE_UINT32, 931 configMember.addConfigurationOption("sim_location_x", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
859 "Grid Location (X Axis)", "1000", false); 932 "Grid Location (X Axis)", "1000", false);
860 configMember.addConfigurationOption("sim_location_y", ConfigurationOption.ConfigurationTypes.TYPE_UINT32, 933 configMember.addConfigurationOption("sim_location_y", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
861 "Grid Location (Y Axis)", "1000", false); 934 "Grid Location (Y Axis)", "1000", false);
935 configMember.addConfigurationOption("sim_size_x", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
936 "Size of region in X dimension", Constants.RegionSize.ToString(), false);
937 configMember.addConfigurationOption("sim_size_y", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
938 "Size of region in Y dimension", Constants.RegionSize.ToString(), false);
939 configMember.addConfigurationOption("sim_size_z", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
940 "Size of region in Z dimension", Constants.RegionHeight.ToString(), false);
941
862 //m_configMember.addConfigurationOption("datastore", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, "Filename for local storage", "OpenSim.db", false); 942 //m_configMember.addConfigurationOption("datastore", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, "Filename for local storage", "OpenSim.db", false);
863 configMember.addConfigurationOption("internal_ip_address", 943 configMember.addConfigurationOption("internal_ip_address",
864 ConfigurationOption.ConfigurationTypes.TYPE_IP_ADDRESS, 944 ConfigurationOption.ConfigurationTypes.TYPE_IP_ADDRESS,
@@ -916,10 +996,19 @@ namespace OpenSim.Framework
916 RegionName = (string) configuration_result; 996 RegionName = (string) configuration_result;
917 break; 997 break;
918 case "sim_location_x": 998 case "sim_location_x":
919 m_regionLocX = (uint) configuration_result; 999 LegacyRegionLocX = (uint) configuration_result;
920 break; 1000 break;
921 case "sim_location_y": 1001 case "sim_location_y":
922 m_regionLocY = (uint) configuration_result; 1002 LegacyRegionLocY = (uint) configuration_result;
1003 break;
1004 case "sim_size_x":
1005 RegionSizeX = (uint) configuration_result;
1006 break;
1007 case "sim_size_y":
1008 RegionSizeY = (uint) configuration_result;
1009 break;
1010 case "sim_size_z":
1011 RegionSizeZ = (uint) configuration_result;
923 break; 1012 break;
924 case "internal_ip_address": 1013 case "internal_ip_address":
925 IPAddress address = (IPAddress) configuration_result; 1014 IPAddress address = (IPAddress) configuration_result;
@@ -1000,8 +1089,13 @@ namespace OpenSim.Framework
1000 args["external_host_name"] = OSD.FromString(ExternalHostName); 1089 args["external_host_name"] = OSD.FromString(ExternalHostName);
1001 args["http_port"] = OSD.FromString(HttpPort.ToString()); 1090 args["http_port"] = OSD.FromString(HttpPort.ToString());
1002 args["server_uri"] = OSD.FromString(ServerURI); 1091 args["server_uri"] = OSD.FromString(ServerURI);
1003 args["region_xloc"] = OSD.FromString(RegionLocX.ToString()); 1092
1004 args["region_yloc"] = OSD.FromString(RegionLocY.ToString()); 1093 args["region_xloc"] = OSD.FromString(LegacyRegionLocX.ToString());
1094 args["region_yloc"] = OSD.FromString(LegacyRegionLocY.ToString());
1095 args["region_size_x"] = OSD.FromString(RegionSizeX.ToString());
1096 args["region_size_y"] = OSD.FromString(RegionSizeY.ToString());
1097 args["region_size_z"] = OSD.FromString(RegionSizeZ.ToString());
1098
1005 args["internal_ep_address"] = OSD.FromString(InternalEndPoint.Address.ToString()); 1099 args["internal_ep_address"] = OSD.FromString(InternalEndPoint.Address.ToString());
1006 args["internal_ep_port"] = OSD.FromString(InternalEndPoint.Port.ToString()); 1100 args["internal_ep_port"] = OSD.FromString(InternalEndPoint.Port.ToString());
1007 if ((RemotingAddress != null) && !RemotingAddress.Equals("")) 1101 if ((RemotingAddress != null) && !RemotingAddress.Equals(""))
@@ -1032,14 +1126,21 @@ namespace OpenSim.Framework
1032 { 1126 {
1033 uint locx; 1127 uint locx;
1034 UInt32.TryParse(args["region_xloc"].AsString(), out locx); 1128 UInt32.TryParse(args["region_xloc"].AsString(), out locx);
1035 RegionLocX = locx; 1129 LegacyRegionLocX = locx;
1036 } 1130 }
1037 if (args["region_yloc"] != null) 1131 if (args["region_yloc"] != null)
1038 { 1132 {
1039 uint locy; 1133 uint locy;
1040 UInt32.TryParse(args["region_yloc"].AsString(), out locy); 1134 UInt32.TryParse(args["region_yloc"].AsString(), out locy);
1041 RegionLocY = locy; 1135 LegacyRegionLocY = locy;
1042 } 1136 }
1137 if (args.ContainsKey("region_size_x"))
1138 RegionSizeX = (uint)args["region_size_x"].AsInteger();
1139 if (args.ContainsKey("region_size_y"))
1140 RegionSizeY = (uint)args["region_size_y"].AsInteger();
1141 if (args.ContainsKey("region_size_z"))
1142 RegionSizeZ = (uint)args["region_size_z"].AsInteger();
1143
1043 IPAddress ip_addr = null; 1144 IPAddress ip_addr = null;
1044 if (args["internal_ep_address"] != null) 1145 if (args["internal_ep_address"] != null)
1045 { 1146 {
@@ -1076,23 +1177,5 @@ namespace OpenSim.Framework
1076 regionInfo.ServerURI = serverURI; 1177 regionInfo.ServerURI = serverURI;
1077 return regionInfo; 1178 return regionInfo;
1078 } 1179 }
1079
1080 public Dictionary<string, object> ToKeyValuePairs()
1081 {
1082 Dictionary<string, object> kvp = new Dictionary<string, object>();
1083 kvp["uuid"] = RegionID.ToString();
1084 kvp["locX"] = RegionLocX.ToString();
1085 kvp["locY"] = RegionLocY.ToString();
1086 kvp["external_ip_address"] = ExternalEndPoint.Address.ToString();
1087 kvp["external_port"] = ExternalEndPoint.Port.ToString();
1088 kvp["external_host_name"] = ExternalHostName;
1089 kvp["http_port"] = HttpPort.ToString();
1090 kvp["internal_ip_address"] = InternalEndPoint.Address.ToString();
1091 kvp["internal_port"] = InternalEndPoint.Port.ToString();
1092 kvp["alternate_ports"] = m_allow_alternate_ports.ToString();
1093 kvp["server_uri"] = ServerURI;
1094
1095 return kvp;
1096 }
1097 } 1180 }
1098} 1181}
diff --git a/OpenSim/Framework/TerrainData.cs b/OpenSim/Framework/TerrainData.cs
new file mode 100644
index 0000000..103359b
--- /dev/null
+++ b/OpenSim/Framework/TerrainData.cs
@@ -0,0 +1,260 @@
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
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.Reflection;
32
33using OpenMetaverse;
34
35using log4net;
36
37namespace OpenSim.Framework
38{
39 public abstract class TerrainData
40 {
41 // Terrain always is a square
42 public int SizeX { get; protected set; }
43 public int SizeY { get; protected set; }
44 public int SizeZ { get; protected set; }
45
46 public abstract float this[int x, int y] { get; set; }
47 // Someday terrain will have caves
48 public abstract float this[int x, int y, int z] { get; set; }
49
50 public bool IsTainted { get; protected set; }
51 public abstract bool IsTaintedAt(int xx, int yy);
52 public abstract void ClearTaint();
53
54 // Return a representation of this terrain for storing as a blob in the database.
55 // Returns 'true' to say blob was stored in the 'out' locations.
56 public abstract bool GetDatabaseBlob(out int DBFormatRevisionCode, out Array blob);
57
58 // return a special compressed representation of the heightmap in shorts
59 public abstract short[] GetCompressedMap();
60 public abstract float CompressionFactor { get; }
61 public abstract void SetCompressedMap(short[] cmap, float pCompressionFactor);
62
63 public abstract TerrainData Clone();
64 }
65
66 // The terrain is stored in the database as a blob with a 'revision' field.
67 // Some implementations of terrain storage would fill the revision field with
68 // the time the terrain was stored. When real revisions were added and this
69 // feature removed, that left some old entries with the time in the revision
70 // field.
71 // Thus, if revision is greater than 'RevisionHigh' then terrain db entry is
72 // left over and it is presumed to be 'Legacy256'.
73 // Numbers are arbitrary and are chosen to to reduce possible mis-interpretation.
74 // If a revision does not match any of these, it is assumed to be Legacy256.
75 public enum DBTerrainRevision
76 {
77 // Terrain is 'double[256,256]'
78 Legacy256 = 11,
79 // Terrain is 'int32, int32, float[,]' where the shorts are X and Y dimensions
80 // The dimensions are presumed to be multiples of 16 and, more likely, multiples of 256.
81 Variable2D = 22,
82 // A revision that is not listed above or any revision greater than this value is 'Legacy256'.
83 RevisionHigh = 1234
84 }
85
86 // Version of terrain that is a heightmap.
87 // This should really be 'LLOptimizedHeightmapTerrainData' as it includes knowledge
88 // of 'patches' which are 16x16 terrain areas which can be sent separately to the viewer.
89 // The heighmap is kept as an array of short integers. The integer values are converted to
90 // and from floats by TerrainCompressionFactor. Shorts are used to limit storage used.
91 public class HeightmapTerrainData : TerrainData
92 {
93 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
94 private static string LogHeader = "[TERRAIN DATA]";
95
96 // TerrainData.this[x, y]
97 public override float this[int x, int y]
98 {
99 get { return FromCompressedHeight(m_heightmap[x, y]); }
100 set {
101 short newVal = ToCompressedHeight(value);
102 if (m_heightmap[x, y] != newVal)
103 {
104 m_heightmap[x, y] = newVal;
105 m_taint[x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize] = true;
106 m_log.DebugFormat("{0} set[{1},{2}] to {3} ({4})", LogHeader, x, y, value, newVal);
107 }
108 }
109 }
110
111 // TerrainData.this[x, y, z]
112 public override float this[int x, int y, int z]
113 {
114 get { return this[x, y]; }
115 set { this[x, y] = value; }
116 }
117
118 // TerrainData.ClearTaint
119 public override void ClearTaint()
120 {
121 IsTainted = false;
122 for (int ii = 0; ii < m_taint.GetLength(0); ii++)
123 for (int jj = 0; jj < m_taint.GetLength(1); jj++)
124 m_taint[ii, jj] = false;
125 }
126
127 public override bool IsTaintedAt(int xx, int yy)
128 {
129 return m_taint[xx / Constants.TerrainPatchSize, yy / Constants.TerrainPatchSize];
130 }
131
132 // TerrainData.GetDatabaseBlob
133 // The user wants something to store in the database.
134 public override bool GetDatabaseBlob(out int DBRevisionCode, out Array blob)
135 {
136 DBRevisionCode = (int)DBTerrainRevision.Legacy256;
137 blob = LegacyTerrainSerialization();
138 return false;
139 }
140
141 // TerrainData.CompressionFactor
142 private float m_compressionFactor = 100.0f;
143 public override float CompressionFactor { get { return m_compressionFactor; } }
144
145 // TerrainData.GetCompressedMap
146 public override short[] GetCompressedMap()
147 {
148 short[] newMap = new short[SizeX * SizeY];
149
150 int ind = 0;
151 for (int xx = 0; xx < SizeX; xx++)
152 for (int yy = 0; yy < SizeY; yy++)
153 newMap[ind++] = m_heightmap[xx, yy];
154
155 return newMap;
156
157 }
158 // TerrainData.SetCompressedMap
159 public override void SetCompressedMap(short[] cmap, float pCompressionFactor)
160 {
161 m_compressionFactor = pCompressionFactor;
162
163 int ind = 0;
164 for (int xx = 0; xx < SizeX; xx++)
165 for (int yy = 0; yy < SizeY; yy++)
166 m_heightmap[xx, yy] = cmap[ind++];
167 }
168
169 // TerrainData.Clone
170 public override TerrainData Clone()
171 {
172 HeightmapTerrainData ret = new HeightmapTerrainData(SizeX, SizeY, SizeZ);
173 ret.m_heightmap = (short[,])this.m_heightmap.Clone();
174 return ret;
175 }
176
177 // =============================================================
178
179 private short[,] m_heightmap;
180 // Remember subregions of the heightmap that has changed.
181 private bool[,] m_taint;
182
183 // To save space (especially for large regions), keep the height as a short integer
184 // that is coded as the float height times the compression factor (usually '100'
185 // to make for two decimal points).
186 public short ToCompressedHeight(double pHeight)
187 {
188 return (short)(pHeight * CompressionFactor);
189 }
190
191 public float FromCompressedHeight(short pHeight)
192 {
193 return ((float)pHeight) / CompressionFactor;
194 }
195
196 // To keep with the legacy theme, create an instance of this class based on the
197 // way terrain used to be passed around.
198 public HeightmapTerrainData(double[,] pTerrain)
199 {
200 SizeX = pTerrain.GetLength(0);
201 SizeY = pTerrain.GetLength(1);
202 SizeZ = (int)Constants.RegionHeight;
203 m_compressionFactor = 100.0f;
204
205 m_heightmap = new short[SizeX, SizeY];
206 for (int ii = 0; ii < SizeX; ii++)
207 {
208 for (int jj = 0; jj < SizeY; jj++)
209 {
210 m_heightmap[ii, jj] = ToCompressedHeight(pTerrain[ii, jj]);
211
212 }
213 }
214
215 m_taint = new bool[SizeX / Constants.TerrainPatchSize, SizeY / Constants.TerrainPatchSize];
216 ClearTaint();
217 }
218
219 // Create underlying structures but don't initialize the heightmap assuming the caller will immediately do that
220 public HeightmapTerrainData(int pX, int pY, int pZ)
221 {
222 SizeX = pX;
223 SizeY = pY;
224 SizeZ = pZ;
225 m_compressionFactor = 100.0f;
226 m_heightmap = new short[SizeX, SizeY];
227 m_taint = new bool[SizeX / Constants.TerrainPatchSize, SizeY / Constants.TerrainPatchSize];
228 ClearTaint();
229 }
230
231 public HeightmapTerrainData(short[] cmap, float pCompressionFactor, int pX, int pY, int pZ) : this(pX, pY, pZ)
232 {
233 SetCompressedMap(cmap, pCompressionFactor);
234 }
235
236
237 // Just create an array of doubles. Presumes the caller implicitly knows the size.
238 public Array LegacyTerrainSerialization()
239 {
240 Array ret = null;
241 using (MemoryStream str = new MemoryStream(SizeX * SizeY * sizeof(double)))
242 {
243 using (BinaryWriter bw = new BinaryWriter(str))
244 {
245 // TODO: COMPATIBILITY - Add byte-order conversions
246 for (int ii = 0; ii < SizeX; ii++)
247 for (int jj = 0; jj < SizeY; jj++)
248 {
249 double height = this[ii, jj];
250 if (height == 0.0)
251 height = double.Epsilon;
252 bw.Write(height);
253 }
254 }
255 ret = str.ToArray();
256 }
257 return ret;
258 }
259 }
260}