31 using System.Reflection;
33 using System.Xml.Serialization;
36 using OpenSim.Framework;
37 using OpenSim.Region.Framework.Interfaces;
43 namespace OpenSim.
Region.Framework.Scenes
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51 private static string LogHeader =
"[TERRAIN CHANNEL]";
55 public int Width {
get {
return m_terrainData.SizeX; } }
57 public int Height {
get {
return m_terrainData.SizeY; } }
58 public int Altitude {
get {
return m_terrainData.SizeZ; } }
80 if (type.Equals(
"flat"))
90 int hmSizeX = pM.GetLength(0);
91 int hmSizeY = pM.GetLength(1);
95 for (
int xx = 0; xx < pSizeX; xx++)
96 for (
int yy = 0; yy < pSizeY; yy++)
97 if (xx > hmSizeX || yy > hmSizeY)
98 m_terrainData[xx, yy] = TerrainData.DefaultTerrainHeight;
100 m_terrainData[xx, yy] = (float)pM[xx, yy];
105 m_terrainData = pTerrData;
108 #region ITerrainChannel Members
119 return m_terrainData;
128 return m_terrainData.GetFloatsSerialized();
134 double[,] heights =
new double[Width, Height];
137 for (
int ii = 0; ii < Width; ii++)
139 for (
int jj = 0; jj < Height; jj++)
141 heights[ii, jj] = (double)m_terrainData[ii, jj];
150 public double this[
int x,
int y]
153 if (x < 0 || x >= Width || y < 0 || y >= Height)
155 return (
double)m_terrainData[x, y];
159 if (Double.IsNaN(value) || Double.IsInfinity(value))
162 m_terrainData[x, y] = (float)value;
169 if (x < 0 || x >= Width || y < 0 || y >= Height)
171 return m_terrainData[(int)x, (
int)y];
177 return m_terrainData.IsTaintedAt(x, y);
183 XmlWriterSettings settings =
new XmlWriterSettings();
184 settings.Encoding = Util.UTF8;
185 using (StringWriter sw =
new StringWriter())
187 using (XmlWriter writer = XmlWriter.Create(sw, settings))
191 string output = sw.ToString();
199 StringReader sr =
new StringReader(data);
200 XmlTextReader reader =
new XmlTextReader(sr);
209 public void Merge(
ITerrainChannel newTerrain, Vector3 displacement,
float radianRotation, Vector2 rotationDisplacement)
211 m_log.DebugFormat(
"{0} Merge. inSize=<{1},{2}>, disp={3}, rot={4}, rotDisp={5}, outSize=<{6},{7}>", LogHeader,
212 newTerrain.Width, newTerrain.Height,
213 displacement, radianRotation, rotationDisplacement,
214 m_terrainData.SizeX, m_terrainData.SizeY);
215 for (
int xx = 0; xx < newTerrain.Width; xx++)
217 for (
int yy = 0; yy < newTerrain.Height; yy++)
219 int dispX = (int)displacement.X;
220 int dispY = (
int)displacement.Y;
221 float newHeight = (float)newTerrain[xx, yy] + displacement.Z;
222 if (radianRotation == 0)
227 if (dispX >= 0 && dispX < m_terrainData.SizeX && dispY >= 0 && dispY < m_terrainData.SizeY)
229 m_terrainData[dispX, dispY] = newHeight;
237 dispX += (int)(rotationDisplacement.X
238 + ((
float)xx - rotationDisplacement.X) * Math.Cos(radianRotation)
239 - ((float)yy - rotationDisplacement.Y) * Math.Sin(radianRotation) );
241 dispY += (int)(rotationDisplacement.Y
242 + ((
float)xx - rotationDisplacement.X) * Math.Sin(radianRotation)
243 + ((float)yy - rotationDisplacement.Y) * Math.Cos(radianRotation) );
245 if (dispX >= 0 && dispX < m_terrainData.SizeX && dispY >= 0 && dispY < m_terrainData.SizeY)
247 float oldHeight = m_terrainData[dispX, dispY];
249 for (
int sxx = dispX - 2; sxx < dispX + 2; sxx++)
251 for (
int syy = dispY - 2; syy < dispY + 2; syy++)
253 if (sxx >= 0 && sxx < m_terrainData.SizeX && syy >= 0 && syy < m_terrainData.SizeY)
255 if (sxx == dispX && syy == dispY)
258 m_terrainData[dispX, dispY] = newHeight;
262 if (Math.Abs(m_terrainData[sxx, syy] - newHeight) > 1f)
265 m_terrainData[sxx, syy] = newHeight;
273 if (dispX >= 0 && dispX < m_terrainData.SizeX && dispY >= 0 && dispY < m_terrainData.SizeY)
275 m_terrainData[dispX, dispY] = (float)newTerrain[xx, yy];
299 m_log.DebugFormat(
"{0} MergeWithBounding: inSize=<{1},{2}>, rot={3}, boundingOrigin={4}, boundingSize={5}, disp={6}, outSize=<{7},{8}>",
300 LogHeader, newTerrain.Width, newTerrain.Height, rotationDegrees, boundingOrigin.ToString(),
301 boundingSize.ToString(), displacement, m_terrainData.SizeX, m_terrainData.SizeY);
304 int baseX = newTerrain.Width;
305 int baseY = newTerrain.Height;
308 int offsetX = baseX / 4;
309 int offsetY = baseY / 4;
310 int tmpX = baseX + baseX / 2;
311 int tmpY = baseY + baseY / 2;
312 int centreX = tmpX / 2;
313 int centreY = tmpY / 2;
315 for (
int xx = 0; xx < tmpX; xx++)
316 for (
int yy = 0; yy < tmpY; yy++)
317 terrain_tmp[xx, yy] = -65535f;
319 double radianRotation = Math.PI * rotationDegrees / 180f;
320 double cosR = Math.Cos(radianRotation);
321 double sinR = Math.Sin(radianRotation);
322 if (rotationDegrees < 0f) rotationDegrees += 360f;
329 for (y = 0; y <= tmpY; y++)
331 for (x = 0; x <= tmpX; x++)
333 if (rotationDegrees == 0f)
338 else if (rotationDegrees == 90f)
341 sy = tmpY - 1 - x - offsetY;
343 else if (rotationDegrees == 180f)
345 sx = tmpX - 1 - x - offsetX;
346 sy = tmpY - 1 - y - offsetY;
348 else if (rotationDegrees == 270f)
350 sx = tmpX - 1 - y - offsetX;
356 sx = centreX + (int)Math.Round((((
double)x - centreX) * cosR) + (((
double)y - centreY) * sinR)) - offsetX;
357 sy = centreY + (int)Math.Round((((
double)y - centreY) * cosR) - (((
double)x - centreX) * sinR)) - offsetY;
360 if (sx >= 0 && sx < baseX && sy >= 0 && sy < baseY)
364 terrain_tmp[x, y] = (float)newTerrain[sx, sy];
368 m_log.DebugFormat(
"{0} MergeWithBounding - Rotate: Out of Bounds sx={1} sy={2} dx={3} dy={4}", sx, sy, x, y);
377 int newX = m_terrainData.SizeX;
378 int newY = m_terrainData.SizeY;
380 int dispX = (int)Math.Floor(displacement.X);
381 int dispY = (int)Math.Floor(displacement.Y);
384 int startX = (int)Math.Floor(boundingOrigin.X) + offsetX;
385 if (startX > tmpX) startX = tmpX;
386 if (startX < 0) startX = 0;
387 int startY = (int)Math.Floor(boundingOrigin.Y) + offsetY;
388 if (startY > tmpY) startY = tmpY;
389 if (startY < 0) startY = 0;
391 int endX = (int)Math.Floor(boundingOrigin.X + boundingSize.X) + offsetX;
392 if (endX > tmpX) endX = tmpX;
393 if (endX < 0) endX = 0;
394 int endY = (int)Math.Floor(boundingOrigin.Y + boundingSize.Y) + offsetY;
395 if (endY > tmpY) endY = tmpY;
396 if (endY < 0) endY = 0;
402 for (y = startY; y < endY; y++)
404 for (x = startX; x < endX; x++)
406 dx = x - startX + dispX;
407 dy = y - startY + dispY;
408 if (dx >= 0 && dx < newX && dy >= 0 && dy < newY)
412 float newHeight = (float)terrain_tmp[x, y];
413 if (newHeight != -65535f) m_terrainData[dx, dy] = newHeight + displacement.Z;
417 m_log.DebugFormat(
"{0} MergeWithBounding - Bound & Displace: Out of Bounds sx={1} sy={2} dx={3} dy={4}", x, y, dx, dy);
429 copy.m_terrainData = m_terrainData.Clone();
433 private void WriteXml(XmlWriter writer)
439 writer.WriteStartElement(String.Empty,
"TerrainMap", String.Empty);
441 writer.WriteEndElement();
446 writer.WriteStartElement(String.Empty,
"TerrainMap2", String.Empty);
448 writer.WriteEndElement();
452 private void ReadXml(XmlReader reader)
455 if (reader.IsStartElement(
"TerrainMap"))
457 reader.ReadStartElement(
"TerrainMap");
462 reader.ReadStartElement(
"TerrainMap2");
468 private void ToXml(XmlWriter xmlWriter)
470 float[] mapData = GetFloatsSerialised();
471 byte[] buffer =
new byte[mapData.Length * 4];
472 for (
int i = 0; i < mapData.Length; i++)
474 byte[] value = BitConverter.GetBytes(mapData[i]);
475 Array.Copy(value, 0, buffer, (i * 4), 4);
477 XmlSerializer serializer =
new XmlSerializer(typeof(byte[]));
478 serializer.Serialize(xmlWriter, buffer);
482 private void FromXml(XmlReader xmlReader)
484 XmlSerializer serializer =
new XmlSerializer(typeof(byte[]));
485 byte[] dataArray = (byte[])serializer.Deserialize(xmlReader);
490 for (
int y = 0; y < Height; y++)
492 for (
int x = 0; x < Width; x++)
495 value = BitConverter.ToSingle(dataArray, index);
497 this[x, y] = (double)value;
502 private class TerrainChannelXMLPackage
508 public float CompressionFactor;
510 public TerrainChannelXMLPackage(
int pX,
int pY,
int pZ,
float pCompressionFactor,
float[] pMap)
516 CompressionFactor = pCompressionFactor;
522 private void ToXml2(XmlWriter xmlWriter)
524 TerrainChannelXMLPackage
package = new TerrainChannelXMLPackage(Width, Height, Altitude, m_terrainData.CompressionFactor,
525 m_terrainData.GetCompressedMap());
526 XmlSerializer serializer =
new XmlSerializer(typeof(TerrainChannelXMLPackage));
527 serializer.Serialize(xmlWriter, package);
531 private void FromXml2(XmlReader xmlReader)
533 XmlSerializer serializer =
new XmlSerializer(typeof(TerrainChannelXMLPackage));
534 TerrainChannelXMLPackage
package = (TerrainChannelXMLPackage)serializer.Deserialize(xmlReader);
535 m_terrainData =
new HeightmapTerrainData(package.Map, package.CompressionFactor, package.SizeX, package.SizeY, package.SizeZ);
539 private void PinHeadIsland()
541 float cx = m_terrainData.SizeX * 0.5f;
542 float cy = m_terrainData.SizeY * 0.5f;
544 for (
int x = 0; x < Width; x++)
546 for (
int y = 0; y < Height; y++)
550 float spherFacA = (float)(TerrainUtil.SphericalFactor(x, y, cx, cy, 50) * 0.01d);
551 float spherFacB = (float)(TerrainUtil.SphericalFactor(x, y, cx, cy, 100) * 0.001d);
556 m_terrainData[x, y] = h;
561 private void FlatLand()
563 m_terrainData.ClearLand();
float GetHeightAtXYZ(float x, float y, float z)
TerrainChannel(double[,] pM, int pSizeX, int pSizeY, int pAltitude)
TerrainData GetTerrainData()
float[] GetFloatsSerialised()
Squash the entire heightmap into a single dimensioned array
TerrainChannel(TerrainData pTerrData)
void LoadFromXmlString(string data)
TerrainChannel(String type, int pX, int pY, int pZ)
bool Tainted(int x, int y)
void MergeWithBounding(ITerrainChannel newTerrain, Vector3 displacement, float rotationDegrees, Vector2 boundingOrigin, Vector2 boundingSize)
A new version of terrain merge that processes the terrain in a specific order and corrects the proble...
ITerrainChannel MakeCopy()
TerrainChannel(int pX, int pY)
A new version of the old Channel class, simplified
TerrainData m_terrainData
void Merge(ITerrainChannel newTerrain, Vector3 displacement, float radianRotation, Vector2 rotationDisplacement)