diff options
Diffstat (limited to 'OpenSim/Region/Physics/OdePlugin')
-rw-r--r-- | OpenSim/Region/Physics/OdePlugin/OdePlugin.cs | 243 |
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 | { |