aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/UbitOdePlugin
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs1
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/ODEMeshWorker.cs931
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs858
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs18
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs454
5 files changed, 1442 insertions, 820 deletions
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs
index c363310..f5bf05d 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs
@@ -172,7 +172,6 @@ namespace OpenSim.Region.Physics.OdePlugin
172 // force lower density for testing 172 // force lower density for testing
173 m_density = 3.0f; 173 m_density = 3.0f;
174 174
175
176 mu = parent_scene.AvatarFriction; 175 mu = parent_scene.AvatarFriction;
177 176
178 walkDivisor = walk_divisor; 177 walkDivisor = walk_divisor;
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODEMeshWorker.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODEMeshWorker.cs
new file mode 100644
index 0000000..73dd2fd
--- /dev/null
+++ b/OpenSim/Region/Physics/UbitOdePlugin/ODEMeshWorker.cs
@@ -0,0 +1,931 @@
1/*
2 * AJLDuarte 2012
3 */
4
5using System;
6using System.Threading;
7using System.Collections.Generic;
8using System.IO;
9using System.Reflection;
10using System.Runtime.InteropServices;
11using System.Text;
12using OpenSim.Framework;
13using OpenSim.Region.Physics.Manager;
14using OdeAPI;
15using log4net;
16using Nini.Config;
17using OpenMetaverse;
18
19namespace OpenSim.Region.Physics.OdePlugin
20{
21 public enum MeshState : byte
22 {
23 noNeed = 0,
24
25 loadingAsset = 1,
26
27 AssetOK = 0x0f, // 00001111
28
29 NeedMask = 0x30, // 00110000
30 needMesh = 0x10, // 00010000
31 needAsset = 0x20, // 00100000
32
33 FailMask = 0xC0, // 11000000
34 AssetFailed = 0x40, // 01000000
35 MeshFailed = 0x80, // 10000000
36
37 MeshNoColide = FailMask | needAsset
38 }
39
40 public enum meshWorkerCmnds : byte
41 {
42 nop = 0,
43 addnew,
44 changefull,
45 changesize,
46 changeshapetype,
47 getmesh,
48 }
49
50 public class ODEPhysRepData
51 {
52 public PhysicsActor actor;
53 public PrimitiveBaseShape pbs;
54 public IMesh mesh;
55
56 public Vector3 size;
57 public Vector3 OBB;
58 public Vector3 OBBOffset;
59
60 public float volume;
61
62 public byte shapetype;
63 public bool hasOBB;
64 public bool hasMeshVolume;
65 public MeshState meshState;
66 public UUID? assetID;
67 public meshWorkerCmnds comand;
68 }
69
70 public class ODEMeshWorker
71 {
72
73 private ILog m_log;
74 private OdeScene m_scene;
75 private IMesher m_mesher;
76
77 public bool meshSculptedPrim = true;
78 public bool forceSimplePrimMeshing = false;
79 public float meshSculptLOD = 32;
80 public float MeshSculptphysicalLOD = 32;
81
82
83 private OpenSim.Framework.BlockingQueue<ODEPhysRepData> createqueue = new OpenSim.Framework.BlockingQueue<ODEPhysRepData>();
84 private bool m_running;
85
86 private Thread m_thread;
87
88 public ODEMeshWorker(OdeScene pScene, ILog pLog, IMesher pMesher, IConfig pConfig)
89 {
90 m_scene = pScene;
91 m_log = pLog;
92 m_mesher = pMesher;
93
94 if (pConfig != null)
95 {
96 forceSimplePrimMeshing = pConfig.GetBoolean("force_simple_prim_meshing", forceSimplePrimMeshing);
97 meshSculptedPrim = pConfig.GetBoolean("mesh_sculpted_prim", meshSculptedPrim);
98 meshSculptLOD = pConfig.GetFloat("mesh_lod", meshSculptLOD);
99 MeshSculptphysicalLOD = pConfig.GetFloat("mesh_physical_lod", MeshSculptphysicalLOD);
100 }
101 m_running = true;
102 m_thread = new Thread(DoWork);
103 m_thread.Start();
104 }
105
106 private void DoWork()
107 {
108 m_mesher.ExpireFileCache();
109
110 while(m_running)
111 {
112 ODEPhysRepData nextRep = createqueue.Dequeue();
113 if(!m_running)
114 return;
115 if (nextRep == null)
116 continue;
117 if (m_scene.haveActor(nextRep.actor))
118 {
119 switch (nextRep.comand)
120 {
121 case meshWorkerCmnds.changefull:
122 case meshWorkerCmnds.changeshapetype:
123 case meshWorkerCmnds.changesize:
124 GetMesh(nextRep);
125 if (CreateActorPhysRep(nextRep) && m_scene.haveActor(nextRep.actor))
126 m_scene.AddChange(nextRep.actor, changes.PhysRepData, nextRep);
127 break;
128 case meshWorkerCmnds.getmesh:
129 DoRepDataGetMesh(nextRep);
130 break;
131 }
132 }
133 }
134 }
135
136 public void Stop()
137 {
138 try
139 {
140 m_thread.Abort();
141 createqueue.Clear();
142 }
143 catch
144 {
145 }
146 }
147
148 public void ChangeActorPhysRep(PhysicsActor actor, PrimitiveBaseShape pbs,
149 Vector3 size, byte shapetype)
150 {
151 ODEPhysRepData repData = new ODEPhysRepData();
152 repData.actor = actor;
153 repData.pbs = pbs;
154 repData.size = size;
155 repData.shapetype = shapetype;
156
157 CheckMesh(repData);
158 CalcVolumeData(repData);
159 m_scene.AddChange(actor, changes.PhysRepData, repData);
160 return;
161 }
162
163 public ODEPhysRepData NewActorPhysRep(PhysicsActor actor, PrimitiveBaseShape pbs,
164 Vector3 size, byte shapetype)
165 {
166 ODEPhysRepData repData = new ODEPhysRepData();
167 repData.actor = actor;
168 repData.pbs = pbs;
169 repData.size = size;
170 repData.shapetype = shapetype;
171
172 CheckMesh(repData);
173 CalcVolumeData(repData);
174 m_scene.AddChange(actor, changes.AddPhysRep, repData);
175 return repData;
176 }
177
178 public void RequestMesh(ODEPhysRepData repData)
179 {
180 repData.mesh = null;
181
182 if (repData.meshState == MeshState.needAsset)
183 {
184 PrimitiveBaseShape pbs = repData.pbs;
185
186 // check if we got outdated
187
188 if (!pbs.SculptEntry || pbs.SculptTexture == UUID.Zero)
189 {
190 repData.meshState = MeshState.noNeed;
191 return;
192 }
193
194 repData.assetID = pbs.SculptTexture;
195 repData.meshState = MeshState.loadingAsset;
196
197 repData.comand = meshWorkerCmnds.getmesh;
198 createqueue.Enqueue(repData);
199 }
200 }
201
202 // creates and prepares a mesh to use and calls parameters estimation
203 public bool CreateActorPhysRep(ODEPhysRepData repData)
204 {
205 IMesh mesh = repData.mesh;
206
207 if (mesh != null)
208 {
209 IntPtr vertices, indices;
210 int vertexCount, indexCount;
211 int vertexStride, triStride;
212
213 mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount);
214 mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount);
215
216 if (vertexCount == 0 || indexCount == 0)
217 {
218 m_log.WarnFormat("[PHYSICS]: Invalid mesh data on prim {0} mesh UUID {1}",
219 repData.actor.Name, repData.pbs.SculptTexture.ToString());
220 repData.meshState = MeshState.MeshFailed;
221 repData.hasOBB = false;
222 repData.mesh = null;
223 m_scene.mesher.ReleaseMesh(mesh);
224 }
225 else
226 {
227 repData.OBBOffset = mesh.GetCentroid();
228 repData.OBB = mesh.GetOBB();
229 repData.hasOBB = true;
230 mesh.releaseSourceMeshData();
231 }
232 }
233 CalcVolumeData(repData);
234 return true;
235 }
236
237 public void AssetLoaded(ODEPhysRepData repData)
238 {
239 if (m_scene.haveActor(repData.actor))
240 {
241 if (needsMeshing(repData.pbs)) // no need for pbs now?
242 {
243 repData.comand = meshWorkerCmnds.changefull;
244 createqueue.Enqueue(repData);
245 }
246 }
247 else
248 repData.pbs.SculptData = Utils.EmptyBytes;
249 }
250
251 public void DoRepDataGetMesh(ODEPhysRepData repData)
252 {
253 if (!repData.pbs.SculptEntry)
254 return;
255
256 if (repData.meshState != MeshState.loadingAsset)
257 return;
258
259 if (repData.assetID == null || repData.assetID == UUID.Zero)
260 return;
261
262 if (repData.assetID != repData.pbs.SculptTexture)
263 return;
264
265 // check if it is in cache
266 GetMesh(repData);
267 if (repData.meshState != MeshState.needAsset)
268 {
269 CreateActorPhysRep(repData);
270 m_scene.AddChange(repData.actor, changes.PhysRepData, repData);
271 return;
272 }
273
274 RequestAssetDelegate assetProvider = m_scene.RequestAssetMethod;
275 if (assetProvider == null)
276 return;
277 ODEAssetRequest asr = new ODEAssetRequest(this, assetProvider, repData, m_log);
278 }
279
280
281 /// <summary>
282 /// Routine to figure out if we need to mesh this prim with our mesher
283 /// </summary>
284 /// <param name="pbs"></param>
285 /// <returns></returns>
286 public bool needsMeshing(PrimitiveBaseShape pbs)
287 {
288 // check sculpts or meshs
289 if (pbs.SculptEntry)
290 {
291 if (meshSculptedPrim)
292 return true;
293
294 if (pbs.SculptType == (byte)SculptType.Mesh) // always do meshs
295 return true;
296
297 return false;
298 }
299
300 if (forceSimplePrimMeshing)
301 return true;
302
303 // if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since ODE can use an internal representation for the prim
304
305 if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
306 || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1
307 && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z))
308 {
309
310 if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
311 && pbs.ProfileHollow == 0
312 && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
313 && pbs.PathBegin == 0 && pbs.PathEnd == 0
314 && pbs.PathTaperX == 0 && pbs.PathTaperY == 0
315 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
316 && pbs.PathShearX == 0 && pbs.PathShearY == 0)
317 {
318 return false;
319 }
320 }
321
322 // following code doesn't give meshs to boxes and spheres ever
323 // and it's odd.. so for now just return true if asked to force meshs
324 // hopefully mesher will fail if doesn't suport so things still get basic boxes
325
326 int iPropertiesNotSupportedDefault = 0;
327
328 if (pbs.ProfileHollow != 0)
329 iPropertiesNotSupportedDefault++;
330
331 if ((pbs.PathBegin != 0) || pbs.PathEnd != 0)
332 iPropertiesNotSupportedDefault++;
333
334 if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0))
335 iPropertiesNotSupportedDefault++;
336
337 if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0)
338 iPropertiesNotSupportedDefault++;
339
340 if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100))
341 iPropertiesNotSupportedDefault++;
342
343 if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0))
344 iPropertiesNotSupportedDefault++;
345
346 if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight)
347 iPropertiesNotSupportedDefault++;
348
349 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 && (pbs.Scale.X != pbs.Scale.Y || pbs.Scale.Y != pbs.Scale.Z || pbs.Scale.Z != pbs.Scale.X))
350 iPropertiesNotSupportedDefault++;
351
352 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1)
353 iPropertiesNotSupportedDefault++;
354
355 // test for torus
356 if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
357 {
358 if (pbs.PathCurve == (byte)Extrusion.Curve1)
359 {
360 iPropertiesNotSupportedDefault++;
361 }
362 }
363 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
364 {
365 if (pbs.PathCurve == (byte)Extrusion.Straight)
366 {
367 iPropertiesNotSupportedDefault++;
368 }
369
370 // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
371 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
372 {
373 iPropertiesNotSupportedDefault++;
374 }
375 }
376 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
377 {
378 if (pbs.PathCurve == (byte)Extrusion.Curve1 || pbs.PathCurve == (byte)Extrusion.Curve2)
379 {
380 iPropertiesNotSupportedDefault++;
381 }
382 }
383 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
384 {
385 if (pbs.PathCurve == (byte)Extrusion.Straight)
386 {
387 iPropertiesNotSupportedDefault++;
388 }
389 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
390 {
391 iPropertiesNotSupportedDefault++;
392 }
393 }
394
395 if (iPropertiesNotSupportedDefault == 0)
396 {
397 return false;
398 }
399 return true;
400 }
401
402 // see if we need a mesh and if so if we have a cached one
403 // called with a new repData
404 public void CheckMesh(ODEPhysRepData repData)
405 {
406 PhysicsActor actor = repData.actor;
407 PrimitiveBaseShape pbs = repData.pbs;
408
409 if (!needsMeshing(pbs))
410 {
411 repData.meshState = MeshState.noNeed;
412 return;
413 }
414
415 IMesh mesh = null;
416
417 Vector3 size = repData.size;
418 byte shapetype = repData.shapetype;
419
420 bool convex;
421
422 int clod = (int)LevelOfDetail.High;
423 if (shapetype == 0)
424 convex = false;
425 else
426 {
427 convex = true;
428 if (pbs.SculptType != (byte)SculptType.Mesh)
429 clod = (int)LevelOfDetail.Low;
430 }
431
432 mesh = m_mesher.GetMesh(actor.Name, pbs, size, clod, true, convex);
433
434 if (mesh == null)
435 {
436 if (pbs.SculptEntry)
437 {
438 if (pbs.SculptTexture != null && pbs.SculptTexture != UUID.Zero)
439 {
440 repData.assetID = pbs.SculptTexture;
441 repData.meshState = MeshState.needAsset;
442 }
443 else
444 repData.meshState = MeshState.MeshFailed;
445
446 return;
447 }
448 else
449 {
450 repData.meshState = MeshState.needMesh;
451 mesh = m_mesher.CreateMesh(actor.Name, pbs, size, clod, true, convex, true);
452 if (mesh == null)
453 {
454 repData.meshState = MeshState.MeshFailed;
455 return;
456 }
457 }
458 }
459
460 repData.meshState = MeshState.AssetOK;
461 repData.mesh = mesh;
462
463 if (pbs.SculptEntry)
464 {
465 repData.assetID = pbs.SculptTexture;
466 }
467
468 pbs.SculptData = Utils.EmptyBytes;
469 return ;
470 }
471
472 public void GetMesh(ODEPhysRepData repData)
473 {
474 PhysicsActor actor = repData.actor;
475
476 PrimitiveBaseShape pbs = repData.pbs;
477
478 repData.mesh = null;
479 repData.hasOBB = false;
480
481 if (!needsMeshing(pbs))
482 {
483 repData.meshState = MeshState.noNeed;
484 return;
485 }
486
487 if (repData.meshState == MeshState.MeshFailed)
488 return;
489
490 if (pbs.SculptEntry)
491 {
492 if (repData.meshState == MeshState.AssetFailed)
493 {
494 if (pbs.SculptTexture == repData.assetID)
495 return;
496 }
497 }
498
499 repData.meshState = MeshState.noNeed;
500
501 IMesh mesh = null;
502 Vector3 size = repData.size;
503 byte shapetype = repData.shapetype;
504
505 bool convex;
506 int clod = (int)LevelOfDetail.High;
507 if (shapetype == 0)
508 convex = false;
509 else
510 {
511 convex = true;
512 if (pbs.SculptType != (byte)SculptType.Mesh)
513 clod = (int)LevelOfDetail.Low;
514 }
515
516 mesh = m_mesher.CreateMesh(actor.Name, pbs, size, clod, true, convex, true);
517
518 if (mesh == null)
519 {
520 if (pbs.SculptEntry)
521 {
522 if (pbs.SculptTexture == UUID.Zero)
523 return;
524
525 repData.assetID = pbs.SculptTexture;
526
527 if (pbs.SculptData == null || pbs.SculptData.Length == 0)
528 {
529 repData.meshState = MeshState.needAsset;
530 return;
531 }
532 }
533 }
534
535 repData.mesh = mesh;
536 repData.pbs.SculptData = Utils.EmptyBytes;
537
538 if (mesh == null)
539 {
540 if (pbs.SculptEntry)
541 repData.meshState = MeshState.AssetFailed;
542 else
543 repData.meshState = MeshState.MeshFailed;
544
545 return;
546 }
547
548 repData.meshState = MeshState.AssetOK;
549
550 return;
551 }
552
553 private void CalculateBasicPrimVolume(ODEPhysRepData repData)
554 {
555 PrimitiveBaseShape _pbs = repData.pbs;
556 Vector3 _size = repData.size;
557
558 float volume = _size.X * _size.Y * _size.Z; // default
559 float tmp;
560
561 float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f;
562 float hollowVolume = hollowAmount * hollowAmount;
563
564 switch (_pbs.ProfileShape)
565 {
566 case ProfileShape.Square:
567 // default box
568
569 if (_pbs.PathCurve == (byte)Extrusion.Straight)
570 {
571 if (hollowAmount > 0.0)
572 {
573 switch (_pbs.HollowShape)
574 {
575 case HollowShape.Square:
576 case HollowShape.Same:
577 break;
578
579 case HollowShape.Circle:
580
581 hollowVolume *= 0.78539816339f;
582 break;
583
584 case HollowShape.Triangle:
585
586 hollowVolume *= (0.5f * .5f);
587 break;
588
589 default:
590 hollowVolume = 0;
591 break;
592 }
593 volume *= (1.0f - hollowVolume);
594 }
595 }
596
597 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
598 {
599 //a tube
600
601 volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX);
602 tmp = 1.0f - 2.0e-2f * (float)(200 - _pbs.PathScaleY);
603 volume -= volume * tmp * tmp;
604
605 if (hollowAmount > 0.0)
606 {
607 hollowVolume *= hollowAmount;
608
609 switch (_pbs.HollowShape)
610 {
611 case HollowShape.Square:
612 case HollowShape.Same:
613 break;
614
615 case HollowShape.Circle:
616 hollowVolume *= 0.78539816339f;
617 break;
618
619 case HollowShape.Triangle:
620 hollowVolume *= 0.5f * 0.5f;
621 break;
622 default:
623 hollowVolume = 0;
624 break;
625 }
626 volume *= (1.0f - hollowVolume);
627 }
628 }
629
630 break;
631
632 case ProfileShape.Circle:
633
634 if (_pbs.PathCurve == (byte)Extrusion.Straight)
635 {
636 volume *= 0.78539816339f; // elipse base
637
638 if (hollowAmount > 0.0)
639 {
640 switch (_pbs.HollowShape)
641 {
642 case HollowShape.Same:
643 case HollowShape.Circle:
644 break;
645
646 case HollowShape.Square:
647 hollowVolume *= 0.5f * 2.5984480504799f;
648 break;
649
650 case HollowShape.Triangle:
651 hollowVolume *= .5f * 1.27323954473516f;
652 break;
653
654 default:
655 hollowVolume = 0;
656 break;
657 }
658 volume *= (1.0f - hollowVolume);
659 }
660 }
661
662 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
663 {
664 volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX);
665 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
666 volume *= (1.0f - tmp * tmp);
667
668 if (hollowAmount > 0.0)
669 {
670
671 // calculate the hollow volume by it's shape compared to the prim shape
672 hollowVolume *= hollowAmount;
673
674 switch (_pbs.HollowShape)
675 {
676 case HollowShape.Same:
677 case HollowShape.Circle:
678 break;
679
680 case HollowShape.Square:
681 hollowVolume *= 0.5f * 2.5984480504799f;
682 break;
683
684 case HollowShape.Triangle:
685 hollowVolume *= .5f * 1.27323954473516f;
686 break;
687
688 default:
689 hollowVolume = 0;
690 break;
691 }
692 volume *= (1.0f - hollowVolume);
693 }
694 }
695 break;
696
697 case ProfileShape.HalfCircle:
698 if (_pbs.PathCurve == (byte)Extrusion.Curve1)
699 {
700 volume *= 0.5236f;
701
702 if (hollowAmount > 0.0)
703 {
704 hollowVolume *= hollowAmount;
705
706 switch (_pbs.HollowShape)
707 {
708 case HollowShape.Circle:
709 case HollowShape.Triangle: // diference in sl is minor and odd
710 case HollowShape.Same:
711 break;
712
713 case HollowShape.Square:
714 hollowVolume *= 0.909f;
715 break;
716
717 // case HollowShape.Triangle:
718 // hollowVolume *= .827f;
719 // break;
720 default:
721 hollowVolume = 0;
722 break;
723 }
724 volume *= (1.0f - hollowVolume);
725 }
726
727 }
728 break;
729
730 case ProfileShape.EquilateralTriangle:
731
732 if (_pbs.PathCurve == (byte)Extrusion.Straight)
733 {
734 volume *= 0.32475953f;
735
736 if (hollowAmount > 0.0)
737 {
738
739 // calculate the hollow volume by it's shape compared to the prim shape
740 switch (_pbs.HollowShape)
741 {
742 case HollowShape.Same:
743 case HollowShape.Triangle:
744 hollowVolume *= .25f;
745 break;
746
747 case HollowShape.Square:
748 hollowVolume *= 0.499849f * 3.07920140172638f;
749 break;
750
751 case HollowShape.Circle:
752 // Hollow shape is a perfect cyllinder in respect to the cube's scale
753 // Cyllinder hollow volume calculation
754
755 hollowVolume *= 0.1963495f * 3.07920140172638f;
756 break;
757
758 default:
759 hollowVolume = 0;
760 break;
761 }
762 volume *= (1.0f - hollowVolume);
763 }
764 }
765 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
766 {
767 volume *= 0.32475953f;
768 volume *= 0.01f * (float)(200 - _pbs.PathScaleX);
769 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
770 volume *= (1.0f - tmp * tmp);
771
772 if (hollowAmount > 0.0)
773 {
774
775 hollowVolume *= hollowAmount;
776
777 switch (_pbs.HollowShape)
778 {
779 case HollowShape.Same:
780 case HollowShape.Triangle:
781 hollowVolume *= .25f;
782 break;
783
784 case HollowShape.Square:
785 hollowVolume *= 0.499849f * 3.07920140172638f;
786 break;
787
788 case HollowShape.Circle:
789
790 hollowVolume *= 0.1963495f * 3.07920140172638f;
791 break;
792
793 default:
794 hollowVolume = 0;
795 break;
796 }
797 volume *= (1.0f - hollowVolume);
798 }
799 }
800 break;
801
802 default:
803 break;
804 }
805
806 float taperX1;
807 float taperY1;
808 float taperX;
809 float taperY;
810 float pathBegin;
811 float pathEnd;
812 float profileBegin;
813 float profileEnd;
814
815 if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible)
816 {
817 taperX1 = _pbs.PathScaleX * 0.01f;
818 if (taperX1 > 1.0f)
819 taperX1 = 2.0f - taperX1;
820 taperX = 1.0f - taperX1;
821
822 taperY1 = _pbs.PathScaleY * 0.01f;
823 if (taperY1 > 1.0f)
824 taperY1 = 2.0f - taperY1;
825 taperY = 1.0f - taperY1;
826 }
827 else
828 {
829 taperX = _pbs.PathTaperX * 0.01f;
830 if (taperX < 0.0f)
831 taperX = -taperX;
832 taperX1 = 1.0f - taperX;
833
834 taperY = _pbs.PathTaperY * 0.01f;
835 if (taperY < 0.0f)
836 taperY = -taperY;
837 taperY1 = 1.0f - taperY;
838 }
839
840 volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY);
841
842 pathBegin = (float)_pbs.PathBegin * 2.0e-5f;
843 pathEnd = 1.0f - (float)_pbs.PathEnd * 2.0e-5f;
844 volume *= (pathEnd - pathBegin);
845
846 // this is crude aproximation
847 profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f;
848 profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f;
849 volume *= (profileEnd - profileBegin);
850
851 repData.volume = volume;
852 }
853
854 private void CalcVolumeData(ODEPhysRepData repData)
855 {
856 if (repData.hasOBB)
857 {
858 Vector3 OBB = repData.OBB;
859 }
860 else
861 {
862 Vector3 OBB = repData.size;
863 OBB.X *= 0.5f;
864 OBB.Y *= 0.5f;
865 OBB.Z *= 0.5f;
866
867 repData.OBB = OBB;
868 repData.OBBOffset = Vector3.Zero;
869 }
870
871 CalculateBasicPrimVolume(repData);
872 }
873 }
874
875 public class ODEAssetRequest
876 {
877 ODEMeshWorker m_worker;
878 private ILog m_log;
879 ODEPhysRepData repData;
880
881 public ODEAssetRequest(ODEMeshWorker pWorker, RequestAssetDelegate provider,
882 ODEPhysRepData pRepData, ILog plog)
883 {
884 m_worker = pWorker;
885 m_log = plog;
886 repData = pRepData;
887
888 repData.meshState = MeshState.AssetFailed;
889 if (provider == null)
890 return;
891
892 if (repData.assetID == null)
893 return;
894
895 UUID assetID = (UUID) repData.assetID;
896 if (assetID == UUID.Zero)
897 return;
898
899 repData.meshState = MeshState.loadingAsset;
900 provider(assetID, ODEassetReceived);
901 }
902
903 void ODEassetReceived(AssetBase asset)
904 {
905 repData.meshState = MeshState.AssetFailed;
906 if (asset != null)
907 {
908 if (asset.Data != null && asset.Data.Length > 0)
909 {
910 repData.meshState = MeshState.noNeed;
911
912 if (!repData.pbs.SculptEntry)
913 return;
914 if (repData.pbs.SculptTexture != repData.assetID)
915 return;
916
917 repData.pbs.SculptData = new byte[asset.Data.Length];
918 asset.Data.CopyTo(repData.pbs.SculptData,0);
919 repData.meshState = MeshState.AssetOK;
920 m_worker.AssetLoaded(repData);
921 }
922 else
923 m_log.WarnFormat("[PHYSICS]: asset provider returned invalid mesh data for prim {0} asset UUID {1}.",
924 repData.actor.Name, asset.ID.ToString());
925 }
926 else
927 m_log.WarnFormat("[PHYSICS]: asset provider returned null asset fo mesh of prim {0}.",
928 repData.actor.Name);
929 }
930 }
931} \ No newline at end of file
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs
index f2f4725..ce67cc4 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs
@@ -79,7 +79,7 @@ namespace OpenSim.Region.Physics.OdePlugin
79 private bool m_lastdoneSelected; 79 private bool m_lastdoneSelected;
80 internal bool m_outbounds; 80 internal bool m_outbounds;
81 81
82 private Quaternion m_lastorientation = new Quaternion(); 82 private Quaternion m_lastorientation;
83 private Quaternion _orientation; 83 private Quaternion _orientation;
84 84
85 private Vector3 _position; 85 private Vector3 _position;
@@ -91,33 +91,30 @@ namespace OpenSim.Region.Physics.OdePlugin
91 private Vector3 _size; 91 private Vector3 _size;
92 private Vector3 _acceleration; 92 private Vector3 _acceleration;
93 private Vector3 m_angularlock = Vector3.One; 93 private Vector3 m_angularlock = Vector3.One;
94 private IntPtr Amotor = IntPtr.Zero; 94 private IntPtr Amotor;
95 95
96 private Vector3 m_force; 96 private Vector3 m_force;
97 private Vector3 m_forceacc; 97 private Vector3 m_forceacc;
98 private Vector3 m_angularForceacc; 98 private Vector3 m_angularForceacc;
99 99
100 private float m_invTimeStep = 50.0f; 100 private float m_invTimeStep;
101 private float m_timeStep = .02f; 101 private float m_timeStep;
102 102
103 private Vector3 m_PIDTarget; 103 private Vector3 m_PIDTarget;
104 private float m_PIDTau; 104 private float m_PIDTau;
105 private bool m_usePID; 105 private bool m_usePID;
106 106
107 // KF: These next 7 params apply to llSetHoverHeight(float height, integer water, float tau),
108 // and are for non-VEHICLES only.
109
110 private float m_PIDHoverHeight; 107 private float m_PIDHoverHeight;
111 private float m_PIDHoverTau; 108 private float m_PIDHoverTau;
112 private bool m_useHoverPID; 109 private bool m_useHoverPID;
113 private PIDHoverType m_PIDHoverType = PIDHoverType.Ground; 110 private PIDHoverType m_PIDHoverType;
114 private float m_targetHoverHeight; 111 private float m_targetHoverHeight;
115 private float m_groundHeight; 112 private float m_groundHeight;
116 private float m_waterHeight; 113 private float m_waterHeight;
117 private float m_buoyancy; //KF: m_buoyancy should be set by llSetBuoyancy() for non-vehicle. 114 private float m_buoyancy; //KF: m_buoyancy should be set by llSetBuoyancy() for non-vehicle.
118 115
119 private int body_autodisable_frames = 5; 116 private int body_autodisable_frames;
120 public int bodydisablecontrol = 0; 117 public int bodydisablecontrol;
121 118
122 119
123 // Default we're a Geometry 120 // Default we're a Geometry
@@ -147,12 +144,16 @@ namespace OpenSim.Region.Physics.OdePlugin
147 private IMesh m_mesh; 144 private IMesh m_mesh;
148 private object m_meshlock = new object(); 145 private object m_meshlock = new object();
149 private PrimitiveBaseShape _pbs; 146 private PrimitiveBaseShape _pbs;
147
148 private UUID? m_assetID;
149 private MeshState m_meshState;
150
150 public OdeScene _parent_scene; 151 public OdeScene _parent_scene;
151 152
152 /// <summary> 153 /// <summary>
153 /// The physics space which contains prim geometry 154 /// The physics space which contains prim geometry
154 /// </summary> 155 /// </summary>
155 public IntPtr m_targetSpace = IntPtr.Zero; 156 public IntPtr m_targetSpace;
156 157
157 public IntPtr prim_geom; 158 public IntPtr prim_geom;
158 public IntPtr _triMeshData; 159 public IntPtr _triMeshData;
@@ -166,27 +167,32 @@ namespace OpenSim.Region.Physics.OdePlugin
166 167
167 public IntPtr collide_geom; // for objects: geom if single prim space it linkset 168 public IntPtr collide_geom; // for objects: geom if single prim space it linkset
168 169
169 private float m_density = 10.000006836f; // Aluminum g/cm3; 170 private float m_density;
170 private byte m_shapetype; 171 private byte m_shapetype;
171 public bool _zeroFlag; 172 public bool _zeroFlag;
172 private bool m_lastUpdateSent; 173 private bool m_lastUpdateSent;
173 174
174 public IntPtr Body = IntPtr.Zero; 175 public IntPtr Body;
175 176
176 private Vector3 _target_velocity; 177 private Vector3 _target_velocity;
177 178
178 public Vector3 primOOBsize; // prim real dimensions from mesh 179 public Vector3 m_OBBOffset;
179 public Vector3 primOOBoffset; // its centroid out of mesh or rest aabb 180 public Vector3 m_OBB;
180 public float primOOBradiusSQ; 181 public float primOOBradiusSQ;
182
183 private bool m_hasOBB = true;
184
185 private float m_physCost;
186 private float m_streamCost;
187
181 public d.Mass primdMass; // prim inertia information on it's own referencial 188 public d.Mass primdMass; // prim inertia information on it's own referencial
182 float primMass; // prim own mass 189 float primMass; // prim own mass
183 float primVolume; // prim own volume; 190 float primVolume; // prim own volume;
184 float _mass; // object mass acording to case 191 float _mass; // object mass acording to case
185 private bool hasOOBoffsetFromMesh = false; // if true we did compute it form mesh centroid, else from aabb
186 192
187 public int givefakepos = 0; 193 public int givefakepos;
188 private Vector3 fakepos; 194 private Vector3 fakepos;
189 public int givefakeori = 0; 195 public int givefakeori;
190 private Quaternion fakeori; 196 private Quaternion fakeori;
191 197
192 private int m_eventsubscription; 198 private int m_eventsubscription;
@@ -271,7 +277,23 @@ namespace OpenSim.Region.Physics.OdePlugin
271 cdata.mu *= veh.FrictionFactor; 277 cdata.mu *= veh.FrictionFactor;
272// cdata.mu *= 0; 278// cdata.mu *= 0;
273 } 279 }
274 } 280 }
281
282 public override float PhysicsCost
283 {
284 get
285 {
286 return m_physCost;
287 }
288 }
289
290 public override float StreamCost
291 {
292 get
293 {
294 return m_streamCost;
295 }
296 }
275 297
276 public override int PhysicsActorType 298 public override int PhysicsActorType
277 { 299 {
@@ -394,7 +416,7 @@ namespace OpenSim.Region.Physics.OdePlugin
394 { 416 {
395 if (value.IsFinite()) 417 if (value.IsFinite())
396 { 418 {
397 AddChange(changes.Size, value); 419 _parent_scene.m_meshWorker.ChangeActorPhysRep(this, _pbs, value, m_shapetype);
398 } 420 }
399 else 421 else
400 { 422 {
@@ -464,7 +486,7 @@ namespace OpenSim.Region.Physics.OdePlugin
464 q.Z = dq.Z; 486 q.Z = dq.Z;
465 q.W = dq.W; 487 q.W = dq.W;
466 488
467 Vector3 Ptot = primOOBoffset * q; 489 Vector3 Ptot = m_OBBOffset * q;
468 dtmp = d.GeomGetPosition(prim_geom); 490 dtmp = d.GeomGetPosition(prim_geom);
469 Ptot.X += dtmp.X; 491 Ptot.X += dtmp.X;
470 Ptot.Y += dtmp.Y; 492 Ptot.Y += dtmp.Y;
@@ -504,7 +526,7 @@ namespace OpenSim.Region.Physics.OdePlugin
504 { 526 {
505 get 527 get
506 { 528 {
507 return primOOBsize; 529 return m_OBB;
508 } 530 }
509 } 531 }
510 532
@@ -512,7 +534,7 @@ namespace OpenSim.Region.Physics.OdePlugin
512 { 534 {
513 get 535 get
514 { 536 {
515 return primOOBoffset; 537 return m_OBBOffset;
516 } 538 }
517 } 539 }
518 540
@@ -528,7 +550,8 @@ namespace OpenSim.Region.Physics.OdePlugin
528 { 550 {
529 set 551 set
530 { 552 {
531 AddChange(changes.Shape, value); 553// AddChange(changes.Shape, value);
554 _parent_scene.m_meshWorker.ChangeActorPhysRep(this, value, _size, m_shapetype);
532 } 555 }
533 } 556 }
534 557
@@ -541,11 +564,10 @@ namespace OpenSim.Region.Physics.OdePlugin
541 set 564 set
542 { 565 {
543 m_shapetype = value; 566 m_shapetype = value;
544 AddChange(changes.Shape, null); 567 _parent_scene.m_meshWorker.ChangeActorPhysRep(this, _pbs, _size, value);
545 } 568 }
546 } 569 }
547 570
548
549 public override Vector3 Velocity 571 public override Vector3 Velocity
550 { 572 {
551 get 573 get
@@ -619,6 +641,9 @@ namespace OpenSim.Region.Physics.OdePlugin
619 { 641 {
620 fakeori = value; 642 fakeori = value;
621 givefakeori++; 643 givefakeori++;
644
645 value.Normalize();
646
622 AddChange(changes.Orientation, value); 647 AddChange(changes.Orientation, value);
623 } 648 }
624 else 649 else
@@ -1012,7 +1037,6 @@ namespace OpenSim.Region.Physics.OdePlugin
1012 m_invTimeStep = 1f / m_timeStep; 1037 m_invTimeStep = 1f / m_timeStep;
1013 1038
1014 m_density = parent_scene.geomDefaultDensity; 1039 m_density = parent_scene.geomDefaultDensity;
1015 // m_tensor = parent_scene.bodyMotorJointMaxforceTensor;
1016 body_autodisable_frames = parent_scene.bodyFramesAutoDisable; 1040 body_autodisable_frames = parent_scene.bodyFramesAutoDisable;
1017 1041
1018 prim_geom = IntPtr.Zero; 1042 prim_geom = IntPtr.Zero;
@@ -1064,7 +1088,6 @@ namespace OpenSim.Region.Physics.OdePlugin
1064 m_colliderfilter = 0; 1088 m_colliderfilter = 0;
1065 m_NoColide = false; 1089 m_NoColide = false;
1066 1090
1067 hasOOBoffsetFromMesh = false;
1068 _triMeshData = IntPtr.Zero; 1091 _triMeshData = IntPtr.Zero;
1069 1092
1070 m_shapetype = _shapeType; 1093 m_shapetype = _shapeType;
@@ -1079,27 +1102,14 @@ namespace OpenSim.Region.Physics.OdePlugin
1079 mu = parent_scene.m_materialContactsData[(int)Material.Wood].mu; 1102 mu = parent_scene.m_materialContactsData[(int)Material.Wood].mu;
1080 bounce = parent_scene.m_materialContactsData[(int)Material.Wood].bounce; 1103 bounce = parent_scene.m_materialContactsData[(int)Material.Wood].bounce;
1081 1104
1082 CalcPrimBodyData(); 1105 m_building = true; // control must set this to false when done
1083 1106
1084 m_mesh = null; 1107 // get basic mass parameters
1085 if (_parent_scene.needsMeshing(pbs) && (pbs.SculptData.Length > 0)) 1108 ODEPhysRepData repData = _parent_scene.m_meshWorker.NewActorPhysRep(this, _pbs, _size, m_shapetype);
1086 {
1087 bool convex;
1088 int clod = (int)LevelOfDetail.High;
1089 if (m_shapetype == 0)
1090 convex = false;
1091 else
1092 {
1093 convex = true;
1094 if (_pbs.SculptType != (byte)SculptType.Mesh)
1095 clod = (int)LevelOfDetail.Low;
1096 }
1097 m_mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, clod, true, convex);
1098 }
1099 1109
1100 m_building = true; // control must set this to false when done 1110 primVolume = repData.volume;
1101 1111
1102 AddChange(changes.Add, null); 1112 UpdatePrimBodyData();
1103 } 1113 }
1104 1114
1105 private void resetCollisionAccounting() 1115 private void resetCollisionAccounting()
@@ -1323,76 +1333,88 @@ namespace OpenSim.Region.Physics.OdePlugin
1323 } 1333 }
1324 } 1334 }
1325 1335
1326 private bool setMesh(OdeScene parent_scene)
1327 {
1328 IntPtr vertices, indices;
1329 int vertexCount, indexCount;
1330 int vertexStride, triStride;
1331 1336
1332 if (Body != IntPtr.Zero) 1337 private void SetGeom(IntPtr geom)
1338 {
1339 prim_geom = geom;
1340 //Console.WriteLine("SetGeom to " + prim_geom + " for " + Name);
1341 if (prim_geom != IntPtr.Zero)
1333 { 1342 {
1334 if (childPrim) 1343
1344 if (m_NoColide)
1335 { 1345 {
1336 if (_parent != null) 1346 d.GeomSetCategoryBits(prim_geom, 0);
1347 if (m_isphysical)
1337 { 1348 {
1338 OdePrim parent = (OdePrim)_parent; 1349 d.GeomSetCollideBits(prim_geom, (uint)CollisionCategories.Land);
1339 parent.ChildDelink(this, false); 1350 }
1351 else
1352 {
1353 d.GeomSetCollideBits(prim_geom, 0);
1354 d.GeomDisable(prim_geom);
1340 } 1355 }
1341 } 1356 }
1342 else 1357 else
1343 { 1358 {
1344 DestroyBody(); 1359 d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
1360 d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
1345 } 1361 }
1346 }
1347 1362
1348 IMesh mesh = null; 1363 UpdatePrimBodyData();
1364 _parent_scene.actor_name_map[prim_geom] = this;
1349 1365
1350 lock (m_meshlock) 1366/*
1351 { 1367// debug
1352 if (m_mesh == null) 1368 d.AABB aabb;
1353 { 1369 d.GeomGetAABB(prim_geom, out aabb);
1354 bool convex; 1370 float x = aabb.MaxX - aabb.MinX;
1355 int clod = (int)LevelOfDetail.High; 1371 float y = aabb.MaxY - aabb.MinY;
1372 float z = aabb.MaxZ - aabb.MinZ;
1373 if( x > 60.0f || y > 60.0f || z > 60.0f)
1374 m_log.WarnFormat("[PHYSICS]: large prim geo {0},size {1}, AABBsize <{2},{3},{4}, mesh {5} at {6}",
1375 Name, _size.ToString(), x, y, z, _pbs.SculptEntry ? _pbs.SculptTexture.ToString() : "primMesh", _position.ToString());
1376 else if (x < 0.001f || y < 0.001f || z < 0.001f)
1377 m_log.WarnFormat("[PHYSICS]: small prim geo {0},size {1}, AABBsize <{2},{3},{4}, mesh {5} at {6}",
1378 Name, _size.ToString(), x, y, z, _pbs.SculptEntry ? _pbs.SculptTexture.ToString() : "primMesh", _position.ToString());
1379
1380//
1381*/
1356 1382
1357 if (m_shapetype == 0) 1383 }
1358 convex = false; 1384 else
1359 else 1385 m_log.Warn("Setting bad Geom");
1360 { 1386 }
1361 convex = true;
1362 if (_pbs.SculptType != (byte)SculptType.Mesh)
1363 clod = (int)LevelOfDetail.Low;
1364 }
1365 1387
1366 mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, clod, true, convex); 1388 private bool GetMeshGeom()
1367 } 1389 {
1368 else 1390 IntPtr vertices, indices;
1369 { 1391 int vertexCount, indexCount;
1370 mesh = m_mesh; 1392 int vertexStride, triStride;
1371 } 1393
1394 IMesh mesh = m_mesh;
1372 1395
1373 if (mesh == null) 1396 if (mesh == null)
1374 { 1397 return false;
1375 m_log.WarnFormat("[PHYSICS]: CreateMesh Failed on prim {0} at <{1},{2},{3}>.", Name, _position.X, _position.Y, _position.Z);
1376 return false;
1377 }
1378 1398
1399 mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount);
1400 mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount);
1379 1401
1380 mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount); // Note, that vertices are fixed in unmanaged heap 1402 if (vertexCount == 0 || indexCount == 0)
1381 mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount); // Also fixed, needs release after usage 1403 {
1404 m_log.WarnFormat("[PHYSICS]: Invalid mesh data on OdePrim {0}, mesh {1}",
1405 Name, _pbs.SculptEntry ? _pbs.SculptTexture.ToString() : "primMesh");
1382 1406
1383 if (vertexCount == 0 || indexCount == 0) 1407 m_hasOBB = false;
1384 { 1408 m_OBBOffset = Vector3.Zero;
1385 m_log.WarnFormat("[PHYSICS]: Got invalid mesh on prim {0} at <{1},{2},{3}>. mesh UUID {4}", 1409 m_OBB = _size * 0.5f;
1386 Name, _position.X, _position.Y, _position.Z, _pbs.SculptTexture.ToString());
1387 mesh.releaseSourceMeshData();
1388 return false;
1389 }
1390 1410
1391 primOOBoffset = mesh.GetCentroid(); 1411 m_physCost = 0.1f;
1392 hasOOBoffsetFromMesh = true; 1412 m_streamCost = 1.0f;
1393 1413
1394 mesh.releaseSourceMeshData(); 1414 _parent_scene.mesher.ReleaseMesh(mesh);
1395 m_mesh = mesh; 1415 m_meshState = MeshState.MeshFailed;
1416 m_mesh = null;
1417 return false;
1396 } 1418 }
1397 1419
1398 IntPtr geo = IntPtr.Zero; 1420 IntPtr geo = IntPtr.Zero;
@@ -1404,7 +1426,6 @@ namespace OpenSim.Region.Physics.OdePlugin
1404 d.GeomTriMeshDataBuildSimple(_triMeshData, vertices, vertexStride, vertexCount, indices, indexCount, triStride); 1426 d.GeomTriMeshDataBuildSimple(_triMeshData, vertices, vertexStride, vertexCount, indices, indexCount, triStride);
1405 d.GeomTriMeshDataPreprocess(_triMeshData); 1427 d.GeomTriMeshDataPreprocess(_triMeshData);
1406 1428
1407 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1408 geo = d.CreateTriMesh(m_targetSpace, _triMeshData, null, null, null); 1429 geo = d.CreateTriMesh(m_targetSpace, _triMeshData, null, null, null);
1409 } 1430 }
1410 1431
@@ -1413,85 +1434,65 @@ namespace OpenSim.Region.Physics.OdePlugin
1413 m_log.ErrorFormat("[PHYSICS]: SetGeom Mesh failed for {0} exception: {1}", Name, e); 1434 m_log.ErrorFormat("[PHYSICS]: SetGeom Mesh failed for {0} exception: {1}", Name, e);
1414 if (_triMeshData != IntPtr.Zero) 1435 if (_triMeshData != IntPtr.Zero)
1415 { 1436 {
1416 d.GeomTriMeshDataDestroy(_triMeshData); 1437 try
1417 _triMeshData = IntPtr.Zero;
1418 }
1419 return false;
1420 }
1421
1422 SetGeom(geo);
1423 return true;
1424 }
1425
1426 private void SetGeom(IntPtr geom)
1427 {
1428 prim_geom = geom;
1429 //Console.WriteLine("SetGeom to " + prim_geom + " for " + Name);
1430 if (prim_geom != IntPtr.Zero)
1431 {
1432
1433 if (m_NoColide)
1434 {
1435 d.GeomSetCategoryBits(prim_geom, 0);
1436 if (m_isphysical)
1437 { 1438 {
1438 d.GeomSetCollideBits(prim_geom, (uint)CollisionCategories.Land); 1439 d.GeomTriMeshDataDestroy(_triMeshData);
1439 } 1440 }
1440 else 1441 catch
1441 { 1442 {
1442 d.GeomSetCollideBits(prim_geom, 0);
1443 d.GeomDisable(prim_geom);
1444 } 1443 }
1445 } 1444 }
1446 else 1445 _triMeshData = IntPtr.Zero;
1447 {
1448 d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
1449 d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
1450 }
1451 1446
1452 CalcPrimBodyData(); 1447 m_hasOBB = false;
1448 m_OBBOffset = Vector3.Zero;
1449 m_OBB = _size * 0.5f;
1450 m_physCost = 0.1f;
1451 m_streamCost = 1.0f;
1452
1453 _parent_scene.mesher.ReleaseMesh(mesh);
1454 m_meshState = MeshState.MeshFailed;
1455 m_mesh = null;
1456 return false;
1457 }
1453 1458
1454 _parent_scene.actor_name_map[prim_geom] = this; 1459 m_physCost = 0.0013f * (float)indexCount;
1460 // todo
1461 m_streamCost = 1.0f;
1455 1462
1456 } 1463 SetGeom(geo);
1457 else
1458 m_log.Warn("Setting bad Geom");
1459 }
1460 1464
1465 return true;
1466 }
1461 1467
1462 /// <summary>
1463 /// Create a geometry for the given mesh in the given target space.
1464 /// </summary>
1465 /// <param name="m_targetSpace"></param>
1466 /// <param name="mesh">If null, then a mesh is used that is based on the profile shape data.</param>
1467 private void CreateGeom() 1468 private void CreateGeom()
1468 { 1469 {
1469 if (_triMeshData != IntPtr.Zero) 1470 bool hasMesh = false;
1470 {
1471 d.GeomTriMeshDataDestroy(_triMeshData);
1472 _triMeshData = IntPtr.Zero;
1473 }
1474 1471
1475 bool haveMesh = false;
1476 hasOOBoffsetFromMesh = false;
1477 m_NoColide = false; 1472 m_NoColide = false;
1478 1473
1479 if (_parent_scene.needsMeshing(_pbs)) 1474 if ((m_meshState & MeshState.MeshNoColide) != 0)
1475 m_NoColide = true;
1476
1477 else if(m_mesh != null)
1480 { 1478 {
1481 haveMesh = setMesh(_parent_scene); // this will give a mesh to non trivial known prims 1479 if (GetMeshGeom())
1482 if (!haveMesh) 1480 hasMesh = true;
1481 else
1483 m_NoColide = true; 1482 m_NoColide = true;
1484 } 1483 }
1485 1484
1486 if (!haveMesh) 1485
1486 if (!hasMesh)
1487 { 1487 {
1488 IntPtr geo = IntPtr.Zero;
1489
1488 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1 1490 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1
1489 && _size.X == _size.Y && _size.Y == _size.Z) 1491 && _size.X == _size.Y && _size.Y == _size.Z)
1490 { // it's a sphere 1492 { // it's a sphere
1491 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1492 try 1493 try
1493 { 1494 {
1494 SetGeom(d.CreateSphere(m_targetSpace, _size.X * 0.5f)); 1495 geo = d.CreateSphere(m_targetSpace, _size.X * 0.5f);
1495 } 1496 }
1496 catch (Exception e) 1497 catch (Exception e)
1497 { 1498 {
@@ -1501,11 +1502,9 @@ namespace OpenSim.Region.Physics.OdePlugin
1501 } 1502 }
1502 else 1503 else
1503 {// do it as a box 1504 {// do it as a box
1504 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1505 try 1505 try
1506 { 1506 {
1507 //Console.WriteLine(" CreateGeom 4"); 1507 geo = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
1508 SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
1509 } 1508 }
1510 catch (Exception e) 1509 catch (Exception e)
1511 { 1510 {
@@ -1513,19 +1512,18 @@ namespace OpenSim.Region.Physics.OdePlugin
1513 return; 1512 return;
1514 } 1513 }
1515 } 1514 }
1515 m_physCost = 0.1f;
1516 m_streamCost = 1.0f;
1517 SetGeom(geo);
1516 } 1518 }
1517 } 1519 }
1518 1520
1519 /// <summary>
1520 /// Set a new geometry for this prim.
1521 /// </summary>
1522 /// <param name="geom"></param>
1523 private void RemoveGeom() 1521 private void RemoveGeom()
1524 { 1522 {
1525 if (prim_geom != IntPtr.Zero) 1523 if (prim_geom != IntPtr.Zero)
1526 { 1524 {
1527// _parent_scene.geom_name_map.Remove(prim_geom);
1528 _parent_scene.actor_name_map.Remove(prim_geom); 1525 _parent_scene.actor_name_map.Remove(prim_geom);
1526
1529 try 1527 try
1530 { 1528 {
1531 d.GeomDestroy(prim_geom); 1529 d.GeomDestroy(prim_geom);
@@ -1534,11 +1532,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1534 d.GeomTriMeshDataDestroy(_triMeshData); 1532 d.GeomTriMeshDataDestroy(_triMeshData);
1535 _triMeshData = IntPtr.Zero; 1533 _triMeshData = IntPtr.Zero;
1536 } 1534 }
1537
1538 } 1535 }
1539
1540
1541 // catch (System.AccessViolationException)
1542 catch (Exception e) 1536 catch (Exception e)
1543 { 1537 {
1544 m_log.ErrorFormat("[PHYSICS]: PrimGeom destruction failed for {0} exception {1}", Name, e); 1538 m_log.ErrorFormat("[PHYSICS]: PrimGeom destruction failed for {0} exception {1}", Name, e);
@@ -1546,29 +1540,26 @@ namespace OpenSim.Region.Physics.OdePlugin
1546 1540
1547 prim_geom = IntPtr.Zero; 1541 prim_geom = IntPtr.Zero;
1548 collide_geom = IntPtr.Zero; 1542 collide_geom = IntPtr.Zero;
1543 m_targetSpace = IntPtr.Zero;
1549 } 1544 }
1550 else 1545 else
1551 { 1546 {
1552 m_log.ErrorFormat("[PHYSICS]: PrimGeom destruction BAD {0}", Name); 1547 m_log.ErrorFormat("[PHYSICS]: PrimGeom destruction BAD {0}", Name);
1553 } 1548 }
1554 1549
1555 if (m_mesh != null) 1550 lock (m_meshlock)
1556 { 1551 {
1557 _parent_scene.mesher.ReleaseMesh(m_mesh); 1552 if (m_mesh != null)
1558 m_mesh = null; 1553 {
1554 _parent_scene.mesher.ReleaseMesh(m_mesh);
1555 m_mesh = null;
1556 }
1559 } 1557 }
1560 1558
1561 Body = IntPtr.Zero; 1559 Body = IntPtr.Zero;
1562 hasOOBoffsetFromMesh = false; 1560 m_hasOBB = false;
1563 } 1561 }
1564/* 1562
1565 private void ChildSetGeom(OdePrim odePrim)
1566 {
1567 // well..
1568 DestroyBody();
1569 MakeBody();
1570 }
1571*/
1572 //sets non physical prim m_targetSpace to right space in spaces grid for static prims 1563 //sets non physical prim m_targetSpace to right space in spaces grid for static prims
1573 // should only be called for non physical prims unless they are becoming non physical 1564 // should only be called for non physical prims unless they are becoming non physical
1574 private void SetInStaticSpace(OdePrim prim) 1565 private void SetInStaticSpace(OdePrim prim)
@@ -1631,9 +1622,6 @@ namespace OpenSim.Region.Physics.OdePlugin
1631 1622
1632 if (Body != IntPtr.Zero) 1623 if (Body != IntPtr.Zero)
1633 { 1624 {
1634// d.BodyDestroy(Body);
1635// Body = IntPtr.Zero;
1636 // do a more complet destruction
1637 DestroyBody(); 1625 DestroyBody();
1638 m_log.Warn("[PHYSICS]: MakeBody called having a body"); 1626 m_log.Warn("[PHYSICS]: MakeBody called having a body");
1639 } 1627 }
@@ -2143,339 +2131,9 @@ namespace OpenSim.Region.Physics.OdePlugin
2143 2131
2144 #region Mass Calculation 2132 #region Mass Calculation
2145 2133
2146 private float CalculatePrimVolume() 2134 private void UpdatePrimBodyData()
2147 { 2135 {
2148 float volume = _size.X * _size.Y * _size.Z; // default 2136 primMass = m_density * primVolume;
2149 float tmp;
2150
2151 float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f;
2152 float hollowVolume = hollowAmount * hollowAmount;
2153
2154 switch (_pbs.ProfileShape)
2155 {
2156 case ProfileShape.Square:
2157 // default box
2158
2159 if (_pbs.PathCurve == (byte)Extrusion.Straight)
2160 {
2161 if (hollowAmount > 0.0)
2162 {
2163 switch (_pbs.HollowShape)
2164 {
2165 case HollowShape.Square:
2166 case HollowShape.Same:
2167 break;
2168
2169 case HollowShape.Circle:
2170
2171 hollowVolume *= 0.78539816339f;
2172 break;
2173
2174 case HollowShape.Triangle:
2175
2176 hollowVolume *= (0.5f * .5f);
2177 break;
2178
2179 default:
2180 hollowVolume = 0;
2181 break;
2182 }
2183 volume *= (1.0f - hollowVolume);
2184 }
2185 }
2186
2187 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
2188 {
2189 //a tube
2190
2191 volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX);
2192 tmp = 1.0f - 2.0e-2f * (float)(200 - _pbs.PathScaleY);
2193 volume -= volume * tmp * tmp;
2194
2195 if (hollowAmount > 0.0)
2196 {
2197 hollowVolume *= hollowAmount;
2198
2199 switch (_pbs.HollowShape)
2200 {
2201 case HollowShape.Square:
2202 case HollowShape.Same:
2203 break;
2204
2205 case HollowShape.Circle:
2206 hollowVolume *= 0.78539816339f;
2207 break;
2208
2209 case HollowShape.Triangle:
2210 hollowVolume *= 0.5f * 0.5f;
2211 break;
2212 default:
2213 hollowVolume = 0;
2214 break;
2215 }
2216 volume *= (1.0f - hollowVolume);
2217 }
2218 }
2219
2220 break;
2221
2222 case ProfileShape.Circle:
2223
2224 if (_pbs.PathCurve == (byte)Extrusion.Straight)
2225 {
2226 volume *= 0.78539816339f; // elipse base
2227
2228 if (hollowAmount > 0.0)
2229 {
2230 switch (_pbs.HollowShape)
2231 {
2232 case HollowShape.Same:
2233 case HollowShape.Circle:
2234 break;
2235
2236 case HollowShape.Square:
2237 hollowVolume *= 0.5f * 2.5984480504799f;
2238 break;
2239
2240 case HollowShape.Triangle:
2241 hollowVolume *= .5f * 1.27323954473516f;
2242 break;
2243
2244 default:
2245 hollowVolume = 0;
2246 break;
2247 }
2248 volume *= (1.0f - hollowVolume);
2249 }
2250 }
2251
2252 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
2253 {
2254 volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX);
2255 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
2256 volume *= (1.0f - tmp * tmp);
2257
2258 if (hollowAmount > 0.0)
2259 {
2260
2261 // calculate the hollow volume by it's shape compared to the prim shape
2262 hollowVolume *= hollowAmount;
2263
2264 switch (_pbs.HollowShape)
2265 {
2266 case HollowShape.Same:
2267 case HollowShape.Circle:
2268 break;
2269
2270 case HollowShape.Square:
2271 hollowVolume *= 0.5f * 2.5984480504799f;
2272 break;
2273
2274 case HollowShape.Triangle:
2275 hollowVolume *= .5f * 1.27323954473516f;
2276 break;
2277
2278 default:
2279 hollowVolume = 0;
2280 break;
2281 }
2282 volume *= (1.0f - hollowVolume);
2283 }
2284 }
2285 break;
2286
2287 case ProfileShape.HalfCircle:
2288 if (_pbs.PathCurve == (byte)Extrusion.Curve1)
2289 {
2290 volume *= 0.5236f;
2291
2292 if (hollowAmount > 0.0)
2293 {
2294 hollowVolume *= hollowAmount;
2295
2296 switch (_pbs.HollowShape)
2297 {
2298 case HollowShape.Circle:
2299 case HollowShape.Triangle: // diference in sl is minor and odd
2300 case HollowShape.Same:
2301 break;
2302
2303 case HollowShape.Square:
2304 hollowVolume *= 0.909f;
2305 break;
2306
2307 // case HollowShape.Triangle:
2308 // hollowVolume *= .827f;
2309 // break;
2310 default:
2311 hollowVolume = 0;
2312 break;
2313 }
2314 volume *= (1.0f - hollowVolume);
2315 }
2316
2317 }
2318 break;
2319
2320 case ProfileShape.EquilateralTriangle:
2321
2322 if (_pbs.PathCurve == (byte)Extrusion.Straight)
2323 {
2324 volume *= 0.32475953f;
2325
2326 if (hollowAmount > 0.0)
2327 {
2328
2329 // calculate the hollow volume by it's shape compared to the prim shape
2330 switch (_pbs.HollowShape)
2331 {
2332 case HollowShape.Same:
2333 case HollowShape.Triangle:
2334 hollowVolume *= .25f;
2335 break;
2336
2337 case HollowShape.Square:
2338 hollowVolume *= 0.499849f * 3.07920140172638f;
2339 break;
2340
2341 case HollowShape.Circle:
2342 // Hollow shape is a perfect cyllinder in respect to the cube's scale
2343 // Cyllinder hollow volume calculation
2344
2345 hollowVolume *= 0.1963495f * 3.07920140172638f;
2346 break;
2347
2348 default:
2349 hollowVolume = 0;
2350 break;
2351 }
2352 volume *= (1.0f - hollowVolume);
2353 }
2354 }
2355 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
2356 {
2357 volume *= 0.32475953f;
2358 volume *= 0.01f * (float)(200 - _pbs.PathScaleX);
2359 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
2360 volume *= (1.0f - tmp * tmp);
2361
2362 if (hollowAmount > 0.0)
2363 {
2364
2365 hollowVolume *= hollowAmount;
2366
2367 switch (_pbs.HollowShape)
2368 {
2369 case HollowShape.Same:
2370 case HollowShape.Triangle:
2371 hollowVolume *= .25f;
2372 break;
2373
2374 case HollowShape.Square:
2375 hollowVolume *= 0.499849f * 3.07920140172638f;
2376 break;
2377
2378 case HollowShape.Circle:
2379
2380 hollowVolume *= 0.1963495f * 3.07920140172638f;
2381 break;
2382
2383 default:
2384 hollowVolume = 0;
2385 break;
2386 }
2387 volume *= (1.0f - hollowVolume);
2388 }
2389 }
2390 break;
2391
2392 default:
2393 break;
2394 }
2395
2396 float taperX1;
2397 float taperY1;
2398 float taperX;
2399 float taperY;
2400 float pathBegin;
2401 float pathEnd;
2402 float profileBegin;
2403 float profileEnd;
2404
2405 if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible)
2406 {
2407 taperX1 = _pbs.PathScaleX * 0.01f;
2408 if (taperX1 > 1.0f)
2409 taperX1 = 2.0f - taperX1;
2410 taperX = 1.0f - taperX1;
2411
2412 taperY1 = _pbs.PathScaleY * 0.01f;
2413 if (taperY1 > 1.0f)
2414 taperY1 = 2.0f - taperY1;
2415 taperY = 1.0f - taperY1;
2416 }
2417 else
2418 {
2419 taperX = _pbs.PathTaperX * 0.01f;
2420 if (taperX < 0.0f)
2421 taperX = -taperX;
2422 taperX1 = 1.0f - taperX;
2423
2424 taperY = _pbs.PathTaperY * 0.01f;
2425 if (taperY < 0.0f)
2426 taperY = -taperY;
2427 taperY1 = 1.0f - taperY;
2428 }
2429
2430 volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY);
2431
2432 pathBegin = (float)_pbs.PathBegin * 2.0e-5f;
2433 pathEnd = 1.0f - (float)_pbs.PathEnd * 2.0e-5f;
2434 volume *= (pathEnd - pathBegin);
2435
2436 // this is crude aproximation
2437 profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f;
2438 profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f;
2439 volume *= (profileEnd - profileBegin);
2440
2441 return volume;
2442 }
2443
2444
2445 private void CalcPrimBodyData()
2446 {
2447 float volume;
2448
2449 if (prim_geom == IntPtr.Zero)
2450 {
2451 // Ubit let's have a initial basic OOB
2452 primOOBsize.X = _size.X;
2453 primOOBsize.Y = _size.Y;
2454 primOOBsize.Z = _size.Z;
2455 primOOBoffset = Vector3.Zero;
2456 }
2457 else
2458 {
2459 d.AABB AABB;
2460 d.GeomGetAABB(prim_geom, out AABB); // get the AABB from engine geom
2461
2462 primOOBsize.X = (AABB.MaxX - AABB.MinX);
2463 primOOBsize.Y = (AABB.MaxY - AABB.MinY);
2464 primOOBsize.Z = (AABB.MaxZ - AABB.MinZ);
2465 if (!hasOOBoffsetFromMesh)
2466 {
2467 primOOBoffset.X = (AABB.MaxX + AABB.MinX) * 0.5f;
2468 primOOBoffset.Y = (AABB.MaxY + AABB.MinY) * 0.5f;
2469 primOOBoffset.Z = (AABB.MaxZ + AABB.MinZ) * 0.5f;
2470 }
2471 }
2472
2473 // also its own inertia and mass
2474 // keep using basic shape mass for now
2475 volume = CalculatePrimVolume();
2476
2477 primVolume = volume;
2478 primMass = m_density * volume;
2479 2137
2480 if (primMass <= 0) 2138 if (primMass <= 0)
2481 primMass = 0.0001f;//ckrinke: Mass must be greater then zero. 2139 primMass = 0.0001f;//ckrinke: Mass must be greater then zero.
@@ -2484,17 +2142,31 @@ namespace OpenSim.Region.Physics.OdePlugin
2484 2142
2485 _mass = primMass; // just in case 2143 _mass = primMass; // just in case
2486 2144
2487 d.MassSetBoxTotal(out primdMass, primMass, primOOBsize.X, primOOBsize.Y, primOOBsize.Z); 2145 d.MassSetBoxTotal(out primdMass, primMass, m_OBB.X, m_OBB.Y, m_OBB.Z);
2488 2146
2489 d.MassTranslate(ref primdMass, 2147 d.MassTranslate(ref primdMass,
2490 primOOBoffset.X, 2148 m_OBBOffset.X,
2491 primOOBoffset.Y, 2149 m_OBBOffset.Y,
2492 primOOBoffset.Z); 2150 m_OBBOffset.Z);
2493 2151
2494 primOOBsize *= 0.5f; // let obb size be a corner coords 2152 primOOBradiusSQ = m_OBB.LengthSquared();
2495 primOOBradiusSQ = primOOBsize.LengthSquared();
2496 }
2497 2153
2154 if (_triMeshData != IntPtr.Zero)
2155 {
2156 float pc = m_physCost;
2157 float psf = primOOBradiusSQ;
2158 psf *= 1.33f * .2f;
2159 pc *= psf;
2160 if (pc < 0.1f)
2161 pc = 0.1f;
2162
2163 m_physCost = pc;
2164 }
2165 else
2166 m_physCost = 0.1f;
2167
2168 m_streamCost = 1.0f;
2169 }
2498 2170
2499 #endregion 2171 #endregion
2500 2172
@@ -2575,6 +2247,14 @@ namespace OpenSim.Region.Physics.OdePlugin
2575 _orientation.Y = qtmp.Y; 2247 _orientation.Y = qtmp.Y;
2576 _orientation.Z = qtmp.Z; 2248 _orientation.Z = qtmp.Z;
2577 _orientation.W = qtmp.W; 2249 _orientation.W = qtmp.W;
2250/*
2251// Debug
2252 float qlen = _orientation.Length();
2253 if (qlen > 1.01f || qlen < 0.99)
2254 m_log.WarnFormat("[PHYSICS]: Got nonnorm quaternion from geom in Object {0} norm {1}", Name, qlen);
2255//
2256*/
2257 _orientation.Normalize();
2578 2258
2579 d.Vector3 lpos = d.GeomGetPosition(prim_geom); 2259 d.Vector3 lpos = d.GeomGetPosition(prim_geom);
2580 _position.X = lpos.X; 2260 _position.X = lpos.X;
@@ -2684,27 +2364,6 @@ namespace OpenSim.Region.Physics.OdePlugin
2684 2364
2685 private void changeadd() 2365 private void changeadd()
2686 { 2366 {
2687 CreateGeom();
2688
2689 if (prim_geom != IntPtr.Zero)
2690 {
2691 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
2692 d.Quaternion myrot = new d.Quaternion();
2693 myrot.X = _orientation.X;
2694 myrot.Y = _orientation.Y;
2695 myrot.Z = _orientation.Z;
2696 myrot.W = _orientation.W;
2697 d.GeomSetQuaternion(prim_geom, ref myrot);
2698
2699 if (!m_isphysical)
2700 {
2701 SetInStaticSpace(this);
2702 UpdateCollisionCatFlags();
2703 ApplyCollisionCatFlags();
2704 }
2705 else
2706 MakeBody();
2707 }
2708 } 2367 }
2709 2368
2710 private void changeAngularLock(Vector3 newLock) 2369 private void changeAngularLock(Vector3 newLock)
@@ -2774,6 +2433,9 @@ namespace OpenSim.Region.Physics.OdePlugin
2774 _target_velocity = Vector3.Zero; 2433 _target_velocity = Vector3.Zero;
2775 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE) 2434 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
2776 m_vehicle.Stop(); 2435 m_vehicle.Stop();
2436
2437 _zeroFlag = false;
2438 base.RequestPhysicsterseUpdate();
2777 } 2439 }
2778 2440
2779 if (Body != IntPtr.Zero) 2441 if (Body != IntPtr.Zero)
@@ -3148,7 +2810,63 @@ namespace OpenSim.Region.Physics.OdePlugin
3148 resetCollisionAccounting(); 2810 resetCollisionAccounting();
3149 } 2811 }
3150 2812
3151 private void changeprimsizeshape() 2813 private void changeSize(Vector3 newSize)
2814 {
2815 }
2816
2817 private void changeShape(PrimitiveBaseShape newShape)
2818 {
2819 }
2820
2821 private void changeAddPhysRep(ODEPhysRepData repData)
2822 {
2823 _size = repData.size; //??
2824 _pbs = repData.pbs;
2825 m_shapetype = repData.shapetype;
2826
2827 m_mesh = repData.mesh;
2828
2829 m_assetID = repData.assetID;
2830 m_meshState = repData.meshState;
2831
2832 m_hasOBB = repData.hasOBB;
2833 m_OBBOffset = repData.OBBOffset;
2834 m_OBB = repData.OBB;
2835
2836 primVolume = repData.volume;
2837
2838 CreateGeom();
2839
2840 if (prim_geom != IntPtr.Zero)
2841 {
2842 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
2843 d.Quaternion myrot = new d.Quaternion();
2844 myrot.X = _orientation.X;
2845 myrot.Y = _orientation.Y;
2846 myrot.Z = _orientation.Z;
2847 myrot.W = _orientation.W;
2848 d.GeomSetQuaternion(prim_geom, ref myrot);
2849 }
2850
2851 if (!m_isphysical)
2852 {
2853 SetInStaticSpace(this);
2854 UpdateCollisionCatFlags();
2855 ApplyCollisionCatFlags();
2856 }
2857 else
2858 MakeBody();
2859
2860 if ((m_meshState & MeshState.NeedMask) != 0)
2861 {
2862 repData.size = _size;
2863 repData.pbs = _pbs;
2864 repData.shapetype = m_shapetype;
2865 _parent_scene.m_meshWorker.RequestMesh(repData);
2866 }
2867 }
2868
2869 private void changePhysRepData(ODEPhysRepData repData)
3152 { 2870 {
3153 CheckDelaySelect(); 2871 CheckDelaySelect();
3154 2872
@@ -3170,16 +2888,22 @@ namespace OpenSim.Region.Physics.OdePlugin
3170 2888
3171 RemoveGeom(); 2889 RemoveGeom();
3172 2890
3173 // we don't need to do space calculation because the client sends a position update also. 2891 _size = repData.size;
3174 if (_size.X <= 0) 2892 _pbs = repData.pbs;
3175 _size.X = 0.01f; 2893 m_shapetype = repData.shapetype;
3176 if (_size.Y <= 0)
3177 _size.Y = 0.01f;
3178 if (_size.Z <= 0)
3179 _size.Z = 0.01f;
3180 // Construction of new prim
3181 2894
3182 CreateGeom(); 2895 m_mesh = repData.mesh;
2896
2897 m_assetID = repData.assetID;
2898 m_meshState = repData.meshState;
2899
2900 m_hasOBB = repData.hasOBB;
2901 m_OBBOffset = repData.OBBOffset;
2902 m_OBB = repData.OBB;
2903
2904 primVolume = repData.volume;
2905
2906 CreateGeom();
3183 2907
3184 if (prim_geom != IntPtr.Zero) 2908 if (prim_geom != IntPtr.Zero)
3185 { 2909 {
@@ -3202,29 +2926,24 @@ namespace OpenSim.Region.Physics.OdePlugin
3202 } 2926 }
3203 } 2927 }
3204 else 2928 else
3205 MakeBody(); 2929 MakeBody();
3206 } 2930 }
3207
3208 else 2931 else
3209 { 2932 {
2933 SetInStaticSpace(this);
3210 UpdateCollisionCatFlags(); 2934 UpdateCollisionCatFlags();
3211 ApplyCollisionCatFlags(); 2935 ApplyCollisionCatFlags();
3212 } 2936 }
3213 2937
3214 resetCollisionAccounting(); 2938 resetCollisionAccounting();
3215 }
3216
3217 private void changeSize(Vector3 newSize)
3218 {
3219 _size = newSize;
3220 changeprimsizeshape();
3221 }
3222 2939
3223 private void changeShape(PrimitiveBaseShape newShape) 2940 if ((m_meshState & MeshState.NeedMask) != 0)
3224 { 2941 {
3225 if(newShape != null) 2942 repData.size = _size;
3226 _pbs = newShape; 2943 repData.pbs = _pbs;
3227 changeprimsizeshape(); 2944 repData.shapetype = m_shapetype;
2945 _parent_scene.m_meshWorker.RequestMesh(repData);
2946 }
3228 } 2947 }
3229 2948
3230 private void changeFloatOnWater(bool newval) 2949 private void changeFloatOnWater(bool newval)
@@ -3891,7 +3610,7 @@ namespace OpenSim.Region.Physics.OdePlugin
3891 3610
3892 public bool DoAChange(changes what, object arg) 3611 public bool DoAChange(changes what, object arg)
3893 { 3612 {
3894 if (prim_geom == IntPtr.Zero && what != changes.Add && what != changes.Remove) 3613 if (prim_geom == IntPtr.Zero && what != changes.Add && what != changes.AddPhysRep && what != changes.Remove)
3895 { 3614 {
3896 return false; 3615 return false;
3897 } 3616 }
@@ -3902,6 +3621,11 @@ namespace OpenSim.Region.Physics.OdePlugin
3902 case changes.Add: 3621 case changes.Add:
3903 changeadd(); 3622 changeadd();
3904 break; 3623 break;
3624
3625 case changes.AddPhysRep:
3626 changeAddPhysRep((ODEPhysRepData)arg);
3627 break;
3628
3905 case changes.Remove: 3629 case changes.Remove:
3906 //If its being removed, we don't want to rebuild the physical rep at all, so ignore this stuff... 3630 //If its being removed, we don't want to rebuild the physical rep at all, so ignore this stuff...
3907 //When we return true, it destroys all of the prims in the linkset anyway 3631 //When we return true, it destroys all of the prims in the linkset anyway
@@ -3984,6 +3708,10 @@ namespace OpenSim.Region.Physics.OdePlugin
3984 changeShape((PrimitiveBaseShape)arg); 3708 changeShape((PrimitiveBaseShape)arg);
3985 break; 3709 break;
3986 3710
3711 case changes.PhysRepData:
3712 changePhysRepData((ODEPhysRepData) arg);
3713 break;
3714
3987 case changes.CollidesWater: 3715 case changes.CollidesWater:
3988 changeFloatOnWater((bool)arg); 3716 changeFloatOnWater((bool)arg);
3989 break; 3717 break;
@@ -4072,6 +3800,8 @@ namespace OpenSim.Region.Physics.OdePlugin
4072 donullchange(); 3800 donullchange();
4073 break; 3801 break;
4074 3802
3803
3804
4075 default: 3805 default:
4076 donullchange(); 3806 donullchange();
4077 break; 3807 break;
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs
index 21fe9c0..799a324 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs
@@ -129,7 +129,7 @@ namespace OpenSim.Region.Physics.OdePlugin
129 req.length = length; 129 req.length = length;
130 req.Normal = direction; 130 req.Normal = direction;
131 req.Origin = position; 131 req.Origin = position;
132 req.filter = RayFilterFlags.AllPrims; 132 req.filter = RayFilterFlags.AllPrims | RayFilterFlags.land;
133 133
134 m_PendingRequests.Enqueue(req); 134 m_PendingRequests.Enqueue(req);
135 } 135 }
@@ -288,7 +288,10 @@ namespace OpenSim.Region.Physics.OdePlugin
288 catflags |= CollisionCategories.Water; 288 catflags |= CollisionCategories.Water;
289 289
290 if (catflags != 0) 290 if (catflags != 0)
291 {
292 d.GeomSetCollideBits(ray, (uint)catflags);
291 doSpaceRay(req); 293 doSpaceRay(req);
294 }
292 } 295 }
293 else 296 else
294 { 297 {
@@ -314,7 +317,8 @@ namespace OpenSim.Region.Physics.OdePlugin
314 /// 317 ///
315 318
316 private const RayFilterFlags FilterActiveSpace = RayFilterFlags.agent | RayFilterFlags.physical | RayFilterFlags.LSLPhanton; 319 private const RayFilterFlags FilterActiveSpace = RayFilterFlags.agent | RayFilterFlags.physical | RayFilterFlags.LSLPhanton;
317 private const RayFilterFlags FilterStaticSpace = RayFilterFlags.water | RayFilterFlags.land | RayFilterFlags.nonphysical | RayFilterFlags.LSLPhanton; 320// private const RayFilterFlags FilterStaticSpace = RayFilterFlags.water | RayFilterFlags.land | RayFilterFlags.nonphysical | RayFilterFlags.LSLPhanton;
321 private const RayFilterFlags FilterStaticSpace = RayFilterFlags.water | RayFilterFlags.nonphysical | RayFilterFlags.LSLPhanton;
318 322
319 private void doSpaceRay(ODERayRequest req) 323 private void doSpaceRay(ODERayRequest req)
320 { 324 {
@@ -323,6 +327,16 @@ namespace OpenSim.Region.Physics.OdePlugin
323 d.SpaceCollide2(ray, m_scene.ActiveSpace, IntPtr.Zero, nearCallback); 327 d.SpaceCollide2(ray, m_scene.ActiveSpace, IntPtr.Zero, nearCallback);
324 if ((CurrentRayFilter & FilterStaticSpace) != 0 && (m_contactResults.Count < CurrentMaxCount)) 328 if ((CurrentRayFilter & FilterStaticSpace) != 0 && (m_contactResults.Count < CurrentMaxCount))
325 d.SpaceCollide2(ray, m_scene.StaticSpace, IntPtr.Zero, nearCallback); 329 d.SpaceCollide2(ray, m_scene.StaticSpace, IntPtr.Zero, nearCallback);
330 if ((CurrentRayFilter & RayFilterFlags.land) != 0 && (m_contactResults.Count < CurrentMaxCount))
331 {
332 // current ode land to ray collisions is very bad
333 // so for now limit its range badly
334
335 if (req.length > 30.0f)
336 d.GeomRaySetLength(ray, 30.0f);
337
338 d.SpaceCollide2(ray, m_scene.GroundSpace, IntPtr.Zero, nearCallback);
339 }
326 340
327 if (req.callbackMethod is RaycastCallback) 341 if (req.callbackMethod is RaycastCallback)
328 { 342 {
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs
index f126644..b98f177 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs
@@ -60,6 +60,7 @@ namespace OpenSim.Region.Physics.OdePlugin
60 public int lastframe; 60 public int lastframe;
61 } 61 }
62 62
63
63 // colision flags of things others can colide with 64 // colision flags of things others can colide with
64 // rays, sensors, probes removed since can't be colided with 65 // rays, sensors, probes removed since can't be colided with
65 // The top space where things are placed provided further selection 66 // The top space where things are placed provided further selection
@@ -109,7 +110,7 @@ namespace OpenSim.Region.Physics.OdePlugin
109 110
110 light = 7 // compatibility with old viewers 111 light = 7 // compatibility with old viewers
111 } 112 }
112 113
113 public enum changes : int 114 public enum changes : int
114 { 115 {
115 Add = 0, // arg null. finishs the prim creation. should be used internally only ( to remove later ?) 116 Add = 0, // arg null. finishs the prim creation. should be used internally only ( to remove later ?)
@@ -147,6 +148,8 @@ namespace OpenSim.Region.Physics.OdePlugin
147 148
148 Size, 149 Size,
149 Shape, 150 Shape,
151 PhysRepData,
152 AddPhysRep,
150 153
151 CollidesWater, 154 CollidesWater,
152 VolumeDtc, 155 VolumeDtc,
@@ -230,11 +233,6 @@ namespace OpenSim.Region.Physics.OdePlugin
230 private float minimumGroundFlightOffset = 3f; 233 private float minimumGroundFlightOffset = 3f;
231 public float maximumMassObject = 10000.01f; 234 public float maximumMassObject = 10000.01f;
232 235
233 public bool meshSculptedPrim = true;
234 public bool forceSimplePrimMeshing = false;
235
236 public float meshSculptLOD = 32;
237 public float MeshSculptphysicalLOD = 32;
238 236
239 public float geomDefaultDensity = 10.000006836f; 237 public float geomDefaultDensity = 10.000006836f;
240 238
@@ -302,6 +300,7 @@ namespace OpenSim.Region.Physics.OdePlugin
302 public IntPtr TopSpace; // the global space 300 public IntPtr TopSpace; // the global space
303 public IntPtr ActiveSpace; // space for active prims 301 public IntPtr ActiveSpace; // space for active prims
304 public IntPtr StaticSpace; // space for the static things around 302 public IntPtr StaticSpace; // space for the static things around
303 public IntPtr GroundSpace; // space for ground
305 304
306 // some speedup variables 305 // some speedup variables
307 private int spaceGridMaxX; 306 private int spaceGridMaxX;
@@ -313,7 +312,7 @@ namespace OpenSim.Region.Physics.OdePlugin
313 private IntPtr[] staticPrimspaceOffRegion; 312 private IntPtr[] staticPrimspaceOffRegion;
314 313
315 public Object OdeLock; 314 public Object OdeLock;
316 private static Object SimulationLock; 315 public static Object SimulationLock;
317 316
318 public IMesher mesher; 317 public IMesher mesher;
319 318
@@ -328,7 +327,7 @@ namespace OpenSim.Region.Physics.OdePlugin
328 private PhysicsScene m_parentScene = null; 327 private PhysicsScene m_parentScene = null;
329 328
330 private ODERayCastRequestManager m_rayCastManager; 329 private ODERayCastRequestManager m_rayCastManager;
331 330 public ODEMeshWorker m_meshWorker;
332 331
333/* maybe needed if ode uses tls 332/* maybe needed if ode uses tls
334 private void checkThread() 333 private void checkThread()
@@ -361,6 +360,8 @@ namespace OpenSim.Region.Physics.OdePlugin
361 nearCallback = near; 360 nearCallback = near;
362 361
363 m_rayCastManager = new ODERayCastRequestManager(this); 362 m_rayCastManager = new ODERayCastRequestManager(this);
363
364
364 lock (OdeLock) 365 lock (OdeLock)
365 { 366 {
366 // Create the world and the first space 367 // Create the world and the first space
@@ -372,6 +373,7 @@ namespace OpenSim.Region.Physics.OdePlugin
372 // now the major subspaces 373 // now the major subspaces
373 ActiveSpace = d.HashSpaceCreate(TopSpace); 374 ActiveSpace = d.HashSpaceCreate(TopSpace);
374 StaticSpace = d.HashSpaceCreate(TopSpace); 375 StaticSpace = d.HashSpaceCreate(TopSpace);
376 GroundSpace = d.HashSpaceCreate(TopSpace);
375 } 377 }
376 catch 378 catch
377 { 379 {
@@ -381,10 +383,12 @@ namespace OpenSim.Region.Physics.OdePlugin
381 d.HashSpaceSetLevels(TopSpace, -2, 8); 383 d.HashSpaceSetLevels(TopSpace, -2, 8);
382 d.HashSpaceSetLevels(ActiveSpace, -2, 8); 384 d.HashSpaceSetLevels(ActiveSpace, -2, 8);
383 d.HashSpaceSetLevels(StaticSpace, -2, 8); 385 d.HashSpaceSetLevels(StaticSpace, -2, 8);
386 d.HashSpaceSetLevels(GroundSpace, 0, 8);
384 387
385 // demote to second level 388 // demote to second level
386 d.SpaceSetSublevel(ActiveSpace, 1); 389 d.SpaceSetSublevel(ActiveSpace, 1);
387 d.SpaceSetSublevel(StaticSpace, 1); 390 d.SpaceSetSublevel(StaticSpace, 1);
391 d.SpaceSetSublevel(GroundSpace, 1);
388 392
389 d.GeomSetCategoryBits(ActiveSpace, (uint)(CollisionCategories.Space | 393 d.GeomSetCategoryBits(ActiveSpace, (uint)(CollisionCategories.Space |
390 CollisionCategories.Geom | 394 CollisionCategories.Geom |
@@ -402,6 +406,9 @@ namespace OpenSim.Region.Physics.OdePlugin
402 )); 406 ));
403 d.GeomSetCollideBits(StaticSpace, 0); 407 d.GeomSetCollideBits(StaticSpace, 0);
404 408
409 d.GeomSetCategoryBits(GroundSpace, (uint)(CollisionCategories.Land));
410 d.GeomSetCollideBits(GroundSpace, 0);
411
405 contactgroup = d.JointGroupCreate(0); 412 contactgroup = d.JointGroupCreate(0);
406 //contactgroup 413 //contactgroup
407 414
@@ -440,9 +447,11 @@ namespace OpenSim.Region.Physics.OdePlugin
440 447
441 int contactsPerCollision = 80; 448 int contactsPerCollision = 80;
442 449
450 IConfig physicsconfig = null;
451
443 if (m_config != null) 452 if (m_config != null)
444 { 453 {
445 IConfig physicsconfig = m_config.Configs["ODEPhysicsSettings"]; 454 physicsconfig = m_config.Configs["ODEPhysicsSettings"];
446 if (physicsconfig != null) 455 if (physicsconfig != null)
447 { 456 {
448 gravityx = physicsconfig.GetFloat("world_gravityx", gravityx); 457 gravityx = physicsconfig.GetFloat("world_gravityx", gravityx);
@@ -469,27 +478,7 @@ namespace OpenSim.Region.Physics.OdePlugin
469 478
470 geomDefaultDensity = physicsconfig.GetFloat("geometry_default_density", geomDefaultDensity); 479 geomDefaultDensity = physicsconfig.GetFloat("geometry_default_density", geomDefaultDensity);
471 bodyFramesAutoDisable = physicsconfig.GetInt("body_frames_auto_disable", bodyFramesAutoDisable); 480 bodyFramesAutoDisable = physicsconfig.GetInt("body_frames_auto_disable", bodyFramesAutoDisable);
472/* 481
473 bodyPIDD = physicsconfig.GetFloat("body_pid_derivative", bodyPIDD);
474 bodyPIDG = physicsconfig.GetFloat("body_pid_gain", bodyPIDG);
475*/
476 forceSimplePrimMeshing = physicsconfig.GetBoolean("force_simple_prim_meshing", forceSimplePrimMeshing);
477 meshSculptedPrim = physicsconfig.GetBoolean("mesh_sculpted_prim", meshSculptedPrim);
478 meshSculptLOD = physicsconfig.GetFloat("mesh_lod", meshSculptLOD);
479 MeshSculptphysicalLOD = physicsconfig.GetFloat("mesh_physical_lod", MeshSculptphysicalLOD);
480/*
481 if (Environment.OSVersion.Platform == PlatformID.Unix)
482 {
483 avPIDD = physicsconfig.GetFloat("av_pid_derivative_linux", avPIDD);
484 avPIDP = physicsconfig.GetFloat("av_pid_proportional_linux", avPIDP);
485 }
486 else
487 {
488
489 avPIDD = physicsconfig.GetFloat("av_pid_derivative_win", avPIDD);
490 avPIDP = physicsconfig.GetFloat("av_pid_proportional_win", avPIDP);
491 }
492*/
493 physics_logging = physicsconfig.GetBoolean("physics_logging", false); 482 physics_logging = physicsconfig.GetBoolean("physics_logging", false);
494 physics_logging_interval = physicsconfig.GetInt("physics_logging_interval", 0); 483 physics_logging_interval = physicsconfig.GetInt("physics_logging_interval", 0);
495 physics_logging_append_existing_logfile = physicsconfig.GetBoolean("physics_logging_append_existing_logfile", false); 484 physics_logging_append_existing_logfile = physicsconfig.GetBoolean("physics_logging_append_existing_logfile", false);
@@ -499,6 +488,8 @@ namespace OpenSim.Region.Physics.OdePlugin
499 } 488 }
500 } 489 }
501 490
491 m_meshWorker = new ODEMeshWorker(this, m_log, meshmerizer, physicsconfig);
492
502 HalfOdeStep = ODE_STEPSIZE * 0.5f; 493 HalfOdeStep = ODE_STEPSIZE * 0.5f;
503 odetimestepMS = (int)(1000.0f * ODE_STEPSIZE +0.5f); 494 odetimestepMS = (int)(1000.0f * ODE_STEPSIZE +0.5f);
504 495
@@ -727,6 +718,32 @@ namespace OpenSim.Region.Physics.OdePlugin
727 718
728 if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact)) 719 if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact))
729 return; 720 return;
721/*
722// debug
723 PhysicsActor dp2;
724 if (d.GeomGetClass(g1) == d.GeomClassID.HeightfieldClass)
725 {
726 d.AABB aabb;
727 d.GeomGetAABB(g2, out aabb);
728 float x = aabb.MaxX - aabb.MinX;
729 float y = aabb.MaxY - aabb.MinY;
730 float z = aabb.MaxZ - aabb.MinZ;
731 if (x > 60.0f || y > 60.0f || z > 60.0f)
732 {
733 if (!actor_name_map.TryGetValue(g2, out dp2))
734 m_log.WarnFormat("[PHYSICS]: failed actor mapping for geom 2");
735 else
736 m_log.WarnFormat("[PHYSICS]: land versus large prim geo {0},size {1}, AABBsize <{2},{3},{4}>, at {5} ori {6},({7})",
737 dp2.Name, dp2.Size, x, y, z,
738 dp2.Position.ToString(),
739 dp2.Orientation.ToString(),
740 dp2.Orientation.Length());
741 return;
742 }
743 }
744//
745*/
746
730 747
731 if(d.GeomGetCategoryBits(g1) == (uint)CollisionCategories.VolumeDtc || 748 if(d.GeomGetCategoryBits(g1) == (uint)CollisionCategories.VolumeDtc ||
732 d.GeomGetCategoryBits(g1) == (uint)CollisionCategories.VolumeDtc) 749 d.GeomGetCategoryBits(g1) == (uint)CollisionCategories.VolumeDtc)
@@ -1225,6 +1242,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1225 chr.CollidingObj = false; 1242 chr.CollidingObj = false;
1226 // do colisions with static space 1243 // do colisions with static space
1227 d.SpaceCollide2(StaticSpace, chr.Shell, IntPtr.Zero, nearCallback); 1244 d.SpaceCollide2(StaticSpace, chr.Shell, IntPtr.Zero, nearCallback);
1245 // no coll with gnd
1228 } 1246 }
1229 } 1247 }
1230 catch (AccessViolationException) 1248 catch (AccessViolationException)
@@ -1253,7 +1271,10 @@ namespace OpenSim.Region.Physics.OdePlugin
1253 if (!prm.m_outbounds) 1271 if (!prm.m_outbounds)
1254 { 1272 {
1255 if (d.BodyIsEnabled(prm.Body)) 1273 if (d.BodyIsEnabled(prm.Body))
1274 {
1256 d.SpaceCollide2(StaticSpace, prm.collide_geom, IntPtr.Zero, nearCallback); 1275 d.SpaceCollide2(StaticSpace, prm.collide_geom, IntPtr.Zero, nearCallback);
1276 d.SpaceCollide2(GroundSpace, prm.collide_geom, IntPtr.Zero, nearCallback);
1277 }
1257 } 1278 }
1258 } 1279 }
1259 } 1280 }
@@ -1295,6 +1316,15 @@ namespace OpenSim.Region.Physics.OdePlugin
1295 _collisionEventPrimRemove.Add(obj); 1316 _collisionEventPrimRemove.Add(obj);
1296 } 1317 }
1297 1318
1319 public override float TimeDilation
1320 {
1321 get { return m_timeDilation; }
1322 }
1323
1324 public override bool SupportsNINJAJoints
1325 {
1326 get { return false; }
1327 }
1298 1328
1299 #region Add/Remove Entities 1329 #region Add/Remove Entities
1300 1330
@@ -1350,117 +1380,59 @@ namespace OpenSim.Region.Physics.OdePlugin
1350 ((OdeCharacter) actor).Destroy(); 1380 ((OdeCharacter) actor).Destroy();
1351 } 1381 }
1352 1382
1353 private PhysicsActor AddPrim(String name, Vector3 position, Vector3 size, Quaternion rotation,
1354 PrimitiveBaseShape pbs, bool isphysical, uint localID)
1355 {
1356 Vector3 pos = position;
1357 Vector3 siz = size;
1358 Quaternion rot = rotation;
1359 1383
1360 OdePrim newPrim; 1384 public void addActivePrim(OdePrim activatePrim)
1361 lock (OdeLock) 1385 {
1386 // adds active prim..
1387 lock (_activeprims)
1362 { 1388 {
1363 newPrim = new OdePrim(name, this, pos, siz, rot, pbs, isphysical,false,0,localID); 1389 if (!_activeprims.Contains(activatePrim))
1364 1390 _activeprims.Add(activatePrim);
1365 lock (_prims)
1366 _prims.Add(newPrim);
1367 } 1391 }
1368 return newPrim;
1369 } 1392 }
1370 1393
1371 private PhysicsActor AddPrim(String name, Vector3 position, Vector3 size, Quaternion rotation, 1394 public void addActiveGroups(OdePrim activatePrim)
1372 PrimitiveBaseShape pbs, bool isphysical, bool isPhantom, uint localID)
1373 { 1395 {
1374 Vector3 pos = position; 1396 lock (_activegroups)
1375 Vector3 siz = size;
1376 Quaternion rot = rotation;
1377
1378 OdePrim newPrim;
1379 lock (OdeLock)
1380 { 1397 {
1381 newPrim = new OdePrim(name, this, pos, siz, rot, pbs, isphysical, isPhantom, 0, localID); 1398 if (!_activegroups.Contains(activatePrim))
1382 1399 _activegroups.Add(activatePrim);
1383 lock (_prims)
1384 _prims.Add(newPrim);
1385 } 1400 }
1386 return newPrim;
1387 } 1401 }
1388 1402
1389 private PhysicsActor AddPrim(String name, Vector3 position, Vector3 size, Quaternion rotation, 1403 private PhysicsActor AddPrim(String name, Vector3 position, Vector3 size, Quaternion rotation,
1390 PrimitiveBaseShape pbs, bool isphysical, bool isPhantom, byte shapeType, uint localID) 1404 PrimitiveBaseShape pbs, bool isphysical, bool isPhantom, byte shapeType, uint localID)
1391 { 1405 {
1392 Vector3 pos = position;
1393 Vector3 siz = size;
1394 Quaternion rot = rotation;
1395
1396 OdePrim newPrim; 1406 OdePrim newPrim;
1397 lock (OdeLock) 1407 lock (OdeLock)
1398 { 1408 {
1399 newPrim = new OdePrim(name, this, pos, siz, rot, pbs, isphysical, isPhantom, shapeType, localID); 1409 newPrim = new OdePrim(name, this, position, size, rotation, pbs, isphysical, isPhantom, shapeType, localID);
1400
1401 lock (_prims) 1410 lock (_prims)
1402 _prims.Add(newPrim); 1411 _prims.Add(newPrim);
1403 } 1412 }
1404 return newPrim; 1413 return newPrim;
1405 } 1414 }
1406 1415
1407 public void addActivePrim(OdePrim activatePrim)
1408 {
1409 // adds active prim..
1410 lock (_activeprims)
1411 {
1412 if (!_activeprims.Contains(activatePrim))
1413 _activeprims.Add(activatePrim);
1414 }
1415 }
1416
1417 public void addActiveGroups(OdePrim activatePrim)
1418 {
1419 lock (_activegroups)
1420 {
1421 if (!_activegroups.Contains(activatePrim))
1422 _activegroups.Add(activatePrim);
1423 }
1424 }
1425
1426 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, 1416 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
1427 Vector3 size, Quaternion rotation, bool isPhysical, bool isPhantom, uint localid) 1417 Vector3 size, Quaternion rotation, bool isPhysical, bool isPhantom, uint localid)
1428 { 1418 {
1429 return AddPrim(primName, position, size, rotation, pbs, isPhysical, isPhantom, localid); 1419 return AddPrim(primName, position, size, rotation, pbs, isPhysical, isPhantom, 0 , localid);
1430 } 1420 }
1431 1421
1432 1422
1433 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, 1423 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
1434 Vector3 size, Quaternion rotation, bool isPhysical, uint localid) 1424 Vector3 size, Quaternion rotation, bool isPhysical, uint localid)
1435 { 1425 {
1436#if SPAM 1426 return AddPrim(primName, position, size, rotation, pbs, isPhysical,false, 0, localid);
1437 m_log.DebugFormat("[PHYSICS]: Adding physics actor to {0}", primName);
1438#endif
1439
1440 return AddPrim(primName, position, size, rotation, pbs, isPhysical, localid);
1441 } 1427 }
1442 1428
1443 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, 1429 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
1444 Vector3 size, Quaternion rotation, bool isPhysical, bool isPhantom, byte shapeType, uint localid) 1430 Vector3 size, Quaternion rotation, bool isPhysical, bool isPhantom, byte shapeType, uint localid)
1445 { 1431 {
1446#if SPAM
1447 m_log.DebugFormat("[PHYSICS]: Adding physics actor to {0}", primName);
1448#endif
1449 1432
1450 return AddPrim(primName, position, size, rotation, pbs, isPhysical,isPhantom, shapeType, localid); 1433 return AddPrim(primName, position, size, rotation, pbs, isPhysical,isPhantom, shapeType, localid);
1451 } 1434 }
1452 1435
1453 public override float TimeDilation
1454 {
1455 get { return m_timeDilation; }
1456 }
1457
1458 public override bool SupportsNINJAJoints
1459 {
1460 get { return false; }
1461 }
1462
1463
1464 public void remActivePrim(OdePrim deactivatePrim) 1436 public void remActivePrim(OdePrim deactivatePrim)
1465 { 1437 {
1466 lock (_activeprims) 1438 lock (_activeprims)
@@ -1513,6 +1485,28 @@ namespace OpenSim.Region.Physics.OdePlugin
1513 } 1485 }
1514 1486
1515 } 1487 }
1488
1489 public bool havePrim(OdePrim prm)
1490 {
1491 lock (_prims)
1492 return _prims.Contains(prm);
1493 }
1494
1495 public bool haveActor(PhysicsActor actor)
1496 {
1497 if (actor is OdePrim)
1498 {
1499 lock (_prims)
1500 return _prims.Contains((OdePrim)actor);
1501 }
1502 else if (actor is OdeCharacter)
1503 {
1504 lock (_characters)
1505 return _characters.Contains((OdeCharacter)actor);
1506 }
1507 return false;
1508 }
1509
1516 #endregion 1510 #endregion
1517 1511
1518 #region Space Separation Calculation 1512 #region Space Separation Calculation
@@ -1615,135 +1609,6 @@ namespace OpenSim.Region.Physics.OdePlugin
1615 1609
1616 #endregion 1610 #endregion
1617 1611
1618 /// <summary>
1619 /// Routine to figure out if we need to mesh this prim with our mesher
1620 /// </summary>
1621 /// <param name="pbs"></param>
1622 /// <returns></returns>
1623 public bool needsMeshing(PrimitiveBaseShape pbs)
1624 {
1625 // check sculpts or meshs
1626 if (pbs.SculptEntry)
1627 {
1628 if (meshSculptedPrim)
1629 return true;
1630
1631 if (pbs.SculptType == (byte)SculptType.Mesh) // always do meshs
1632 return true;
1633
1634 return false;
1635 }
1636
1637 if (forceSimplePrimMeshing)
1638 return true;
1639
1640 // if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since ODE can use an internal representation for the prim
1641
1642 if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
1643 || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1
1644 && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z))
1645 {
1646
1647 if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
1648 && pbs.ProfileHollow == 0
1649 && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
1650 && pbs.PathBegin == 0 && pbs.PathEnd == 0
1651 && pbs.PathTaperX == 0 && pbs.PathTaperY == 0
1652 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
1653 && pbs.PathShearX == 0 && pbs.PathShearY == 0)
1654 {
1655#if SPAM
1656 m_log.Warn("NonMesh");
1657#endif
1658 return false;
1659 }
1660 }
1661
1662 // following code doesn't give meshs to boxes and spheres ever
1663 // and it's odd.. so for now just return true if asked to force meshs
1664 // hopefully mesher will fail if doesn't suport so things still get basic boxes
1665
1666 int iPropertiesNotSupportedDefault = 0;
1667
1668 if (pbs.ProfileHollow != 0)
1669 iPropertiesNotSupportedDefault++;
1670
1671 if ((pbs.PathBegin != 0) || pbs.PathEnd != 0)
1672 iPropertiesNotSupportedDefault++;
1673
1674 if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0))
1675 iPropertiesNotSupportedDefault++;
1676
1677 if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0)
1678 iPropertiesNotSupportedDefault++;
1679
1680 if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100))
1681 iPropertiesNotSupportedDefault++;
1682
1683 if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0))
1684 iPropertiesNotSupportedDefault++;
1685
1686 if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight)
1687 iPropertiesNotSupportedDefault++;
1688
1689 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 && (pbs.Scale.X != pbs.Scale.Y || pbs.Scale.Y != pbs.Scale.Z || pbs.Scale.Z != pbs.Scale.X))
1690 iPropertiesNotSupportedDefault++;
1691
1692 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte) Extrusion.Curve1)
1693 iPropertiesNotSupportedDefault++;
1694
1695 // test for torus
1696 if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
1697 {
1698 if (pbs.PathCurve == (byte)Extrusion.Curve1)
1699 {
1700 iPropertiesNotSupportedDefault++;
1701 }
1702 }
1703 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
1704 {
1705 if (pbs.PathCurve == (byte)Extrusion.Straight)
1706 {
1707 iPropertiesNotSupportedDefault++;
1708 }
1709
1710 // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
1711 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
1712 {
1713 iPropertiesNotSupportedDefault++;
1714 }
1715 }
1716 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
1717 {
1718 if (pbs.PathCurve == (byte)Extrusion.Curve1 || pbs.PathCurve == (byte)Extrusion.Curve2)
1719 {
1720 iPropertiesNotSupportedDefault++;
1721 }
1722 }
1723 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
1724 {
1725 if (pbs.PathCurve == (byte)Extrusion.Straight)
1726 {
1727 iPropertiesNotSupportedDefault++;
1728 }
1729 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
1730 {
1731 iPropertiesNotSupportedDefault++;
1732 }
1733 }
1734
1735 if (iPropertiesNotSupportedDefault == 0)
1736 {
1737#if SPAM
1738 m_log.Warn("NonMesh");
1739#endif
1740 return false;
1741 }
1742#if SPAM
1743 m_log.Debug("Mesh");
1744#endif
1745 return true;
1746 }
1747 1612
1748 /// <summary> 1613 /// <summary>
1749 /// Called to queue a change to a actor 1614 /// Called to queue a change to a actor
@@ -1766,8 +1631,52 @@ namespace OpenSim.Region.Physics.OdePlugin
1766 /// </summary> 1631 /// </summary>
1767 /// <param name="prim"></param> 1632 /// <param name="prim"></param>
1768 public override void AddPhysicsActorTaint(PhysicsActor prim) 1633 public override void AddPhysicsActorTaint(PhysicsActor prim)
1634 {
1635 }
1636
1637 // does all pending changes generated during region load process
1638 public override void PrepareSimulation()
1639 {
1640 lock (OdeLock)
1769 { 1641 {
1642 if (world == IntPtr.Zero)
1643 {
1644 ChangesQueue.Clear();
1645 return;
1646 }
1647
1648 ODEchangeitem item;
1649
1650 int donechanges = 0;
1651 if (ChangesQueue.Count > 0)
1652 {
1653 m_log.InfoFormat("[ODE] start processing pending actor operations");
1654 int tstart = Util.EnvironmentTickCount();
1655
1656 while (ChangesQueue.Dequeue(out item))
1657 {
1658 if (item.actor != null)
1659 {
1660 try
1661 {
1662 if (item.actor is OdeCharacter)
1663 ((OdeCharacter)item.actor).DoAChange(item.what, item.arg);
1664 else if (((OdePrim)item.actor).DoAChange(item.what, item.arg))
1665 RemovePrimThreadLocked((OdePrim)item.actor);
1666 }
1667 catch
1668 {
1669 m_log.WarnFormat("[PHYSICS]: Operation failed for a actor {0} {1}",
1670 item.actor.Name, item.what.ToString());
1671 }
1672 }
1673 donechanges++;
1674 }
1675 int time = Util.EnvironmentTickCountSubtract(tstart);
1676 m_log.InfoFormat("[ODE] finished {0} operations in {1}ms", donechanges, time);
1677 }
1770 } 1678 }
1679 }
1771 1680
1772 /// <summary> 1681 /// <summary>
1773 /// This is our main simulate loop 1682 /// This is our main simulate loop
@@ -1813,21 +1722,17 @@ namespace OpenSim.Region.Physics.OdePlugin
1813 lock(OdeLock) 1722 lock(OdeLock)
1814 { 1723 {
1815 if (world == IntPtr.Zero) 1724 if (world == IntPtr.Zero)
1725 {
1726 ChangesQueue.Clear();
1816 return 0; 1727 return 0;
1728 }
1817 1729
1818 // adjust number of iterations per step 1730 ODEchangeitem item;
1731
1732
1733
1734 d.WorldSetQuickStepNumIterations(world, curphysiteractions);
1819 1735
1820// try
1821// {
1822 d.WorldSetQuickStepNumIterations(world, curphysiteractions);
1823/* }
1824 catch (StackOverflowException)
1825 {
1826 m_log.Error("[PHYSICS]: The operating system wasn't able to allocate enough memory for the simulation. Restarting the sim.");
1827// ode.drelease(world);
1828 base.TriggerPhysicsBasedRestart();
1829 }
1830*/
1831 while (step_time > HalfOdeStep && nodeframes < 10) //limit number of steps so we don't say here for ever 1736 while (step_time > HalfOdeStep && nodeframes < 10) //limit number of steps so we don't say here for ever
1832 { 1737 {
1833 try 1738 try
@@ -1835,14 +1740,12 @@ namespace OpenSim.Region.Physics.OdePlugin
1835 // clear pointer/counter to contacts to pass into joints 1740 // clear pointer/counter to contacts to pass into joints
1836 m_global_contactcount = 0; 1741 m_global_contactcount = 0;
1837 1742
1838 ODEchangeitem item; 1743 if (ChangesQueue.Count > 0)
1839
1840 if(ChangesQueue.Count >0)
1841 { 1744 {
1842 int ttmpstart = Util.EnvironmentTickCount(); 1745 int ttmpstart = Util.EnvironmentTickCount();
1843 int ttmp; 1746 int ttmp;
1844 1747
1845 while(ChangesQueue.Dequeue(out item)) 1748 while (ChangesQueue.Dequeue(out item))
1846 { 1749 {
1847 if (item.actor != null) 1750 if (item.actor != null)
1848 { 1751 {
@@ -1851,12 +1754,13 @@ namespace OpenSim.Region.Physics.OdePlugin
1851 if (item.actor is OdeCharacter) 1754 if (item.actor is OdeCharacter)
1852 ((OdeCharacter)item.actor).DoAChange(item.what, item.arg); 1755 ((OdeCharacter)item.actor).DoAChange(item.what, item.arg);
1853 else if (((OdePrim)item.actor).DoAChange(item.what, item.arg)) 1756 else if (((OdePrim)item.actor).DoAChange(item.what, item.arg))
1854 RemovePrimThreadLocked((OdePrim)item.actor); 1757 RemovePrimThreadLocked((OdePrim)item.actor);
1855 } 1758 }
1856 catch 1759 catch
1857 { 1760 {
1858 m_log.Warn("[PHYSICS]: doChange failed for a actor"); 1761 m_log.WarnFormat("[PHYSICS]: doChange failed for a actor {0} {1}",
1859 }; 1762 item.actor.Name, item.what.ToString());
1763 }
1860 } 1764 }
1861 ttmp = Util.EnvironmentTickCountSubtract(ttmpstart); 1765 ttmp = Util.EnvironmentTickCountSubtract(ttmpstart);
1862 if (ttmp > 20) 1766 if (ttmp > 20)
@@ -1994,10 +1898,47 @@ namespace OpenSim.Region.Physics.OdePlugin
1994 mesher.ExpireReleaseMeshs(); 1898 mesher.ExpireReleaseMeshs();
1995 m_lastMeshExpire = now; 1899 m_lastMeshExpire = now;
1996 } 1900 }
1901
1902// information block running in debug only
1997/* 1903/*
1998 int nactivegeoms = d.SpaceGetNumGeoms(ActiveSpace); 1904 int ntopactivegeoms = d.SpaceGetNumGeoms(ActiveSpace);
1999 int nstaticgeoms = d.SpaceGetNumGeoms(StaticSpace); 1905 int ntopstaticgeoms = d.SpaceGetNumGeoms(StaticSpace);
1906 int ngroundgeoms = d.SpaceGetNumGeoms(GroundSpace);
1907
1908 int nactivegeoms = 0;
1909 int nactivespaces = 0;
1910
1911 int nstaticgeoms = 0;
1912 int nstaticspaces = 0;
1913 IntPtr sp;
1914
1915 for (int i = 0; i < ntopactivegeoms; i++)
1916 {
1917 sp = d.SpaceGetGeom(ActiveSpace, i);
1918 if (d.GeomIsSpace(sp))
1919 {
1920 nactivespaces++;
1921 nactivegeoms += d.SpaceGetNumGeoms(sp);
1922 }
1923 else
1924 nactivegeoms++;
1925 }
1926
1927 for (int i = 0; i < ntopstaticgeoms; i++)
1928 {
1929 sp = d.SpaceGetGeom(StaticSpace, i);
1930 if (d.GeomIsSpace(sp))
1931 {
1932 nstaticspaces++;
1933 nstaticgeoms += d.SpaceGetNumGeoms(sp);
1934 }
1935 else
1936 nstaticgeoms++;
1937 }
1938
2000 int ntopgeoms = d.SpaceGetNumGeoms(TopSpace); 1939 int ntopgeoms = d.SpaceGetNumGeoms(TopSpace);
1940
1941 int totgeoms = nstaticgeoms + nactivegeoms + ngroundgeoms + 1; // one ray
2001 int nbodies = d.NTotalBodies; 1942 int nbodies = d.NTotalBodies;
2002 int ngeoms = d.NTotalGeoms; 1943 int ngeoms = d.NTotalGeoms;
2003*/ 1944*/
@@ -2294,7 +2235,9 @@ namespace OpenSim.Region.Physics.OdePlugin
2294 offset, thickness, wrap); 2235 offset, thickness, wrap);
2295 2236
2296 d.GeomHeightfieldDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1); 2237 d.GeomHeightfieldDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1);
2297 GroundGeom = d.CreateHeightfield(StaticSpace, HeightmapData, 1); 2238
2239 GroundGeom = d.CreateHeightfield(GroundSpace, HeightmapData, 1);
2240
2298 if (GroundGeom != IntPtr.Zero) 2241 if (GroundGeom != IntPtr.Zero)
2299 { 2242 {
2300 d.GeomSetCategoryBits(GroundGeom, (uint)(CollisionCategories.Land)); 2243 d.GeomSetCategoryBits(GroundGeom, (uint)(CollisionCategories.Land));
@@ -2415,12 +2358,13 @@ namespace OpenSim.Region.Physics.OdePlugin
2415 thickness, wrap); 2358 thickness, wrap);
2416 2359
2417// d.GeomUbitTerrainDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1); 2360// d.GeomUbitTerrainDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1);
2418 GroundGeom = d.CreateUbitTerrain(StaticSpace, HeightmapData, 1); 2361 GroundGeom = d.CreateUbitTerrain(GroundSpace, HeightmapData, 1);
2419 if (GroundGeom != IntPtr.Zero) 2362 if (GroundGeom != IntPtr.Zero)
2420 { 2363 {
2421 d.GeomSetCategoryBits(GroundGeom, (uint)(CollisionCategories.Land)); 2364 d.GeomSetCategoryBits(GroundGeom, (uint)(CollisionCategories.Land));
2422 d.GeomSetCollideBits(GroundGeom, 0); 2365 d.GeomSetCollideBits(GroundGeom, 0);
2423 2366
2367
2424 PhysicsActor pa = new NullPhysicsActor(); 2368 PhysicsActor pa = new NullPhysicsActor();
2425 pa.Name = "Terrain"; 2369 pa.Name = "Terrain";
2426 pa.PhysicsActorType = (int)ActorTypes.Ground; 2370 pa.PhysicsActorType = (int)ActorTypes.Ground;
@@ -2599,6 +2543,9 @@ namespace OpenSim.Region.Physics.OdePlugin
2599*/ 2543*/
2600 public override void Dispose() 2544 public override void Dispose()
2601 { 2545 {
2546 if (m_meshWorker != null)
2547 m_meshWorker.Stop();
2548
2602 lock (OdeLock) 2549 lock (OdeLock)
2603 { 2550 {
2604 m_rayCastManager.Dispose(); 2551 m_rayCastManager.Dispose();
@@ -2633,6 +2580,7 @@ namespace OpenSim.Region.Physics.OdePlugin
2633 d.GeomDestroy(GroundGeom); 2580 d.GeomDestroy(GroundGeom);
2634 } 2581 }
2635 2582
2583
2636 RegionTerrain.Clear(); 2584 RegionTerrain.Clear();
2637 2585
2638 if (TerrainHeightFieldHeightsHandlers.Count > 0) 2586 if (TerrainHeightFieldHeightsHandlers.Count > 0)