diff options
Diffstat (limited to 'OpenSim/Framework/TerrainData.cs')
-rw-r--r-- | OpenSim/Framework/TerrainData.cs | 113 |
1 files changed, 102 insertions, 11 deletions
diff --git a/OpenSim/Framework/TerrainData.cs b/OpenSim/Framework/TerrainData.cs index 8cb1aef..bee6814 100644 --- a/OpenSim/Framework/TerrainData.cs +++ b/OpenSim/Framework/TerrainData.cs | |||
@@ -44,9 +44,19 @@ namespace OpenSim.Framework | |||
44 | // Someday terrain will have caves | 44 | // Someday terrain will have caves |
45 | public abstract float this[int x, int y, int z] { get; set; } | 45 | public abstract float this[int x, int y, int z] { get; set; } |
46 | 46 | ||
47 | public bool IsTainted { get; protected set; } | ||
48 | public abstract bool IsTaintedAt(int xx, int yy); | ||
49 | public abstract void ClearTaint(); | ||
50 | |||
47 | // Return a representation of this terrain for storing as a blob in the database. | 51 | // Return a representation of this terrain for storing as a blob in the database. |
48 | // Returns 'true' to say blob was stored in the 'out' locations. | 52 | // Returns 'true' to say blob was stored in the 'out' locations. |
49 | public abstract bool GetDatabaseBlob(out int DBFormatRevisionCode, out Array blob); | 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(); | ||
50 | } | 60 | } |
51 | 61 | ||
52 | // The terrain is stored as a blob in the database with a 'revision' field. | 62 | // The terrain is stored as a blob in the database with a 'revision' field. |
@@ -72,13 +82,23 @@ namespace OpenSim.Framework | |||
72 | // Version of terrain that is a heightmap. | 82 | // Version of terrain that is a heightmap. |
73 | // This should really be 'LLOptimizedHeightmapTerrainData' as it includes knowledge | 83 | // This should really be 'LLOptimizedHeightmapTerrainData' as it includes knowledge |
74 | // of 'patches' which are 16x16 terrain areas which can be sent separately to the viewer. | 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. | ||
75 | public class HeightmapTerrainData : TerrainData | 87 | public class HeightmapTerrainData : TerrainData |
76 | { | 88 | { |
77 | // TerrainData.this[x, y] | 89 | // TerrainData.this[x, y] |
78 | public override float this[int x, int y] | 90 | public override float this[int x, int y] |
79 | { | 91 | { |
80 | get { return m_heightmap[x * SizeX + y]; } | 92 | get { return FromCompressedHeight(m_heightmap[x, y]); } |
81 | set { m_heightmap[x * SizeX + y] = value; } | 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 | } | ||
82 | } | 102 | } |
83 | 103 | ||
84 | // TerrainData.this[x, y, z] | 104 | // TerrainData.this[x, y, z] |
@@ -88,6 +108,20 @@ namespace OpenSim.Framework | |||
88 | set { this[x, y] = value; } | 108 | set { this[x, y] = value; } |
89 | } | 109 | } |
90 | 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 | |||
91 | // TerrainData.GetDatabaseBlob | 125 | // TerrainData.GetDatabaseBlob |
92 | // The user wants something to store in the database. | 126 | // The user wants something to store in the database. |
93 | public override bool GetDatabaseBlob(out int DBRevisionCode, out Array blob) | 127 | public override bool GetDatabaseBlob(out int DBRevisionCode, out Array blob) |
@@ -96,7 +130,53 @@ namespace OpenSim.Framework | |||
96 | blob = LegacyTerrainSerialization(); | 130 | blob = LegacyTerrainSerialization(); |
97 | return false; | 131 | return false; |
98 | } | 132 | } |
99 | private float[] m_heightmap; | 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 | } | ||
100 | 180 | ||
101 | // To keep with the legacy theme, this can be created with the way terrain | 181 | // To keep with the legacy theme, this can be created with the way terrain |
102 | // used to passed around as. | 182 | // used to passed around as. |
@@ -106,26 +186,37 @@ namespace OpenSim.Framework | |||
106 | SizeY = pTerrain.GetLength(1); | 186 | SizeY = pTerrain.GetLength(1); |
107 | SizeZ = (int)Constants.RegionHeight; | 187 | SizeZ = (int)Constants.RegionHeight; |
108 | 188 | ||
109 | int idx = 0; | 189 | m_heightmap = new short[SizeX, SizeY]; |
110 | m_heightmap = new float[SizeX * SizeY]; | ||
111 | for (int ii = 0; ii < SizeX; ii++) | 190 | for (int ii = 0; ii < SizeX; ii++) |
112 | { | 191 | { |
113 | for (int jj = 0; jj < SizeY; jj++) | 192 | for (int jj = 0; jj < SizeY; jj++) |
114 | { | 193 | { |
115 | m_heightmap[idx++] = (float)pTerrain[ii, jj]; | 194 | m_heightmap[ii, jj] = ToCompressedHeight(pTerrain[ii, jj]); |
116 | 195 | ||
117 | } | 196 | } |
118 | } | 197 | } |
198 | |||
199 | m_taint = new bool[SizeX / Constants.TerrainPatchSize, SizeY / Constants.TerrainPatchSize]; | ||
200 | ClearTaint(); | ||
119 | } | 201 | } |
120 | 202 | ||
121 | public HeightmapTerrainData(float[] pHeightmap, int pX, int pY, int pZ) | 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) | ||
122 | { | 205 | { |
123 | m_heightmap = pHeightmap; | ||
124 | SizeX = pX; | 206 | SizeX = pX; |
125 | SizeY = pY; | 207 | SizeY = pY; |
126 | SizeZ = pZ; | 208 | SizeZ = pZ; |
209 | m_heightmap = new short[SizeX, SizeY]; | ||
210 | m_taint = new bool[SizeX / Constants.TerrainPatchSize, SizeY / Constants.TerrainPatchSize]; | ||
211 | ClearTaint(); | ||
127 | } | 212 | } |
128 | 213 | ||
214 | public HeightmapTerrainData(short[] cmap, int pX, int pY, int pZ) : this(pX, pY, pZ) | ||
215 | { | ||
216 | SetCompressedMap(cmap); | ||
217 | } | ||
218 | |||
219 | |||
129 | // Just create an array of doubles. Presumes the caller implicitly knows the size. | 220 | // Just create an array of doubles. Presumes the caller implicitly knows the size. |
130 | public Array LegacyTerrainSerialization() | 221 | public Array LegacyTerrainSerialization() |
131 | { | 222 | { |
@@ -135,12 +226,12 @@ namespace OpenSim.Framework | |||
135 | using (BinaryWriter bw = new BinaryWriter(str)) | 226 | using (BinaryWriter bw = new BinaryWriter(str)) |
136 | { | 227 | { |
137 | // TODO: COMPATIBILITY - Add byte-order conversions | 228 | // TODO: COMPATIBILITY - Add byte-order conversions |
138 | for (int ii = 0; ii < m_heightmap.Length; ii++) | 229 | for (int ii = 0; ii < SizeX; ii++) |
230 | for (int jj = 0; jj < SizeY; jj++) | ||
139 | { | 231 | { |
140 | double height = (double)m_heightmap[ii]; | 232 | double height = this[ii, jj]; |
141 | if (height == 0.0) | 233 | if (height == 0.0) |
142 | height = double.Epsilon; | 234 | height = double.Epsilon; |
143 | |||
144 | bw.Write(height); | 235 | bw.Write(height); |
145 | } | 236 | } |
146 | } | 237 | } |