aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/Physics/OdePlugin/OdePlugin.cs243
1 files changed, 146 insertions, 97 deletions
diff --git a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
index 05604c3..948b2d9 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
@@ -99,6 +99,9 @@ namespace OpenSim.Region.Physics.OdePlugin
99 public IntPtr world; 99 public IntPtr world;
100 100
101 public IntPtr space; 101 public IntPtr space;
102 // split static geometry collision handling into spaces of 64 meters
103 public IntPtr[] staticPrimspace = new IntPtr[64];
104
102 public static Object OdeLock = new Object(); 105 public static Object OdeLock = new Object();
103 106
104 public IMesher mesher; 107 public IMesher mesher;
@@ -157,124 +160,144 @@ namespace OpenSim.Region.Physics.OdePlugin
157 } 160 }
158 161
159 162
160 // This function blatantly ripped off from BoxStack.cs 163
161 private void near(IntPtr space, IntPtr g1, IntPtr g2) 164 private void near(IntPtr space, IntPtr g1, IntPtr g2)
162 { 165 {
163
164 // no lock here! It's invoked from within Simulate(), which is thread-locked 166 // no lock here! It's invoked from within Simulate(), which is thread-locked
165 IntPtr b1 = d.GeomGetBody(g1); 167 if (d.GeomIsSpace(g1) || d.GeomIsSpace(g2) )
166 IntPtr b2 = d.GeomGetBody(g2); 168 {
169 // Separating static prim geometry spaces.
170 // We'll be calling near recursivly if one
171 // of them is a space to find all of the
172 // contact points in the space
167 173
174 d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback);
175 //Colliding a space or a geom with a space or a geom.
168 176
169 if (g1 == g2) 177 //Collide all geoms in each space..
170 return; // Can't collide with yourself 178 if (d.GeomIsSpace(g1)) d.SpaceCollide(g1, IntPtr.Zero, nearCallback);
171 179 if (d.GeomIsSpace(g2)) d.SpaceCollide(g2, IntPtr.Zero, nearCallback);
172 180
181 }
182 else
183 {
184 // Colliding Geom To Geom
185 // This portion of the function 'was' blatantly ripped off from BoxStack.cs
186
187 IntPtr b1 = d.GeomGetBody(g1);
188 IntPtr b2 = d.GeomGetBody(g2);
173 189
174 if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact))
175 return;
176 190
191 if (g1 == g2)
192 return; // Can't collide with yourself
193
177 194
178 d.GeomClassID id = d.GeomGetClass(g1);
179
180 String name1 = null;
181 String name2 = null;
182 195
183 if (!geom_name_map.TryGetValue(g1, out name1)) 196 if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact))
184 { 197 return;
185 name1 = "null";
186 }
187 if (!geom_name_map.TryGetValue(g2, out name2))
188 {
189 name2 = "null";
190 }
191 198
192 if (id == d.GeomClassID.TriMeshClass)
193 {
194
195 199
196// MainLog.Instance.Verbose("near: A collision was detected between {1} and {2}", 0, name1, name2); 200 d.GeomClassID id = d.GeomGetClass(g1);
197 //System.Console.WriteLine("near: A collision was detected between {1} and {2}", 0, name1, name2); 201
198 } 202 String name1 = null;
199 203 String name2 = null;
200 int count;
201
202 count = d.Collide(g1, g2, contacts.GetLength(0), contacts, d.ContactGeom.SizeOf);
203
204 for (int i = 0; i < count; i++)
205 {
206 IntPtr joint;
207 // If we're colliding with terrain, use 'TerrainContact' instead of contact.
208 // allows us to have different settings
209 PhysicsActor p1;
210 PhysicsActor p2;
211 204
212 if (!actor_name_map.TryGetValue(g2, out p1)) 205 if (!geom_name_map.TryGetValue(g1, out name1))
213 { 206 {
214 p1 = PANull; 207 name1 = "null";
215 } 208 }
216 if (!actor_name_map.TryGetValue(g2, out p2)) 209 if (!geom_name_map.TryGetValue(g2, out name2))
217 { 210 {
218 p2 = PANull; 211 name2 = "null";
219 } 212 }
220 213
221 // We only need to test p2 for 'jump crouch purposes' 214 if (id == d.GeomClassID.TriMeshClass)
222 p2.IsColliding = true; 215 {
223 216
224 switch(p1.PhysicsActorType) {
225 case (int)ActorTypes.Agent:
226 p2.CollidingObj = true;
227 break;
228 case (int)ActorTypes.Prim:
229 p2.CollidingObj = true;
230 break;
231 case (int)ActorTypes.Unknown:
232 p2.CollidingGround = true;
233 break;
234 }
235 217
236 if (name1 == "Terrain" || name2 == "Terrain") 218 // MainLog.Instance.Verbose("near: A collision was detected between {1} and {2}", 0, name1, name2);
219 //System.Console.WriteLine("near: A collision was detected between {1} and {2}", 0, name1, name2);
220 }
221
222 int count;
223
224 count = d.Collide(g1, g2, contacts.GetLength(0), contacts, d.ContactGeom.SizeOf);
225
226 for (int i = 0; i < count; i++)
237 { 227 {
238 if ((p2.PhysicsActorType == (int)ActorTypes.Agent) && (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) 228 IntPtr joint;
229 // If we're colliding with terrain, use 'TerrainContact' instead of contact.
230 // allows us to have different settings
231 PhysicsActor p1;
232 PhysicsActor p2;
233
234 if (!actor_name_map.TryGetValue(g2, out p1))
239 { 235 {
240 AvatarMovementTerrainContact.geom = contacts[i]; 236 p1 = PANull;
241 joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementTerrainContact);
242 } 237 }
243 else 238 if (!actor_name_map.TryGetValue(g2, out p2))
244 { 239 {
245 TerrainContact.geom = contacts[i]; 240 p2 = PANull;
246 joint = d.JointCreateContact(world, contactgroup, ref TerrainContact);
247 } 241 }
248 242
249 243 // We only need to test p2 for 'jump crouch purposes'
250 } 244 p2.IsColliding = true;
251 else 245
252 { 246 switch(p1.PhysicsActorType) {
253 if ((p2.PhysicsActorType == (int)ActorTypes.Agent) && (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) 247 case (int)ActorTypes.Agent:
248 p2.CollidingObj = true;
249 break;
250 case (int)ActorTypes.Prim:
251 p2.CollidingObj = true;
252 break;
253 case (int)ActorTypes.Unknown:
254 p2.CollidingGround = true;
255 break;
256 }
257
258 if (name1 == "Terrain" || name2 == "Terrain")
254 { 259 {
255 AvatarMovementprimContact.geom = contacts[i]; 260 if ((p2.PhysicsActorType == (int)ActorTypes.Agent) && (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f))
256 joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementprimContact); 261 {
262 AvatarMovementTerrainContact.geom = contacts[i];
263 joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementTerrainContact);
264 }
265 else
266 {
267 TerrainContact.geom = contacts[i];
268 joint = d.JointCreateContact(world, contactgroup, ref TerrainContact);
269 }
270
271
257 } 272 }
258 else 273 else
259 { 274 {
260 contact.geom = contacts[i]; 275 if ((p2.PhysicsActorType == (int)ActorTypes.Agent) && (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f))
261 joint = d.JointCreateContact(world, contactgroup, ref contact); 276 {
277 AvatarMovementprimContact.geom = contacts[i];
278 joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementprimContact);
279 }
280 else
281 {
282 contact.geom = contacts[i];
283 joint = d.JointCreateContact(world, contactgroup, ref contact);
284
285 }
262 286
263 } 287 }
264 288
265 } 289
266 290 d.JointAttach(joint, b1, b2);
267
268 d.JointAttach(joint, b1, b2);
269 291
270 292
271 293
272 if (count > 3) 294 if (count > 3)
273 { 295 {
274 p2.ThrottleUpdates = true; 296 p2.ThrottleUpdates = true;
297 }
298 //System.Console.WriteLine(count.ToString());
299 //System.Console.WriteLine("near: A collision was detected between {1} and {2}", 0, name1, name2);
275 } 300 }
276 //System.Console.WriteLine(count.ToString());
277 //System.Console.WriteLine("near: A collision was detected between {1} and {2}", 0, name1, name2);
278 } 301 }
279 } 302 }
280 303
@@ -368,9 +391,24 @@ namespace OpenSim.Region.Physics.OdePlugin
368 } 391 }
369 } 392 }
370 393
394 public IntPtr recalculateSpaceForGeom(IntPtr geom, PhysicsVector pos)
395 {
396 //Todo recalculate space the prim is in.
397
398
399 return space;
400 }
401
402 public IntPtr calculateSpaceForNewGeom(PhysicsVector pos)
403 {
404
405 return space;
406 }
407
371 private PhysicsActor AddPrim(String name, PhysicsVector position, PhysicsVector size, Quaternion rotation, 408 private PhysicsActor AddPrim(String name, PhysicsVector position, PhysicsVector size, Quaternion rotation,
372 IMesh mesh, PrimitiveBaseShape pbs, bool isphysical) 409 IMesh mesh, PrimitiveBaseShape pbs, bool isphysical)
373 { 410 {
411
374 PhysicsVector pos = new PhysicsVector(); 412 PhysicsVector pos = new PhysicsVector();
375 pos.X = position.X; 413 pos.X = position.X;
376 pos.Y = position.Y; 414 pos.Y = position.Y;
@@ -384,10 +422,12 @@ namespace OpenSim.Region.Physics.OdePlugin
384 rot.x = rotation.x; 422 rot.x = rotation.x;
385 rot.y = rotation.y; 423 rot.y = rotation.y;
386 rot.z = rotation.z; 424 rot.z = rotation.z;
425
426 IntPtr targetspace = calculateSpaceForNewGeom(pos);
387 OdePrim newPrim; 427 OdePrim newPrim;
388 lock (OdeLock) 428 lock (OdeLock)
389 { 429 {
390 newPrim = new OdePrim(name, this, pos, siz, rot, mesh, pbs, isphysical); 430 newPrim = new OdePrim(name, this, targetspace, pos, siz, rot, mesh, pbs, isphysical);
391 } 431 }
392 _prims.Add(newPrim); 432 _prims.Add(newPrim);
393 return newPrim; 433 return newPrim;
@@ -1145,6 +1185,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1145 private IMesh _mesh; 1185 private IMesh _mesh;
1146 private PrimitiveBaseShape _pbs; 1186 private PrimitiveBaseShape _pbs;
1147 private OdeScene _parent_scene; 1187 private OdeScene _parent_scene;
1188 private IntPtr m_targetSpace = (IntPtr)0;
1148 public IntPtr prim_geom; 1189 public IntPtr prim_geom;
1149 public IntPtr _triMeshData; 1190 public IntPtr _triMeshData;
1150 private bool iscolliding = false; 1191 private bool iscolliding = false;
@@ -1163,7 +1204,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1163 private int debugcounter = 0; 1204 private int debugcounter = 0;
1164 1205
1165 1206
1166 public OdePrim(String primName, OdeScene parent_scene, PhysicsVector pos, PhysicsVector size, 1207 public OdePrim(String primName, OdeScene parent_scene, IntPtr targetSpace, PhysicsVector pos, PhysicsVector size,
1167 Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool pisPhysical) 1208 Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool pisPhysical)
1168 { 1209 {
1169 1210
@@ -1177,12 +1218,19 @@ namespace OpenSim.Region.Physics.OdePlugin
1177 _mesh = mesh; 1218 _mesh = mesh;
1178 _pbs = pbs; 1219 _pbs = pbs;
1179 _parent_scene = parent_scene; 1220 _parent_scene = parent_scene;
1180 1221 m_targetSpace = targetSpace;
1222
1181 if (pos.Z < 0) 1223 if (pos.Z < 0)
1182 m_isphysical = false; 1224 m_isphysical = false;
1183 else 1225 else
1184 m_isphysical = pisPhysical; 1226 {
1227 m_isphysical = pisPhysical;
1228 // If we're physical, we need to be in the master space for now.
1229 // linksets *should* be in a space together.. but are not currently
1230 if (m_isphysical)
1231 m_targetSpace = _parent_scene.space;
1185 1232
1233 }
1186 m_primName = primName; 1234 m_primName = primName;
1187 1235
1188 1236
@@ -1195,7 +1243,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1195 } 1243 }
1196 else 1244 else
1197 { 1245 {
1198 prim_geom = d.CreateBox(parent_scene.space, _size.X, _size.Y, _size.Z); 1246 prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
1199 } 1247 }
1200 1248
1201 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); 1249 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
@@ -1281,7 +1329,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1281 3*sizeof (int)); 1329 3*sizeof (int));
1282 d.GeomTriMeshDataPreprocess(_triMeshData); 1330 d.GeomTriMeshDataPreprocess(_triMeshData);
1283 1331
1284 prim_geom = d.CreateTriMesh(parent_scene.space, _triMeshData, parent_scene.triCallback, null, null); 1332 prim_geom = d.CreateTriMesh(m_targetSpace, _triMeshData, parent_scene.triCallback, null, null);
1285 1333
1286 if (IsPhysical && Body == (IntPtr)0) 1334 if (IsPhysical && Body == (IntPtr)0)
1287 { 1335 {
@@ -1375,6 +1423,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1375 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); 1423 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
1376 1424
1377 } 1425 }
1426 m_targetSpace = _parent_scene.recalculateSpaceForGeom(prim_geom, _position);
1378 } 1427 }
1379 } 1428 }
1380 } 1429 }
@@ -1414,10 +1463,10 @@ namespace OpenSim.Region.Physics.OdePlugin
1414 } 1463 }
1415 else 1464 else
1416 { 1465 {
1417 prim_geom = d.CreateBox(_parent_scene.space, _size.X, _size.Y, _size.Z); 1466 prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
1418 } 1467 }
1419 } else { 1468 } else {
1420 prim_geom = d.CreateBox(_parent_scene.space, _size.X, _size.Y, _size.Z); 1469 prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
1421 1470
1422 if (IsPhysical && Body == (IntPtr)0) 1471 if (IsPhysical && Body == (IntPtr)0)
1423 { 1472 {
@@ -1428,8 +1477,8 @@ namespace OpenSim.Region.Physics.OdePlugin
1428 } 1477 }
1429 1478
1430 } 1479 }
1431 1480
1432 1481 m_targetSpace = _parent_scene.recalculateSpaceForGeom(prim_geom, _position);
1433 _parent_scene.geom_name_map[prim_geom] = oldname; 1482 _parent_scene.geom_name_map[prim_geom] = oldname;
1434 1483
1435 } 1484 }
@@ -1468,10 +1517,10 @@ namespace OpenSim.Region.Physics.OdePlugin
1468 } 1517 }
1469 else 1518 else
1470 { 1519 {
1471 prim_geom = d.CreateBox(_parent_scene.space, _size.X, _size.Y, _size.Z); 1520 prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
1472 } 1521 }
1473 } else { 1522 } else {
1474 prim_geom = d.CreateBox(_parent_scene.space, _size.X, _size.Y, _size.Z); 1523 prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
1475 } 1524 }
1476 if (IsPhysical && Body == (IntPtr)0) 1525 if (IsPhysical && Body == (IntPtr)0)
1477 { 1526 {