diff options
Diffstat (limited to 'OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs')
-rw-r--r-- | OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs | 318 |
1 files changed, 255 insertions, 63 deletions
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs index 1a6907d..3e0ccef 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs | |||
@@ -156,6 +156,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
156 | private readonly ILog m_log; | 156 | private readonly ILog m_log; |
157 | // private Dictionary<string, sCollisionData> m_storedCollisions = new Dictionary<string, sCollisionData>(); | 157 | // private Dictionary<string, sCollisionData> m_storedCollisions = new Dictionary<string, sCollisionData>(); |
158 | 158 | ||
159 | public bool OdeUbitLib = false; | ||
159 | // private int threadid = 0; | 160 | // private int threadid = 0; |
160 | private Random fluidRandomizer = new Random(Environment.TickCount); | 161 | private Random fluidRandomizer = new Random(Environment.TickCount); |
161 | 162 | ||
@@ -374,7 +375,14 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
374 | mesher = meshmerizer; | 375 | mesher = meshmerizer; |
375 | m_config = config; | 376 | m_config = config; |
376 | 377 | ||
377 | // m_log.WarnFormat("ODE configuration: {0}", d.GetConfiguration("ODE")); | 378 | string ode_config = d.GetConfiguration("ODE"); |
379 | m_log.WarnFormat("ODE configuration: {0}", ode_config); | ||
380 | |||
381 | if (ode_config.Contains("ODE_Ubit")) | ||
382 | { | ||
383 | OdeUbitLib = true; | ||
384 | } | ||
385 | |||
378 | /* | 386 | /* |
379 | if (region != null) | 387 | if (region != null) |
380 | { | 388 | { |
@@ -527,13 +535,24 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
527 | 535 | ||
528 | // sets a global contact for a joint for contactgeom , and base contact description) | 536 | // sets a global contact for a joint for contactgeom , and base contact description) |
529 | 537 | ||
530 | private IntPtr CreateContacJoint(ref d.ContactGeom contactGeom, float mu, float bounce,float cfm,float erp) | 538 | private IntPtr CreateContacJoint(ref d.ContactGeom contactGeom, float mu, float bounce, float cfm, float erpscale, float dscale) |
531 | { | 539 | { |
532 | if (GlobalContactsArray == IntPtr.Zero || m_global_contactcount >= maxContactsbeforedeath) | 540 | if (GlobalContactsArray == IntPtr.Zero || m_global_contactcount >= maxContactsbeforedeath) |
533 | return IntPtr.Zero; | 541 | return IntPtr.Zero; |
534 | 542 | ||
543 | float erp = contactGeom.depth; | ||
544 | erp *= erpscale; | ||
545 | if (erp < minERP) | ||
546 | erp = minERP; | ||
547 | else if (erp > MaxERP) | ||
548 | erp = MaxERP; | ||
549 | |||
550 | float depth = contactGeom.depth * dscale; | ||
551 | if (depth > 0.5f) | ||
552 | depth = 0.5f; | ||
553 | |||
535 | d.Contact newcontact = new d.Contact(); | 554 | d.Contact newcontact = new d.Contact(); |
536 | newcontact.geom.depth = contactGeom.depth; | 555 | newcontact.geom.depth = depth; |
537 | newcontact.geom.g1 = contactGeom.g1; | 556 | newcontact.geom.g1 = contactGeom.g1; |
538 | newcontact.geom.g2 = contactGeom.g2; | 557 | newcontact.geom.g2 = contactGeom.g2; |
539 | newcontact.geom.pos = contactGeom.pos; | 558 | newcontact.geom.pos = contactGeom.pos; |
@@ -692,6 +711,10 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
692 | float bounce = 0; | 711 | float bounce = 0; |
693 | float cfm = 0.0001f; | 712 | float cfm = 0.0001f; |
694 | float erp = 0.1f; | 713 | float erp = 0.1f; |
714 | float erpscale = 1.0f; | ||
715 | float dscale = 1.0f; | ||
716 | bool IgnoreNegSides = false; | ||
717 | |||
695 | 718 | ||
696 | ContactData contactdata1 = new ContactData(0, 0, false); | 719 | ContactData contactdata1 = new ContactData(0, 0, false); |
697 | ContactData contactdata2 = new ContactData(0, 0, false); | 720 | ContactData contactdata2 = new ContactData(0, 0, false); |
@@ -781,10 +804,14 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
781 | cfm = p1.Mass; | 804 | cfm = p1.Mass; |
782 | if (cfm > p2.Mass) | 805 | if (cfm > p2.Mass) |
783 | cfm = p2.Mass; | 806 | cfm = p2.Mass; |
784 | cfm = (float)Math.Sqrt(cfm); | 807 | dscale = 10 / cfm; |
785 | cfm *= 0.0001f; | 808 | dscale = (float)Math.Sqrt(dscale); |
786 | if (cfm > 0.8f) | 809 | if (dscale > 1.0f) |
787 | cfm = 0.8f; | 810 | dscale = 1.0f; |
811 | erpscale = cfm * 0.01f; | ||
812 | cfm = 0.0001f / cfm; | ||
813 | if (cfm > 0.01f) | ||
814 | cfm = 0.01f; | ||
788 | 815 | ||
789 | if ((Math.Abs(p2.Velocity.X - p1.Velocity.X) > 0.1f || Math.Abs(p2.Velocity.Y - p1.Velocity.Y) > 0.1f)) | 816 | if ((Math.Abs(p2.Velocity.X - p1.Velocity.X) > 0.1f || Math.Abs(p2.Velocity.Y - p1.Velocity.Y) > 0.1f)) |
790 | mu *= frictionMovementMult; | 817 | mu *= frictionMovementMult; |
@@ -801,11 +828,22 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
801 | if (Math.Abs(p1.Velocity.X) > 0.1f || Math.Abs(p1.Velocity.Y) > 0.1f) | 828 | if (Math.Abs(p1.Velocity.X) > 0.1f || Math.Abs(p1.Velocity.Y) > 0.1f) |
802 | mu *= frictionMovementMult; | 829 | mu *= frictionMovementMult; |
803 | p1.CollidingGround = true; | 830 | p1.CollidingGround = true; |
831 | |||
804 | cfm = p1.Mass; | 832 | cfm = p1.Mass; |
805 | cfm = (float)Math.Sqrt(cfm); | 833 | dscale = 10 / cfm; |
806 | cfm *= 0.0001f; | 834 | dscale = (float)Math.Sqrt(dscale); |
807 | if (cfm > 0.8f) | 835 | if (dscale > 1.0f) |
808 | cfm = 0.8f; | 836 | dscale = 1.0f; |
837 | erpscale = cfm * 0.01f; | ||
838 | cfm = 0.0001f / cfm; | ||
839 | if (cfm > 0.01f) | ||
840 | cfm = 0.01f; | ||
841 | |||
842 | if (d.GeomGetClass(g1) == d.GeomClassID.TriMeshClass) | ||
843 | { | ||
844 | if (curContact.side1 > 0) | ||
845 | IgnoreNegSides = true; | ||
846 | } | ||
809 | 847 | ||
810 | } | 848 | } |
811 | else if (name == "Water") | 849 | else if (name == "Water") |
@@ -830,11 +868,21 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
830 | p2.getContactData(ref contactdata2); | 868 | p2.getContactData(ref contactdata2); |
831 | bounce = contactdata2.bounce * TerrainBounce; | 869 | bounce = contactdata2.bounce * TerrainBounce; |
832 | mu = (float)Math.Sqrt(contactdata2.mu * TerrainFriction); | 870 | mu = (float)Math.Sqrt(contactdata2.mu * TerrainFriction); |
871 | |||
833 | cfm = p2.Mass; | 872 | cfm = p2.Mass; |
834 | cfm = (float)Math.Sqrt(cfm); | 873 | dscale = 10 / cfm; |
835 | cfm *= 0.0001f; | 874 | dscale = (float)Math.Sqrt(dscale); |
836 | if (cfm > 0.8f) | 875 | |
837 | cfm = 0.8f; | 876 | if (dscale > 1.0f) |
877 | dscale = 1.0f; | ||
878 | |||
879 | erpscale = cfm * 0.01f; | ||
880 | cfm = 0.0001f / cfm; | ||
881 | if (cfm > 0.01f) | ||
882 | cfm = 0.01f; | ||
883 | |||
884 | if (curContact.side1 > 0) // should be 2 ? | ||
885 | IgnoreNegSides = true; | ||
838 | 886 | ||
839 | if (Math.Abs(p2.Velocity.X) > 0.1f || Math.Abs(p2.Velocity.Y) > 0.1f) | 887 | if (Math.Abs(p2.Velocity.X) > 0.1f || Math.Abs(p2.Velocity.Y) > 0.1f) |
840 | mu *= frictionMovementMult; | 888 | mu *= frictionMovementMult; |
@@ -862,39 +910,45 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
862 | int i = 0; | 910 | int i = 0; |
863 | while(true) | 911 | while(true) |
864 | { | 912 | { |
865 | if (dop1foot && (p1.Position.Z - curContact.pos.Z) > (p1.Size.Z - avCapRadius) * 0.5f) | ||
866 | p1.IsColliding = true; | ||
867 | if (dop2foot && (p2.Position.Z - curContact.pos.Z) > (p2.Size.Z - avCapRadius) * 0.5f) | ||
868 | p2.IsColliding = true; | ||
869 | 913 | ||
914 | if (IgnoreNegSides && curContact.side1 < 0) | ||
915 | { | ||
916 | if (++i >= count) | ||
917 | break; | ||
870 | 918 | ||
871 | erp = curContact.depth; | 919 | if (!GetCurContactGeom(i, ref curContact)) |
872 | if (erp < minERP) | 920 | break; |
873 | erp = minERP; | 921 | } |
874 | else if (erp > MaxERP) | 922 | else |
875 | erp = MaxERP; | ||
876 | 923 | ||
877 | Joint = CreateContacJoint(ref curContact, mu, bounce,cfm,erp); | 924 | { |
878 | d.JointAttach(Joint, b1, b2); | 925 | if (dop1foot && (p1.Position.Z - curContact.pos.Z) > (p1.Size.Z - avCapRadius) * 0.5f) |
926 | p1.IsColliding = true; | ||
927 | if (dop2foot && (p2.Position.Z - curContact.pos.Z) > (p2.Size.Z - avCapRadius) * 0.5f) | ||
928 | p2.IsColliding = true; | ||
879 | 929 | ||
880 | if (++m_global_contactcount >= maxContactsbeforedeath) | 930 | Joint = CreateContacJoint(ref curContact, mu, bounce, cfm, erpscale, dscale); |
881 | break; | 931 | d.JointAttach(Joint, b1, b2); |
882 | 932 | ||
883 | if(++i >= count) | 933 | if (++m_global_contactcount >= maxContactsbeforedeath) |
884 | break; | 934 | break; |
885 | 935 | ||
886 | if (!GetCurContactGeom(i, ref curContact)) | 936 | if (++i >= count) |
887 | break; | 937 | break; |
888 | 938 | ||
889 | if (curContact.depth > maxDepthContact.PenetrationDepth) | 939 | if (!GetCurContactGeom(i, ref curContact)) |
890 | { | 940 | break; |
891 | maxDepthContact.Position.X = curContact.pos.X; | 941 | |
892 | maxDepthContact.Position.Y = curContact.pos.Y; | 942 | if (curContact.depth > maxDepthContact.PenetrationDepth) |
893 | maxDepthContact.Position.Z = curContact.pos.Z; | 943 | { |
894 | maxDepthContact.SurfaceNormal.X = curContact.normal.X; | 944 | maxDepthContact.Position.X = curContact.pos.X; |
895 | maxDepthContact.SurfaceNormal.Y = curContact.normal.Y; | 945 | maxDepthContact.Position.Y = curContact.pos.Y; |
896 | maxDepthContact.SurfaceNormal.Z = curContact.normal.Z; | 946 | maxDepthContact.Position.Z = curContact.pos.Z; |
897 | maxDepthContact.PenetrationDepth = curContact.depth; | 947 | maxDepthContact.SurfaceNormal.X = curContact.normal.X; |
948 | maxDepthContact.SurfaceNormal.Y = curContact.normal.Y; | ||
949 | maxDepthContact.SurfaceNormal.Z = curContact.normal.Z; | ||
950 | maxDepthContact.PenetrationDepth = curContact.depth; | ||
951 | } | ||
898 | } | 952 | } |
899 | } | 953 | } |
900 | 954 | ||
@@ -1865,13 +1919,12 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1865 | 1919 | ||
1866 | public float GetTerrainHeightAtXY(float x, float y) | 1920 | public float GetTerrainHeightAtXY(float x, float y) |
1867 | { | 1921 | { |
1868 | // assumes 1m size grid and constante size square regions | 1922 | |
1869 | // needs to know about sims around in future | ||
1870 | // region offset in mega position | ||
1871 | 1923 | ||
1872 | int offsetX = ((int)(x / (int)Constants.RegionSize)) * (int)Constants.RegionSize; | 1924 | int offsetX = ((int)(x / (int)Constants.RegionSize)) * (int)Constants.RegionSize; |
1873 | int offsetY = ((int)(y / (int)Constants.RegionSize)) * (int)Constants.RegionSize; | 1925 | int offsetY = ((int)(y / (int)Constants.RegionSize)) * (int)Constants.RegionSize; |
1874 | 1926 | ||
1927 | |||
1875 | IntPtr heightFieldGeom = IntPtr.Zero; | 1928 | IntPtr heightFieldGeom = IntPtr.Zero; |
1876 | 1929 | ||
1877 | // get region map | 1930 | // get region map |
@@ -1903,28 +1956,55 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1903 | 1956 | ||
1904 | int regsize = (int)Constants.RegionSize + 3; // map size see setterrain number of samples | 1957 | int regsize = (int)Constants.RegionSize + 3; // map size see setterrain number of samples |
1905 | 1958 | ||
1906 | // we still have square fixed size regions | 1959 | if (OdeUbitLib) |
1907 | // also flip x and y because of how map is done for ODE fliped axis | ||
1908 | // so ix,iy,dx and dy are inter exchanged | ||
1909 | if (x < regsize - 1) | ||
1910 | { | ||
1911 | iy = (int)x; | ||
1912 | dy = x - (float)iy; | ||
1913 | } | ||
1914 | else // out world use external height | ||
1915 | { | 1960 | { |
1916 | iy = regsize - 1; | 1961 | if (x < regsize - 1) |
1917 | dy = 0; | 1962 | { |
1918 | } | 1963 | ix = (int)x; |
1919 | if (y < regsize - 1) | 1964 | dx = x - (float)ix; |
1920 | { | 1965 | } |
1921 | ix = (int)y; | 1966 | else // out world use external height |
1922 | dx = y - (float)ix; | 1967 | { |
1968 | ix = regsize - 1; | ||
1969 | dx = 0; | ||
1970 | } | ||
1971 | if (y < regsize - 1) | ||
1972 | { | ||
1973 | iy = (int)y; | ||
1974 | dy = y - (float)iy; | ||
1975 | } | ||
1976 | else | ||
1977 | { | ||
1978 | iy = regsize - 1; | ||
1979 | dy = 0; | ||
1980 | } | ||
1923 | } | 1981 | } |
1982 | |||
1924 | else | 1983 | else |
1925 | { | 1984 | { |
1926 | ix = regsize - 1; | 1985 | // we still have square fixed size regions |
1927 | dx = 0; | 1986 | // also flip x and y because of how map is done for ODE fliped axis |
1987 | // so ix,iy,dx and dy are inter exchanged | ||
1988 | if (x < regsize - 1) | ||
1989 | { | ||
1990 | iy = (int)x; | ||
1991 | dy = x - (float)iy; | ||
1992 | } | ||
1993 | else // out world use external height | ||
1994 | { | ||
1995 | iy = regsize - 1; | ||
1996 | dy = 0; | ||
1997 | } | ||
1998 | if (y < regsize - 1) | ||
1999 | { | ||
2000 | ix = (int)y; | ||
2001 | dx = y - (float)ix; | ||
2002 | } | ||
2003 | else | ||
2004 | { | ||
2005 | ix = regsize - 1; | ||
2006 | dx = 0; | ||
2007 | } | ||
1928 | } | 2008 | } |
1929 | 2009 | ||
1930 | float h0; | 2010 | float h0; |
@@ -1951,6 +2031,8 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1951 | 2031 | ||
1952 | return h0 + h1 + h2; | 2032 | return h0 + h1 + h2; |
1953 | } | 2033 | } |
2034 | |||
2035 | |||
1954 | public override void SetTerrain(float[] heightMap) | 2036 | public override void SetTerrain(float[] heightMap) |
1955 | { | 2037 | { |
1956 | if (m_worldOffset != Vector3.Zero && m_parentScene != null) | 2038 | if (m_worldOffset != Vector3.Zero && m_parentScene != null) |
@@ -1972,7 +2054,15 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1972 | } | 2054 | } |
1973 | 2055 | ||
1974 | public void SetTerrain(float[] heightMap, Vector3 pOffset) | 2056 | public void SetTerrain(float[] heightMap, Vector3 pOffset) |
1975 | { | 2057 | { |
2058 | if (OdeUbitLib) | ||
2059 | UbitSetTerrain(heightMap, pOffset); | ||
2060 | else | ||
2061 | OriSetTerrain(heightMap, pOffset); | ||
2062 | } | ||
2063 | |||
2064 | public void OriSetTerrain(float[] heightMap, Vector3 pOffset) | ||
2065 | { | ||
1976 | // assumes 1m size grid and constante size square regions | 2066 | // assumes 1m size grid and constante size square regions |
1977 | // needs to know about sims around in future | 2067 | // needs to know about sims around in future |
1978 | 2068 | ||
@@ -2086,6 +2176,108 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
2086 | } | 2176 | } |
2087 | } | 2177 | } |
2088 | 2178 | ||
2179 | public void UbitSetTerrain(float[] heightMap, Vector3 pOffset) | ||
2180 | { | ||
2181 | // assumes 1m size grid and constante size square regions | ||
2182 | // needs to know about sims around in future | ||
2183 | |||
2184 | float[] _heightmap; | ||
2185 | |||
2186 | uint heightmapWidth = Constants.RegionSize + 2; | ||
2187 | uint heightmapHeight = Constants.RegionSize + 2; | ||
2188 | |||
2189 | uint heightmapWidthSamples = heightmapWidth + 1; | ||
2190 | uint heightmapHeightSamples = heightmapHeight + 1; | ||
2191 | |||
2192 | _heightmap = new float[heightmapWidthSamples * heightmapHeightSamples]; | ||
2193 | |||
2194 | |||
2195 | uint regionsize = Constants.RegionSize; | ||
2196 | |||
2197 | float hfmin = float.MaxValue; | ||
2198 | // float hfmax = float.MinValue; | ||
2199 | float val; | ||
2200 | |||
2201 | |||
2202 | uint maxXXYY = regionsize - 1; | ||
2203 | // adding one margin all around so things don't fall in edges | ||
2204 | |||
2205 | uint xx; | ||
2206 | uint yy = 0; | ||
2207 | uint yt = 0; | ||
2208 | |||
2209 | for (uint y = 0; y < heightmapHeightSamples; y++) | ||
2210 | { | ||
2211 | if (y > 1 && y < maxXXYY) | ||
2212 | yy += regionsize; | ||
2213 | xx = 0; | ||
2214 | for (uint x = 0; x < heightmapWidthSamples; x++) | ||
2215 | { | ||
2216 | if (x > 1 && x < maxXXYY) | ||
2217 | xx++; | ||
2218 | |||
2219 | val = heightMap[yy + xx]; | ||
2220 | if (val < 0.0f) | ||
2221 | val = 0.0f; // no neg terrain as in chode | ||
2222 | _heightmap[yt + x] = val; | ||
2223 | |||
2224 | if (hfmin > val) | ||
2225 | hfmin = val; | ||
2226 | // if (hfmax < val) | ||
2227 | // hfmax = val; | ||
2228 | } | ||
2229 | yt += heightmapWidthSamples; | ||
2230 | } | ||
2231 | lock (OdeLock) | ||
2232 | { | ||
2233 | IntPtr GroundGeom = IntPtr.Zero; | ||
2234 | if (RegionTerrain.TryGetValue(pOffset, out GroundGeom)) | ||
2235 | { | ||
2236 | RegionTerrain.Remove(pOffset); | ||
2237 | if (GroundGeom != IntPtr.Zero) | ||
2238 | { | ||
2239 | if (TerrainHeightFieldHeights.ContainsKey(GroundGeom)) | ||
2240 | { | ||
2241 | TerrainHeightFieldHeightsHandlers[GroundGeom].Free(); | ||
2242 | TerrainHeightFieldHeightsHandlers.Remove(GroundGeom); | ||
2243 | TerrainHeightFieldHeights.Remove(GroundGeom); | ||
2244 | } | ||
2245 | d.SpaceRemove(StaticSpace, GroundGeom); | ||
2246 | d.GeomDestroy(GroundGeom); | ||
2247 | } | ||
2248 | } | ||
2249 | IntPtr HeightmapData = d.GeomHeightfieldDataCreate(); | ||
2250 | |||
2251 | const int wrap = 0; | ||
2252 | float thickness = hfmin; | ||
2253 | if (thickness < 0) | ||
2254 | thickness = 1; | ||
2255 | |||
2256 | GCHandle _heightmaphandler = GCHandle.Alloc(_heightmap, GCHandleType.Pinned); | ||
2257 | |||
2258 | d.GeomUbitTerrainDataBuild(HeightmapData, _heightmaphandler.AddrOfPinnedObject(), 0, 1.0f, | ||
2259 | (int)heightmapWidthSamples, (int)heightmapHeightSamples, | ||
2260 | thickness, wrap); | ||
2261 | |||
2262 | // d.GeomUbitTerrainDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1); | ||
2263 | GroundGeom = d.CreateUbitTerrain(StaticSpace, HeightmapData, 1); | ||
2264 | if (GroundGeom != IntPtr.Zero) | ||
2265 | { | ||
2266 | d.GeomSetCategoryBits(GroundGeom, (int)(CollisionCategories.Land)); | ||
2267 | d.GeomSetCollideBits(GroundGeom, (int)(CollisionCategories.Space)); | ||
2268 | |||
2269 | } | ||
2270 | geom_name_map[GroundGeom] = "Terrain"; | ||
2271 | |||
2272 | d.GeomSetPosition(GroundGeom, pOffset.X + (float)Constants.RegionSize * 0.5f, pOffset.Y + (float)Constants.RegionSize * 0.5f, 0); | ||
2273 | RegionTerrain.Add(pOffset, GroundGeom, GroundGeom); | ||
2274 | // TerrainHeightFieldHeights.Add(GroundGeom, ODElandMap); | ||
2275 | TerrainHeightFieldHeights.Add(GroundGeom, _heightmap); | ||
2276 | TerrainHeightFieldHeightsHandlers.Add(GroundGeom, _heightmaphandler); | ||
2277 | } | ||
2278 | } | ||
2279 | |||
2280 | |||
2089 | public override void DeleteTerrain() | 2281 | public override void DeleteTerrain() |
2090 | { | 2282 | { |
2091 | } | 2283 | } |