From 13b1c5dfcef6e6e74709da8d588ed48d99d560d2 Mon Sep 17 00:00:00 2001
From: UbitUmarov
Date: Sat, 5 Sep 2015 17:50:55 +0100
Subject: let ode suport var size regions

Signed-off-by: Diva Canto <diva@metaverseink.com>
---
 .../PhysicsModules/Ode/ODERayCastRequestManager.cs |   7 +
 OpenSim/Region/PhysicsModules/Ode/OdeScene.cs      | 288 ++++++++++-----------
 2 files changed, 143 insertions(+), 152 deletions(-)

diff --git a/OpenSim/Region/PhysicsModules/Ode/ODERayCastRequestManager.cs b/OpenSim/Region/PhysicsModules/Ode/ODERayCastRequestManager.cs
index 21bfea3..aafc7c6 100644
--- a/OpenSim/Region/PhysicsModules/Ode/ODERayCastRequestManager.cs
+++ b/OpenSim/Region/PhysicsModules/Ode/ODERayCastRequestManager.cs
@@ -172,6 +172,13 @@ namespace OpenSim.Region.PhysicsModule.ODE
         /// <param name="req"></param>
         private void RayCast(ODERayCastRequest req)
         {
+            // UBIT: limit ray lenght or collisions will take all avaiable stack space
+            // this value may still be too large, depending on machine configuration
+            // of maximum stack
+            float len = req.length;
+            if (len > 250f)
+                len = 250f;
+
             // Create the ray
             IntPtr ray = d.CreateRay(m_scene.space, req.length);
             d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z);
diff --git a/OpenSim/Region/PhysicsModules/Ode/OdeScene.cs b/OpenSim/Region/PhysicsModules/Ode/OdeScene.cs
index f49b0f7..19b957f 100644
--- a/OpenSim/Region/PhysicsModules/Ode/OdeScene.cs
+++ b/OpenSim/Region/PhysicsModules/Ode/OdeScene.cs
@@ -25,6 +25,12 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+// Ubit changes for varsize regions
+// note that raycasts need to have limited range
+// (even in normal regions)
+// or aplication thread stack may just blowup
+// see RayCast(ODERayCastRequest req)
+
 //#define USE_DRAWSTUFF
 //#define SPAM
 
@@ -270,8 +276,10 @@ namespace OpenSim.Region.PhysicsModule.ODE
 
         private Random fluidRandomizer = new Random(Environment.TickCount);
 
-        private const uint m_regionWidth = Constants.RegionSize;
-        private const uint m_regionHeight = Constants.RegionSize;
+        public bool m_suportCombine = true;
+
+        private uint m_regionWidth = Constants.RegionSize;
+        private uint m_regionHeight = Constants.RegionSize;
 
         private float ODE_STEPSIZE = 0.0178f;
         private float metersInSpace = 29.9f;
@@ -297,7 +305,7 @@ namespace OpenSim.Region.PhysicsModule.ODE
 
         private IntPtr contactgroup;
 
-        internal IntPtr WaterGeom;
+//        internal IntPtr WaterGeom;
 
         private float nmTerrainContactFriction = 255.0f;
         private float nmTerrainContactBounce = 0.1f;
@@ -514,17 +522,17 @@ namespace OpenSim.Region.PhysicsModule.ODE
         public d.Vector3 xyz = new d.Vector3(128.1640f, 128.3079f, 25.7600f);
         public d.Vector3 hpr = new d.Vector3(125.5000f, -17.0000f, 0.0000f);
 
-        // TODO: unused: private uint heightmapWidth = m_regionWidth + 1;
-        // TODO: unused: private uint heightmapHeight = m_regionHeight + 1;
-        // TODO: unused: private uint heightmapWidthSamples;
-        // TODO: unused: private uint heightmapHeightSamples;
-
         private volatile int m_global_contactcount = 0;
 
         private Vector3 m_worldOffset = Vector3.Zero;
         public Vector2 WorldExtents = new Vector2((int)Constants.RegionSize, (int)Constants.RegionSize);
         private PhysicsScene m_parentScene = null;
 
+        float spacesPerMeterX;
+        float spacesPerMeterY;
+        int spaceGridMaxX;
+        int spaceGridMaxY;
+
         private ODERayCastRequestManager m_rayCastManager;
 
 
@@ -583,10 +591,12 @@ namespace OpenSim.Region.PhysicsModule.ODE
 
             scene.RegisterModuleInterface<PhysicsScene>(this);
             Vector3 extent = new Vector3(scene.RegionInfo.RegionSizeX, scene.RegionInfo.RegionSizeY, scene.RegionInfo.RegionSizeZ);
-            Initialise();
+            Initialise(extent);
             InitialiseFromConfig(m_config);
+
+            // This may not be that good since terrain may not be avaiable at this point
             base.Initialise(scene.PhysicsRequestAsset, 
-                (scene.Heightmap != null ? scene.Heightmap.GetFloatsSerialised() : new float[Constants.RegionSize * Constants.RegionSize]), 
+                (scene.Heightmap != null ? scene.Heightmap.GetFloatsSerialised() : new float[(int)(extent.X * extent.Y)]), 
                 (float)scene.RegionInfo.RegionSettings.WaterHeight);
 
         }
@@ -613,8 +623,15 @@ namespace OpenSim.Region.PhysicsModule.ODE
         /// Sets many properties that ODE requires to be stable
         /// These settings need to be tweaked 'exactly' right or weird stuff happens.
         /// </summary>
-        private void Initialise()
+        private void Initialise(Vector3 regionExtent)
         {
+			WorldExtents.X = regionExtent.X;
+            m_regionWidth = (uint)regionExtent.X;
+            WorldExtents.Y = regionExtent.Y;
+            m_regionHeight = (uint)regionExtent.Y;
+			
+            m_suportCombine = false;
+			
             nearCallback = near;
             triCallback = TriCallback;
             triArrayCallback = TriArrayCallback;
@@ -633,7 +650,7 @@ namespace OpenSim.Region.PhysicsModule.ODE
             viewthread.Start();
             #endif
 
-            _watermap = new float[258 * 258];
+ //           _watermap = new float[258 * 258];
 
             // Zero out the prim spaces array (we split our space into smaller spaces so
             // we can hit test less.
@@ -780,7 +797,31 @@ namespace OpenSim.Region.PhysicsModule.ODE
 
             contacts = new d.ContactGeom[contactsPerCollision];
 
-            staticPrimspace = new IntPtr[(int)(300 / metersInSpace), (int)(300 / metersInSpace)];
+            spacesPerMeterX = 1.0f / metersInSpace;
+            spacesPerMeterY = 1.0f / metersInSpace;
+
+            spaceGridMaxX = (int)(WorldExtents.X * spacesPerMeterX);
+            spaceGridMaxY = (int)(WorldExtents.Y * spacesPerMeterY);
+
+            // ubit: limit number of spaces
+            if (spaceGridMaxX > 24)
+            {
+                spaceGridMaxX = 24;
+                spacesPerMeterX =  spaceGridMaxX / WorldExtents.X;
+            }
+            if (spaceGridMaxY > 24)
+            {
+                spaceGridMaxY = 24;
+                spacesPerMeterY = spaceGridMaxY / WorldExtents.Y ;
+            }
+
+            staticPrimspace = new IntPtr[spaceGridMaxX, spaceGridMaxY]; 
+
+            // make this index limits
+            spaceGridMaxX--;
+            spaceGridMaxY--;
+
+
 
             // Centeral contact friction and bounce
             // ckrinke 11/10/08 Enabling soft_erp but not soft_cfm until I figure out why
@@ -1964,6 +2005,8 @@ namespace OpenSim.Region.PhysicsModule.ODE
 
         public override void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents)
         {
+            if (!m_suportCombine)
+                return;
             m_worldOffset = offset;
             WorldExtents = new Vector2(extents.X, extents.Y);
             m_parentScene = pScene;
@@ -1972,12 +2015,17 @@ namespace OpenSim.Region.PhysicsModule.ODE
         // Recovered for use by fly height. Kitto Flora
         internal float GetTerrainHeightAtXY(float x, float y)
         {
-            int offsetX = ((int)(x / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
-            int offsetY = ((int)(y / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
-
             IntPtr heightFieldGeom = IntPtr.Zero;
+            int offsetX = 0;
+            int offsetY = 0;
+
+            if (m_suportCombine)
+            {
+                offsetX = ((int)(x / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
+                offsetY = ((int)(y / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
+            }
 
-            if (RegionTerrain.TryGetValue(new Vector3(offsetX,offsetY,0), out heightFieldGeom))
+            if(RegionTerrain.TryGetValue(new Vector3(offsetX,offsetY,0), out heightFieldGeom))
             {
                 if (heightFieldGeom != IntPtr.Zero)
                 {
@@ -1991,8 +2039,8 @@ namespace OpenSim.Region.PhysicsModule.ODE
                             (int)x < 0.001f || (int)y < 0.001f)
                             return 0;
 
-                        x = x - offsetX;
-                        y = y - offsetY;
+                        x = x - offsetX + 1f;
+                        y = y - offsetY + 1f;
 
                         index = (int)((int)x * ((int)Constants.RegionSize + 2) + (int)y);
 
@@ -2828,16 +2876,16 @@ namespace OpenSim.Region.PhysicsModule.ODE
         {
             int[] returnint = new int[2];
 
-            returnint[0] = (int) (pos.X/metersInSpace);
+            returnint[0] = (int) (pos.X * spacesPerMeterX);
 
-            if (returnint[0] > ((int) (259f/metersInSpace)))
-                returnint[0] = ((int) (259f/metersInSpace));
+            if (returnint[0] > spaceGridMaxX)
+                returnint[0] = spaceGridMaxX;
             if (returnint[0] < 0)
                 returnint[0] = 0;
 
-            returnint[1] = (int) (pos.Y/metersInSpace);
-            if (returnint[1] > ((int) (259f/metersInSpace)))
-                returnint[1] = ((int) (259f/metersInSpace));
+            returnint[1] = (int)(pos.Y * spacesPerMeterY);
+            if (returnint[1] > spaceGridMaxY)
+                returnint[1] = spaceGridMaxY;
             if (returnint[1] < 0)
                 returnint[1] = 0;
 
@@ -3591,6 +3639,7 @@ namespace OpenSim.Region.PhysicsModule.ODE
             get { return false; }
         }
 
+/* godd try.. but not a fix
         #region ODE Specific Terrain Fixes
         private float[] ResizeTerrain512NearestNeighbour(float[] heightMap)
         {
@@ -3857,7 +3906,7 @@ namespace OpenSim.Region.PhysicsModule.ODE
         }
 
         #endregion
-
+*/
         public override void SetTerrain(float[] heightMap)
         {
             if (m_worldOffset != Vector3.Zero && m_parentScene != null)
@@ -3878,71 +3927,65 @@ namespace OpenSim.Region.PhysicsModule.ODE
             int startTime = Util.EnvironmentTickCount();
             m_log.DebugFormat("[ODE SCENE]: Setting terrain for {0} with offset {1}", PhysicsSceneName, pOffset);
 
-            // this._heightmap[i] = (double)heightMap[i];
-            // dbm (danx0r) -- creating a buffer zone of one extra sample all around
-            //_origheightmap = heightMap;
-           
+            
             float[] _heightmap;
 
-            // zero out a heightmap array float array (single dimension [flattened]))
-            //if ((int)Constants.RegionSize == 256)
-            //    _heightmap = new float[514 * 514];
-            //else
-
-            _heightmap = new float[(((int)Constants.RegionSize + 2) * ((int)Constants.RegionSize + 2))];
+            // ok im lasy this are just a aliases
+            uint regionsizeX = m_regionWidth;
+            uint regionsizeY = m_regionHeight;
 
-            uint heightmapWidth = Constants.RegionSize + 1;
-            uint heightmapHeight = Constants.RegionSize + 1;
+            // map is rotated
+            uint heightmapWidth = regionsizeY + 2;
+            uint heightmapHeight = regionsizeX + 2;
 
-            uint heightmapWidthSamples;
+            uint heightmapWidthSamples = heightmapWidth + 1;
+            uint heightmapHeightSamples = heightmapHeight + 1;
 
-            uint heightmapHeightSamples;
+            _heightmap = new float[heightmapWidthSamples * heightmapHeightSamples];
 
-            //if (((int)Constants.RegionSize) == 256)
-            //{
-            //    heightmapWidthSamples = 2 * (uint)Constants.RegionSize + 2;
-            //    heightmapHeightSamples = 2 * (uint)Constants.RegionSize + 2;
-            //    heightmapWidth++;
-            //    heightmapHeight++;
-            //}
-            //else
-            //{
-
-                heightmapWidthSamples = (uint)Constants.RegionSize + 1;
-                heightmapHeightSamples = (uint)Constants.RegionSize + 1;
-            //}
 
             const float scale = 1.0f;
             const float offset = 0.0f;
-            const float thickness = 0.2f;
+            const float thickness = 10f;
             const int wrap = 0;
 
-            int regionsize = (int) Constants.RegionSize + 2;
-            //Double resolution
-            //if (((int)Constants.RegionSize) == 256)
-            //    heightMap = ResizeTerrain512Interpolation(heightMap);
 
+            float hfmin = float.MaxValue;
+            float hfmax = float.MinValue;
+            float val;
+            uint xx;
+            uint yy;
 
-           // if (((int)Constants.RegionSize) == 256 && (int)Constants.RegionSize == 256)
-           //     regionsize = 512;
+            uint maxXX = regionsizeX - 1;
+            uint maxYY = regionsizeY - 1;
 
-            float hfmin = 2000;
-            float hfmax = -2000;
-            
-            for (int x = 0; x < heightmapWidthSamples; x++)
+            // flipping map adding one margin all around so things don't fall in edges
+
+            uint xt = 0;
+            xx = 0;
+
+
+            for (uint x = 0; x < heightmapWidthSamples; x++)
             {
-                for (int y = 0; y < heightmapHeightSamples; y++)
+                if (x > 1 && xx < maxXX)
+                    xx++;
+                yy = 0;
+                for (uint y = 0; y < heightmapHeightSamples; y++)
                 {
-                    int xx = Util.Clip(x - 1, 0, regionsize - 1);
-                    int yy = Util.Clip(y - 1, 0, regionsize - 1);
-                    
-                    
-                    float val= heightMap[yy * (int)Constants.RegionSize + xx];
-                     _heightmap[x * ((int)Constants.RegionSize + 2) + y] = val;
-                    
-                    hfmin = (val < hfmin) ? val : hfmin;
-                    hfmax = (val > hfmax) ? val : hfmax;
+                    if (y > 1 && y < maxYY)
+                        yy += regionsizeX;
+
+                    val = heightMap[yy + xx];
+                    if (val < 0.0f)
+                        val = 0.0f;
+                    _heightmap[xt + y] = val;
+
+                    if (hfmin > val)
+                        hfmin = val;
+                    if (hfmax < val)
+                        hfmax = val;
                 }
+                xt += heightmapHeightSamples;
             }
 
             lock (OdeLock)
@@ -3963,9 +4006,10 @@ namespace OpenSim.Region.PhysicsModule.ODE
 
                 }
                 IntPtr HeightmapData = d.GeomHeightfieldDataCreate();
-                d.GeomHeightfieldDataBuildSingle(HeightmapData, _heightmap, 0, heightmapWidth + 1, heightmapHeight + 1,
-                                                 (int)heightmapWidthSamples + 1, (int)heightmapHeightSamples + 1, scale,
+                d.GeomHeightfieldDataBuildSingle(HeightmapData, _heightmap, 0, heightmapWidth, heightmapHeight,
+                                                 (int)heightmapWidthSamples, (int)heightmapHeightSamples, scale,
                                                  offset, thickness, wrap);
+
                 d.GeomHeightfieldDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1);
                 GroundGeom = d.CreateHeightfield(space, HeightmapData, 1);
                 if (GroundGeom != IntPtr.Zero)
@@ -3980,17 +4024,15 @@ namespace OpenSim.Region.PhysicsModule.ODE
 
                 Quaternion q1 = Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), 1.5707f);
                 Quaternion q2 = Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), 1.5707f);
-                //Axiom.Math.Quaternion q3 = Axiom.Math.Quaternion.FromAngleAxis(3.14f, new Axiom.Math.Vector3(0, 0, 1));
 
                 q1 = q1 * q2;
-                //q1 = q1 * q3;
                 Vector3 v3;
                 float angle;
                 q1.GetAxisAngle(out v3, out angle);
 
                 d.RFromAxisAndAngle(out R, v3.X, v3.Y, v3.Z, angle);
                 d.GeomSetRotation(GroundGeom, ref R);
-                d.GeomSetPosition(GroundGeom, (pOffset.X + ((int)Constants.RegionSize * 0.5f)), (pOffset.Y + ((int)Constants.RegionSize * 0.5f)), 0);
+                d.GeomSetPosition(GroundGeom, pOffset.X + regionsizeX * 0.5f, pOffset.Y + regionsizeY * 0.5f, 0);
                 IntPtr testGround = IntPtr.Zero;
                 if (RegionTerrain.TryGetValue(pOffset, out testGround))
                 {
@@ -4015,89 +4057,31 @@ namespace OpenSim.Region.PhysicsModule.ODE
 
         public override bool SupportsCombining()
         {
-            return true;
+            return m_suportCombine;
         }
 
-//        public override void UnCombine(PhysicsScene pScene)
-//        {
-//            IntPtr localGround = IntPtr.Zero;
-////            float[] localHeightfield;
-//            bool proceed = false;
-//            List<IntPtr> geomDestroyList = new List<IntPtr>();
-//
-//            lock (OdeLock)
-//            {
-//                if (RegionTerrain.TryGetValue(Vector3.Zero, out localGround))
-//                {
-//                    foreach (IntPtr geom in TerrainHeightFieldHeights.Keys)
-//                    {
-//                        if (geom == localGround)
-//                        {
-////                            localHeightfield = TerrainHeightFieldHeights[geom];
-//                            proceed = true;
-//                        }
-//                        else
-//                        {
-//                            geomDestroyList.Add(geom);
-//                        }
-//                    }
-//
-//                    if (proceed)
-//                    {
-//                        m_worldOffset = Vector3.Zero;
-//                        WorldExtents = new Vector2((int)Constants.RegionSize, (int)Constants.RegionSize);
-//                        m_parentScene = null;
-//
-//                        foreach (IntPtr g in geomDestroyList)
-//                        {
-//                            // removingHeightField needs to be done or the garbage collector will
-//                            // collect the terrain data before we tell ODE to destroy it causing 
-//                            // memory corruption
-//                            if (TerrainHeightFieldHeights.ContainsKey(g))
-//                            {
-////                                float[] removingHeightField = TerrainHeightFieldHeights[g];
-//                                TerrainHeightFieldHeights.Remove(g);
-//
-//                                if (RegionTerrain.ContainsKey(g))
-//                                {
-//                                    RegionTerrain.Remove(g);
-//                                }
-//
-//                                d.GeomDestroy(g);
-//                                //removingHeightField = new float[0];
-//                            }
-//                        }
-//
-//                    }
-//                    else
-//                    {
-//                        m_log.Warn("[PHYSICS]: Couldn't proceed with UnCombine.  Region has inconsistant data.");
-//                    }
-//                }
-//            }
-//        }
-
         public override void SetWaterLevel(float baseheight)
         {
             waterlevel = baseheight;
-            randomizeWater(waterlevel);
+//            randomizeWater(waterlevel);
         }
 
+/*
         private void randomizeWater(float baseheight)
         {
-            const uint heightmapWidth = m_regionWidth + 2;
-            const uint heightmapHeight = m_regionHeight + 2;
-            const uint heightmapWidthSamples = m_regionWidth + 2;
-            const uint heightmapHeightSamples = m_regionHeight + 2;
-            const float scale = 1.0f;
-            const float offset = 0.0f;
-            const float thickness = 2.9f;
-            const int wrap = 0;
+            uint heightmapWidth = m_regionWidth + 2;
+            uint heightmapHeight = m_regionHeight + 2;
+            uint heightmapWidthSamples = m_regionWidth + 2;
+            uint heightmapHeightSamples = m_regionHeight + 2;
+            float scale = 1.0f;
+            float offset = 0.0f;
+            float thickness = 2.9f;
+            int wrap = 0;
 
             for (int i = 0; i < (258 * 258); i++)
             {
                 _watermap[i] = (baseheight-0.1f) + ((float)fluidRandomizer.Next(1,9) / 10f);
-               // m_log.Info((baseheight - 0.1f) + ((float)fluidRandomizer.Next(1, 9) / 10f));
+                // m_log.Info((baseheight - 0.1f) + ((float)fluidRandomizer.Next(1, 9) / 10f));
             }
 
             lock (OdeLock)
@@ -4108,8 +4092,8 @@ namespace OpenSim.Region.PhysicsModule.ODE
                 }
                 IntPtr HeightmapData = d.GeomHeightfieldDataCreate();
                 d.GeomHeightfieldDataBuildSingle(HeightmapData, _watermap, 0, heightmapWidth, heightmapHeight,
-                                                 (int)heightmapWidthSamples, (int)heightmapHeightSamples, scale,
-                                                 offset, thickness, wrap);
+                                                    (int)heightmapWidthSamples, (int)heightmapHeightSamples, scale,
+                                                    offset, thickness, wrap);
                 d.GeomHeightfieldDataSetBounds(HeightmapData, m_regionWidth, m_regionHeight);
                 WaterGeom = d.CreateHeightfield(space, HeightmapData, 1);
                 if (WaterGeom != IntPtr.Zero)
@@ -4137,7 +4121,7 @@ namespace OpenSim.Region.PhysicsModule.ODE
                 d.GeomSetPosition(WaterGeom, 128, 128, 0);
             }
         }
-
+*/
         public override void Dispose()
         {
             _worldInitialized = false;
-- 
cgit v1.1