aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics
diff options
context:
space:
mode:
authorJustin Clark-Casey (justincc)2009-11-03 19:11:09 +0000
committerJustin Clark-Casey (justincc)2009-11-03 19:11:09 +0000
commitaf0e5d097480de264e7501e7d5d35328be5640bb (patch)
tree4ca5cd796ed9618dc9134a6e5eee1f7e7912bee4 /OpenSim/Region/Physics
parentminor: remove some mono compiler warnings (diff)
parentFixed a couple of NREs in corner cases. (diff)
downloadopensim-SC_OLD-af0e5d097480de264e7501e7d5d35328be5640bb.zip
opensim-SC_OLD-af0e5d097480de264e7501e7d5d35328be5640bb.tar.gz
opensim-SC_OLD-af0e5d097480de264e7501e7d5d35328be5640bb.tar.bz2
opensim-SC_OLD-af0e5d097480de264e7501e7d5d35328be5640bb.tar.xz
Merge branch 'master' of ssh://justincc@opensimulator.org/var/git/opensim
Diffstat (limited to 'OpenSim/Region/Physics')
-rw-r--r--OpenSim/Region/Physics/Manager/PhysicsActor.cs29
-rw-r--r--OpenSim/Region/Physics/Manager/PhysicsScene.cs5
-rw-r--r--OpenSim/Region/Physics/Meshing/Meshmerizer.cs14
-rw-r--r--OpenSim/Region/Physics/Meshing/PrimMesher.cs843
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODECharacter.cs4
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODEPrim.cs4
-rw-r--r--OpenSim/Region/Physics/OdePlugin/OdePlugin.cs158
7 files changed, 139 insertions, 918 deletions
diff --git a/OpenSim/Region/Physics/Manager/PhysicsActor.cs b/OpenSim/Region/Physics/Manager/PhysicsActor.cs
index 6bfdff2..f58129d 100644
--- a/OpenSim/Region/Physics/Manager/PhysicsActor.cs
+++ b/OpenSim/Region/Physics/Manager/PhysicsActor.cs
@@ -52,6 +52,20 @@ namespace OpenSim.Region.Physics.Manager
52 , Absolute 52 , Absolute
53 } 53 }
54 54
55 public struct ContactPoint
56 {
57 public Vector3 Position;
58 public Vector3 SurfaceNormal;
59 public float PenetrationDepth;
60
61 public ContactPoint(Vector3 position, Vector3 surfaceNormal, float penetrationDepth)
62 {
63 Position = position;
64 SurfaceNormal = surfaceNormal;
65 PenetrationDepth = penetrationDepth;
66 }
67 }
68
55 public class CollisionEventUpdate : EventArgs 69 public class CollisionEventUpdate : EventArgs
56 { 70 {
57 // Raising the event on the object, so don't need to provide location.. further up the tree knows that info. 71 // Raising the event on the object, so don't need to provide location.. further up the tree knows that info.
@@ -59,9 +73,9 @@ namespace OpenSim.Region.Physics.Manager
59 public int m_colliderType; 73 public int m_colliderType;
60 public int m_GenericStartEnd; 74 public int m_GenericStartEnd;
61 //public uint m_LocalID; 75 //public uint m_LocalID;
62 public Dictionary<uint,float> m_objCollisionList = new Dictionary<uint,float>(); 76 public Dictionary<uint, ContactPoint> m_objCollisionList = new Dictionary<uint, ContactPoint>();
63 77
64 public CollisionEventUpdate(uint localID, int colliderType, int GenericStartEnd, Dictionary<uint, float> objCollisionList) 78 public CollisionEventUpdate(uint localID, int colliderType, int GenericStartEnd, Dictionary<uint, ContactPoint> objCollisionList)
65 { 79 {
66 m_colliderType = colliderType; 80 m_colliderType = colliderType;
67 m_GenericStartEnd = GenericStartEnd; 81 m_GenericStartEnd = GenericStartEnd;
@@ -72,8 +86,7 @@ namespace OpenSim.Region.Physics.Manager
72 { 86 {
73 m_colliderType = (int) ActorTypes.Unknown; 87 m_colliderType = (int) ActorTypes.Unknown;
74 m_GenericStartEnd = 1; 88 m_GenericStartEnd = 1;
75 // m_objCollisionList = null; 89 m_objCollisionList = new Dictionary<uint, ContactPoint>();
76 m_objCollisionList = new Dictionary<uint, float>();
77 } 90 }
78 91
79 public int collidertype 92 public int collidertype
@@ -88,16 +101,16 @@ namespace OpenSim.Region.Physics.Manager
88 set { m_GenericStartEnd = value; } 101 set { m_GenericStartEnd = value; }
89 } 102 }
90 103
91 public void addCollider(uint localID, float depth) 104 public void addCollider(uint localID, ContactPoint contact)
92 { 105 {
93 if (!m_objCollisionList.ContainsKey(localID)) 106 if (!m_objCollisionList.ContainsKey(localID))
94 { 107 {
95 m_objCollisionList.Add(localID, depth); 108 m_objCollisionList.Add(localID, contact);
96 } 109 }
97 else 110 else
98 { 111 {
99 if (m_objCollisionList[localID] < depth) 112 if (m_objCollisionList[localID].PenetrationDepth < contact.PenetrationDepth)
100 m_objCollisionList[localID] = depth; 113 m_objCollisionList[localID] = contact;
101 } 114 }
102 } 115 }
103 } 116 }
diff --git a/OpenSim/Region/Physics/Manager/PhysicsScene.cs b/OpenSim/Region/Physics/Manager/PhysicsScene.cs
index bb0d18e..6d515e9 100644
--- a/OpenSim/Region/Physics/Manager/PhysicsScene.cs
+++ b/OpenSim/Region/Physics/Manager/PhysicsScene.cs
@@ -75,6 +75,11 @@ namespace OpenSim.Region.Physics.Manager
75 public abstract PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, 75 public abstract PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
76 Vector3 size, Quaternion rotation, bool isPhysical); 76 Vector3 size, Quaternion rotation, bool isPhysical);
77 77
78 public virtual float TimeDilation
79 {
80 get { return 1.0f; }
81 }
82
78 public virtual bool SupportsNINJAJoints 83 public virtual bool SupportsNINJAJoints
79 { 84 {
80 get { return false; } 85 get { return false; }
diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
index fbe1949..fded95e 100644
--- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
+++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
@@ -284,9 +284,13 @@ namespace OpenSim.Region.Physics.Meshing
284 284
285 try 285 try
286 { 286 {
287 idata = CSJ2K.J2kImage.FromBytes(primShape.SculptData); 287 OpenMetaverse.Imaging.ManagedImage unusedData;
288 OpenMetaverse.Imaging.OpenJPEG.DecodeToImage(primShape.SculptData, out unusedData, out idata);
289 unusedData = null;
288 290
289 if (cacheSculptMaps) 291 //idata = CSJ2K.J2kImage.FromBytes(primShape.SculptData);
292
293 if (cacheSculptMaps && idata != null)
290 { 294 {
291 try { idata.Save(decodedSculptFileName, ImageFormat.MemoryBmp); } 295 try { idata.Save(decodedSculptFileName, ImageFormat.MemoryBmp); }
292 catch (Exception e) { m_log.Error("[SCULPT]: unable to cache sculpt map " + decodedSculptFileName + " " + e.Message); } 296 catch (Exception e) { m_log.Error("[SCULPT]: unable to cache sculpt map " + decodedSculptFileName + " " + e.Message); }
@@ -299,12 +303,12 @@ namespace OpenSim.Region.Physics.Meshing
299 } 303 }
300 catch (IndexOutOfRangeException) 304 catch (IndexOutOfRangeException)
301 { 305 {
302 m_log.Error("[PHYSICS]: OpenJpeg was unable to decode this. Physics Proxy generation failed"); 306 m_log.Error("[PHYSICS]: OpenJpeg was unable to decode this. Physics Proxy generation failed");
303 return null; 307 return null;
304 } 308 }
305 catch (Exception) 309 catch (Exception ex)
306 { 310 {
307 m_log.Error("[PHYSICS]: Unable to generate a Sculpty physics proxy. Sculpty texture decode failed!"); 311 m_log.Error("[PHYSICS]: Unable to generate a Sculpty physics proxy. Sculpty texture decode failed: " + ex.Message);
308 return null; 312 return null;
309 } 313 }
310 } 314 }
diff --git a/OpenSim/Region/Physics/Meshing/PrimMesher.cs b/OpenSim/Region/Physics/Meshing/PrimMesher.cs
index 47ce615..c7c9160 100644
--- a/OpenSim/Region/Physics/Meshing/PrimMesher.cs
+++ b/OpenSim/Region/Physics/Meshing/PrimMesher.cs
@@ -67,11 +67,6 @@ namespace PrimMesher
67 Normalize(); 67 Normalize();
68 } 68 }
69 69
70 public Quat Identity()
71 {
72 return new Quat(0.0f, 0.0f, 0.0f, 1.0f);
73 }
74
75 public float Length() 70 public float Length()
76 { 71 {
77 return (float)Math.Sqrt(X * X + Y * Y + Z * Z + W * W); 72 return (float)Math.Sqrt(X * X + Y * Y + Z * Z + W * W);
@@ -660,7 +655,7 @@ namespace PrimMesher
660 this.faceNumbers = new List<int>(); 655 this.faceNumbers = new List<int>();
661 656
662 Coord center = new Coord(0.0f, 0.0f, 0.0f); 657 Coord center = new Coord(0.0f, 0.0f, 0.0f);
663 bool hasCenter = false; 658 //bool hasCenter = false;
664 659
665 List<Coord> hollowCoords = new List<Coord>(); 660 List<Coord> hollowCoords = new List<Coord>();
666 List<Coord> hollowNormals = new List<Coord>(); 661 List<Coord> hollowNormals = new List<Coord>();
@@ -727,7 +722,7 @@ namespace PrimMesher
727 else if (!simpleFace) 722 else if (!simpleFace)
728 { 723 {
729 this.coords.Add(center); 724 this.coords.Add(center);
730 hasCenter = true; 725 //hasCenter = true;
731 if (this.calcVertexNormals) 726 if (this.calcVertexNormals)
732 this.vertexNormals.Add(new Coord(0.0f, 0.0f, 1.0f)); 727 this.vertexNormals.Add(new Coord(0.0f, 0.0f, 1.0f));
733 this.us.Add(0.0f); 728 this.us.Add(0.0f);
@@ -1541,7 +1536,7 @@ namespace PrimMesher
1541 } 1536 }
1542 1537
1543 /// <summary> 1538 /// <summary>
1544 /// Extrudes a profile along a straight line path. Used for prim types box, cylinder, and prism. 1539 /// Extrudes a profile along a path.
1545 /// </summary> 1540 /// </summary>
1546 public void Extrude(PathType pathType) 1541 public void Extrude(PathType pathType)
1547 { 1542 {
@@ -1557,7 +1552,6 @@ namespace PrimMesher
1557 if (this.calcVertexNormals) 1552 if (this.calcVertexNormals)
1558 this.normals = new List<Coord>(); 1553 this.normals = new List<Coord>();
1559 1554
1560 //int step = 0;
1561 int steps = 1; 1555 int steps = 1;
1562 1556
1563 float length = this.pathCutEnd - this.pathCutBegin; 1557 float length = this.pathCutEnd - this.pathCutBegin;
@@ -1579,20 +1573,6 @@ namespace PrimMesher
1579 if (twistTotalAbs > 0.01f) 1573 if (twistTotalAbs > 0.01f)
1580 steps += (int)(twistTotalAbs * 3.66); // dahlia's magic number 1574 steps += (int)(twistTotalAbs * 3.66); // dahlia's magic number
1581 1575
1582 //float start = -0.5f;
1583 //float stepSize = length / (float)steps;
1584 //float percentOfPathMultiplier = stepSize;
1585 //float xProfileScale = 1.0f;
1586 //float yProfileScale = 1.0f;
1587 //float xOffset = 0.0f;
1588 //float yOffset = 0.0f;
1589 //float zOffset = start;
1590 //float xOffsetStepIncrement = this.topShearX / steps;
1591 //float yOffsetStepIncrement = this.topShearY / steps;
1592
1593 //float percentOfPath = this.pathCutBegin;
1594 //zOffset += percentOfPath;
1595
1596 float hollow = this.hollow; 1576 float hollow = this.hollow;
1597 1577
1598 // sanity checks 1578 // sanity checks
@@ -1662,7 +1642,6 @@ namespace PrimMesher
1662 cut2Vert = hasHollow ? profile.numOuterVerts - 1 : profile.numOuterVerts; 1642 cut2Vert = hasHollow ? profile.numOuterVerts - 1 : profile.numOuterVerts;
1663 } 1643 }
1664 1644
1665
1666 if (initialProfileRot != 0.0f) 1645 if (initialProfileRot != 0.0f)
1667 { 1646 {
1668 profile.AddRot(new Quat(new Coord(0.0f, 0.0f, 1.0f), initialProfileRot)); 1647 profile.AddRot(new Quat(new Coord(0.0f, 0.0f, 1.0f), initialProfileRot));
@@ -1693,24 +1672,6 @@ namespace PrimMesher
1693 path.stepsPerRevolution = stepsPerRevolution; 1672 path.stepsPerRevolution = stepsPerRevolution;
1694 1673
1695 path.Create(pathType, steps); 1674 path.Create(pathType, steps);
1696 /*
1697 public int twistBegin = 0;
1698 public int twistEnd = 0;
1699 public float topShearX = 0.0f;
1700 public float topShearY = 0.0f;
1701 public float pathCutBegin = 0.0f;
1702 public float pathCutEnd = 1.0f;
1703 public float dimpleBegin = 0.0f;
1704 public float dimpleEnd = 1.0f;
1705 public float skew = 0.0f;
1706 public float holeSizeX = 1.0f; // called pathScaleX in pbs
1707 public float holeSizeY = 0.25f;
1708 public float taperX = 0.0f;
1709 public float taperY = 0.0f;
1710 public float radius = 0.0f;
1711 public float revolutions = 1.0f;
1712 public int stepsPerRevolution = 24;
1713 */
1714 1675
1715 bool needEndFaces = false; 1676 bool needEndFaces = false;
1716 if (pathType == PathType.Circular) 1677 if (pathType == PathType.Circular)
@@ -1796,7 +1757,6 @@ namespace PrimMesher
1796 int numVerts = newLayer.coords.Count; 1757 int numVerts = newLayer.coords.Count;
1797 Face newFace = new Face(); 1758 Face newFace = new Face();
1798 1759
1799 //if (step > 0)
1800 if (nodeIndex > 0) 1760 if (nodeIndex > 0)
1801 { 1761 {
1802 int startVert = coordsLen + 1; 1762 int startVert = coordsLen + 1;
@@ -1812,7 +1772,6 @@ namespace PrimMesher
1812 iNext = startVert; 1772 iNext = startVert;
1813 1773
1814 int whichVert = i - startVert; 1774 int whichVert = i - startVert;
1815 //int whichVert2 = i - lastCoordsLen;
1816 1775
1817 newFace.v1 = i; 1776 newFace.v1 = i;
1818 newFace.v2 = i - numVerts; 1777 newFace.v2 = i - numVerts;
@@ -1982,809 +1941,27 @@ namespace PrimMesher
1982 1941
1983 1942
1984 /// <summary> 1943 /// <summary>
1944 /// DEPRICATED - use Extrude(PathType.Linear) instead
1985 /// Extrudes a profile along a straight line path. Used for prim types box, cylinder, and prism. 1945 /// Extrudes a profile along a straight line path. Used for prim types box, cylinder, and prism.
1986 /// </summary> 1946 /// </summary>
1947 ///
1987 public void ExtrudeLinear() 1948 public void ExtrudeLinear()
1988 { 1949 {
1989 this.coords = new List<Coord>(); 1950 this.Extrude(PathType.Linear);
1990 this.faces = new List<Face>();
1991
1992 if (this.viewerMode)
1993 {
1994 this.viewerFaces = new List<ViewerFace>();
1995 this.calcVertexNormals = true;
1996 }
1997
1998 if (this.calcVertexNormals)
1999 this.normals = new List<Coord>();
2000
2001 int step = 0;
2002 int steps = 1;
2003
2004 float length = this.pathCutEnd - this.pathCutBegin;
2005 normalsProcessed = false;
2006
2007 if (this.viewerMode && this.sides == 3)
2008 {
2009 // prisms don't taper well so add some vertical resolution
2010 // other prims may benefit from this but just do prisms for now
2011 if (Math.Abs(this.taperX) > 0.01 || Math.Abs(this.taperY) > 0.01)
2012 steps = (int)(steps * 4.5 * length);
2013 }
2014
2015
2016 float twistBegin = this.twistBegin / 360.0f * twoPi;
2017 float twistEnd = this.twistEnd / 360.0f * twoPi;
2018 float twistTotal = twistEnd - twistBegin;
2019 float twistTotalAbs = Math.Abs(twistTotal);
2020 if (twistTotalAbs > 0.01f)
2021 steps += (int)(twistTotalAbs * 3.66); // dahlia's magic number
2022
2023 float start = -0.5f;
2024 float stepSize = length / (float)steps;
2025 float percentOfPathMultiplier = stepSize;
2026 float xProfileScale = 1.0f;
2027 float yProfileScale = 1.0f;
2028 float xOffset = 0.0f;
2029 float yOffset = 0.0f;
2030 float zOffset = start;
2031 float xOffsetStepIncrement = this.topShearX / steps;
2032 float yOffsetStepIncrement = this.topShearY / steps;
2033
2034 float percentOfPath = this.pathCutBegin;
2035 zOffset += percentOfPath;
2036
2037 float hollow = this.hollow;
2038
2039 // sanity checks
2040 float initialProfileRot = 0.0f;
2041 if (this.sides == 3)
2042 {
2043 if (this.hollowSides == 4)
2044 {
2045 if (hollow > 0.7f)
2046 hollow = 0.7f;
2047 hollow *= 0.707f;
2048 }
2049 else hollow *= 0.5f;
2050 }
2051 else if (this.sides == 4)
2052 {
2053 initialProfileRot = 1.25f * (float)Math.PI;
2054 if (this.hollowSides != 4)
2055 hollow *= 0.707f;
2056 }
2057 else if (this.sides == 24 && this.hollowSides == 4)
2058 hollow *= 1.414f;
2059
2060 Profile profile = new Profile(this.sides, this.profileStart, this.profileEnd, hollow, this.hollowSides, true, calcVertexNormals);
2061 this.errorMessage = profile.errorMessage;
2062
2063 this.numPrimFaces = profile.numPrimFaces;
2064
2065 int cut1Vert = -1;
2066 int cut2Vert = -1;
2067 if (hasProfileCut)
2068 {
2069 cut1Vert = hasHollow ? profile.coords.Count - 1 : 0;
2070 cut2Vert = hasHollow ? profile.numOuterVerts - 1 : profile.numOuterVerts;
2071 }
2072
2073 if (initialProfileRot != 0.0f)
2074 {
2075 profile.AddRot(new Quat(new Coord(0.0f, 0.0f, 1.0f), initialProfileRot));
2076 if (viewerMode)
2077 profile.MakeFaceUVs();
2078 }
2079
2080 Coord lastCutNormal1 = new Coord();
2081 Coord lastCutNormal2 = new Coord();
2082 float lastV = 1.0f;
2083
2084 bool done = false;
2085 while (!done)
2086 {
2087 Profile newLayer = profile.Copy();
2088
2089 if (this.taperX == 0.0f)
2090 xProfileScale = 1.0f;
2091 else if (this.taperX > 0.0f)
2092 xProfileScale = 1.0f - percentOfPath * this.taperX;
2093 else xProfileScale = 1.0f + (1.0f - percentOfPath) * this.taperX;
2094
2095 if (this.taperY == 0.0f)
2096 yProfileScale = 1.0f;
2097 else if (this.taperY > 0.0f)
2098 yProfileScale = 1.0f - percentOfPath * this.taperY;
2099 else yProfileScale = 1.0f + (1.0f - percentOfPath) * this.taperY;
2100
2101 if (xProfileScale != 1.0f || yProfileScale != 1.0f)
2102 newLayer.Scale(xProfileScale, yProfileScale);
2103
2104 float twist = twistBegin + twistTotal * percentOfPath;
2105 if (twist != 0.0f)
2106 newLayer.AddRot(new Quat(new Coord(0.0f, 0.0f, 1.0f), twist));
2107
2108 newLayer.AddPos(xOffset, yOffset, zOffset);
2109
2110 if (step == 0)
2111 {
2112 newLayer.FlipNormals();
2113
2114 // add the top faces to the viewerFaces list here
2115 if (this.viewerMode)
2116 {
2117 Coord faceNormal = newLayer.faceNormal;
2118 ViewerFace newViewerFace = new ViewerFace(profile.bottomFaceNumber);
2119 int numFaces = newLayer.faces.Count;
2120 List<Face> faces = newLayer.faces;
2121
2122 for (int i = 0; i < numFaces; i++)
2123 {
2124 Face face = faces[i];
2125 newViewerFace.v1 = newLayer.coords[face.v1];
2126 newViewerFace.v2 = newLayer.coords[face.v2];
2127 newViewerFace.v3 = newLayer.coords[face.v3];
2128
2129 newViewerFace.coordIndex1 = face.v1;
2130 newViewerFace.coordIndex2 = face.v2;
2131 newViewerFace.coordIndex3 = face.v3;
2132
2133 newViewerFace.n1 = faceNormal;
2134 newViewerFace.n2 = faceNormal;
2135 newViewerFace.n3 = faceNormal;
2136
2137 newViewerFace.uv1 = newLayer.faceUVs[face.v1];
2138 newViewerFace.uv2 = newLayer.faceUVs[face.v2];
2139 newViewerFace.uv3 = newLayer.faceUVs[face.v3];
2140
2141 this.viewerFaces.Add(newViewerFace);
2142 }
2143 }
2144 }
2145
2146 // append this layer
2147
2148 int coordsLen = this.coords.Count;
2149 int lastCoordsLen = coordsLen;
2150 newLayer.AddValue2FaceVertexIndices(coordsLen);
2151
2152 this.coords.AddRange(newLayer.coords);
2153
2154 if (this.calcVertexNormals)
2155 {
2156 newLayer.AddValue2FaceNormalIndices(this.normals.Count);
2157 this.normals.AddRange(newLayer.vertexNormals);
2158 }
2159
2160 if (percentOfPath < this.pathCutBegin + 0.01f || percentOfPath > this.pathCutEnd - 0.01f)
2161 this.faces.AddRange(newLayer.faces);
2162
2163 // fill faces between layers
2164
2165 int numVerts = newLayer.coords.Count;
2166 Face newFace = new Face();
2167
2168 if (step > 0)
2169 {
2170 int startVert = coordsLen + 1;
2171 int endVert = this.coords.Count;
2172
2173 if (sides < 5 || this.hasProfileCut || hollow > 0.0f)
2174 startVert--;
2175
2176 for (int i = startVert; i < endVert; i++)
2177 {
2178 int iNext = i + 1;
2179 if (i == endVert - 1)
2180 iNext = startVert;
2181
2182 int whichVert = i - startVert;
2183 //int whichVert2 = i - lastCoordsLen;
2184
2185 newFace.v1 = i;
2186 newFace.v2 = i - numVerts;
2187 newFace.v3 = iNext - numVerts;
2188 this.faces.Add(newFace);
2189
2190 newFace.v2 = iNext - numVerts;
2191 newFace.v3 = iNext;
2192 this.faces.Add(newFace);
2193
2194 if (this.viewerMode)
2195 {
2196 // add the side faces to the list of viewerFaces here
2197 //int primFaceNum = 1;
2198 //if (whichVert >= sides)
2199 // primFaceNum = 2;
2200 int primFaceNum = profile.faceNumbers[whichVert];
2201
2202 ViewerFace newViewerFace1 = new ViewerFace(primFaceNum);
2203 ViewerFace newViewerFace2 = new ViewerFace(primFaceNum);
2204
2205 float u1 = newLayer.us[whichVert];
2206 float u2 = 1.0f;
2207 if (whichVert < newLayer.us.Count - 1)
2208 u2 = newLayer.us[whichVert + 1];
2209
2210 if (whichVert == cut1Vert || whichVert == cut2Vert)
2211 {
2212 u1 = 0.0f;
2213 u2 = 1.0f;
2214 }
2215 else if (sides < 5)
2216 { // boxes and prisms have one texture face per side of the prim, so the U values have to be scaled
2217 // to reflect the entire texture width
2218 u1 *= sides;
2219 u2 *= sides;
2220 u2 -= (int)u1;
2221 u1 -= (int)u1;
2222 if (u2 < 0.1f)
2223 u2 = 1.0f;
2224
2225 //newViewerFace2.primFaceNumber = newViewerFace1.primFaceNumber = whichVert + 1;
2226 }
2227
2228 newViewerFace1.uv1.U = u1;
2229 newViewerFace1.uv2.U = u1;
2230 newViewerFace1.uv3.U = u2;
2231
2232 newViewerFace1.uv1.V = 1.0f - percentOfPath;
2233 newViewerFace1.uv2.V = lastV;
2234 newViewerFace1.uv3.V = lastV;
2235
2236 newViewerFace2.uv1.U = u1;
2237 newViewerFace2.uv2.U = u2;
2238 newViewerFace2.uv3.U = u2;
2239
2240 newViewerFace2.uv1.V = 1.0f - percentOfPath;
2241 newViewerFace2.uv2.V = lastV;
2242 newViewerFace2.uv3.V = 1.0f - percentOfPath;
2243
2244 newViewerFace1.v1 = this.coords[i];
2245 newViewerFace1.v2 = this.coords[i - numVerts];
2246 newViewerFace1.v3 = this.coords[iNext - numVerts];
2247
2248 newViewerFace2.v1 = this.coords[i];
2249 newViewerFace2.v2 = this.coords[iNext - numVerts];
2250 newViewerFace2.v3 = this.coords[iNext];
2251
2252 newViewerFace1.coordIndex1 = i;
2253 newViewerFace1.coordIndex2 = i - numVerts;
2254 newViewerFace1.coordIndex3 = iNext - numVerts;
2255
2256 newViewerFace2.coordIndex1 = i;
2257 newViewerFace2.coordIndex2 = iNext - numVerts;
2258 newViewerFace2.coordIndex3 = iNext;
2259
2260 // profile cut faces
2261 if (whichVert == cut1Vert)
2262 {
2263 newViewerFace1.n1 = newLayer.cutNormal1;
2264 newViewerFace1.n2 = newViewerFace1.n3 = lastCutNormal1;
2265
2266 newViewerFace2.n1 = newViewerFace2.n3 = newLayer.cutNormal1;
2267 newViewerFace2.n2 = lastCutNormal1;
2268 }
2269 else if (whichVert == cut2Vert)
2270 {
2271 newViewerFace1.n1 = newLayer.cutNormal2;
2272 newViewerFace1.n2 = newViewerFace1.n3 = lastCutNormal2;
2273
2274 newViewerFace2.n1 = newViewerFace2.n3 = newLayer.cutNormal2;
2275 newViewerFace2.n2 = lastCutNormal2;
2276 }
2277
2278 else // outer and hollow faces
2279 {
2280 if ((sides < 5 && whichVert < newLayer.numOuterVerts) || (hollowSides < 5 && whichVert >= newLayer.numOuterVerts))
2281 {
2282 newViewerFace1.CalcSurfaceNormal();
2283 newViewerFace2.CalcSurfaceNormal();
2284 }
2285 else
2286 {
2287 newViewerFace1.n1 = this.normals[i];
2288 newViewerFace1.n2 = this.normals[i - numVerts];
2289 newViewerFace1.n3 = this.normals[iNext - numVerts];
2290
2291 newViewerFace2.n1 = this.normals[i];
2292 newViewerFace2.n2 = this.normals[iNext - numVerts];
2293 newViewerFace2.n3 = this.normals[iNext];
2294 }
2295 }
2296
2297 //newViewerFace2.primFaceNumber = newViewerFace1.primFaceNumber = newLayer.faceNumbers[whichVert];
2298
2299 this.viewerFaces.Add(newViewerFace1);
2300 this.viewerFaces.Add(newViewerFace2);
2301
2302 }
2303 }
2304 }
2305
2306 lastCutNormal1 = newLayer.cutNormal1;
2307 lastCutNormal2 = newLayer.cutNormal2;
2308 lastV = 1.0f - percentOfPath;
2309
2310 // calc the step for the next iteration of the loop
2311
2312 if (step < steps)
2313 {
2314 step += 1;
2315 percentOfPath += percentOfPathMultiplier;
2316 xOffset += xOffsetStepIncrement;
2317 yOffset += yOffsetStepIncrement;
2318 zOffset += stepSize;
2319 if (percentOfPath > this.pathCutEnd)
2320 done = true;
2321 }
2322 else done = true;
2323
2324 if (done && viewerMode)
2325 {
2326 // add the top faces to the viewerFaces list here
2327 Coord faceNormal = newLayer.faceNormal;
2328 ViewerFace newViewerFace = new ViewerFace();
2329 newViewerFace.primFaceNumber = 0;
2330 int numFaces = newLayer.faces.Count;
2331 List<Face> faces = newLayer.faces;
2332
2333 for (int i = 0; i < numFaces; i++)
2334 {
2335 Face face = faces[i];
2336 newViewerFace.v1 = newLayer.coords[face.v1 - coordsLen];
2337 newViewerFace.v2 = newLayer.coords[face.v2 - coordsLen];
2338 newViewerFace.v3 = newLayer.coords[face.v3 - coordsLen];
2339
2340 newViewerFace.coordIndex1 = face.v1 - coordsLen;
2341 newViewerFace.coordIndex2 = face.v2 - coordsLen;
2342 newViewerFace.coordIndex3 = face.v3 - coordsLen;
2343
2344 newViewerFace.n1 = faceNormal;
2345 newViewerFace.n2 = faceNormal;
2346 newViewerFace.n3 = faceNormal;
2347
2348 newViewerFace.uv1 = newLayer.faceUVs[face.v1 - coordsLen];
2349 newViewerFace.uv2 = newLayer.faceUVs[face.v2 - coordsLen];
2350 newViewerFace.uv3 = newLayer.faceUVs[face.v3 - coordsLen];
2351
2352 this.viewerFaces.Add(newViewerFace);
2353 }
2354 }
2355 }
2356 } 1951 }
2357 1952
2358 1953
2359 /// <summary> 1954 /// <summary>
1955 /// DEPRICATED - use Extrude(PathType.Circular) instead
2360 /// Extrude a profile into a circular path prim mesh. Used for prim types torus, tube, and ring. 1956 /// Extrude a profile into a circular path prim mesh. Used for prim types torus, tube, and ring.
2361 /// </summary> 1957 /// </summary>
1958 ///
2362 public void ExtrudeCircular() 1959 public void ExtrudeCircular()
2363 { 1960 {
2364 this.coords = new List<Coord>(); 1961 this.Extrude(PathType.Circular);
2365 this.faces = new List<Face>();
2366
2367 if (this.viewerMode)
2368 {
2369 this.viewerFaces = new List<ViewerFace>();
2370 this.calcVertexNormals = true;
2371 }
2372
2373 if (this.calcVertexNormals)
2374 this.normals = new List<Coord>();
2375
2376 int step = 0;
2377 int steps = 24;
2378
2379 normalsProcessed = false;
2380
2381 float twistBegin = this.twistBegin / 360.0f * twoPi;
2382 float twistEnd = this.twistEnd / 360.0f * twoPi;
2383 float twistTotal = twistEnd - twistBegin;
2384
2385 // if the profile has a lot of twist, add more layers otherwise the layers may overlap
2386 // and the resulting mesh may be quite inaccurate. This method is arbitrary and doesn't
2387 // accurately match the viewer
2388 float twistTotalAbs = Math.Abs(twistTotal);
2389 if (twistTotalAbs > 0.01f)
2390 {
2391 if (twistTotalAbs > Math.PI * 1.5f)
2392 steps *= 2;
2393 if (twistTotalAbs > Math.PI * 3.0f)
2394 steps *= 2;
2395 }
2396
2397 float yPathScale = this.holeSizeY * 0.5f;
2398 float pathLength = this.pathCutEnd - this.pathCutBegin;
2399 float totalSkew = this.skew * 2.0f * pathLength;
2400 float skewStart = this.pathCutBegin * 2.0f * this.skew - this.skew;
2401 float xOffsetTopShearXFactor = this.topShearX * (0.25f + 0.5f * (0.5f - this.holeSizeY));
2402 float yShearCompensation = 1.0f + Math.Abs(this.topShearY) * 0.25f;
2403
2404 // It's not quite clear what pushY (Y top shear) does, but subtracting it from the start and end
2405 // angles appears to approximate it's effects on path cut. Likewise, adding it to the angle used
2406 // to calculate the sine for generating the path radius appears to approximate it's effects there
2407 // too, but there are some subtle differences in the radius which are noticeable as the prim size
2408 // increases and it may affect megaprims quite a bit. The effect of the Y top shear parameter on
2409 // the meshes generated with this technique appear nearly identical in shape to the same prims when
2410 // displayed by the viewer.
2411
2412 float startAngle = (twoPi * this.pathCutBegin * this.revolutions) - this.topShearY * 0.9f;
2413 float endAngle = (twoPi * this.pathCutEnd * this.revolutions) - this.topShearY * 0.9f;
2414 float stepSize = twoPi / this.stepsPerRevolution;
2415
2416 step = (int)(startAngle / stepSize);
2417 int firstStep = step;
2418 float angle = startAngle;
2419 float hollow = this.hollow;
2420
2421 // sanity checks
2422 float initialProfileRot = 0.0f;
2423 if (this.sides == 3)
2424 {
2425 initialProfileRot = (float)Math.PI;
2426 if (this.hollowSides == 4)
2427 {
2428 if (hollow > 0.7f)
2429 hollow = 0.7f;
2430 hollow *= 0.707f;
2431 }
2432 else hollow *= 0.5f;
2433 }
2434 else if (this.sides == 4)
2435 {
2436 initialProfileRot = 0.25f * (float)Math.PI;
2437 if (this.hollowSides != 4)
2438 hollow *= 0.707f;
2439 }
2440 else if (this.sides > 4)
2441 {
2442 initialProfileRot = (float)Math.PI;
2443 if (this.hollowSides == 4)
2444 {
2445 if (hollow > 0.7f)
2446 hollow = 0.7f;
2447 hollow /= 0.7f;
2448 }
2449 }
2450
2451 bool needEndFaces = false;
2452 if (this.pathCutBegin != 0.0f || this.pathCutEnd != 1.0f)
2453 needEndFaces = true;
2454 else if (this.taperX != 0.0f || this.taperY != 0.0f)
2455 needEndFaces = true;
2456 else if (this.skew != 0.0f)
2457 needEndFaces = true;
2458 else if (twistTotal != 0.0f)
2459 needEndFaces = true;
2460 else if (this.radius != 0.0f)
2461 needEndFaces = true;
2462
2463 Profile profile = new Profile(this.sides, this.profileStart, this.profileEnd, hollow, this.hollowSides, needEndFaces, calcVertexNormals);
2464 this.errorMessage = profile.errorMessage;
2465
2466 this.numPrimFaces = profile.numPrimFaces;
2467
2468 int cut1Vert = -1;
2469 int cut2Vert = -1;
2470 if (hasProfileCut)
2471 {
2472 cut1Vert = hasHollow ? profile.coords.Count - 1 : 0;
2473 cut2Vert = hasHollow ? profile.numOuterVerts - 1 : profile.numOuterVerts;
2474 }
2475
2476 if (initialProfileRot != 0.0f)
2477 {
2478 profile.AddRot(new Quat(new Coord(0.0f, 0.0f, 1.0f), initialProfileRot));
2479 if (viewerMode)
2480 profile.MakeFaceUVs();
2481 }
2482
2483 Coord lastCutNormal1 = new Coord();
2484 Coord lastCutNormal2 = new Coord();
2485 float lastV = 1.0f;
2486
2487 bool done = false;
2488 while (!done) // loop through the length of the path and add the layers
2489 {
2490 bool isEndLayer = false;
2491 if (angle <= startAngle + .01f || angle >= endAngle - .01f)
2492 isEndLayer = true;
2493
2494 Profile newLayer = profile.Copy();
2495
2496 float xProfileScale = (1.0f - Math.Abs(this.skew)) * this.holeSizeX;
2497 float yProfileScale = this.holeSizeY;
2498
2499 float percentOfPath = angle / (twoPi * this.revolutions);
2500 float percentOfAngles = (angle - startAngle) / (endAngle - startAngle);
2501
2502 if (this.taperX > 0.01f)
2503 xProfileScale *= 1.0f - percentOfPath * this.taperX;
2504 else if (this.taperX < -0.01f)
2505 xProfileScale *= 1.0f + (1.0f - percentOfPath) * this.taperX;
2506
2507 if (this.taperY > 0.01f)
2508 yProfileScale *= 1.0f - percentOfPath * this.taperY;
2509 else if (this.taperY < -0.01f)
2510 yProfileScale *= 1.0f + (1.0f - percentOfPath) * this.taperY;
2511
2512 if (xProfileScale != 1.0f || yProfileScale != 1.0f)
2513 newLayer.Scale(xProfileScale, yProfileScale);
2514
2515 float radiusScale = 1.0f;
2516 if (this.radius > 0.001f)
2517 radiusScale = 1.0f - this.radius * percentOfPath;
2518 else if (this.radius < 0.001f)
2519 radiusScale = 1.0f + this.radius * (1.0f - percentOfPath);
2520
2521 float twist = twistBegin + twistTotal * percentOfPath;
2522
2523 float xOffset = 0.5f * (skewStart + totalSkew * percentOfAngles);
2524 xOffset += (float)Math.Sin(angle) * xOffsetTopShearXFactor;
2525
2526 float yOffset = yShearCompensation * (float)Math.Cos(angle) * (0.5f - yPathScale) * radiusScale;
2527
2528 float zOffset = (float)Math.Sin(angle + this.topShearY) * (0.5f - yPathScale) * radiusScale;
2529
2530 // next apply twist rotation to the profile layer
2531 if (twistTotal != 0.0f || twistBegin != 0.0f)
2532 newLayer.AddRot(new Quat(new Coord(0.0f, 0.0f, 1.0f), twist));
2533
2534 // now orient the rotation of the profile layer relative to it's position on the path
2535 // adding taperY to the angle used to generate the quat appears to approximate the viewer
2536 newLayer.AddRot(new Quat(new Coord(1.0f, 0.0f, 0.0f), angle + this.topShearY));
2537 newLayer.AddPos(xOffset, yOffset, zOffset);
2538
2539 if (isEndLayer && angle <= startAngle + .01f)
2540 {
2541 newLayer.FlipNormals();
2542
2543 // add the top faces to the viewerFaces list here
2544 if (this.viewerMode && needEndFaces)
2545 {
2546 Coord faceNormal = newLayer.faceNormal;
2547 ViewerFace newViewerFace = new ViewerFace();
2548 newViewerFace.primFaceNumber = 0;
2549 foreach (Face face in newLayer.faces)
2550 {
2551 newViewerFace.v1 = newLayer.coords[face.v1];
2552 newViewerFace.v2 = newLayer.coords[face.v2];
2553 newViewerFace.v3 = newLayer.coords[face.v3];
2554
2555 newViewerFace.coordIndex1 = face.v1;
2556 newViewerFace.coordIndex2 = face.v2;
2557 newViewerFace.coordIndex3 = face.v3;
2558
2559 newViewerFace.n1 = faceNormal;
2560 newViewerFace.n2 = faceNormal;
2561 newViewerFace.n3 = faceNormal;
2562
2563 newViewerFace.uv1 = newLayer.faceUVs[face.v1];
2564 newViewerFace.uv2 = newLayer.faceUVs[face.v2];
2565 newViewerFace.uv3 = newLayer.faceUVs[face.v3];
2566
2567 this.viewerFaces.Add(newViewerFace);
2568 }
2569 }
2570 }
2571
2572 // append the layer and fill in the sides
2573
2574 int coordsLen = this.coords.Count;
2575 newLayer.AddValue2FaceVertexIndices(coordsLen);
2576
2577 this.coords.AddRange(newLayer.coords);
2578
2579 if (this.calcVertexNormals)
2580 {
2581 newLayer.AddValue2FaceNormalIndices(this.normals.Count);
2582 this.normals.AddRange(newLayer.vertexNormals);
2583 }
2584
2585 if (isEndLayer)
2586 this.faces.AddRange(newLayer.faces);
2587
2588 // fill faces between layers
2589
2590 int numVerts = newLayer.coords.Count;
2591 Face newFace = new Face();
2592 if (step > firstStep)
2593 {
2594 int startVert = coordsLen + 1;
2595 int endVert = this.coords.Count;
2596
2597 if (sides < 5 || this.hasProfileCut || hollow > 0.0f)
2598 startVert--;
2599
2600 for (int i = startVert; i < endVert; i++)
2601 {
2602 int iNext = i + 1;
2603 if (i == endVert - 1)
2604 iNext = startVert;
2605
2606 int whichVert = i - startVert;
2607
2608 newFace.v1 = i;
2609 newFace.v2 = i - numVerts;
2610 newFace.v3 = iNext - numVerts;
2611 this.faces.Add(newFace);
2612
2613 newFace.v2 = iNext - numVerts;
2614 newFace.v3 = iNext;
2615 this.faces.Add(newFace);
2616
2617 if (this.viewerMode)
2618 {
2619 int primFaceNumber = profile.faceNumbers[whichVert];
2620 if (!needEndFaces)
2621 primFaceNumber -= 1;
2622
2623 // add the side faces to the list of viewerFaces here
2624 ViewerFace newViewerFace1 = new ViewerFace(primFaceNumber);
2625 ViewerFace newViewerFace2 = new ViewerFace(primFaceNumber);
2626 float u1 = newLayer.us[whichVert];
2627 float u2 = 1.0f;
2628 if (whichVert < newLayer.us.Count - 1)
2629 u2 = newLayer.us[whichVert + 1];
2630
2631 if (whichVert == cut1Vert || whichVert == cut2Vert)
2632 {
2633 u1 = 0.0f;
2634 u2 = 1.0f;
2635 }
2636 else if (sides < 5)
2637 { // boxes and prisms have one texture face per side of the prim, so the U values have to be scaled
2638 // to reflect the entire texture width
2639 u1 *= sides;
2640 u2 *= sides;
2641 u2 -= (int)u1;
2642 u1 -= (int)u1;
2643 if (u2 < 0.1f)
2644 u2 = 1.0f;
2645
2646 //newViewerFace2.primFaceNumber = newViewerFace1.primFaceNumber = whichVert + 1;
2647 }
2648
2649 newViewerFace1.uv1.U = u1;
2650 newViewerFace1.uv2.U = u1;
2651 newViewerFace1.uv3.U = u2;
2652
2653 newViewerFace1.uv1.V = 1.0f - percentOfPath;
2654 newViewerFace1.uv2.V = lastV;
2655 newViewerFace1.uv3.V = lastV;
2656
2657 newViewerFace2.uv1.U = u1;
2658 newViewerFace2.uv2.U = u2;
2659 newViewerFace2.uv3.U = u2;
2660
2661 newViewerFace2.uv1.V = 1.0f - percentOfPath;
2662 newViewerFace2.uv2.V = lastV;
2663 newViewerFace2.uv3.V = 1.0f - percentOfPath;
2664
2665 newViewerFace1.v1 = this.coords[i];
2666 newViewerFace1.v2 = this.coords[i - numVerts];
2667 newViewerFace1.v3 = this.coords[iNext - numVerts];
2668
2669 newViewerFace2.v1 = this.coords[i];
2670 newViewerFace2.v2 = this.coords[iNext - numVerts];
2671 newViewerFace2.v3 = this.coords[iNext];
2672
2673 newViewerFace1.coordIndex1 = i;
2674 newViewerFace1.coordIndex2 = i - numVerts;
2675 newViewerFace1.coordIndex3 = iNext - numVerts;
2676
2677 newViewerFace2.coordIndex1 = i;
2678 newViewerFace2.coordIndex2 = iNext - numVerts;
2679 newViewerFace2.coordIndex3 = iNext;
2680
2681 // profile cut faces
2682 if (whichVert == cut1Vert)
2683 {
2684 newViewerFace1.n1 = newLayer.cutNormal1;
2685 newViewerFace1.n2 = newViewerFace1.n3 = lastCutNormal1;
2686
2687 newViewerFace2.n1 = newViewerFace2.n3 = newLayer.cutNormal1;
2688 newViewerFace2.n2 = lastCutNormal1;
2689 }
2690 else if (whichVert == cut2Vert)
2691 {
2692 newViewerFace1.n1 = newLayer.cutNormal2;
2693 newViewerFace1.n2 = newViewerFace1.n3 = lastCutNormal2;
2694
2695 newViewerFace2.n1 = newViewerFace2.n3 = newLayer.cutNormal2;
2696 newViewerFace2.n2 = lastCutNormal2;
2697 }
2698 else // periphery faces
2699 {
2700 if (sides < 5 && whichVert < newLayer.numOuterVerts)
2701 {
2702 newViewerFace1.n1 = this.normals[i];
2703 newViewerFace1.n2 = this.normals[i - numVerts];
2704 newViewerFace1.n3 = this.normals[i - numVerts];
2705
2706 newViewerFace2.n1 = this.normals[i];
2707 newViewerFace2.n2 = this.normals[i - numVerts];
2708 newViewerFace2.n3 = this.normals[i];
2709 }
2710 else if (hollowSides < 5 && whichVert >= newLayer.numOuterVerts)
2711 {
2712 newViewerFace1.n1 = this.normals[iNext];
2713 newViewerFace1.n2 = this.normals[iNext - numVerts];
2714 newViewerFace1.n3 = this.normals[iNext - numVerts];
2715
2716 newViewerFace2.n1 = this.normals[iNext];
2717 newViewerFace2.n2 = this.normals[iNext - numVerts];
2718 newViewerFace2.n3 = this.normals[iNext];
2719 }
2720 else
2721 {
2722 newViewerFace1.n1 = this.normals[i];
2723 newViewerFace1.n2 = this.normals[i - numVerts];
2724 newViewerFace1.n3 = this.normals[iNext - numVerts];
2725
2726 newViewerFace2.n1 = this.normals[i];
2727 newViewerFace2.n2 = this.normals[iNext - numVerts];
2728 newViewerFace2.n3 = this.normals[iNext];
2729 }
2730 }
2731
2732 //newViewerFace1.primFaceNumber = newViewerFace2.primFaceNumber = newLayer.faceNumbers[whichVert];
2733 this.viewerFaces.Add(newViewerFace1);
2734 this.viewerFaces.Add(newViewerFace2);
2735
2736 }
2737 }
2738 }
2739
2740 lastCutNormal1 = newLayer.cutNormal1;
2741 lastCutNormal2 = newLayer.cutNormal2;
2742 lastV = 1.0f - percentOfPath;
2743
2744 // calculate terms for next iteration
2745 // calculate the angle for the next iteration of the loop
2746
2747 if (angle >= endAngle - 0.01)
2748 done = true;
2749 else
2750 {
2751 step += 1;
2752 angle = stepSize * step;
2753 if (angle > endAngle)
2754 angle = endAngle;
2755 }
2756
2757 if (done && viewerMode && needEndFaces)
2758 {
2759 // add the bottom faces to the viewerFaces list here
2760 Coord faceNormal = newLayer.faceNormal;
2761 ViewerFace newViewerFace = new ViewerFace();
2762 //newViewerFace.primFaceNumber = newLayer.bottomFaceNumber + 1;
2763 newViewerFace.primFaceNumber = newLayer.bottomFaceNumber;
2764 foreach (Face face in newLayer.faces)
2765 {
2766 newViewerFace.v1 = newLayer.coords[face.v1 - coordsLen];
2767 newViewerFace.v2 = newLayer.coords[face.v2 - coordsLen];
2768 newViewerFace.v3 = newLayer.coords[face.v3 - coordsLen];
2769
2770 newViewerFace.coordIndex1 = face.v1 - coordsLen;
2771 newViewerFace.coordIndex2 = face.v2 - coordsLen;
2772 newViewerFace.coordIndex3 = face.v3 - coordsLen;
2773
2774 newViewerFace.n1 = faceNormal;
2775 newViewerFace.n2 = faceNormal;
2776 newViewerFace.n3 = faceNormal;
2777
2778 newViewerFace.uv1 = newLayer.faceUVs[face.v1 - coordsLen];
2779 newViewerFace.uv2 = newLayer.faceUVs[face.v2 - coordsLen];
2780 newViewerFace.uv3 = newLayer.faceUVs[face.v3 - coordsLen];
2781
2782 this.viewerFaces.Add(newViewerFace);
2783 }
2784 }
2785 }
2786 } 1962 }
2787 1963
1964
2788 private Coord SurfaceNormal(Coord c1, Coord c2, Coord c3) 1965 private Coord SurfaceNormal(Coord c1, Coord c2, Coord c3)
2789 { 1966 {
2790 Coord edge1 = new Coord(c2.X - c1.X, c2.Y - c1.Y, c2.Z - c1.Z); 1967 Coord edge1 = new Coord(c2.X - c1.X, c2.Y - c1.Y, c2.Z - c1.Z);
diff --git a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
index c86bc62..1bc4a25 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
@@ -1209,11 +1209,11 @@ namespace OpenSim.Region.Physics.OdePlugin
1209 m_requestedUpdateFrequency = 0; 1209 m_requestedUpdateFrequency = 0;
1210 m_eventsubscription = 0; 1210 m_eventsubscription = 0;
1211 } 1211 }
1212 public void AddCollisionEvent(uint CollidedWith, float depth) 1212 public void AddCollisionEvent(uint CollidedWith, ContactPoint contact)
1213 { 1213 {
1214 if (m_eventsubscription > 0) 1214 if (m_eventsubscription > 0)
1215 { 1215 {
1216 CollisionEventsThisFrame.addCollider(CollidedWith, depth); 1216 CollisionEventsThisFrame.addCollider(CollidedWith, contact);
1217 } 1217 }
1218 } 1218 }
1219 1219
diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
index 49bbab9..fa42023 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
@@ -2958,11 +2958,11 @@ Console.WriteLine(" JointCreateFixed");
2958 m_eventsubscription = 0; 2958 m_eventsubscription = 0;
2959 } 2959 }
2960 2960
2961 public void AddCollisionEvent(uint CollidedWith, float depth) 2961 public void AddCollisionEvent(uint CollidedWith, ContactPoint contact)
2962 { 2962 {
2963 if (CollisionEventsThisFrame == null) 2963 if (CollisionEventsThisFrame == null)
2964 CollisionEventsThisFrame = new CollisionEventUpdate(); 2964 CollisionEventsThisFrame = new CollisionEventUpdate();
2965 CollisionEventsThisFrame.addCollider(CollidedWith,depth); 2965 CollisionEventsThisFrame.addCollider(CollidedWith, contact);
2966 } 2966 }
2967 2967
2968 public void SendCollisions() 2968 public void SendCollisions()
diff --git a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
index 73ad15e..3c9a31d 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
@@ -159,6 +159,7 @@ namespace OpenSim.Region.Physics.OdePlugin
159 159
160 private float ODE_STEPSIZE = 0.020f; 160 private float ODE_STEPSIZE = 0.020f;
161 private float metersInSpace = 29.9f; 161 private float metersInSpace = 29.9f;
162 private float m_timeDilation = 1.0f;
162 163
163 public float gravityx = 0f; 164 public float gravityx = 0f;
164 public float gravityy = 0f; 165 public float gravityy = 0f;
@@ -177,8 +178,8 @@ namespace OpenSim.Region.Physics.OdePlugin
177 //private int m_returncollisions = 10; 178 //private int m_returncollisions = 10;
178 179
179 private readonly IntPtr contactgroup; 180 private readonly IntPtr contactgroup;
180 internal IntPtr LandGeom;
181 181
182 internal IntPtr LandGeom;
182 internal IntPtr WaterGeom; 183 internal IntPtr WaterGeom;
183 184
184 private float nmTerrainContactFriction = 255.0f; 185 private float nmTerrainContactFriction = 255.0f;
@@ -250,7 +251,7 @@ namespace OpenSim.Region.Physics.OdePlugin
250 private bool m_NINJA_physics_joints_enabled = false; 251 private bool m_NINJA_physics_joints_enabled = false;
251 //private Dictionary<String, IntPtr> jointpart_name_map = new Dictionary<String,IntPtr>(); 252 //private Dictionary<String, IntPtr> jointpart_name_map = new Dictionary<String,IntPtr>();
252 private readonly Dictionary<String, List<PhysicsJoint>> joints_connecting_actor = new Dictionary<String, List<PhysicsJoint>>(); 253 private readonly Dictionary<String, List<PhysicsJoint>> joints_connecting_actor = new Dictionary<String, List<PhysicsJoint>>();
253 private d.ContactGeom[] contacts = new d.ContactGeom[80]; 254 private d.ContactGeom[] contacts;
254 private readonly List<PhysicsJoint> requestedJointsToBeCreated = new List<PhysicsJoint>(); // lock only briefly. accessed by external code (to request new joints) and by OdeScene.Simulate() to move those joints into pending/active 255 private readonly List<PhysicsJoint> requestedJointsToBeCreated = new List<PhysicsJoint>(); // lock only briefly. accessed by external code (to request new joints) and by OdeScene.Simulate() to move those joints into pending/active
255 private readonly List<PhysicsJoint> pendingJoints = new List<PhysicsJoint>(); // can lock for longer. accessed only by OdeScene. 256 private readonly List<PhysicsJoint> pendingJoints = new List<PhysicsJoint>(); // can lock for longer. accessed only by OdeScene.
256 private readonly List<PhysicsJoint> activeJoints = new List<PhysicsJoint>(); // can lock for longer. accessed only by OdeScene. 257 private readonly List<PhysicsJoint> activeJoints = new List<PhysicsJoint>(); // can lock for longer. accessed only by OdeScene.
@@ -396,6 +397,8 @@ namespace OpenSim.Region.Physics.OdePlugin
396 avStandupTensor = 550000f; 397 avStandupTensor = 550000f;
397 } 398 }
398 399
400 int contactsPerCollision = 80;
401
399 if (m_config != null) 402 if (m_config != null)
400 { 403 {
401 IConfig physicsconfig = m_config.Configs["ODEPhysicsSettings"]; 404 IConfig physicsconfig = m_config.Configs["ODEPhysicsSettings"];
@@ -438,6 +441,8 @@ namespace OpenSim.Region.Physics.OdePlugin
438 avCapRadius = physicsconfig.GetFloat("av_capsule_radius", 0.37f); 441 avCapRadius = physicsconfig.GetFloat("av_capsule_radius", 0.37f);
439 avCapsuleTilted = physicsconfig.GetBoolean("av_capsule_tilted", true); 442 avCapsuleTilted = physicsconfig.GetBoolean("av_capsule_tilted", true);
440 443
444 contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", 80);
445
441 geomContactPointsStartthrottle = physicsconfig.GetInt("geom_contactpoints_start_throttling", 3); 446 geomContactPointsStartthrottle = physicsconfig.GetInt("geom_contactpoints_start_throttling", 3);
442 geomUpdatesPerThrottledUpdate = physicsconfig.GetInt("geom_updates_before_throttled_update", 15); 447 geomUpdatesPerThrottledUpdate = physicsconfig.GetInt("geom_updates_before_throttled_update", 15);
443 geomCrossingFailuresBeforeOutofbounds = physicsconfig.GetInt("geom_crossing_failures_before_outofbounds", 5); 448 geomCrossingFailuresBeforeOutofbounds = physicsconfig.GetInt("geom_crossing_failures_before_outofbounds", 5);
@@ -475,10 +480,11 @@ namespace OpenSim.Region.Physics.OdePlugin
475 480
476 m_NINJA_physics_joints_enabled = physicsconfig.GetBoolean("use_NINJA_physics_joints", false); 481 m_NINJA_physics_joints_enabled = physicsconfig.GetBoolean("use_NINJA_physics_joints", false);
477 minimumGroundFlightOffset = physicsconfig.GetFloat("minimum_ground_flight_offset", 3f); 482 minimumGroundFlightOffset = physicsconfig.GetFloat("minimum_ground_flight_offset", 3f);
478
479 } 483 }
480 } 484 }
481 485
486 contacts = new d.ContactGeom[contactsPerCollision];
487
482 staticPrimspace = new IntPtr[(int)(300 / metersInSpace), (int)(300 / metersInSpace)]; 488 staticPrimspace = new IntPtr[(int)(300 / metersInSpace), (int)(300 / metersInSpace)];
483 489
484 // Centeral contact friction and bounce 490 // Centeral contact friction and bounce
@@ -771,7 +777,9 @@ namespace OpenSim.Region.Physics.OdePlugin
771 777
772 lock (contacts) 778 lock (contacts)
773 { 779 {
774 count = d.Collide(g1, g2, contacts.GetLength(0), contacts, d.ContactGeom.SizeOf); 780 count = d.Collide(g1, g2, contacts.Length, contacts, d.ContactGeom.SizeOf);
781 if (count > contacts.Length)
782 m_log.Error("[PHYSICS]: Got " + count + " contacts when we asked for a maximum of " + contacts.Length);
775 } 783 }
776 } 784 }
777 catch (SEHException) 785 catch (SEHException)
@@ -799,7 +807,7 @@ namespace OpenSim.Region.Physics.OdePlugin
799 p2 = PANull; 807 p2 = PANull;
800 } 808 }
801 809
802 float max_collision_depth = 0f; 810 ContactPoint maxDepthContact = new ContactPoint();
803 if (p1.CollisionScore + count >= float.MaxValue) 811 if (p1.CollisionScore + count >= float.MaxValue)
804 p1.CollisionScore = 0; 812 p1.CollisionScore = 0;
805 p1.CollisionScore += count; 813 p1.CollisionScore += count;
@@ -810,9 +818,17 @@ namespace OpenSim.Region.Physics.OdePlugin
810 818
811 for (int i = 0; i < count; i++) 819 for (int i = 0; i < count; i++)
812 { 820 {
821 d.ContactGeom curContact = contacts[i];
813 822
823 if (curContact.depth > maxDepthContact.PenetrationDepth)
824 {
825 maxDepthContact = new ContactPoint(
826 new Vector3(curContact.pos.X, curContact.pos.Y, curContact.pos.Z),
827 new Vector3(curContact.normal.X, curContact.normal.Y, curContact.normal.Z),
828 curContact.depth
829 );
830 }
814 831
815 max_collision_depth = (contacts[i].depth > max_collision_depth) ? contacts[i].depth : max_collision_depth;
816 //m_log.Warn("[CCOUNT]: " + count); 832 //m_log.Warn("[CCOUNT]: " + count);
817 IntPtr joint; 833 IntPtr joint;
818 // If we're colliding with terrain, use 'TerrainContact' instead of contact. 834 // If we're colliding with terrain, use 'TerrainContact' instead of contact.
@@ -829,7 +845,7 @@ namespace OpenSim.Region.Physics.OdePlugin
829 p2.CollidingObj = true; 845 p2.CollidingObj = true;
830 break; 846 break;
831 case (int)ActorTypes.Prim: 847 case (int)ActorTypes.Prim:
832 if (p2.Velocity.X > 0 || p2.Velocity.Y > 0 || p2.Velocity.Z > 0) 848 if (p2.Velocity.LengthSquared() > 0.0f)
833 p2.CollidingObj = true; 849 p2.CollidingObj = true;
834 break; 850 break;
835 case (int)ActorTypes.Unknown: 851 case (int)ActorTypes.Unknown:
@@ -845,14 +861,14 @@ namespace OpenSim.Region.Physics.OdePlugin
845 #region InterPenetration Handling - Unintended physics explosions 861 #region InterPenetration Handling - Unintended physics explosions
846# region disabled code1 862# region disabled code1
847 863
848 if (contacts[i].depth >= 0.08f) 864 if (curContact.depth >= 0.08f)
849 { 865 {
850 //This is disabled at the moment only because it needs more tweaking 866 //This is disabled at the moment only because it needs more tweaking
851 //It will eventually be uncommented 867 //It will eventually be uncommented
852 /* 868 /*
853 if (contacts[i].depth >= 1.00f) 869 if (contact.depth >= 1.00f)
854 { 870 {
855 //m_log.Debug("[PHYSICS]: " + contacts[i].depth.ToString()); 871 //m_log.Debug("[PHYSICS]: " + contact.depth.ToString());
856 } 872 }
857 873
858 //If you interpenetrate a prim with an agent 874 //If you interpenetrate a prim with an agent
@@ -862,37 +878,37 @@ namespace OpenSim.Region.Physics.OdePlugin
862 p2.PhysicsActorType == (int) ActorTypes.Prim)) 878 p2.PhysicsActorType == (int) ActorTypes.Prim))
863 { 879 {
864 880
865 //contacts[i].depth = contacts[i].depth * 4.15f; 881 //contact.depth = contact.depth * 4.15f;
866 /* 882 /*
867 if (p2.PhysicsActorType == (int) ActorTypes.Agent) 883 if (p2.PhysicsActorType == (int) ActorTypes.Agent)
868 { 884 {
869 p2.CollidingObj = true; 885 p2.CollidingObj = true;
870 contacts[i].depth = 0.003f; 886 contact.depth = 0.003f;
871 p2.Velocity = p2.Velocity + new PhysicsVector(0, 0, 2.5f); 887 p2.Velocity = p2.Velocity + new PhysicsVector(0, 0, 2.5f);
872 OdeCharacter character = (OdeCharacter) p2; 888 OdeCharacter character = (OdeCharacter) p2;
873 character.SetPidStatus(true); 889 character.SetPidStatus(true);
874 contacts[i].pos = new d.Vector3(contacts[i].pos.X + (p1.Size.X / 2), contacts[i].pos.Y + (p1.Size.Y / 2), contacts[i].pos.Z + (p1.Size.Z / 2)); 890 contact.pos = new d.Vector3(contact.pos.X + (p1.Size.X / 2), contact.pos.Y + (p1.Size.Y / 2), contact.pos.Z + (p1.Size.Z / 2));
875 891
876 } 892 }
877 else 893 else
878 { 894 {
879 895
880 //contacts[i].depth = 0.0000000f; 896 //contact.depth = 0.0000000f;
881 } 897 }
882 if (p1.PhysicsActorType == (int) ActorTypes.Agent) 898 if (p1.PhysicsActorType == (int) ActorTypes.Agent)
883 { 899 {
884 900
885 p1.CollidingObj = true; 901 p1.CollidingObj = true;
886 contacts[i].depth = 0.003f; 902 contact.depth = 0.003f;
887 p1.Velocity = p1.Velocity + new PhysicsVector(0, 0, 2.5f); 903 p1.Velocity = p1.Velocity + new PhysicsVector(0, 0, 2.5f);
888 contacts[i].pos = new d.Vector3(contacts[i].pos.X + (p2.Size.X / 2), contacts[i].pos.Y + (p2.Size.Y / 2), contacts[i].pos.Z + (p2.Size.Z / 2)); 904 contact.pos = new d.Vector3(contact.pos.X + (p2.Size.X / 2), contact.pos.Y + (p2.Size.Y / 2), contact.pos.Z + (p2.Size.Z / 2));
889 OdeCharacter character = (OdeCharacter)p1; 905 OdeCharacter character = (OdeCharacter)p1;
890 character.SetPidStatus(true); 906 character.SetPidStatus(true);
891 } 907 }
892 else 908 else
893 { 909 {
894 910
895 //contacts[i].depth = 0.0000000f; 911 //contact.depth = 0.0000000f;
896 } 912 }
897 913
898 914
@@ -917,7 +933,7 @@ namespace OpenSim.Region.Physics.OdePlugin
917 //AddPhysicsActorTaint(p2); 933 //AddPhysicsActorTaint(p2);
918 //} 934 //}
919 935
920 //if (contacts[i].depth >= 0.25f) 936 //if (contact.depth >= 0.25f)
921 //{ 937 //{
922 // Don't collide, one or both prim will expld. 938 // Don't collide, one or both prim will expld.
923 939
@@ -935,21 +951,21 @@ namespace OpenSim.Region.Physics.OdePlugin
935 //AddPhysicsActorTaint(p2); 951 //AddPhysicsActorTaint(p2);
936 //} 952 //}
937 953
938 //contacts[i].depth = contacts[i].depth / 8f; 954 //contact.depth = contact.depth / 8f;
939 //contacts[i].normal = new d.Vector3(0, 0, 1); 955 //contact.normal = new d.Vector3(0, 0, 1);
940 //} 956 //}
941 //if (op1.m_disabled || op2.m_disabled) 957 //if (op1.m_disabled || op2.m_disabled)
942 //{ 958 //{
943 //Manually disabled objects stay disabled 959 //Manually disabled objects stay disabled
944 //contacts[i].depth = 0f; 960 //contact.depth = 0f;
945 //} 961 //}
946 #endregion 962 #endregion
947 } 963 }
948 */ 964 */
949#endregion 965#endregion
950 if (contacts[i].depth >= 1.00f) 966 if (curContact.depth >= 1.00f)
951 { 967 {
952 //m_log.Info("[P]: " + contacts[i].depth.ToString()); 968 //m_log.Info("[P]: " + contact.depth.ToString());
953 if ((p2.PhysicsActorType == (int) ActorTypes.Agent && 969 if ((p2.PhysicsActorType == (int) ActorTypes.Agent &&
954 p1.PhysicsActorType == (int) ActorTypes.Unknown) || 970 p1.PhysicsActorType == (int) ActorTypes.Unknown) ||
955 (p1.PhysicsActorType == (int) ActorTypes.Agent && 971 (p1.PhysicsActorType == (int) ActorTypes.Agent &&
@@ -962,12 +978,12 @@ namespace OpenSim.Region.Physics.OdePlugin
962 OdeCharacter character = (OdeCharacter) p2; 978 OdeCharacter character = (OdeCharacter) p2;
963 979
964 //p2.CollidingObj = true; 980 //p2.CollidingObj = true;
965 contacts[i].depth = 0.00000003f; 981 curContact.depth = 0.00000003f;
966 p2.Velocity = p2.Velocity + new Vector3(0f, 0f, 0.5f); 982 p2.Velocity = p2.Velocity + new Vector3(0f, 0f, 0.5f);
967 contacts[i].pos = 983 curContact.pos =
968 new d.Vector3(contacts[i].pos.X + (p1.Size.X/2), 984 new d.Vector3(curContact.pos.X + (p1.Size.X/2),
969 contacts[i].pos.Y + (p1.Size.Y/2), 985 curContact.pos.Y + (p1.Size.Y/2),
970 contacts[i].pos.Z + (p1.Size.Z/2)); 986 curContact.pos.Z + (p1.Size.Z/2));
971 character.SetPidStatus(true); 987 character.SetPidStatus(true);
972 } 988 }
973 } 989 }
@@ -980,12 +996,12 @@ namespace OpenSim.Region.Physics.OdePlugin
980 OdeCharacter character = (OdeCharacter) p1; 996 OdeCharacter character = (OdeCharacter) p1;
981 997
982 //p2.CollidingObj = true; 998 //p2.CollidingObj = true;
983 contacts[i].depth = 0.00000003f; 999 curContact.depth = 0.00000003f;
984 p1.Velocity = p1.Velocity + new Vector3(0f, 0f, 0.5f); 1000 p1.Velocity = p1.Velocity + new Vector3(0f, 0f, 0.5f);
985 contacts[i].pos = 1001 curContact.pos =
986 new d.Vector3(contacts[i].pos.X + (p1.Size.X/2), 1002 new d.Vector3(curContact.pos.X + (p1.Size.X/2),
987 contacts[i].pos.Y + (p1.Size.Y/2), 1003 curContact.pos.Y + (p1.Size.Y/2),
988 contacts[i].pos.Z + (p1.Size.Z/2)); 1004 curContact.pos.Z + (p1.Size.Z/2));
989 character.SetPidStatus(true); 1005 character.SetPidStatus(true);
990 } 1006 }
991 } 1007 }
@@ -1007,16 +1023,15 @@ namespace OpenSim.Region.Physics.OdePlugin
1007 if (!skipThisContact && (p2 is OdePrim) && (((OdePrim)p2).m_isVolumeDetect)) 1023 if (!skipThisContact && (p2 is OdePrim) && (((OdePrim)p2).m_isVolumeDetect))
1008 skipThisContact = true; // No collision on volume detect prims 1024 skipThisContact = true; // No collision on volume detect prims
1009 1025
1010 if (!skipThisContact && contacts[i].depth < 0f) 1026 if (!skipThisContact && curContact.depth < 0f)
1011 skipThisContact = true; 1027 skipThisContact = true;
1012 1028
1013 if (!skipThisContact && checkDupe(contacts[i], p2.PhysicsActorType)) 1029 if (!skipThisContact && checkDupe(curContact, p2.PhysicsActorType))
1014 skipThisContact = true; 1030 skipThisContact = true;
1015 1031
1016 int maxContactsbeforedeath = 4000; 1032 const int maxContactsbeforedeath = 4000;
1017 joint = IntPtr.Zero; 1033 joint = IntPtr.Zero;
1018 1034
1019
1020 if (!skipThisContact) 1035 if (!skipThisContact)
1021 { 1036 {
1022 // If we're colliding against terrain 1037 // If we're colliding against terrain
@@ -1027,8 +1042,8 @@ namespace OpenSim.Region.Physics.OdePlugin
1027 (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) 1042 (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f))
1028 { 1043 {
1029 // Use the movement terrain contact 1044 // Use the movement terrain contact
1030 AvatarMovementTerrainContact.geom = contacts[i]; 1045 AvatarMovementTerrainContact.geom = curContact;
1031 _perloopContact.Add(contacts[i]); 1046 _perloopContact.Add(curContact);
1032 if (m_global_contactcount < maxContactsbeforedeath) 1047 if (m_global_contactcount < maxContactsbeforedeath)
1033 { 1048 {
1034 joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementTerrainContact); 1049 joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementTerrainContact);
@@ -1040,8 +1055,8 @@ namespace OpenSim.Region.Physics.OdePlugin
1040 if (p2.PhysicsActorType == (int)ActorTypes.Agent) 1055 if (p2.PhysicsActorType == (int)ActorTypes.Agent)
1041 { 1056 {
1042 // Use the non moving terrain contact 1057 // Use the non moving terrain contact
1043 TerrainContact.geom = contacts[i]; 1058 TerrainContact.geom = curContact;
1044 _perloopContact.Add(contacts[i]); 1059 _perloopContact.Add(curContact);
1045 if (m_global_contactcount < maxContactsbeforedeath) 1060 if (m_global_contactcount < maxContactsbeforedeath)
1046 { 1061 {
1047 joint = d.JointCreateContact(world, contactgroup, ref TerrainContact); 1062 joint = d.JointCreateContact(world, contactgroup, ref TerrainContact);
@@ -1066,8 +1081,8 @@ namespace OpenSim.Region.Physics.OdePlugin
1066 material = ((OdePrim)p2).m_material; 1081 material = ((OdePrim)p2).m_material;
1067 1082
1068 //m_log.DebugFormat("Material: {0}", material); 1083 //m_log.DebugFormat("Material: {0}", material);
1069 m_materialContacts[material, movintYN].geom = contacts[i]; 1084 m_materialContacts[material, movintYN].geom = curContact;
1070 _perloopContact.Add(contacts[i]); 1085 _perloopContact.Add(curContact);
1071 1086
1072 if (m_global_contactcount < maxContactsbeforedeath) 1087 if (m_global_contactcount < maxContactsbeforedeath)
1073 { 1088 {
@@ -1092,8 +1107,8 @@ namespace OpenSim.Region.Physics.OdePlugin
1092 if (p2 is OdePrim) 1107 if (p2 is OdePrim)
1093 material = ((OdePrim)p2).m_material; 1108 material = ((OdePrim)p2).m_material;
1094 //m_log.DebugFormat("Material: {0}", material); 1109 //m_log.DebugFormat("Material: {0}", material);
1095 m_materialContacts[material, movintYN].geom = contacts[i]; 1110 m_materialContacts[material, movintYN].geom = curContact;
1096 _perloopContact.Add(contacts[i]); 1111 _perloopContact.Add(curContact);
1097 1112
1098 if (m_global_contactcount < maxContactsbeforedeath) 1113 if (m_global_contactcount < maxContactsbeforedeath)
1099 { 1114 {
@@ -1121,20 +1136,20 @@ namespace OpenSim.Region.Physics.OdePlugin
1121 */ 1136 */
1122 //WaterContact.surface.soft_cfm = 0.0000f; 1137 //WaterContact.surface.soft_cfm = 0.0000f;
1123 //WaterContact.surface.soft_erp = 0.00000f; 1138 //WaterContact.surface.soft_erp = 0.00000f;
1124 if (contacts[i].depth > 0.1f) 1139 if (curContact.depth > 0.1f)
1125 { 1140 {
1126 contacts[i].depth *= 52; 1141 curContact.depth *= 52;
1127 //contacts[i].normal = new d.Vector3(0, 0, 1); 1142 //contact.normal = new d.Vector3(0, 0, 1);
1128 //contacts[i].pos = new d.Vector3(0, 0, contacts[i].pos.Z - 5f); 1143 //contact.pos = new d.Vector3(0, 0, contact.pos.Z - 5f);
1129 } 1144 }
1130 WaterContact.geom = contacts[i]; 1145 WaterContact.geom = curContact;
1131 _perloopContact.Add(contacts[i]); 1146 _perloopContact.Add(curContact);
1132 if (m_global_contactcount < maxContactsbeforedeath) 1147 if (m_global_contactcount < maxContactsbeforedeath)
1133 { 1148 {
1134 joint = d.JointCreateContact(world, contactgroup, ref WaterContact); 1149 joint = d.JointCreateContact(world, contactgroup, ref WaterContact);
1135 m_global_contactcount++; 1150 m_global_contactcount++;
1136 } 1151 }
1137 //m_log.Info("[PHYSICS]: Prim Water Contact" + contacts[i].depth); 1152 //m_log.Info("[PHYSICS]: Prim Water Contact" + contact.depth);
1138 } 1153 }
1139 else 1154 else
1140 { 1155 {
@@ -1145,8 +1160,8 @@ namespace OpenSim.Region.Physics.OdePlugin
1145 if ((Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) 1160 if ((Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f))
1146 { 1161 {
1147 // Use the Movement prim contact 1162 // Use the Movement prim contact
1148 AvatarMovementprimContact.geom = contacts[i]; 1163 AvatarMovementprimContact.geom = curContact;
1149 _perloopContact.Add(contacts[i]); 1164 _perloopContact.Add(curContact);
1150 if (m_global_contactcount < maxContactsbeforedeath) 1165 if (m_global_contactcount < maxContactsbeforedeath)
1151 { 1166 {
1152 joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementprimContact); 1167 joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementprimContact);
@@ -1156,8 +1171,8 @@ namespace OpenSim.Region.Physics.OdePlugin
1156 else 1171 else
1157 { 1172 {
1158 // Use the non movement contact 1173 // Use the non movement contact
1159 contact.geom = contacts[i]; 1174 contact.geom = curContact;
1160 _perloopContact.Add(contacts[i]); 1175 _perloopContact.Add(curContact);
1161 1176
1162 if (m_global_contactcount < maxContactsbeforedeath) 1177 if (m_global_contactcount < maxContactsbeforedeath)
1163 { 1178 {
@@ -1175,8 +1190,8 @@ namespace OpenSim.Region.Physics.OdePlugin
1175 material = ((OdePrim)p2).m_material; 1190 material = ((OdePrim)p2).m_material;
1176 1191
1177 //m_log.DebugFormat("Material: {0}", material); 1192 //m_log.DebugFormat("Material: {0}", material);
1178 m_materialContacts[material, 0].geom = contacts[i]; 1193 m_materialContacts[material, 0].geom = curContact;
1179 _perloopContact.Add(contacts[i]); 1194 _perloopContact.Add(curContact);
1180 1195
1181 if (m_global_contactcount < maxContactsbeforedeath) 1196 if (m_global_contactcount < maxContactsbeforedeath)
1182 { 1197 {
@@ -1194,7 +1209,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1194 } 1209 }
1195 1210
1196 } 1211 }
1197 collision_accounting_events(p1, p2, max_collision_depth); 1212 collision_accounting_events(p1, p2, maxDepthContact);
1198 if (count > geomContactPointsStartthrottle) 1213 if (count > geomContactPointsStartthrottle)
1199 { 1214 {
1200 // If there are more then 3 contact points, it's likely 1215 // If there are more then 3 contact points, it's likely
@@ -1278,7 +1293,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1278 return result; 1293 return result;
1279 } 1294 }
1280 1295
1281 private void collision_accounting_events(PhysicsActor p1, PhysicsActor p2, float collisiondepth) 1296 private void collision_accounting_events(PhysicsActor p1, PhysicsActor p2, ContactPoint contact)
1282 { 1297 {
1283 // obj1LocalID = 0; 1298 // obj1LocalID = 0;
1284 //returncollisions = false; 1299 //returncollisions = false;
@@ -1299,7 +1314,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1299 case ActorTypes.Agent: 1314 case ActorTypes.Agent:
1300 cc1 = (OdeCharacter)p1; 1315 cc1 = (OdeCharacter)p1;
1301 obj2LocalID = cc1.m_localID; 1316 obj2LocalID = cc1.m_localID;
1302 cc1.AddCollisionEvent(cc2.m_localID, collisiondepth); 1317 cc1.AddCollisionEvent(cc2.m_localID, contact);
1303 //ctype = (int)CollisionCategories.Character; 1318 //ctype = (int)CollisionCategories.Character;
1304 1319
1305 //if (cc1.CollidingObj) 1320 //if (cc1.CollidingObj)
@@ -1314,7 +1329,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1314 { 1329 {
1315 cp1 = (OdePrim) p1; 1330 cp1 = (OdePrim) p1;
1316 obj2LocalID = cp1.m_localID; 1331 obj2LocalID = cp1.m_localID;
1317 cp1.AddCollisionEvent(cc2.m_localID, collisiondepth); 1332 cp1.AddCollisionEvent(cc2.m_localID, contact);
1318 } 1333 }
1319 //ctype = (int)CollisionCategories.Geom; 1334 //ctype = (int)CollisionCategories.Geom;
1320 1335
@@ -1334,7 +1349,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1334 break; 1349 break;
1335 } 1350 }
1336 1351
1337 cc2.AddCollisionEvent(obj2LocalID, collisiondepth); 1352 cc2.AddCollisionEvent(obj2LocalID, contact);
1338 break; 1353 break;
1339 case ActorTypes.Prim: 1354 case ActorTypes.Prim:
1340 1355
@@ -1350,7 +1365,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1350 { 1365 {
1351 cc1 = (OdeCharacter) p1; 1366 cc1 = (OdeCharacter) p1;
1352 obj2LocalID = cc1.m_localID; 1367 obj2LocalID = cc1.m_localID;
1353 cc1.AddCollisionEvent(cp2.m_localID, collisiondepth); 1368 cc1.AddCollisionEvent(cp2.m_localID, contact);
1354 //ctype = (int)CollisionCategories.Character; 1369 //ctype = (int)CollisionCategories.Character;
1355 1370
1356 //if (cc1.CollidingObj) 1371 //if (cc1.CollidingObj)
@@ -1366,7 +1381,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1366 { 1381 {
1367 cp1 = (OdePrim) p1; 1382 cp1 = (OdePrim) p1;
1368 obj2LocalID = cp1.m_localID; 1383 obj2LocalID = cp1.m_localID;
1369 cp1.AddCollisionEvent(cp2.m_localID, collisiondepth); 1384 cp1.AddCollisionEvent(cp2.m_localID, contact);
1370 //ctype = (int)CollisionCategories.Geom; 1385 //ctype = (int)CollisionCategories.Geom;
1371 1386
1372 //if (cp1.CollidingObj) 1387 //if (cp1.CollidingObj)
@@ -1387,7 +1402,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1387 break; 1402 break;
1388 } 1403 }
1389 1404
1390 cp2.AddCollisionEvent(obj2LocalID, collisiondepth); 1405 cp2.AddCollisionEvent(obj2LocalID, contact);
1391 } 1406 }
1392 break; 1407 break;
1393 } 1408 }
@@ -1750,6 +1765,11 @@ namespace OpenSim.Region.Physics.OdePlugin
1750 return result; 1765 return result;
1751 } 1766 }
1752 1767
1768 public override float TimeDilation
1769 {
1770 get { return m_timeDilation; }
1771 }
1772
1753 public override bool SupportsNINJAJoints 1773 public override bool SupportsNINJAJoints
1754 { 1774 {
1755 get { return m_NINJA_physics_joints_enabled; } 1775 get { return m_NINJA_physics_joints_enabled; }
@@ -2657,8 +2677,10 @@ namespace OpenSim.Region.Physics.OdePlugin
2657 2677
2658 // Figure out the Frames Per Second we're going at. 2678 // Figure out the Frames Per Second we're going at.
2659 //(step_time == 0.004f, there's 250 of those per second. Times the step time/step size 2679 //(step_time == 0.004f, there's 250 of those per second. Times the step time/step size
2660 2680
2661 fps = (step_time/ODE_STEPSIZE) * 1000; 2681 fps = (step_time / ODE_STEPSIZE) * 1000;
2682 // HACK: Using a time dilation of 1.0 to debug rubberbanding issues
2683 //m_timeDilation = Math.Min((step_time / ODE_STEPSIZE) / (0.09375f / ODE_STEPSIZE), 1.0f);
2662 2684
2663 step_time = 0.09375f; 2685 step_time = 0.09375f;
2664 2686