diff --git a/Assets/Plugins.meta b/Assets/Plugins.meta
new file mode 100644
index 0000000..6341370
--- /dev/null
+++ b/Assets/Plugins.meta
@@ -0,0 +1,4 @@
+fileFormatVersion: 2
+guid: e9397f1cc72425345ae40b516554892b
+DefaultImporter:
+ userData:
diff --git a/Assets/Plugins/openjpeg-dotnet.dll b/Assets/Plugins/openjpeg-dotnet.dll
new file mode 100644
index 0000000..6377b8d
Binary files /dev/null and b/Assets/Plugins/openjpeg-dotnet.dll differ
diff --git a/Assets/Plugins/openjpeg-dotnet.dll.meta b/Assets/Plugins/openjpeg-dotnet.dll.meta
new file mode 100644
index 0000000..7ae19c0
--- /dev/null
+++ b/Assets/Plugins/openjpeg-dotnet.dll.meta
@@ -0,0 +1,4 @@
+fileFormatVersion: 2
+guid: 89c98088dfae49d4a851fa03b9336396
+DefaultImporter:
+ userData:
diff --git a/Assets/Scenes/login.unity b/Assets/Scenes/login.unity
index a281da3..ba52d25 100644
Binary files a/Assets/Scenes/login.unity and b/Assets/Scenes/login.unity differ
diff --git a/Assets/Scripts/ImageUtils.cs b/Assets/Scripts/ImageUtils.cs
new file mode 100644
index 0000000..0517ed0
--- /dev/null
+++ b/Assets/Scripts/ImageUtils.cs
@@ -0,0 +1,90 @@
+//
+// Radegast Metaverse Client
+// Copyright (c) 2009-2013, Radegast Development Team
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of the application "Radegast", nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Based on code from Aurora Sim and OpenSimulator
+// Copyright (c) Contributors, http://aurora-sim.org/, http://opensimulator.org/
+//
+// $Id$
+//
+
+
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.IO;
+using System.Reflection;
+using OpenMetaverse;
+using OpenMetaverse.Imaging;
+using OpenMetaverse.Rendering;
+using OpenMetaverse.StructuredData;
+
+namespace Radegast.Rendering
+{
+ public static class ImageUtils
+ {
+ ///
+ /// Performs bilinear interpolation between four values
+ ///
+ /// First, or top left value
+ /// Second, or top right value
+ /// Third, or bottom left value
+ /// Fourth, or bottom right value
+ /// Interpolation value on the X axis, between 0.0 and 1.0
+ /// Interpolation value on fht Y axis, between 0.0 and 1.0
+ /// The bilinearly interpolated result
+ public static float Bilinear(float v00, float v01, float v10, float v11, float xPercent, float yPercent)
+ {
+ return Utils.Lerp(Utils.Lerp(v00, v01, xPercent), Utils.Lerp(v10, v11, xPercent), yPercent);
+ }
+
+ ///
+ /// Performs a high quality image resize
+ ///
+ /// Image to resize
+ /// New width
+ /// New height
+ /// Resized image
+ public static Bitmap ResizeImage(Image image, int width, int height)
+ {
+ Bitmap result = new Bitmap(width, height);
+
+ using (Graphics graphics = Graphics.FromImage(result))
+ {
+ graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
+ graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
+ graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
+ graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
+
+ graphics.DrawImage(image, 0, 0, result.Width, result.Height);
+ }
+
+ return result;
+ }
+ }
+}
diff --git a/Assets/Scripts/ImageUtils.cs.meta b/Assets/Scripts/ImageUtils.cs.meta
new file mode 100644
index 0000000..357296e
--- /dev/null
+++ b/Assets/Scripts/ImageUtils.cs.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: aba027515e0e30948b38890f73e12f04
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
diff --git a/Assets/Scripts/Login.cs b/Assets/Scripts/Login.cs
index 1a34b10..778ec3a 100644
Binary files a/Assets/Scripts/Login.cs and b/Assets/Scripts/Login.cs differ
diff --git a/Assets/Scripts/Perlin.cs.cs b/Assets/Scripts/Perlin.cs.cs
new file mode 100644
index 0000000..487316c
--- /dev/null
+++ b/Assets/Scripts/Perlin.cs.cs
@@ -0,0 +1,278 @@
+//
+// Radegast Metaverse Client
+// Copyright (c) 2009-2013, Radegast Development Team
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of the application "Radegast", nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Based on code from Aurora Sim and OpenSimulator
+// Copyright (c) Contributors, http://aurora-sim.org/, http://opensimulator.org/
+//
+// $Id$
+//
+
+using System;
+using OpenMetaverse;
+
+namespace Radegast.Rendering
+{
+ public static class Perlin
+ {
+ // We use a hardcoded seed to keep the noise generation consistent between runs
+ private const int SEED = 42;
+
+ private const int SAMPLE_SIZE = 1024;
+ private const int B = SAMPLE_SIZE;
+ private const int BM = SAMPLE_SIZE - 1;
+ private const int N = 0x1000;
+
+ private static readonly int[] p = new int[SAMPLE_SIZE + SAMPLE_SIZE + 2];
+ private static readonly float[,] g3 = new float[SAMPLE_SIZE + SAMPLE_SIZE + 2, 3];
+ private static readonly float[,] g2 = new float[SAMPLE_SIZE + SAMPLE_SIZE + 2, 2];
+ private static readonly float[] g1 = new float[SAMPLE_SIZE + SAMPLE_SIZE + 2];
+
+ static Perlin()
+ {
+ Random rng = new Random(SEED);
+ int i, j, k;
+
+ for (i = 0; i < B; i++)
+ {
+ p[i] = i;
+ g1[i] = (float)((rng.Next() % (B + B)) - B) / B;
+
+ for (j = 0; j < 2; j++)
+ g2[i, j] = (float)((rng.Next() % (B + B)) - B) / B;
+ normalize2(g2, i);
+
+ for (j = 0; j < 3; j++)
+ g3[i, j] = (float)((rng.Next() % (B + B)) - B) / B;
+ normalize3(g3, i);
+ }
+
+ while (--i > 0)
+ {
+ k = p[i];
+ p[i] = p[j = rng.Next() % B];
+ p[j] = k;
+ }
+
+ for (i = 0; i < B + 2; i++)
+ {
+ p[B + i] = p[i];
+ g1[B + i] = g1[i];
+ for (j = 0; j < 2; j++)
+ g2[B + i, j] = g2[i, j];
+ for (j = 0; j < 3; j++)
+ g3[B + i, j] = g3[i, j];
+ }
+ }
+
+ public static float noise1(float arg)
+ {
+ int bx0, bx1;
+ float rx0, rx1, sx, t, u, v;
+
+ t = arg + N;
+ bx0 = ((int)t) & BM;
+ bx1 = (bx0 + 1) & BM;
+ rx0 = t - (int)t;
+ rx1 = rx0 - 1f;
+
+ sx = s_curve(rx0);
+
+ u = rx0 * g1[p[bx0]];
+ v = rx1 * g1[p[bx1]];
+
+ return Utils.Lerp(u, v, sx);
+ }
+
+ public static float noise2(float x, float y)
+ {
+ int bx0, bx1, by0, by1, b00, b10, b01, b11;
+ float rx0, rx1, ry0, ry1, sx, sy, a, b, t, u, v;
+ int i, j;
+
+ t = x + N;
+ bx0 = ((int)t) & BM;
+ bx1 = (bx0 + 1) & BM;
+ rx0 = t - (int)t;
+ rx1 = rx0 - 1f;
+
+ t = y + N;
+ by0 = ((int)t) & BM;
+ by1 = (by0 + 1) & BM;
+ ry0 = t - (int)t;
+ ry1 = ry0 - 1f;
+
+ i = p[bx0];
+ j = p[bx1];
+
+ b00 = p[i + by0];
+ b10 = p[j + by0];
+ b01 = p[i + by1];
+ b11 = p[j + by1];
+
+ sx = s_curve(rx0);
+ sy = s_curve(ry0);
+
+ u = rx0 * g2[b00, 0] + ry0 * g2[b00, 1];
+ v = rx1 * g2[b10, 0] + ry0 * g2[b10, 1];
+ a = Utils.Lerp(u, v, sx);
+
+ u = rx0 * g2[b01, 0] + ry1 * g2[b01, 1];
+ v = rx1 * g2[b11, 0] + ry1 * g2[b11, 1];
+ b = Utils.Lerp(u, v, sx);
+
+ return Utils.Lerp(a, b, sy);
+ }
+
+ public static float noise3(float x, float y, float z)
+ {
+ int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
+ float rx0, rx1, ry0, ry1, rz0, rz1, sy, sz, a, b, c, d, t, u, v;
+ int i, j;
+
+ t = x + N;
+ bx0 = ((int)t) & BM;
+ bx1 = (bx0 + 1) & BM;
+ rx0 = t - (int)t;
+ rx1 = rx0 - 1f;
+
+ t = y + N;
+ by0 = ((int)t) & BM;
+ by1 = (by0 + 1) & BM;
+ ry0 = t - (int)t;
+ ry1 = ry0 - 1f;
+
+ t = z + N;
+ bz0 = ((int)t) & BM;
+ bz1 = (bz0 + 1) & BM;
+ rz0 = t - (int)t;
+ rz1 = rz0 - 1f;
+
+ i = p[bx0];
+ j = p[bx1];
+
+ b00 = p[i + by0];
+ b10 = p[j + by0];
+ b01 = p[i + by1];
+ b11 = p[j + by1];
+
+ t = s_curve(rx0);
+ sy = s_curve(ry0);
+ sz = s_curve(rz0);
+
+ u = rx0 * g3[b00 + bz0, 0] + ry0 * g3[b00 + bz0, 1] + rz0 * g3[b00 + bz0, 2];
+ v = rx1 * g3[b10 + bz0, 0] + ry0 * g3[b10 + bz0, 1] + rz0 * g3[b10 + bz0, 2];
+ a = Utils.Lerp(u, v, t);
+
+ u = rx0 * g3[b01 + bz0, 0] + ry1 * g3[b01 + bz0, 1] + rz0 * g3[b01 + bz0, 2];
+ v = rx1 * g3[b11 + bz0, 0] + ry1 * g3[b11 + bz0, 1] + rz0 * g3[b11 + bz0, 2];
+ b = Utils.Lerp(u, v, t);
+
+ c = Utils.Lerp(a, b, sy);
+
+ u = rx0 * g3[b00 + bz1, 0] + ry0 * g3[b00 + bz1, 1] + rz1 * g3[b00 + bz1, 2];
+ v = rx1 * g3[b10 + bz1, 0] + ry0 * g3[b10 + bz1, 1] + rz1 * g3[b10 + bz1, 2];
+ a = Utils.Lerp(u, v, t);
+
+ u = rx0 * g3[b01 + bz1, 0] + ry1 * g3[b01 + bz1, 1] + rz1 * g3[b01 + bz1, 2];
+ v = rx1 * g3[b11 + bz1, 0] + ry1 * g3[b11 + bz1, 1] + rz1 * g3[b11 + bz1, 2];
+ b = Utils.Lerp(u, v, t);
+
+ d = Utils.Lerp(a, b, sy);
+ return Utils.Lerp(c, d, sz);
+ }
+
+ public static float turbulence1(float x, float freq)
+ {
+ float t;
+ float v;
+
+ for (t = 0f; freq >= 1f; freq *= 0.5f)
+ {
+ v = freq * x;
+ t += noise1(v) / freq;
+ }
+ return t;
+ }
+
+ public static float turbulence2(float x, float y, float freq)
+ {
+ float t;
+ Vector2 vec;
+
+ for (t = 0f; freq >= 1f; freq *= 0.5f)
+ {
+ vec.X = freq * x;
+ vec.Y = freq * y;
+ t += noise2(vec.X, vec.Y) / freq;
+ }
+ return t;
+ }
+
+ public static float turbulence3(float x, float y, float z, float freq)
+ {
+ float t;
+ Vector3 vec;
+
+ for (t = 0f; freq >= 1f; freq *= 0.5f)
+ {
+ vec.X = freq * x;
+ vec.Y = freq * y;
+ vec.Z = freq * z;
+ t += noise3(vec.X, vec.Y, vec.Z) / freq;
+ }
+ return t;
+ }
+
+ private static void normalize2(float[,] v, int i)
+ {
+ float s;
+
+ s = (float)Math.Sqrt(v[i, 0] * v[i, 0] + v[i, 1] * v[i, 1]);
+ s = 1.0f / s;
+ v[i, 0] = v[i, 0] * s;
+ v[i, 1] = v[i, 1] * s;
+ }
+
+ private static void normalize3(float[,] v, int i)
+ {
+ float s;
+
+ s = (float)Math.Sqrt(v[i, 0] * v[i, 0] + v[i, 1] * v[i, 1] + v[i, 2] * v[i, 2]);
+ s = 1.0f / s;
+
+ v[i, 0] = v[i, 0] * s;
+ v[i, 1] = v[i, 1] * s;
+ v[i, 2] = v[i, 2] * s;
+ }
+
+ private static float s_curve(float t)
+ {
+ return t * t * (3f - 2f * t);
+ }
+ }
+}
diff --git a/Assets/Scripts/Perlin.cs.cs.meta b/Assets/Scripts/Perlin.cs.cs.meta
new file mode 100644
index 0000000..4d21a55
--- /dev/null
+++ b/Assets/Scripts/Perlin.cs.cs.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 2fe71911bbe5a5c459ca6939a02aad62
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
diff --git a/Assets/Scripts/TerrainSplat.cs b/Assets/Scripts/TerrainSplat.cs
new file mode 100644
index 0000000..116eb37
--- /dev/null
+++ b/Assets/Scripts/TerrainSplat.cs
@@ -0,0 +1,383 @@
+//
+// Radegast Metaverse Client
+// Copyright (c) 2009-2013, Radegast Development Team
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of the application "Radegast", nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Based on code from Aurora Sim and OpenSimulator
+// Copyright (c) Contributors, http://aurora-sim.org/, http://opensimulator.org/
+//
+// $Id$
+//
+
+
+using System;
+using System.Diagnostics;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.Threading;
+using OpenMetaverse;
+using OpenMetaverse.Imaging;
+
+namespace Radegast.Rendering
+{
+ public static class TerrainSplat
+ {
+ #region Constants
+
+ private static readonly UUID DIRT_DETAIL = new UUID("0bc58228-74a0-7e83-89bc-5c23464bcec5");
+ private static readonly UUID GRASS_DETAIL = new UUID("63338ede-0037-c4fd-855b-015d77112fc8");
+ private static readonly UUID MOUNTAIN_DETAIL = new UUID("303cd381-8560-7579-23f1-f0a880799740");
+ private static readonly UUID ROCK_DETAIL = new UUID("53a2f406-4895-1d13-d541-d2e3b86bc19c");
+ private static readonly int RegionSize = 256;
+
+ private static readonly UUID[] DEFAULT_TERRAIN_DETAIL = new UUID[]
+ {
+ DIRT_DETAIL,
+ GRASS_DETAIL,
+ MOUNTAIN_DETAIL,
+ ROCK_DETAIL
+ };
+
+ private static readonly Color[] DEFAULT_TERRAIN_COLOR = new Color[]
+ {
+ Color.FromArgb(255, 164, 136, 117),
+ Color.FromArgb(255, 65, 87, 47),
+ Color.FromArgb(255, 157, 145, 131),
+ Color.FromArgb(255, 125, 128, 130)
+ };
+
+ private static readonly UUID TERRAIN_CACHE_MAGIC = new UUID("2c0c7ef2-56be-4eb8-aacb-76712c535b4b");
+
+ #endregion Constants
+
+ ///
+ /// Builds a composited terrain texture given the region texture
+ /// and heightmap settings
+ ///
+ /// Terrain heightmap
+ /// Region information including terrain texture parameters
+ /// A composited 256x256 RGB texture ready for rendering
+ /// Based on the algorithm described at http://opensimulator.org/wiki/Terrain_Splatting
+ ///
+ /// HACK: Change RadegastInstance to GridClient
+ public static Bitmap Splat(GridClient client, float[,] heightmap, UUID[] textureIDs, float[] startHeights, float[] heightRanges)
+ {
+ Debug.Assert(textureIDs.Length == 4);
+ Debug.Assert(startHeights.Length == 4);
+ Debug.Assert(heightRanges.Length == 4);
+ int outputSize = 2048;
+
+ Bitmap[] detailTexture = new Bitmap[4];
+
+ // Swap empty terrain textureIDs with default IDs
+ for (int i = 0; i < textureIDs.Length; i++)
+ {
+ if (textureIDs[i] == UUID.Zero)
+ textureIDs[i] = DEFAULT_TERRAIN_DETAIL[i];
+ }
+
+ #region Texture Fetching
+ for (int i = 0; i < 4; i++)
+ {
+ AutoResetEvent textureDone = new AutoResetEvent(false);
+ UUID textureID = textureIDs[i];
+
+ client.Assets.RequestImage(textureID, TextureDownloadCallback(detailTexture, i, textureDone));
+
+ textureDone.WaitOne(3 * 1000, false);
+ }
+
+ #endregion Texture Fetching
+
+ // Fill in any missing textures with a solid color
+ for (int i = 0; i < 4; i++)
+ {
+ if (detailTexture[i] == null)
+ {
+ // Create a solid color texture for this layer
+ detailTexture[i] = new Bitmap(outputSize, outputSize, PixelFormat.Format24bppRgb);
+ using (Graphics gfx = Graphics.FromImage(detailTexture[i]))
+ {
+ using (SolidBrush brush = new SolidBrush(DEFAULT_TERRAIN_COLOR[i]))
+ gfx.FillRectangle(brush, 0, 0, outputSize, outputSize);
+ }
+ }
+ else if (detailTexture[i].Width != outputSize || detailTexture[i].Height != outputSize)
+ {
+ detailTexture[i] = ResizeBitmap(detailTexture[i], 256, 256);
+ }
+ }
+
+ #region Layer Map
+
+ int diff = heightmap.GetLength(0) / RegionSize;
+ float[] layermap = new float[RegionSize * RegionSize];
+
+ for (int y = 0; y < heightmap.GetLength(0); y += diff)
+ {
+ for (int x = 0; x < heightmap.GetLength(1); x += diff)
+ {
+ int newX = x / diff;
+ int newY = y / diff;
+ float height = heightmap[newX, newY];
+
+ float pctX = (float)newX / 255f;
+ float pctY = (float)newY / 255f;
+
+ // Use bilinear interpolation between the four corners of start height and
+ // height range to select the current values at this position
+ float startHeight = ImageUtils.Bilinear(
+ startHeights[0],
+ startHeights[2],
+ startHeights[1],
+ startHeights[3],
+ pctX, pctY);
+ startHeight = Utils.Clamp(startHeight, 0f, 255f);
+
+ float heightRange = ImageUtils.Bilinear(
+ heightRanges[0],
+ heightRanges[2],
+ heightRanges[1],
+ heightRanges[3],
+ pctX, pctY);
+ heightRange = Utils.Clamp(heightRange, 0f, 255f);
+
+ // Generate two frequencies of perlin noise based on our global position
+ // The magic values were taken from http://opensimulator.org/wiki/Terrain_Splatting
+ Vector3 vec = new Vector3
+ (
+ newX * 0.20319f,
+ newY * 0.20319f,
+ height * 0.25f
+ );
+
+ float lowFreq = Perlin.noise2(vec.X * 0.222222f, vec.Y * 0.222222f) * 6.5f;
+ float highFreq = Perlin.turbulence2(vec.X, vec.Y, 2f) * 2.25f;
+ float noise = (lowFreq + highFreq) * 2f;
+
+ // Combine the current height, generated noise, start height, and height range parameters, then scale all of it
+ float layer = ((height + noise - startHeight) / heightRange) * 4f;
+ if (Single.IsNaN(layer))
+ layer = 0f;
+ layermap[newY * RegionSize + newX] = Utils.Clamp(layer, 0f, 3f);
+ }
+ }
+
+ #endregion Layer Map
+
+ #region Texture Compositing
+ Bitmap output = new Bitmap(outputSize, outputSize, PixelFormat.Format24bppRgb);
+ BitmapData outputData = output.LockBits(new Rectangle(0, 0, outputSize, outputSize), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
+
+ unsafe
+ {
+ // Get handles to all of the texture data arrays
+ BitmapData[] datas = new BitmapData[]
+ {
+ detailTexture[0].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[0].PixelFormat),
+ detailTexture[1].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[1].PixelFormat),
+ detailTexture[2].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[2].PixelFormat),
+ detailTexture[3].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[3].PixelFormat)
+ };
+
+ int[] comps = new int[]
+ {
+ (datas[0].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3,
+ (datas[1].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3,
+ (datas[2].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3,
+ (datas[3].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3
+ };
+
+ int[] strides = new int[]
+ {
+ datas[0].Stride,
+ datas[1].Stride,
+ datas[2].Stride,
+ datas[3].Stride
+ };
+
+ IntPtr[] scans = new IntPtr[]
+ {
+ datas[0].Scan0,
+ datas[1].Scan0,
+ datas[2].Scan0,
+ datas[3].Scan0
+ };
+
+ int ratio = outputSize / RegionSize;
+
+ for (int y = 0; y < outputSize; y++)
+ {
+ for (int x = 0; x < outputSize; x++)
+ {
+ float layer = layermap[(y / ratio) * RegionSize + x / ratio];
+ float layerx = layermap[(y / ratio) * RegionSize + Math.Min(outputSize - 1, (x + 1)) / ratio];
+ float layerxx = layermap[(y / ratio) * RegionSize + Math.Max(0, (x - 1)) / ratio];
+ float layery = layermap[Math.Min(outputSize - 1, (y + 1)) / ratio * RegionSize + x / ratio];
+ float layeryy = layermap[(Math.Max(0, (y - 1)) / ratio) * RegionSize + x / ratio];
+
+ // Select two textures
+ int l0 = (int)Math.Floor(layer);
+ int l1 = Math.Min(l0 + 1, 3);
+
+ byte* ptrA = (byte*)scans[l0] + (y % 256) * strides[l0] + (x % 256) * comps[l0];
+ byte* ptrB = (byte*)scans[l1] + (y % 256) * strides[l1] + (x % 256) * comps[l1];
+ byte* ptrO = (byte*)outputData.Scan0 + y * outputData.Stride + x * 3;
+
+ float aB = *(ptrA + 0);
+ float aG = *(ptrA + 1);
+ float aR = *(ptrA + 2);
+
+ int lX = (int)Math.Floor(layerx);
+ byte* ptrX = (byte*)scans[lX] + (y % 256) * strides[lX] + (x % 256) * comps[lX];
+ int lXX = (int)Math.Floor(layerxx);
+ byte* ptrXX = (byte*)scans[lXX] + (y % 256) * strides[lXX] + (x % 256) * comps[lXX];
+ int lY = (int)Math.Floor(layery);
+ byte* ptrY = (byte*)scans[lY] + (y % 256) * strides[lY] + (x % 256) * comps[lY];
+ int lYY = (int)Math.Floor(layeryy);
+ byte* ptrYY = (byte*)scans[lYY] + (y % 256) * strides[lYY] + (x % 256) * comps[lYY];
+
+ float bB = *(ptrB + 0);
+ float bG = *(ptrB + 1);
+ float bR = *(ptrB + 2);
+
+ float layerDiff = layer - l0;
+ float xlayerDiff = layerx - layer;
+ float xxlayerDiff = layerxx - layer;
+ float ylayerDiff = layery - layer;
+ float yylayerDiff = layeryy - layer;
+ // Interpolate between the two selected textures
+ *(ptrO + 0) = (byte)Math.Floor(aB + layerDiff * (bB - aB) +
+ xlayerDiff * (*ptrX - aB) +
+ xxlayerDiff * (*(ptrXX) - aB) +
+ ylayerDiff * (*ptrY - aB) +
+ yylayerDiff * (*(ptrYY) - aB));
+ *(ptrO + 1) = (byte)Math.Floor(aG + layerDiff * (bG - aG) +
+ xlayerDiff * (*(ptrX + 1) - aG) +
+ xxlayerDiff * (*(ptrXX + 1) - aG) +
+ ylayerDiff * (*(ptrY + 1) - aG) +
+ yylayerDiff * (*(ptrYY + 1) - aG));
+ *(ptrO + 2) = (byte)Math.Floor(aR + layerDiff * (bR - aR) +
+ xlayerDiff * (*(ptrX + 2) - aR) +
+ xxlayerDiff * (*(ptrXX + 2) - aR) +
+ ylayerDiff * (*(ptrY + 2) - aR) +
+ yylayerDiff * (*(ptrYY + 2) - aR));
+ }
+ }
+
+ for (int i = 0; i < 4; i++)
+ {
+ detailTexture[i].UnlockBits(datas[i]);
+ detailTexture[i].Dispose();
+ }
+ }
+
+ layermap = null;
+ output.UnlockBits(outputData);
+
+ output.RotateFlip(RotateFlipType.Rotate270FlipNone);
+
+ #endregion Texture Compositing
+
+ return output;
+ }
+
+ private static TextureDownloadCallback TextureDownloadCallback(Bitmap[] detailTexture, int i, AutoResetEvent textureDone)
+ {
+ return (state, assetTexture) =>
+ {
+ if (state == TextureRequestState.Finished && assetTexture != null && assetTexture.AssetData != null)
+ {
+ Image img;
+ ManagedImage mi;
+ OpenJPEG.DecodeToImage(assetTexture.AssetData, out mi, out img);
+ detailTexture[i] = (Bitmap)img;
+ }
+ textureDone.Set();
+ };
+ }
+
+ public static Bitmap ResizeBitmap(Bitmap b, int nWidth, int nHeight)
+ {
+ Bitmap result = new Bitmap(nWidth, nHeight);
+ using (Graphics g = Graphics.FromImage((Image)result))
+ {
+ g.DrawImage(b, 0, 0, nWidth, nHeight);
+ }
+ b.Dispose();
+ return result;
+ }
+
+ public static Bitmap TileBitmap(Bitmap b, int tiles)
+ {
+ Bitmap result = new Bitmap(b.Width * tiles, b.Width * tiles);
+ using (Graphics g = Graphics.FromImage((Image)result))
+ {
+ for (int x = 0; x < tiles; x++)
+ {
+ for (int y = 0; y < tiles; y++)
+ {
+ g.DrawImage(b, x * 256, y * 256, x * 256 + 256, y * 256 + 256);
+ }
+ }
+ }
+ b.Dispose();
+ return result;
+ }
+
+ public static Bitmap SplatSimple(float[,] heightmap)
+ {
+ const float BASE_HSV_H = 93f / 360f;
+ const float BASE_HSV_S = 44f / 100f;
+ const float BASE_HSV_V = 34f / 100f;
+
+ Bitmap img = new Bitmap(256, 256);
+ BitmapData bitmapData = img.LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
+
+ unsafe
+ {
+ for (int y = 255; y >= 0; y--)
+ {
+ for (int x = 0; x < 256; x++)
+ {
+ float normHeight = heightmap[x, y] / 255f;
+ normHeight = Utils.Clamp(normHeight, BASE_HSV_V, 1.0f);
+
+ Color4 color = Color4.FromHSV(BASE_HSV_H, BASE_HSV_S, normHeight);
+
+ byte* ptr = (byte*)bitmapData.Scan0 + y * bitmapData.Stride + x * 3;
+ *(ptr + 0) = (byte)(color.B * 255f);
+ *(ptr + 1) = (byte)(color.G * 255f);
+ *(ptr + 2) = (byte)(color.R * 255f);
+ }
+ }
+ }
+
+ img.UnlockBits(bitmapData);
+ return img;
+ }
+ }
+}
diff --git a/Assets/Scripts/TerrainSplat.cs.meta b/Assets/Scripts/TerrainSplat.cs.meta
new file mode 100644
index 0000000..84a3eeb
--- /dev/null
+++ b/Assets/Scripts/TerrainSplat.cs.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 9f2df0d52788f4b4eae3f038c28f1eb0
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
diff --git a/Assets/smcs.rsp b/Assets/smcs.rsp
new file mode 100644
index 0000000..46ef843
--- /dev/null
+++ b/Assets/smcs.rsp
@@ -0,0 +1 @@
+-unsafe
\ No newline at end of file
diff --git a/Assets/smcs.rsp.meta b/Assets/smcs.rsp.meta
new file mode 100644
index 0000000..91154c1
--- /dev/null
+++ b/Assets/smcs.rsp.meta
@@ -0,0 +1,4 @@
+fileFormatVersion: 2
+guid: cc09cfd06e62d5e4186ebd0cd4083053
+DefaultImporter:
+ userData:
diff --git a/ProjectSettings/ProjectSettings.asset b/ProjectSettings/ProjectSettings.asset
index fad8c7d..65d3b88 100644
Binary files a/ProjectSettings/ProjectSettings.asset and b/ProjectSettings/ProjectSettings.asset differ
diff --git a/ProjectSettings/QualitySettings.asset b/ProjectSettings/QualitySettings.asset
index f290f31..29ba67a 100644
Binary files a/ProjectSettings/QualitySettings.asset and b/ProjectSettings/QualitySettings.asset differ
diff --git a/openjpeg-dotnet.dll b/openjpeg-dotnet.dll
new file mode 100644
index 0000000..6377b8d
Binary files /dev/null and b/openjpeg-dotnet.dll differ
diff --git a/openmetaverse_data/cache/00000000-0000-1111-9999-000000000010 b/openmetaverse_data/cache/00000000-0000-1111-9999-000000000010
new file mode 100644
index 0000000..a50498f
Binary files /dev/null and b/openmetaverse_data/cache/00000000-0000-1111-9999-000000000010 differ
diff --git a/openmetaverse_data/cache/00000000-0000-1111-9999-000000000011 b/openmetaverse_data/cache/00000000-0000-1111-9999-000000000011
new file mode 100644
index 0000000..88908c6
Binary files /dev/null and b/openmetaverse_data/cache/00000000-0000-1111-9999-000000000011 differ
diff --git a/openmetaverse_data/cache/00000000-0000-1111-9999-000000000012 b/openmetaverse_data/cache/00000000-0000-1111-9999-000000000012
new file mode 100644
index 0000000..7bd0cb0
Binary files /dev/null and b/openmetaverse_data/cache/00000000-0000-1111-9999-000000000012 differ
diff --git a/openmetaverse_data/cache/179cdabd-398a-9b6b-1391-4dc333ba321f b/openmetaverse_data/cache/179cdabd-398a-9b6b-1391-4dc333ba321f
new file mode 100644
index 0000000..8971ac3
Binary files /dev/null and b/openmetaverse_data/cache/179cdabd-398a-9b6b-1391-4dc333ba321f differ
diff --git a/openmetaverse_data/cache/5748decc-f629-461c-9a36-a35a221fe21f b/openmetaverse_data/cache/5748decc-f629-461c-9a36-a35a221fe21f
new file mode 100644
index 0000000..69ee4f1
Binary files /dev/null and b/openmetaverse_data/cache/5748decc-f629-461c-9a36-a35a221fe21f differ
diff --git a/openmetaverse_data/cache/6522e74d-1660-4e7f-b601-6f48c1659a77 b/openmetaverse_data/cache/6522e74d-1660-4e7f-b601-6f48c1659a77
new file mode 100644
index 0000000..b932a06
Binary files /dev/null and b/openmetaverse_data/cache/6522e74d-1660-4e7f-b601-6f48c1659a77 differ
diff --git a/openmetaverse_data/cache/abb783e6-3e93-26c0-248a-247666855da3 b/openmetaverse_data/cache/abb783e6-3e93-26c0-248a-247666855da3
new file mode 100644
index 0000000..13c43b4
Binary files /dev/null and b/openmetaverse_data/cache/abb783e6-3e93-26c0-248a-247666855da3 differ
diff --git a/openmetaverse_data/cache/b8d3965a-ad78-bf43-699b-bff8eca6c975 b/openmetaverse_data/cache/b8d3965a-ad78-bf43-699b-bff8eca6c975
new file mode 100644
index 0000000..44f31a0
Binary files /dev/null and b/openmetaverse_data/cache/b8d3965a-ad78-bf43-699b-bff8eca6c975 differ
diff --git a/openmetaverse_data/cache/beb169c7-11ea-fff2-efe5-0f24dc881df2 b/openmetaverse_data/cache/beb169c7-11ea-fff2-efe5-0f24dc881df2
new file mode 100644
index 0000000..ccbeb08
Binary files /dev/null and b/openmetaverse_data/cache/beb169c7-11ea-fff2-efe5-0f24dc881df2 differ