aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Framework')
-rw-r--r--OpenSim/Framework/Constants.cs11
-rw-r--r--OpenSim/Framework/RegionInfo.cs165
-rw-r--r--OpenSim/Framework/TerrainData.cs243
3 files changed, 377 insertions, 42 deletions
diff --git a/OpenSim/Framework/Constants.cs b/OpenSim/Framework/Constants.cs
index a2eb5ee..9ddb34b 100644
--- a/OpenSim/Framework/Constants.cs
+++ b/OpenSim/Framework/Constants.cs
@@ -30,9 +30,18 @@ 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 // Terrain heightmap is kept as shorts that are the float value times this compression factor
40 public const float TerrainCompression = 100.0f;
41 // Since terrain is stored in 16x16 heights, regions must be a multiple of this number and that is the minimum
42 public const int MinRegionSize = 16;
43 public const int TerrainPatchSize = 16;
44
36 public const string DefaultTexture = "89556747-24cb-43ed-920b-47caed15465f"; 45 public const string DefaultTexture = "89556747-24cb-43ed-920b-47caed15465f";
37 46
38 public enum EstateAccessCodex : uint 47 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..bee6814
--- /dev/null
+++ b/OpenSim/Framework/TerrainData.cs
@@ -0,0 +1,243 @@
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;
31
32using OpenMetaverse;
33
34namespace OpenSim.Framework
35{
36 public abstract class TerrainData
37 {
38 // Terrain always is a square
39 public int SizeX { get; protected set; }
40 public int SizeY { get; protected set; }
41 public int SizeZ { get; protected set; }
42
43 public abstract float this[int x, int y] { get; set; }
44 // Someday terrain will have caves
45 public abstract float this[int x, int y, int z] { get; set; }
46
47 public bool IsTainted { get; protected set; }
48 public abstract bool IsTaintedAt(int xx, int yy);
49 public abstract void ClearTaint();
50
51 // Return a representation of this terrain for storing as a blob in the database.
52 // Returns 'true' to say blob was stored in the 'out' locations.
53 public abstract bool GetDatabaseBlob(out int DBFormatRevisionCode, out Array blob);
54
55 // return a special compressed representation of the heightmap in shorts
56 public abstract short[] GetCompressedMap();
57 public abstract void SetCompressedMap(short[] cmap);
58
59 public abstract TerrainData Clone();
60 }
61
62 // The terrain is stored as a blob in the database with a 'revision' field.
63 // Some implementations of terrain storage would fill the revision field with
64 // the time the terrain was stored. When real revisions were added and this
65 // feature removed, that left some old entries with the time in the revision
66 // field.
67 // Thus, if revision is greater than 'RevisionHigh' then terrain db entry is
68 // left over and it is presumed to be 'Legacy256'.
69 // Numbers are arbitrary and are chosen to to reduce possible mis-interpretation.
70 // If a revision does not match any of these, it is assumed to be Legacy256.
71 public enum DBTerrainRevision
72 {
73 // Terrain is 'double[256,256]'
74 Legacy256 = 11,
75 // Terrain is 'int32, int32, float[,]' where the shorts are X and Y dimensions
76 // The dimensions are presumed to be multiples of 16 and, more likely, multiples of 256.
77 Variable2D = 22,
78 // A revision that is not listed above or any revision greater than this value is 'Legacy256'.
79 RevisionHigh = 1234
80 }
81
82 // Version of terrain that is a heightmap.
83 // This should really be 'LLOptimizedHeightmapTerrainData' as it includes knowledge
84 // of 'patches' which are 16x16 terrain areas which can be sent separately to the viewer.
85 // The heighmap is kept as an array of short integers. The integer values are converted to
86 // and from floats by TerrainCompressionFactor.
87 public class HeightmapTerrainData : TerrainData
88 {
89 // TerrainData.this[x, y]
90 public override float this[int x, int y]
91 {
92 get { return FromCompressedHeight(m_heightmap[x, y]); }
93 set {
94 short newVal = ToCompressedHeight(value);
95 if (m_heightmap[x, y] != newVal)
96 {
97 m_heightmap[x, y] = newVal;
98 m_taint[x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize] = true;
99
100 }
101 }
102 }
103
104 // TerrainData.this[x, y, z]
105 public override float this[int x, int y, int z]
106 {
107 get { return this[x, y]; }
108 set { this[x, y] = value; }
109 }
110
111 // TerrainData.ClearTaint
112 public override void ClearTaint()
113 {
114 IsTainted = false;
115 for (int ii = 0; ii < m_taint.GetLength(0); ii++)
116 for (int jj = 0; jj < m_taint.GetLength(1); jj++)
117 m_taint[ii, jj] = false;
118 }
119
120 public override bool IsTaintedAt(int xx, int yy)
121 {
122 return m_taint[xx / Constants.TerrainPatchSize, yy / Constants.TerrainPatchSize];
123 }
124
125 // TerrainData.GetDatabaseBlob
126 // The user wants something to store in the database.
127 public override bool GetDatabaseBlob(out int DBRevisionCode, out Array blob)
128 {
129 DBRevisionCode = (int)DBTerrainRevision.Legacy256;
130 blob = LegacyTerrainSerialization();
131 return false;
132 }
133
134 public override short[] GetCompressedMap()
135 {
136 short[] newMap = new short[SizeX * SizeY];
137
138 int ind = 0;
139 for (int xx = 0; xx < SizeX; xx++)
140 for (int yy = 0; yy < SizeY; yy++)
141 newMap[ind++] = m_heightmap[xx, yy];
142
143 return newMap;
144
145 }
146 public override void SetCompressedMap(short[] cmap)
147 {
148 int ind = 0;
149 for (int xx = 0; xx < SizeX; xx++)
150 for (int yy = 0; yy < SizeY; yy++)
151 m_heightmap[xx, yy] = cmap[ind++];
152 }
153
154 // TerrainData.Clone
155 public override TerrainData Clone()
156 {
157 HeightmapTerrainData ret = new HeightmapTerrainData(SizeX, SizeY, SizeZ);
158 ret.m_heightmap = (short[,])this.m_heightmap.Clone();
159 return ret;
160 }
161
162 // =============================================================
163
164 private short[,] m_heightmap;
165 // Remember subregions of the heightmap that has changed.
166 private bool[,] m_taint;
167
168 // To save space (especially for large regions), keep the height as a short integer
169 // that is coded as the float height times the compression factor (usually '100'
170 // to make for two decimal points).
171 public static short ToCompressedHeight(double pHeight)
172 {
173 return (short)(pHeight * Constants.TerrainCompression);
174 }
175
176 public static float FromCompressedHeight(short pHeight)
177 {
178 return ((float)pHeight) / Constants.TerrainCompression;
179 }
180
181 // To keep with the legacy theme, this can be created with the way terrain
182 // used to passed around as.
183 public HeightmapTerrainData(double[,] pTerrain)
184 {
185 SizeX = pTerrain.GetLength(0);
186 SizeY = pTerrain.GetLength(1);
187 SizeZ = (int)Constants.RegionHeight;
188
189 m_heightmap = new short[SizeX, SizeY];
190 for (int ii = 0; ii < SizeX; ii++)
191 {
192 for (int jj = 0; jj < SizeY; jj++)
193 {
194 m_heightmap[ii, jj] = ToCompressedHeight(pTerrain[ii, jj]);
195
196 }
197 }
198
199 m_taint = new bool[SizeX / Constants.TerrainPatchSize, SizeY / Constants.TerrainPatchSize];
200 ClearTaint();
201 }
202
203 // Create underlying structures but don't initialize the heightmap assuming the caller will immediately do that
204 public HeightmapTerrainData(int pX, int pY, int pZ)
205 {
206 SizeX = pX;
207 SizeY = pY;
208 SizeZ = pZ;
209 m_heightmap = new short[SizeX, SizeY];
210 m_taint = new bool[SizeX / Constants.TerrainPatchSize, SizeY / Constants.TerrainPatchSize];
211 ClearTaint();
212 }
213
214 public HeightmapTerrainData(short[] cmap, int pX, int pY, int pZ) : this(pX, pY, pZ)
215 {
216 SetCompressedMap(cmap);
217 }
218
219
220 // Just create an array of doubles. Presumes the caller implicitly knows the size.
221 public Array LegacyTerrainSerialization()
222 {
223 Array ret = null;
224 using (MemoryStream str = new MemoryStream(SizeX * SizeY * sizeof(double)))
225 {
226 using (BinaryWriter bw = new BinaryWriter(str))
227 {
228 // TODO: COMPATIBILITY - Add byte-order conversions
229 for (int ii = 0; ii < SizeX; ii++)
230 for (int jj = 0; jj < SizeY; jj++)
231 {
232 double height = this[ii, jj];
233 if (height == 0.0)
234 height = double.Epsilon;
235 bw.Write(height);
236 }
237 }
238 ret = str.ToArray();
239 }
240 return ret;
241 }
242 }
243}