aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/PhysicsModules/ubOde/ODEMeshWorker.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/PhysicsModules/ubOde/ODEMeshWorker.cs')
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/ODEMeshWorker.cs946
1 files changed, 946 insertions, 0 deletions
diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODEMeshWorker.cs b/OpenSim/Region/PhysicsModules/ubOde/ODEMeshWorker.cs
new file mode 100644
index 0000000..5465035
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOde/ODEMeshWorker.cs
@@ -0,0 +1,946 @@
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.PhysicsModules.SharedBase;
14using OdeAPI;
15using log4net;
16using Nini.Config;
17using OpenMetaverse;
18
19namespace OpenSim.Region.PhysicsModule.ubOde
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 bool isTooSmall;
66 public MeshState meshState;
67 public UUID? assetID;
68 public meshWorkerCmnds comand;
69 }
70
71 public class ODEMeshWorker
72 {
73 private ILog m_log;
74 private ODEScene m_scene;
75 private IMesher m_mesher;
76
77 public bool meshSculptedPrim = true;
78 public float meshSculptLOD = 32;
79 public float MeshSculptphysicalLOD = 32;
80 public float MinSizeToMeshmerize = 0.1f;
81
82 private OpenSim.Framework.BlockingQueue<ODEPhysRepData> workQueue = new OpenSim.Framework.BlockingQueue<ODEPhysRepData>();
83 private bool m_running;
84
85 private Thread m_thread;
86
87 public ODEMeshWorker(ODEScene pScene, ILog pLog, IMesher pMesher, IConfig pConfig)
88 {
89 m_scene = pScene;
90 m_log = pLog;
91 m_mesher = pMesher;
92
93 if (pConfig != null)
94 {
95 meshSculptedPrim = pConfig.GetBoolean("mesh_sculpted_prim", meshSculptedPrim);
96 meshSculptLOD = pConfig.GetFloat("mesh_lod", meshSculptLOD);
97 MinSizeToMeshmerize = pConfig.GetFloat("mesh_min_size", MinSizeToMeshmerize);
98 MeshSculptphysicalLOD = pConfig.GetFloat("mesh_physical_lod", MeshSculptphysicalLOD);
99 }
100 m_running = true;
101 m_thread = new Thread(DoWork);
102 m_thread.Name = "OdeMeshWorker";
103 m_thread.Start();
104 }
105
106 private void DoWork()
107 {
108 m_mesher.ExpireFileCache();
109
110 while(m_running)
111 {
112 ODEPhysRepData nextRep = workQueue.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 workQueue.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 workQueue.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)) // no need for pbs now?
242 {
243 repData.comand = meshWorkerCmnds.changefull;
244 workQueue.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(ODEPhysRepData repData)
287 {
288 PrimitiveBaseShape pbs = repData.pbs;
289 // check sculpts or meshs
290
291 Vector3 scale = pbs.Scale;
292 if(scale.X <= MinSizeToMeshmerize &&
293 scale.Y <= MinSizeToMeshmerize &&
294 scale.Z <= MinSizeToMeshmerize)
295 {
296 repData.isTooSmall = true;
297 return false;
298 }
299
300 if (pbs.SculptEntry)
301 {
302 if (meshSculptedPrim)
303 return true;
304
305 if (pbs.SculptType == (byte)SculptType.Mesh) // always do meshs
306 return true;
307
308 return false;
309 }
310
311 // convex shapes have no holes
312 ushort profilehollow = pbs.ProfileHollow;
313 if(repData.shapetype == 2)
314 profilehollow = 0;
315
316 // 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
317
318 if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
319 || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1
320 && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z))
321 {
322
323 if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
324 && profilehollow == 0
325 && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
326 && pbs.PathBegin == 0 && pbs.PathEnd == 0
327 && pbs.PathTaperX == 0 && pbs.PathTaperY == 0
328 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
329 && pbs.PathShearX == 0 && pbs.PathShearY == 0)
330 {
331 return false;
332 }
333 }
334
335 // following code doesn't give meshs to boxes and spheres ever
336 // and it's odd.. so for now just return true if asked to force meshs
337 // hopefully mesher will fail if doesn't suport so things still get basic boxes
338
339 int iPropertiesNotSupportedDefault = 0;
340
341 if (profilehollow != 0)
342 iPropertiesNotSupportedDefault++;
343
344 if ((pbs.PathBegin != 0) || pbs.PathEnd != 0)
345 iPropertiesNotSupportedDefault++;
346
347 if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0))
348 iPropertiesNotSupportedDefault++;
349
350 if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0)
351 iPropertiesNotSupportedDefault++;
352
353 if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100))
354 iPropertiesNotSupportedDefault++;
355
356 if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0))
357 iPropertiesNotSupportedDefault++;
358
359 if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight)
360 iPropertiesNotSupportedDefault++;
361
362 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))
363 iPropertiesNotSupportedDefault++;
364
365 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1)
366 iPropertiesNotSupportedDefault++;
367
368 // test for torus
369 if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
370 {
371 if (pbs.PathCurve == (byte)Extrusion.Curve1)
372 {
373 iPropertiesNotSupportedDefault++;
374 }
375 }
376 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
377 {
378 if (pbs.PathCurve == (byte)Extrusion.Straight)
379 {
380 iPropertiesNotSupportedDefault++;
381 }
382
383 // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
384 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
385 {
386 iPropertiesNotSupportedDefault++;
387 }
388 }
389 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
390 {
391 if (pbs.PathCurve == (byte)Extrusion.Curve1 || pbs.PathCurve == (byte)Extrusion.Curve2)
392 {
393 iPropertiesNotSupportedDefault++;
394 }
395 }
396 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
397 {
398 if (pbs.PathCurve == (byte)Extrusion.Straight)
399 {
400 iPropertiesNotSupportedDefault++;
401 }
402 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
403 {
404 iPropertiesNotSupportedDefault++;
405 }
406 }
407
408 if (iPropertiesNotSupportedDefault == 0)
409 {
410 return false;
411 }
412 return true;
413 }
414
415 // see if we need a mesh and if so if we have a cached one
416 // called with a new repData
417 public void CheckMesh(ODEPhysRepData repData)
418 {
419 PhysicsActor actor = repData.actor;
420 PrimitiveBaseShape pbs = repData.pbs;
421
422 if (!needsMeshing(repData))
423 {
424 repData.meshState = MeshState.noNeed;
425 repData.hasOBB = false;
426 return;
427 }
428
429 IMesh mesh = null;
430
431 Vector3 size = repData.size;
432
433 int clod = (int)LevelOfDetail.High;
434 byte shapetype = repData.shapetype;
435 bool convex = shapetype == 2;
436
437 mesh = m_mesher.GetMesh(actor.Name, pbs, size, clod, true, convex);
438
439 if (mesh == null)
440 {
441 if (pbs.SculptEntry)
442 {
443 if (pbs.SculptTexture != null && pbs.SculptTexture != UUID.Zero)
444 {
445 repData.assetID = pbs.SculptTexture;
446 repData.meshState = MeshState.needAsset;
447 }
448 else
449 repData.meshState = MeshState.MeshFailed;
450
451 return;
452 }
453 else
454 {
455 repData.meshState = MeshState.needMesh;
456 mesh = m_mesher.CreateMesh(actor.Name, pbs, size, clod, true, convex, true);
457 if (mesh == null)
458 {
459 repData.meshState = MeshState.MeshFailed;
460 return;
461 }
462 }
463 }
464
465 repData.meshState = MeshState.AssetOK;
466 repData.mesh = mesh;
467 repData.OBB = mesh.GetOBB();
468 repData.OBBOffset = mesh.GetCentroid();
469 repData.hasOBB = true;
470
471 if (pbs.SculptEntry)
472 {
473 repData.assetID = pbs.SculptTexture;
474 }
475
476 pbs.SculptData = Utils.EmptyBytes;
477 return ;
478 }
479
480 public void GetMesh(ODEPhysRepData repData)
481 {
482 PhysicsActor actor = repData.actor;
483
484 PrimitiveBaseShape pbs = repData.pbs;
485
486 repData.mesh = null;
487 repData.hasOBB = false;
488
489 if (!needsMeshing(repData))
490 {
491 repData.meshState = MeshState.noNeed;
492 return;
493 }
494
495 if (repData.meshState == MeshState.MeshFailed)
496 return;
497
498 if (pbs.SculptEntry)
499 {
500 if (repData.meshState == MeshState.AssetFailed)
501 {
502 if (pbs.SculptTexture == repData.assetID)
503 return;
504 }
505 }
506
507 repData.meshState = MeshState.noNeed;
508
509 IMesh mesh = null;
510 Vector3 size = repData.size;
511 byte shapetype = repData.shapetype;
512
513 bool convex;
514 int clod = (int)LevelOfDetail.High;
515 if (shapetype == 0)
516 convex = false;
517 else
518 {
519 convex = true;
520 if (pbs.SculptType != (byte)SculptType.Mesh)
521 clod = (int)LevelOfDetail.Low;
522 }
523
524 mesh = m_mesher.CreateMesh(actor.Name, pbs, size, clod, true, convex, true);
525
526 if (mesh == null)
527 {
528 if (pbs.SculptEntry)
529 {
530 if (pbs.SculptTexture == UUID.Zero)
531 return;
532
533 repData.assetID = pbs.SculptTexture;
534
535 if (pbs.SculptData == null || pbs.SculptData.Length == 0)
536 {
537 repData.meshState = MeshState.needAsset;
538 return;
539 }
540 }
541 }
542
543 repData.mesh = mesh;
544 repData.pbs.SculptData = Utils.EmptyBytes;
545
546 if (mesh == null)
547 {
548 if (pbs.SculptEntry)
549 repData.meshState = MeshState.AssetFailed;
550 else
551 repData.meshState = MeshState.MeshFailed;
552
553 return;
554 }
555
556 repData.meshState = MeshState.AssetOK;
557
558 return;
559 }
560
561 private void CalculateBasicPrimVolume(ODEPhysRepData repData)
562 {
563 Vector3 _size = repData.size;
564
565 float volume = _size.X * _size.Y * _size.Z; // default
566 if(repData.isTooSmall)
567 {
568 repData.volume = volume;
569 return;
570 }
571
572 PrimitiveBaseShape _pbs = repData.pbs;
573 float tmp;
574
575 float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f;
576 float hollowVolume = hollowAmount * hollowAmount;
577
578 switch (_pbs.ProfileShape)
579 {
580 case ProfileShape.Square:
581 // default box
582
583 if (_pbs.PathCurve == (byte)Extrusion.Straight)
584 {
585 if (hollowAmount > 0.0)
586 {
587 switch (_pbs.HollowShape)
588 {
589 case HollowShape.Square:
590 case HollowShape.Same:
591 break;
592
593 case HollowShape.Circle:
594
595 hollowVolume *= 0.78539816339f;
596 break;
597
598 case HollowShape.Triangle:
599
600 hollowVolume *= (0.5f * .5f);
601 break;
602
603 default:
604 hollowVolume = 0;
605 break;
606 }
607 volume *= (1.0f - hollowVolume);
608 }
609 }
610
611 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
612 {
613 //a tube
614
615 volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX);
616 tmp = 1.0f - 2.0e-2f * (float)(200 - _pbs.PathScaleY);
617 volume -= volume * tmp * tmp;
618
619 if (hollowAmount > 0.0)
620 {
621 hollowVolume *= hollowAmount;
622
623 switch (_pbs.HollowShape)
624 {
625 case HollowShape.Square:
626 case HollowShape.Same:
627 break;
628
629 case HollowShape.Circle:
630 hollowVolume *= 0.78539816339f;
631 break;
632
633 case HollowShape.Triangle:
634 hollowVolume *= 0.5f * 0.5f;
635 break;
636 default:
637 hollowVolume = 0;
638 break;
639 }
640 volume *= (1.0f - hollowVolume);
641 }
642 }
643
644 break;
645
646 case ProfileShape.Circle:
647
648 if (_pbs.PathCurve == (byte)Extrusion.Straight)
649 {
650 volume *= 0.78539816339f; // elipse base
651
652 if (hollowAmount > 0.0)
653 {
654 switch (_pbs.HollowShape)
655 {
656 case HollowShape.Same:
657 case HollowShape.Circle:
658 break;
659
660 case HollowShape.Square:
661 hollowVolume *= 0.5f * 2.5984480504799f;
662 break;
663
664 case HollowShape.Triangle:
665 hollowVolume *= .5f * 1.27323954473516f;
666 break;
667
668 default:
669 hollowVolume = 0;
670 break;
671 }
672 volume *= (1.0f - hollowVolume);
673 }
674 }
675
676 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
677 {
678 volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX);
679 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
680 volume *= (1.0f - tmp * tmp);
681
682 if (hollowAmount > 0.0)
683 {
684
685 // calculate the hollow volume by it's shape compared to the prim shape
686 hollowVolume *= hollowAmount;
687
688 switch (_pbs.HollowShape)
689 {
690 case HollowShape.Same:
691 case HollowShape.Circle:
692 break;
693
694 case HollowShape.Square:
695 hollowVolume *= 0.5f * 2.5984480504799f;
696 break;
697
698 case HollowShape.Triangle:
699 hollowVolume *= .5f * 1.27323954473516f;
700 break;
701
702 default:
703 hollowVolume = 0;
704 break;
705 }
706 volume *= (1.0f - hollowVolume);
707 }
708 }
709 break;
710
711 case ProfileShape.HalfCircle:
712 if (_pbs.PathCurve == (byte)Extrusion.Curve1)
713 {
714 volume *= 0.5236f;
715
716 if (hollowAmount > 0.0)
717 {
718 hollowVolume *= hollowAmount;
719
720 switch (_pbs.HollowShape)
721 {
722 case HollowShape.Circle:
723 case HollowShape.Triangle: // diference in sl is minor and odd
724 case HollowShape.Same:
725 break;
726
727 case HollowShape.Square:
728 hollowVolume *= 0.909f;
729 break;
730
731 // case HollowShape.Triangle:
732 // hollowVolume *= .827f;
733 // break;
734 default:
735 hollowVolume = 0;
736 break;
737 }
738 volume *= (1.0f - hollowVolume);
739 }
740
741 }
742 break;
743
744 case ProfileShape.EquilateralTriangle:
745
746 if (_pbs.PathCurve == (byte)Extrusion.Straight)
747 {
748 volume *= 0.32475953f;
749
750 if (hollowAmount > 0.0)
751 {
752
753 // calculate the hollow volume by it's shape compared to the prim shape
754 switch (_pbs.HollowShape)
755 {
756 case HollowShape.Same:
757 case HollowShape.Triangle:
758 hollowVolume *= .25f;
759 break;
760
761 case HollowShape.Square:
762 hollowVolume *= 0.499849f * 3.07920140172638f;
763 break;
764
765 case HollowShape.Circle:
766 // Hollow shape is a perfect cyllinder in respect to the cube's scale
767 // Cyllinder hollow volume calculation
768
769 hollowVolume *= 0.1963495f * 3.07920140172638f;
770 break;
771
772 default:
773 hollowVolume = 0;
774 break;
775 }
776 volume *= (1.0f - hollowVolume);
777 }
778 }
779 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
780 {
781 volume *= 0.32475953f;
782 volume *= 0.01f * (float)(200 - _pbs.PathScaleX);
783 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
784 volume *= (1.0f - tmp * tmp);
785
786 if (hollowAmount > 0.0)
787 {
788
789 hollowVolume *= hollowAmount;
790
791 switch (_pbs.HollowShape)
792 {
793 case HollowShape.Same:
794 case HollowShape.Triangle:
795 hollowVolume *= .25f;
796 break;
797
798 case HollowShape.Square:
799 hollowVolume *= 0.499849f * 3.07920140172638f;
800 break;
801
802 case HollowShape.Circle:
803
804 hollowVolume *= 0.1963495f * 3.07920140172638f;
805 break;
806
807 default:
808 hollowVolume = 0;
809 break;
810 }
811 volume *= (1.0f - hollowVolume);
812 }
813 }
814 break;
815
816 default:
817 break;
818 }
819
820 float taperX1;
821 float taperY1;
822 float taperX;
823 float taperY;
824 float pathBegin;
825 float pathEnd;
826 float profileBegin;
827 float profileEnd;
828
829 if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible)
830 {
831 taperX1 = _pbs.PathScaleX * 0.01f;
832 if (taperX1 > 1.0f)
833 taperX1 = 2.0f - taperX1;
834 taperX = 1.0f - taperX1;
835
836 taperY1 = _pbs.PathScaleY * 0.01f;
837 if (taperY1 > 1.0f)
838 taperY1 = 2.0f - taperY1;
839 taperY = 1.0f - taperY1;
840 }
841 else
842 {
843 taperX = _pbs.PathTaperX * 0.01f;
844 if (taperX < 0.0f)
845 taperX = -taperX;
846 taperX1 = 1.0f - taperX;
847
848 taperY = _pbs.PathTaperY * 0.01f;
849 if (taperY < 0.0f)
850 taperY = -taperY;
851 taperY1 = 1.0f - taperY;
852 }
853
854 volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY);
855
856 pathBegin = (float)_pbs.PathBegin * 2.0e-5f;
857 pathEnd = 1.0f - (float)_pbs.PathEnd * 2.0e-5f;
858 volume *= (pathEnd - pathBegin);
859
860 // this is crude aproximation
861 profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f;
862 profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f;
863 volume *= (profileEnd - profileBegin);
864
865 repData.volume = volume;
866 }
867
868 private void CalcVolumeData(ODEPhysRepData repData)
869 {
870 if (repData.hasOBB)
871 {
872 Vector3 OBB = repData.OBB;
873 }
874 else
875 {
876 Vector3 OBB = repData.size;
877 OBB.X *= 0.5f;
878 OBB.Y *= 0.5f;
879 OBB.Z *= 0.5f;
880
881 repData.OBB = OBB;
882 repData.OBBOffset = Vector3.Zero;
883 }
884
885 CalculateBasicPrimVolume(repData);
886 }
887 }
888
889 public class ODEAssetRequest
890 {
891 ODEMeshWorker m_worker;
892 private ILog m_log;
893 ODEPhysRepData repData;
894
895 public ODEAssetRequest(ODEMeshWorker pWorker, RequestAssetDelegate provider,
896 ODEPhysRepData pRepData, ILog plog)
897 {
898 m_worker = pWorker;
899 m_log = plog;
900 repData = pRepData;
901
902 repData.meshState = MeshState.AssetFailed;
903 if (provider == null)
904 return;
905
906 if (repData.assetID == null)
907 return;
908
909 UUID assetID = (UUID) repData.assetID;
910 if (assetID == UUID.Zero)
911 return;
912
913 repData.meshState = MeshState.loadingAsset;
914 provider(assetID, ODEassetReceived);
915 }
916
917 void ODEassetReceived(AssetBase asset)
918 {
919 repData.meshState = MeshState.AssetFailed;
920 if (asset != null)
921 {
922 if (asset.Data != null && asset.Data.Length > 0)
923 {
924 repData.meshState = MeshState.noNeed;
925
926 if (!repData.pbs.SculptEntry)
927 return;
928 if (repData.pbs.SculptTexture != repData.assetID)
929 return;
930
931// repData.pbs.SculptData = new byte[asset.Data.Length];
932// asset.Data.CopyTo(repData.pbs.SculptData,0);
933 repData.pbs.SculptData = asset.Data;
934 repData.meshState = MeshState.AssetOK;
935 m_worker.AssetLoaded(repData);
936 }
937 else
938 m_log.WarnFormat("[PHYSICS]: asset provider returned invalid mesh data for prim {0} asset UUID {1}.",
939 repData.actor.Name, asset.ID.ToString());
940 }
941 else
942 m_log.WarnFormat("[PHYSICS]: asset provider returned null asset for mesh of prim {0}.",
943 repData.actor.Name);
944 }
945 }
946}