From 13b1c5dfcef6e6e74709da8d588ed48d99d560d2 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sat, 5 Sep 2015 17:50:55 +0100 Subject: [PATCH] let ode suport var size regions Signed-off-by: Diva Canto --- .../Ode/ODERayCastRequestManager.cs | 7 + OpenSim/Region/PhysicsModules/Ode/OdeScene.cs | 290 +++++++++--------- 2 files changed, 144 insertions(+), 153 deletions(-) diff --git a/OpenSim/Region/PhysicsModules/Ode/ODERayCastRequestManager.cs b/OpenSim/Region/PhysicsModules/Ode/ODERayCastRequestManager.cs index 21bfea3eff..aafc7c6a46 100644 --- a/OpenSim/Region/PhysicsModules/Ode/ODERayCastRequestManager.cs +++ b/OpenSim/Region/PhysicsModules/Ode/ODERayCastRequestManager.cs @@ -172,6 +172,13 @@ namespace OpenSim.Region.PhysicsModule.ODE /// 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 f49b0f74e8..19b957f11d 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(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. /// - 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 (RegionTerrain.TryGetValue(new Vector3(offsetX,offsetY,0), out heightFieldGeom)) + 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 (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 + // ok im lasy this are just a aliases + uint regionsizeX = m_regionWidth; + uint regionsizeY = m_regionHeight; - _heightmap = new float[(((int)Constants.RegionSize + 2) * ((int)Constants.RegionSize + 2))]; + // map is rotated + uint heightmapWidth = regionsizeY + 2; + uint heightmapHeight = regionsizeX + 2; - uint heightmapWidth = Constants.RegionSize + 1; - uint heightmapHeight = Constants.RegionSize + 1; + uint heightmapWidthSamples = heightmapWidth + 1; + uint heightmapHeightSamples = heightmapHeight + 1; - uint heightmapWidthSamples; + _heightmap = new float[heightmapWidthSamples * heightmapHeightSamples]; - uint 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; + + uint maxXX = regionsizeX - 1; + uint maxYY = regionsizeY - 1; + + // flipping map adding one margin all around so things don't fall in edges + + uint xt = 0; + xx = 0; - // if (((int)Constants.RegionSize) == 256 && (int)Constants.RegionSize == 256) - // regionsize = 512; - - float hfmin = 2000; - float hfmax = -2000; - - for (int x = 0; x < heightmapWidthSamples; x++) + 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 geomDestroyList = new List(); -// -// 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;