aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/PhysicsModules/Ode/OdeScene.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/PhysicsModules/Ode/OdeScene.cs (renamed from OpenSim/Region/Physics/OdePlugin/OdeScene.cs)686
1 files changed, 240 insertions, 446 deletions
diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/PhysicsModules/Ode/OdeScene.cs
index d53bd90..8cc7f28 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
+++ b/OpenSim/Region/PhysicsModules/Ode/OdeScene.cs
@@ -25,6 +25,12 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28// changes for varsize regions
29// note that raycasts need to have limited range
30// (even in normal regions)
31// or application thread stack may just blowup
32// see RayCast(ODERayCastRequest req)
33
28//#define USE_DRAWSTUFF 34//#define USE_DRAWSTUFF
29//#define SPAM 35//#define SPAM
30 36
@@ -38,15 +44,19 @@ using System.Runtime.InteropServices;
38using System.Threading; 44using System.Threading;
39using log4net; 45using log4net;
40using Nini.Config; 46using Nini.Config;
47using Mono.Addins;
41using Ode.NET; 48using Ode.NET;
42using OpenMetaverse; 49using OpenMetaverse;
43#if USE_DRAWSTUFF 50#if USE_DRAWSTUFF
44using Drawstuff.NET; 51using Drawstuff.NET;
45#endif 52#endif
46using OpenSim.Framework; 53using OpenSim.Framework;
47using OpenSim.Region.Physics.Manager; 54using OpenSim.Region.PhysicsModules.SharedBase;
55using OpenSim.Region.Framework.Scenes;
56using OpenSim.Region.Framework.Interfaces;
57
48 58
49namespace OpenSim.Region.Physics.OdePlugin 59namespace OpenSim.Region.PhysicsModule.ODE
50{ 60{
51 public enum StatusIndicators : int 61 public enum StatusIndicators : int
52 { 62 {
@@ -101,9 +111,12 @@ namespace OpenSim.Region.Physics.OdePlugin
101 Rubber = 6 111 Rubber = 6
102 } 112 }
103 113
104 public class OdeScene : PhysicsScene 114 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ODEPhysicsScene")]
115 public class OdeScene : PhysicsScene, INonSharedRegionModule
105 { 116 {
106 private readonly ILog m_log; 117 private readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType.ToString());
118 private bool m_Enabled = false;
119
107 // private Dictionary<string, sCollisionData> m_storedCollisions = new Dictionary<string, sCollisionData>(); 120 // private Dictionary<string, sCollisionData> m_storedCollisions = new Dictionary<string, sCollisionData>();
108 121
109 /// <summary> 122 /// <summary>
@@ -263,8 +276,10 @@ namespace OpenSim.Region.Physics.OdePlugin
263 276
264 private Random fluidRandomizer = new Random(Environment.TickCount); 277 private Random fluidRandomizer = new Random(Environment.TickCount);
265 278
266 private const uint m_regionWidth = Constants.RegionSize; 279 public bool m_suportCombine = true;
267 private const uint m_regionHeight = Constants.RegionSize; 280
281 private uint m_regionWidth = Constants.RegionSize;
282 private uint m_regionHeight = Constants.RegionSize;
268 283
269 private float ODE_STEPSIZE = 0.0178f; 284 private float ODE_STEPSIZE = 0.0178f;
270 private float metersInSpace = 29.9f; 285 private float metersInSpace = 29.9f;
@@ -288,9 +303,9 @@ namespace OpenSim.Region.Physics.OdePlugin
288 private int framecount = 0; 303 private int framecount = 0;
289 //private int m_returncollisions = 10; 304 //private int m_returncollisions = 10;
290 305
291 private readonly IntPtr contactgroup; 306 private IntPtr contactgroup;
292 307
293 internal IntPtr WaterGeom; 308// internal IntPtr WaterGeom;
294 309
295 private float nmTerrainContactFriction = 255.0f; 310 private float nmTerrainContactFriction = 255.0f;
296 private float nmTerrainContactBounce = 0.1f; 311 private float nmTerrainContactBounce = 0.1f;
@@ -507,31 +522,116 @@ namespace OpenSim.Region.Physics.OdePlugin
507 public d.Vector3 xyz = new d.Vector3(128.1640f, 128.3079f, 25.7600f); 522 public d.Vector3 xyz = new d.Vector3(128.1640f, 128.3079f, 25.7600f);
508 public d.Vector3 hpr = new d.Vector3(125.5000f, -17.0000f, 0.0000f); 523 public d.Vector3 hpr = new d.Vector3(125.5000f, -17.0000f, 0.0000f);
509 524
510 // TODO: unused: private uint heightmapWidth = m_regionWidth + 1;
511 // TODO: unused: private uint heightmapHeight = m_regionHeight + 1;
512 // TODO: unused: private uint heightmapWidthSamples;
513 // TODO: unused: private uint heightmapHeightSamples;
514
515 private volatile int m_global_contactcount = 0; 525 private volatile int m_global_contactcount = 0;
516 526
517 private Vector3 m_worldOffset = Vector3.Zero; 527 private Vector3 m_worldOffset = Vector3.Zero;
518 public Vector2 WorldExtents = new Vector2((int)Constants.RegionSize, (int)Constants.RegionSize); 528 public Vector2 WorldExtents = new Vector2((int)Constants.RegionSize, (int)Constants.RegionSize);
519 private PhysicsScene m_parentScene = null; 529 private PhysicsScene m_parentScene = null;
520 530
531 float spacesPerMeterX;
532 float spacesPerMeterY;
533 int spaceGridMaxX;
534 int spaceGridMaxY;
535
521 private ODERayCastRequestManager m_rayCastManager; 536 private ODERayCastRequestManager m_rayCastManager;
522 537
538
539 #region INonSharedRegionModule
540 public string Name
541 {
542 get { return "OpenDynamicsEngine"; }
543 }
544
545 public Type ReplaceableInterface
546 {
547 get { return null; }
548 }
549
550 public void Initialise(IConfigSource source)
551 {
552 // TODO: Move this out of Startup
553 IConfig config = source.Configs["Startup"];
554 if (config != null)
555 {
556 string physics = config.GetString("physics", string.Empty);
557 if (physics == Name)
558 {
559 m_Enabled = true;
560 m_config = source;
561
562 // We do this so that OpenSimulator on Windows loads the correct native ODE library depending on whether
563 // it's running as a 32-bit process or a 64-bit one. By invoking LoadLibary here, later DLLImports
564 // will find it already loaded later on.
565 //
566 // This isn't necessary for other platforms (e.g. Mac OSX and Linux) since the DLL used can be
567 // controlled in Ode.NET.dll.config
568 if (Util.IsWindows())
569 Util.LoadArchSpecificWindowsDll("ode.dll");
570
571 // Initializing ODE only when a scene is created allows alternative ODE plugins to co-habit (according to
572 // http://opensimulator.org/mantis/view.php?id=2750).
573 d.InitODE();
574
575 }
576 }
577
578 }
579
580 public void Close()
581 {
582 }
583
584 public void AddRegion(Scene scene)
585 {
586 if (!m_Enabled)
587 return;
588
589 EngineType = Name;
590 PhysicsSceneName = EngineType + "/" + scene.RegionInfo.RegionName;
591
592 scene.RegisterModuleInterface<PhysicsScene>(this);
593 Vector3 extent = new Vector3(scene.RegionInfo.RegionSizeX, scene.RegionInfo.RegionSizeY, scene.RegionInfo.RegionSizeZ);
594 Initialise(extent);
595 InitialiseFromConfig(m_config);
596
597 // This may not be that good since terrain may not be avaiable at this point
598 base.Initialise(scene.PhysicsRequestAsset,
599 (scene.Heightmap != null ? scene.Heightmap.GetFloatsSerialised() : new float[(int)(extent.X * extent.Y)]),
600 (float)scene.RegionInfo.RegionSettings.WaterHeight);
601
602 }
603
604 public void RemoveRegion(Scene scene)
605 {
606 if (!m_Enabled)
607 return;
608 }
609
610 public void RegionLoaded(Scene scene)
611 {
612 if (!m_Enabled)
613 return;
614
615 mesher = scene.RequestModuleInterface<IMesher>();
616 if (mesher == null)
617 m_log.WarnFormat("[ODE SCENE]: No mesher in {0}. Things will not work well.", PhysicsSceneName);
618 }
619 #endregion
620
523 /// <summary> 621 /// <summary>
524 /// Initiailizes the scene 622 /// Initiailizes the scene
525 /// Sets many properties that ODE requires to be stable 623 /// Sets many properties that ODE requires to be stable
526 /// These settings need to be tweaked 'exactly' right or weird stuff happens. 624 /// These settings need to be tweaked 'exactly' right or weird stuff happens.
527 /// </summary> 625 /// </summary>
528 /// <param value="name">Name of the scene. Useful in debug messages.</param> 626 private void Initialise(Vector3 regionExtent)
529 public OdeScene(string name)
530 { 627 {
531 m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType.ToString() + "." + name); 628 WorldExtents.X = regionExtent.X;
532 629 m_regionWidth = (uint)regionExtent.X;
533 Name = name; 630 WorldExtents.Y = regionExtent.Y;
534 631 m_regionHeight = (uint)regionExtent.Y;
632
633 m_suportCombine = false;
634
535 nearCallback = near; 635 nearCallback = near;
536 triCallback = TriCallback; 636 triCallback = TriCallback;
537 triArrayCallback = TriArrayCallback; 637 triArrayCallback = TriArrayCallback;
@@ -550,7 +650,7 @@ namespace OpenSim.Region.Physics.OdePlugin
550 viewthread.Start(); 650 viewthread.Start();
551 #endif 651 #endif
552 652
553 _watermap = new float[258 * 258]; 653 // _watermap = new float[258 * 258];
554 654
555 // Zero out the prim spaces array (we split our space into smaller spaces so 655 // Zero out the prim spaces array (we split our space into smaller spaces so
556 // we can hit test less. 656 // we can hit test less.
@@ -571,12 +671,11 @@ namespace OpenSim.Region.Physics.OdePlugin
571 } 671 }
572#endif 672#endif
573 673
574 // Initialize the mesh plugin 674 // Initialize from configs
575 public override void Initialise(IMesher meshmerizer, IConfigSource config) 675 private void InitialiseFromConfig(IConfigSource config)
576 { 676 {
577 InitializeExtraStats(); 677 InitializeExtraStats();
578 678
579 mesher = meshmerizer;
580 m_config = config; 679 m_config = config;
581 // Defaults 680 // Defaults
582 681
@@ -698,7 +797,31 @@ namespace OpenSim.Region.Physics.OdePlugin
698 797
699 contacts = new d.ContactGeom[contactsPerCollision]; 798 contacts = new d.ContactGeom[contactsPerCollision];
700 799
701 staticPrimspace = new IntPtr[(int)(300 / metersInSpace), (int)(300 / metersInSpace)]; 800 spacesPerMeterX = 1.0f / metersInSpace;
801 spacesPerMeterY = 1.0f / metersInSpace;
802
803 spaceGridMaxX = (int)(WorldExtents.X * spacesPerMeterX);
804 spaceGridMaxY = (int)(WorldExtents.Y * spacesPerMeterY);
805
806 // note: limit number of spaces
807 if (spaceGridMaxX > 24)
808 {
809 spaceGridMaxX = 24;
810 spacesPerMeterX = spaceGridMaxX / WorldExtents.X;
811 }
812 if (spaceGridMaxY > 24)
813 {
814 spaceGridMaxY = 24;
815 spacesPerMeterY = spaceGridMaxY / WorldExtents.Y ;
816 }
817
818 staticPrimspace = new IntPtr[spaceGridMaxX, spaceGridMaxY];
819
820 // make this index limits
821 spaceGridMaxX--;
822 spaceGridMaxY--;
823
824
702 825
703 // Centeral contact friction and bounce 826 // Centeral contact friction and bounce
704 // ckrinke 11/10/08 Enabling soft_erp but not soft_cfm until I figure out why 827 // ckrinke 11/10/08 Enabling soft_erp but not soft_cfm until I figure out why
@@ -1817,7 +1940,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1817 } 1940 }
1818 catch (AccessViolationException) 1941 catch (AccessViolationException)
1819 { 1942 {
1820 m_log.ErrorFormat("[ODE SCENE]: Unable to space collide {0}", Name); 1943 m_log.ErrorFormat("[ODE SCENE]: Unable to space collide {0}", PhysicsSceneName);
1821 } 1944 }
1822 1945
1823 //float terrainheight = GetTerrainHeightAtXY(chr.Position.X, chr.Position.Y); 1946 //float terrainheight = GetTerrainHeightAtXY(chr.Position.X, chr.Position.Y);
@@ -1882,6 +2005,8 @@ namespace OpenSim.Region.Physics.OdePlugin
1882 2005
1883 public override void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents) 2006 public override void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents)
1884 { 2007 {
2008 if (!m_suportCombine)
2009 return;
1885 m_worldOffset = offset; 2010 m_worldOffset = offset;
1886 WorldExtents = new Vector2(extents.X, extents.Y); 2011 WorldExtents = new Vector2(extents.X, extents.Y);
1887 m_parentScene = pScene; 2012 m_parentScene = pScene;
@@ -1890,12 +2015,17 @@ namespace OpenSim.Region.Physics.OdePlugin
1890 // Recovered for use by fly height. Kitto Flora 2015 // Recovered for use by fly height. Kitto Flora
1891 internal float GetTerrainHeightAtXY(float x, float y) 2016 internal float GetTerrainHeightAtXY(float x, float y)
1892 { 2017 {
1893 int offsetX = ((int)(x / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
1894 int offsetY = ((int)(y / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
1895
1896 IntPtr heightFieldGeom = IntPtr.Zero; 2018 IntPtr heightFieldGeom = IntPtr.Zero;
2019 int offsetX = 0;
2020 int offsetY = 0;
2021
2022 if (m_suportCombine)
2023 {
2024 offsetX = ((int)(x / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
2025 offsetY = ((int)(y / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
2026 }
1897 2027
1898 if (RegionTerrain.TryGetValue(new Vector3(offsetX,offsetY,0), out heightFieldGeom)) 2028 if(RegionTerrain.TryGetValue(new Vector3(offsetX,offsetY,0), out heightFieldGeom))
1899 { 2029 {
1900 if (heightFieldGeom != IntPtr.Zero) 2030 if (heightFieldGeom != IntPtr.Zero)
1901 { 2031 {
@@ -1909,10 +2039,10 @@ namespace OpenSim.Region.Physics.OdePlugin
1909 (int)x < 0.001f || (int)y < 0.001f) 2039 (int)x < 0.001f || (int)y < 0.001f)
1910 return 0; 2040 return 0;
1911 2041
1912 x = x - offsetX; 2042 x = x - offsetX + 1f;
1913 y = y - offsetY; 2043 y = y - offsetY + 1f;
1914 2044
1915 index = (int)((int)x * ((int)Constants.RegionSize + 2) + (int)y); 2045 index = (int)((int)x * ((int)m_regionHeight +3) + (int)y);
1916 2046
1917 if (index < TerrainHeightFieldHeights[heightFieldGeom].Length) 2047 if (index < TerrainHeightFieldHeights[heightFieldGeom].Length)
1918 { 2048 {
@@ -1968,16 +2098,11 @@ namespace OpenSim.Region.Physics.OdePlugin
1968 2098
1969 #region Add/Remove Entities 2099 #region Add/Remove Entities
1970 2100
1971 public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying) 2101 public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 velocity, Vector3 size, bool isFlying)
1972 { 2102 {
1973 Vector3 pos;
1974 pos.X = position.X;
1975 pos.Y = position.Y;
1976 pos.Z = position.Z;
1977
1978 OdeCharacter newAv 2103 OdeCharacter newAv
1979 = new OdeCharacter( 2104 = new OdeCharacter(
1980 avName, this, pos, size, avPIDD, avPIDP, 2105 avName, this, position, velocity, size, avPIDD, avPIDP,
1981 avCapRadius, avStandupTensor, avDensity, 2106 avCapRadius, avStandupTensor, avDensity,
1982 avMovementDivisorWalk, avMovementDivisorRun); 2107 avMovementDivisorWalk, avMovementDivisorRun);
1983 2108
@@ -2751,16 +2876,16 @@ namespace OpenSim.Region.Physics.OdePlugin
2751 { 2876 {
2752 int[] returnint = new int[2]; 2877 int[] returnint = new int[2];
2753 2878
2754 returnint[0] = (int) (pos.X/metersInSpace); 2879 returnint[0] = (int) (pos.X * spacesPerMeterX);
2755 2880
2756 if (returnint[0] > ((int) (259f/metersInSpace))) 2881 if (returnint[0] > spaceGridMaxX)
2757 returnint[0] = ((int) (259f/metersInSpace)); 2882 returnint[0] = spaceGridMaxX;
2758 if (returnint[0] < 0) 2883 if (returnint[0] < 0)
2759 returnint[0] = 0; 2884 returnint[0] = 0;
2760 2885
2761 returnint[1] = (int) (pos.Y/metersInSpace); 2886 returnint[1] = (int)(pos.Y * spacesPerMeterY);
2762 if (returnint[1] > ((int) (259f/metersInSpace))) 2887 if (returnint[1] > spaceGridMaxY)
2763 returnint[1] = ((int) (259f/metersInSpace)); 2888 returnint[1] = spaceGridMaxY;
2764 if (returnint[1] < 0) 2889 if (returnint[1] < 0)
2765 returnint[1] = 0; 2890 returnint[1] = 0;
2766 2891
@@ -3086,7 +3211,7 @@ namespace OpenSim.Region.Physics.OdePlugin
3086 { 3211 {
3087 m_log.ErrorFormat( 3212 m_log.ErrorFormat(
3088 "[ODE SCENE]: Removing physics character {0} {1} from physics scene {2} due to defect found when moving", 3213 "[ODE SCENE]: Removing physics character {0} {1} from physics scene {2} due to defect found when moving",
3089 actor.Name, actor.LocalID, Name); 3214 actor.Name, actor.LocalID, PhysicsSceneName);
3090 3215
3091 RemoveCharacter(actor); 3216 RemoveCharacter(actor);
3092 actor.DestroyOdeStructures(); 3217 actor.DestroyOdeStructures();
@@ -3202,7 +3327,7 @@ namespace OpenSim.Region.Physics.OdePlugin
3202 { 3327 {
3203 m_log.ErrorFormat( 3328 m_log.ErrorFormat(
3204 "[ODE SCENE]: Removing physics character {0} {1} from physics scene {2} due to defect found when updating position and velocity", 3329 "[ODE SCENE]: Removing physics character {0} {1} from physics scene {2} due to defect found when updating position and velocity",
3205 actor.Name, actor.LocalID, Name); 3330 actor.Name, actor.LocalID, PhysicsSceneName);
3206 3331
3207 RemoveCharacter(actor); 3332 RemoveCharacter(actor);
3208 actor.DestroyOdeStructures(); 3333 actor.DestroyOdeStructures();
@@ -3514,273 +3639,6 @@ namespace OpenSim.Region.Physics.OdePlugin
3514 get { return false; } 3639 get { return false; }
3515 } 3640 }
3516 3641
3517 #region ODE Specific Terrain Fixes
3518 private float[] ResizeTerrain512NearestNeighbour(float[] heightMap)
3519 {
3520 float[] returnarr = new float[262144];
3521 float[,] resultarr = new float[(int)WorldExtents.X, (int)WorldExtents.Y];
3522
3523 // Filling out the array into its multi-dimensional components
3524 for (int y = 0; y < WorldExtents.Y; y++)
3525 {
3526 for (int x = 0; x < WorldExtents.X; x++)
3527 {
3528 resultarr[y, x] = heightMap[y * (int)WorldExtents.Y + x];
3529 }
3530 }
3531
3532 // Resize using Nearest Neighbour
3533
3534 // This particular way is quick but it only works on a multiple of the original
3535
3536 // The idea behind this method can be described with the following diagrams
3537 // second pass and third pass happen in the same loop really.. just separated
3538 // them to show what this does.
3539
3540 // First Pass
3541 // ResultArr:
3542 // 1,1,1,1,1,1
3543 // 1,1,1,1,1,1
3544 // 1,1,1,1,1,1
3545 // 1,1,1,1,1,1
3546 // 1,1,1,1,1,1
3547 // 1,1,1,1,1,1
3548
3549 // Second Pass
3550 // ResultArr2:
3551 // 1,,1,,1,,1,,1,,1,
3552 // ,,,,,,,,,,
3553 // 1,,1,,1,,1,,1,,1,
3554 // ,,,,,,,,,,
3555 // 1,,1,,1,,1,,1,,1,
3556 // ,,,,,,,,,,
3557 // 1,,1,,1,,1,,1,,1,
3558 // ,,,,,,,,,,
3559 // 1,,1,,1,,1,,1,,1,
3560 // ,,,,,,,,,,
3561 // 1,,1,,1,,1,,1,,1,
3562
3563 // Third pass fills in the blanks
3564 // ResultArr2:
3565 // 1,1,1,1,1,1,1,1,1,1,1,1
3566 // 1,1,1,1,1,1,1,1,1,1,1,1
3567 // 1,1,1,1,1,1,1,1,1,1,1,1
3568 // 1,1,1,1,1,1,1,1,1,1,1,1
3569 // 1,1,1,1,1,1,1,1,1,1,1,1
3570 // 1,1,1,1,1,1,1,1,1,1,1,1
3571 // 1,1,1,1,1,1,1,1,1,1,1,1
3572 // 1,1,1,1,1,1,1,1,1,1,1,1
3573 // 1,1,1,1,1,1,1,1,1,1,1,1
3574 // 1,1,1,1,1,1,1,1,1,1,1,1
3575 // 1,1,1,1,1,1,1,1,1,1,1,1
3576
3577 // X,Y = .
3578 // X+1,y = ^
3579 // X,Y+1 = *
3580 // X+1,Y+1 = #
3581
3582 // Filling in like this;
3583 // .*
3584 // ^#
3585 // 1st .
3586 // 2nd *
3587 // 3rd ^
3588 // 4th #
3589 // on single loop.
3590
3591 float[,] resultarr2 = new float[512, 512];
3592 for (int y = 0; y < WorldExtents.Y; y++)
3593 {
3594 for (int x = 0; x < WorldExtents.X; x++)
3595 {
3596 resultarr2[y * 2, x * 2] = resultarr[y, x];
3597
3598 if (y < WorldExtents.Y)
3599 {
3600 resultarr2[(y * 2) + 1, x * 2] = resultarr[y, x];
3601 }
3602 if (x < WorldExtents.X)
3603 {
3604 resultarr2[y * 2, (x * 2) + 1] = resultarr[y, x];
3605 }
3606 if (x < WorldExtents.X && y < WorldExtents.Y)
3607 {
3608 resultarr2[(y * 2) + 1, (x * 2) + 1] = resultarr[y, x];
3609 }
3610 }
3611 }
3612
3613 //Flatten out the array
3614 int i = 0;
3615 for (int y = 0; y < 512; y++)
3616 {
3617 for (int x = 0; x < 512; x++)
3618 {
3619 if (resultarr2[y, x] <= 0)
3620 returnarr[i] = 0.0000001f;
3621 else
3622 returnarr[i] = resultarr2[y, x];
3623
3624 i++;
3625 }
3626 }
3627
3628 return returnarr;
3629 }
3630
3631 private float[] ResizeTerrain512Interpolation(float[] heightMap)
3632 {
3633 float[] returnarr = new float[262144];
3634 float[,] resultarr = new float[512,512];
3635
3636 // Filling out the array into its multi-dimensional components
3637 for (int y = 0; y < 256; y++)
3638 {
3639 for (int x = 0; x < 256; x++)
3640 {
3641 resultarr[y, x] = heightMap[y * 256 + x];
3642 }
3643 }
3644
3645 // Resize using interpolation
3646
3647 // This particular way is quick but it only works on a multiple of the original
3648
3649 // The idea behind this method can be described with the following diagrams
3650 // second pass and third pass happen in the same loop really.. just separated
3651 // them to show what this does.
3652
3653 // First Pass
3654 // ResultArr:
3655 // 1,1,1,1,1,1
3656 // 1,1,1,1,1,1
3657 // 1,1,1,1,1,1
3658 // 1,1,1,1,1,1
3659 // 1,1,1,1,1,1
3660 // 1,1,1,1,1,1
3661
3662 // Second Pass
3663 // ResultArr2:
3664 // 1,,1,,1,,1,,1,,1,
3665 // ,,,,,,,,,,
3666 // 1,,1,,1,,1,,1,,1,
3667 // ,,,,,,,,,,
3668 // 1,,1,,1,,1,,1,,1,
3669 // ,,,,,,,,,,
3670 // 1,,1,,1,,1,,1,,1,
3671 // ,,,,,,,,,,
3672 // 1,,1,,1,,1,,1,,1,
3673 // ,,,,,,,,,,
3674 // 1,,1,,1,,1,,1,,1,
3675
3676 // Third pass fills in the blanks
3677 // ResultArr2:
3678 // 1,1,1,1,1,1,1,1,1,1,1,1
3679 // 1,1,1,1,1,1,1,1,1,1,1,1
3680 // 1,1,1,1,1,1,1,1,1,1,1,1
3681 // 1,1,1,1,1,1,1,1,1,1,1,1
3682 // 1,1,1,1,1,1,1,1,1,1,1,1
3683 // 1,1,1,1,1,1,1,1,1,1,1,1
3684 // 1,1,1,1,1,1,1,1,1,1,1,1
3685 // 1,1,1,1,1,1,1,1,1,1,1,1
3686 // 1,1,1,1,1,1,1,1,1,1,1,1
3687 // 1,1,1,1,1,1,1,1,1,1,1,1
3688 // 1,1,1,1,1,1,1,1,1,1,1,1
3689
3690 // X,Y = .
3691 // X+1,y = ^
3692 // X,Y+1 = *
3693 // X+1,Y+1 = #
3694
3695 // Filling in like this;
3696 // .*
3697 // ^#
3698 // 1st .
3699 // 2nd *
3700 // 3rd ^
3701 // 4th #
3702 // on single loop.
3703
3704 float[,] resultarr2 = new float[512,512];
3705 for (int y = 0; y < (int)Constants.RegionSize; y++)
3706 {
3707 for (int x = 0; x < (int)Constants.RegionSize; x++)
3708 {
3709 resultarr2[y*2, x*2] = resultarr[y, x];
3710
3711 if (y < (int)Constants.RegionSize)
3712 {
3713 if (y + 1 < (int)Constants.RegionSize)
3714 {
3715 if (x + 1 < (int)Constants.RegionSize)
3716 {
3717 resultarr2[(y*2) + 1, x*2] = ((resultarr[y, x] + resultarr[y + 1, x] +
3718 resultarr[y, x + 1] + resultarr[y + 1, x + 1])/4);
3719 }
3720 else
3721 {
3722 resultarr2[(y*2) + 1, x*2] = ((resultarr[y, x] + resultarr[y + 1, x])/2);
3723 }
3724 }
3725 else
3726 {
3727 resultarr2[(y*2) + 1, x*2] = resultarr[y, x];
3728 }
3729 }
3730 if (x < (int)Constants.RegionSize)
3731 {
3732 if (x + 1 < (int)Constants.RegionSize)
3733 {
3734 if (y + 1 < (int)Constants.RegionSize)
3735 {
3736 resultarr2[y*2, (x*2) + 1] = ((resultarr[y, x] + resultarr[y + 1, x] +
3737 resultarr[y, x + 1] + resultarr[y + 1, x + 1])/4);
3738 }
3739 else
3740 {
3741 resultarr2[y*2, (x*2) + 1] = ((resultarr[y, x] + resultarr[y, x + 1])/2);
3742 }
3743 }
3744 else
3745 {
3746 resultarr2[y*2, (x*2) + 1] = resultarr[y, x];
3747 }
3748 }
3749 if (x < (int)Constants.RegionSize && y < (int)Constants.RegionSize)
3750 {
3751 if ((x + 1 < (int)Constants.RegionSize) && (y + 1 < (int)Constants.RegionSize))
3752 {
3753 resultarr2[(y*2) + 1, (x*2) + 1] = ((resultarr[y, x] + resultarr[y + 1, x] +
3754 resultarr[y, x + 1] + resultarr[y + 1, x + 1])/4);
3755 }
3756 else
3757 {
3758 resultarr2[(y*2) + 1, (x*2) + 1] = resultarr[y, x];
3759 }
3760 }
3761 }
3762 }
3763 //Flatten out the array
3764 int i = 0;
3765 for (int y = 0; y < 512; y++)
3766 {
3767 for (int x = 0; x < 512; x++)
3768 {
3769 if (Single.IsNaN(resultarr2[y, x]) || Single.IsInfinity(resultarr2[y, x]))
3770 {
3771 m_log.Warn("[ODE SCENE]: Non finite heightfield element detected. Setting it to 0");
3772 resultarr2[y, x] = 0;
3773 }
3774 returnarr[i] = resultarr2[y, x];
3775 i++;
3776 }
3777 }
3778
3779 return returnarr;
3780 }
3781
3782 #endregion
3783
3784 public override void SetTerrain(float[] heightMap) 3642 public override void SetTerrain(float[] heightMap)
3785 { 3643 {
3786 if (m_worldOffset != Vector3.Zero && m_parentScene != null) 3644 if (m_worldOffset != Vector3.Zero && m_parentScene != null)
@@ -3799,73 +3657,67 @@ namespace OpenSim.Region.Physics.OdePlugin
3799 private void SetTerrain(float[] heightMap, Vector3 pOffset) 3657 private void SetTerrain(float[] heightMap, Vector3 pOffset)
3800 { 3658 {
3801 int startTime = Util.EnvironmentTickCount(); 3659 int startTime = Util.EnvironmentTickCount();
3802 m_log.DebugFormat("[ODE SCENE]: Setting terrain for {0} with offset {1}", Name, pOffset); 3660 m_log.DebugFormat("[ODE SCENE]: Setting terrain for {0} with offset {1}", PhysicsSceneName, pOffset);
3803 3661
3804 // this._heightmap[i] = (double)heightMap[i]; 3662
3805 // dbm (danx0r) -- creating a buffer zone of one extra sample all around
3806 //_origheightmap = heightMap;
3807
3808 float[] _heightmap; 3663 float[] _heightmap;
3809 3664
3810 // zero out a heightmap array float array (single dimension [flattened])) 3665 // ok im lasy this are just a aliases
3811 //if ((int)Constants.RegionSize == 256) 3666 uint regionsizeX = m_regionWidth;
3812 // _heightmap = new float[514 * 514]; 3667 uint regionsizeY = m_regionHeight;
3813 //else
3814 3668
3815 _heightmap = new float[(((int)Constants.RegionSize + 2) * ((int)Constants.RegionSize + 2))]; 3669 // map is rotated
3670 uint heightmapWidth = regionsizeY + 2;
3671 uint heightmapHeight = regionsizeX + 2;
3816 3672
3817 uint heightmapWidth = Constants.RegionSize + 1; 3673 uint heightmapWidthSamples = heightmapWidth + 1;
3818 uint heightmapHeight = Constants.RegionSize + 1; 3674 uint heightmapHeightSamples = heightmapHeight + 1;
3819 3675
3820 uint heightmapWidthSamples; 3676 _heightmap = new float[heightmapWidthSamples * heightmapHeightSamples];
3821 3677
3822 uint heightmapHeightSamples;
3823
3824 //if (((int)Constants.RegionSize) == 256)
3825 //{
3826 // heightmapWidthSamples = 2 * (uint)Constants.RegionSize + 2;
3827 // heightmapHeightSamples = 2 * (uint)Constants.RegionSize + 2;
3828 // heightmapWidth++;
3829 // heightmapHeight++;
3830 //}
3831 //else
3832 //{
3833
3834 heightmapWidthSamples = (uint)Constants.RegionSize + 1;
3835 heightmapHeightSamples = (uint)Constants.RegionSize + 1;
3836 //}
3837 3678
3838 const float scale = 1.0f; 3679 const float scale = 1.0f;
3839 const float offset = 0.0f; 3680 const float offset = 0.0f;
3840 const float thickness = 0.2f; 3681 const float thickness = 10f;
3841 const int wrap = 0; 3682 const int wrap = 0;
3842 3683
3843 int regionsize = (int) Constants.RegionSize + 2;
3844 //Double resolution
3845 //if (((int)Constants.RegionSize) == 256)
3846 // heightMap = ResizeTerrain512Interpolation(heightMap);
3847 3684
3685 float hfmin = float.MaxValue;
3686 float hfmax = float.MinValue;
3687 float val;
3688 uint xx;
3689 uint yy;
3848 3690
3849 // if (((int)Constants.RegionSize) == 256 && (int)Constants.RegionSize == 256) 3691 uint maxXX = regionsizeX - 1;
3850 // regionsize = 512; 3692 uint maxYY = regionsizeY - 1;
3851 3693
3852 float hfmin = 2000; 3694 // flipping map adding one margin all around so things don't fall in edges
3853 float hfmax = -2000; 3695
3854 3696 uint xt = 0;
3855 for (int x = 0; x < heightmapWidthSamples; x++) 3697 xx = 0;
3698
3699
3700 for (uint x = 0; x < heightmapWidthSamples; x++)
3856 { 3701 {
3857 for (int y = 0; y < heightmapHeightSamples; y++) 3702 if (x > 1 && xx < maxXX)
3703 xx++;
3704 yy = 0;
3705 for (uint y = 0; y < heightmapHeightSamples; y++)
3858 { 3706 {
3859 int xx = Util.Clip(x - 1, 0, regionsize - 1); 3707 if (y > 1 && y < maxYY)
3860 int yy = Util.Clip(y - 1, 0, regionsize - 1); 3708 yy += regionsizeX;
3861 3709
3862 3710 val = heightMap[yy + xx];
3863 float val= heightMap[yy * (int)Constants.RegionSize + xx]; 3711 if (val < 0.0f)
3864 _heightmap[x * ((int)Constants.RegionSize + 2) + y] = val; 3712 val = 0.0f;
3865 3713 _heightmap[xt + y] = val;
3866 hfmin = (val < hfmin) ? val : hfmin; 3714
3867 hfmax = (val > hfmax) ? val : hfmax; 3715 if (hfmin > val)
3716 hfmin = val;
3717 if (hfmax < val)
3718 hfmax = val;
3868 } 3719 }
3720 xt += heightmapHeightSamples;
3869 } 3721 }
3870 3722
3871 lock (OdeLock) 3723 lock (OdeLock)
@@ -3886,9 +3738,11 @@ namespace OpenSim.Region.Physics.OdePlugin
3886 3738
3887 } 3739 }
3888 IntPtr HeightmapData = d.GeomHeightfieldDataCreate(); 3740 IntPtr HeightmapData = d.GeomHeightfieldDataCreate();
3889 d.GeomHeightfieldDataBuildSingle(HeightmapData, _heightmap, 0, heightmapWidth + 1, heightmapHeight + 1, 3741 d.GeomHeightfieldDataBuildSingle(HeightmapData, _heightmap, 0,
3890 (int)heightmapWidthSamples + 1, (int)heightmapHeightSamples + 1, scale, 3742 heightmapWidth, heightmapHeight,
3891 offset, thickness, wrap); 3743 (int)heightmapWidthSamples, (int)heightmapHeightSamples,
3744 scale, offset, thickness, wrap);
3745
3892 d.GeomHeightfieldDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1); 3746 d.GeomHeightfieldDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1);
3893 GroundGeom = d.CreateHeightfield(space, HeightmapData, 1); 3747 GroundGeom = d.CreateHeightfield(space, HeightmapData, 1);
3894 if (GroundGeom != IntPtr.Zero) 3748 if (GroundGeom != IntPtr.Zero)
@@ -3903,17 +3757,15 @@ namespace OpenSim.Region.Physics.OdePlugin
3903 3757
3904 Quaternion q1 = Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), 1.5707f); 3758 Quaternion q1 = Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), 1.5707f);
3905 Quaternion q2 = Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), 1.5707f); 3759 Quaternion q2 = Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), 1.5707f);
3906 //Axiom.Math.Quaternion q3 = Axiom.Math.Quaternion.FromAngleAxis(3.14f, new Axiom.Math.Vector3(0, 0, 1));
3907 3760
3908 q1 = q1 * q2; 3761 q1 = q1 * q2;
3909 //q1 = q1 * q3;
3910 Vector3 v3; 3762 Vector3 v3;
3911 float angle; 3763 float angle;
3912 q1.GetAxisAngle(out v3, out angle); 3764 q1.GetAxisAngle(out v3, out angle);
3913 3765
3914 d.RFromAxisAndAngle(out R, v3.X, v3.Y, v3.Z, angle); 3766 d.RFromAxisAndAngle(out R, v3.X, v3.Y, v3.Z, angle);
3915 d.GeomSetRotation(GroundGeom, ref R); 3767 d.GeomSetRotation(GroundGeom, ref R);
3916 d.GeomSetPosition(GroundGeom, (pOffset.X + ((int)Constants.RegionSize * 0.5f)), (pOffset.Y + ((int)Constants.RegionSize * 0.5f)), 0); 3768 d.GeomSetPosition(GroundGeom, pOffset.X + regionsizeX * 0.5f, pOffset.Y + regionsizeY * 0.5f, 0f);
3917 IntPtr testGround = IntPtr.Zero; 3769 IntPtr testGround = IntPtr.Zero;
3918 if (RegionTerrain.TryGetValue(pOffset, out testGround)) 3770 if (RegionTerrain.TryGetValue(pOffset, out testGround))
3919 { 3771 {
@@ -3924,7 +3776,7 @@ namespace OpenSim.Region.Physics.OdePlugin
3924 } 3776 }
3925 3777
3926 m_log.DebugFormat( 3778 m_log.DebugFormat(
3927 "[ODE SCENE]: Setting terrain for {0} took {1}ms", Name, Util.EnvironmentTickCountSubtract(startTime)); 3779 "[ODE SCENE]: Setting terrain for {0} took {1}ms", PhysicsSceneName, Util.EnvironmentTickCountSubtract(startTime));
3928 } 3780 }
3929 3781
3930 public override void DeleteTerrain() 3782 public override void DeleteTerrain()
@@ -3938,89 +3790,31 @@ namespace OpenSim.Region.Physics.OdePlugin
3938 3790
3939 public override bool SupportsCombining() 3791 public override bool SupportsCombining()
3940 { 3792 {
3941 return true; 3793 return m_suportCombine;
3942 } 3794 }
3943 3795
3944// public override void UnCombine(PhysicsScene pScene)
3945// {
3946// IntPtr localGround = IntPtr.Zero;
3947//// float[] localHeightfield;
3948// bool proceed = false;
3949// List<IntPtr> geomDestroyList = new List<IntPtr>();
3950//
3951// lock (OdeLock)
3952// {
3953// if (RegionTerrain.TryGetValue(Vector3.Zero, out localGround))
3954// {
3955// foreach (IntPtr geom in TerrainHeightFieldHeights.Keys)
3956// {
3957// if (geom == localGround)
3958// {
3959//// localHeightfield = TerrainHeightFieldHeights[geom];
3960// proceed = true;
3961// }
3962// else
3963// {
3964// geomDestroyList.Add(geom);
3965// }
3966// }
3967//
3968// if (proceed)
3969// {
3970// m_worldOffset = Vector3.Zero;
3971// WorldExtents = new Vector2((int)Constants.RegionSize, (int)Constants.RegionSize);
3972// m_parentScene = null;
3973//
3974// foreach (IntPtr g in geomDestroyList)
3975// {
3976// // removingHeightField needs to be done or the garbage collector will
3977// // collect the terrain data before we tell ODE to destroy it causing
3978// // memory corruption
3979// if (TerrainHeightFieldHeights.ContainsKey(g))
3980// {
3981//// float[] removingHeightField = TerrainHeightFieldHeights[g];
3982// TerrainHeightFieldHeights.Remove(g);
3983//
3984// if (RegionTerrain.ContainsKey(g))
3985// {
3986// RegionTerrain.Remove(g);
3987// }
3988//
3989// d.GeomDestroy(g);
3990// //removingHeightField = new float[0];
3991// }
3992// }
3993//
3994// }
3995// else
3996// {
3997// m_log.Warn("[PHYSICS]: Couldn't proceed with UnCombine. Region has inconsistant data.");
3998// }
3999// }
4000// }
4001// }
4002
4003 public override void SetWaterLevel(float baseheight) 3796 public override void SetWaterLevel(float baseheight)
4004 { 3797 {
4005 waterlevel = baseheight; 3798 waterlevel = baseheight;
4006 randomizeWater(waterlevel); 3799// randomizeWater(waterlevel);
4007 } 3800 }
4008 3801
3802/*
4009 private void randomizeWater(float baseheight) 3803 private void randomizeWater(float baseheight)
4010 { 3804 {
4011 const uint heightmapWidth = m_regionWidth + 2; 3805 uint heightmapWidth = m_regionWidth + 2;
4012 const uint heightmapHeight = m_regionHeight + 2; 3806 uint heightmapHeight = m_regionHeight + 2;
4013 const uint heightmapWidthSamples = m_regionWidth + 2; 3807 uint heightmapWidthSamples = m_regionWidth + 2;
4014 const uint heightmapHeightSamples = m_regionHeight + 2; 3808 uint heightmapHeightSamples = m_regionHeight + 2;
4015 const float scale = 1.0f; 3809 float scale = 1.0f;
4016 const float offset = 0.0f; 3810 float offset = 0.0f;
4017 const float thickness = 2.9f; 3811 float thickness = 2.9f;
4018 const int wrap = 0; 3812 int wrap = 0;
4019 3813
4020 for (int i = 0; i < (258 * 258); i++) 3814 for (int i = 0; i < (258 * 258); i++)
4021 { 3815 {
4022 _watermap[i] = (baseheight-0.1f) + ((float)fluidRandomizer.Next(1,9) / 10f); 3816 _watermap[i] = (baseheight-0.1f) + ((float)fluidRandomizer.Next(1,9) / 10f);
4023 // m_log.Info((baseheight - 0.1f) + ((float)fluidRandomizer.Next(1, 9) / 10f)); 3817 // m_log.Info((baseheight - 0.1f) + ((float)fluidRandomizer.Next(1, 9) / 10f));
4024 } 3818 }
4025 3819
4026 lock (OdeLock) 3820 lock (OdeLock)
@@ -4031,8 +3825,8 @@ namespace OpenSim.Region.Physics.OdePlugin
4031 } 3825 }
4032 IntPtr HeightmapData = d.GeomHeightfieldDataCreate(); 3826 IntPtr HeightmapData = d.GeomHeightfieldDataCreate();
4033 d.GeomHeightfieldDataBuildSingle(HeightmapData, _watermap, 0, heightmapWidth, heightmapHeight, 3827 d.GeomHeightfieldDataBuildSingle(HeightmapData, _watermap, 0, heightmapWidth, heightmapHeight,
4034 (int)heightmapWidthSamples, (int)heightmapHeightSamples, scale, 3828 (int)heightmapWidthSamples, (int)heightmapHeightSamples, scale,
4035 offset, thickness, wrap); 3829 offset, thickness, wrap);
4036 d.GeomHeightfieldDataSetBounds(HeightmapData, m_regionWidth, m_regionHeight); 3830 d.GeomHeightfieldDataSetBounds(HeightmapData, m_regionWidth, m_regionHeight);
4037 WaterGeom = d.CreateHeightfield(space, HeightmapData, 1); 3831 WaterGeom = d.CreateHeightfield(space, HeightmapData, 1);
4038 if (WaterGeom != IntPtr.Zero) 3832 if (WaterGeom != IntPtr.Zero)
@@ -4060,7 +3854,7 @@ namespace OpenSim.Region.Physics.OdePlugin
4060 d.GeomSetPosition(WaterGeom, 128, 128, 0); 3854 d.GeomSetPosition(WaterGeom, 128, 128, 0);
4061 } 3855 }
4062 } 3856 }
4063 3857*/
4064 public override void Dispose() 3858 public override void Dispose()
4065 { 3859 {
4066 _worldInitialized = false; 3860 _worldInitialized = false;
@@ -4095,8 +3889,8 @@ namespace OpenSim.Region.Physics.OdePlugin
4095 lock (_prims) 3889 lock (_prims)
4096 { 3890 {
4097 List<OdePrim> orderedPrims = new List<OdePrim>(_prims); 3891 List<OdePrim> orderedPrims = new List<OdePrim>(_prims);
4098 orderedPrims.OrderByDescending(p => p.CollisionScore).Take(25); 3892 orderedPrims.OrderByDescending(p => p.CollisionScore);
4099 topColliders = orderedPrims.ToDictionary(p => p.LocalID, p => p.CollisionScore); 3893 topColliders = orderedPrims.Take(25).ToDictionary(p => p.LocalID, p => p.CollisionScore);
4100 3894
4101 foreach (OdePrim p in _prims) 3895 foreach (OdePrim p in _prims)
4102 p.CollisionScore = 0; 3896 p.CollisionScore = 0;