aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/PhysicsModules/UbitOde/ODEMeshWorker.cs
diff options
context:
space:
mode:
authorUbitUmarov2015-09-08 17:21:45 +0100
committerUbitUmarov2015-09-08 17:21:45 +0100
commit5c619fe0ab607be471f6d6fc786da28feff94837 (patch)
tree376535da35dbbdef4a8edf37cf6434e1c465bd77 /OpenSim/Region/PhysicsModules/UbitOde/ODEMeshWorker.cs
parent rename Ubitode (diff)
downloadopensim-SC_OLD-5c619fe0ab607be471f6d6fc786da28feff94837.zip
opensim-SC_OLD-5c619fe0ab607be471f6d6fc786da28feff94837.tar.gz
opensim-SC_OLD-5c619fe0ab607be471f6d6fc786da28feff94837.tar.bz2
opensim-SC_OLD-5c619fe0ab607be471f6d6fc786da28feff94837.tar.xz
opps my files?
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/PhysicsModules/UbitOde/ODEMeshWorker.cs933
1 files changed, 933 insertions, 0 deletions
diff --git a/OpenSim/Region/PhysicsModules/UbitOde/ODEMeshWorker.cs b/OpenSim/Region/PhysicsModules/UbitOde/ODEMeshWorker.cs
new file mode 100644
index 0000000..d4ba8a3
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/UbitOde/ODEMeshWorker.cs
@@ -0,0 +1,933 @@
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.PhysicsModules.UbitOde
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.Name = "OdeMeshWorker";
104 m_thread.Start();
105 }
106
107 private void DoWork()
108 {
109 m_mesher.ExpireFileCache();
110
111 while(m_running)
112 {
113 ODEPhysRepData nextRep = createqueue.Dequeue();
114 if(!m_running)
115 return;
116 if (nextRep == null)
117 continue;
118 if (m_scene.haveActor(nextRep.actor))
119 {
120 switch (nextRep.comand)
121 {
122 case meshWorkerCmnds.changefull:
123 case meshWorkerCmnds.changeshapetype:
124 case meshWorkerCmnds.changesize:
125 GetMesh(nextRep);
126 if (CreateActorPhysRep(nextRep) && m_scene.haveActor(nextRep.actor))
127 m_scene.AddChange(nextRep.actor, changes.PhysRepData, nextRep);
128 break;
129 case meshWorkerCmnds.getmesh:
130 DoRepDataGetMesh(nextRep);
131 break;
132 }
133 }
134 }
135 }
136
137 public void Stop()
138 {
139 try
140 {
141 m_thread.Abort();
142 createqueue.Clear();
143 }
144 catch
145 {
146 }
147 }
148
149 public void ChangeActorPhysRep(PhysicsActor actor, PrimitiveBaseShape pbs,
150 Vector3 size, byte shapetype)
151 {
152 ODEPhysRepData repData = new ODEPhysRepData();
153 repData.actor = actor;
154 repData.pbs = pbs;
155 repData.size = size;
156 repData.shapetype = shapetype;
157
158 CheckMesh(repData);
159 CalcVolumeData(repData);
160 m_scene.AddChange(actor, changes.PhysRepData, repData);
161 return;
162 }
163
164 public ODEPhysRepData NewActorPhysRep(PhysicsActor actor, PrimitiveBaseShape pbs,
165 Vector3 size, byte shapetype)
166 {
167 ODEPhysRepData repData = new ODEPhysRepData();
168 repData.actor = actor;
169 repData.pbs = pbs;
170 repData.size = size;
171 repData.shapetype = shapetype;
172
173 CheckMesh(repData);
174 CalcVolumeData(repData);
175 m_scene.AddChange(actor, changes.AddPhysRep, repData);
176 return repData;
177 }
178
179 public void RequestMesh(ODEPhysRepData repData)
180 {
181 repData.mesh = null;
182
183 if (repData.meshState == MeshState.needAsset)
184 {
185 PrimitiveBaseShape pbs = repData.pbs;
186
187 // check if we got outdated
188
189 if (!pbs.SculptEntry || pbs.SculptTexture == UUID.Zero)
190 {
191 repData.meshState = MeshState.noNeed;
192 return;
193 }
194
195 repData.assetID = pbs.SculptTexture;
196 repData.meshState = MeshState.loadingAsset;
197
198 repData.comand = meshWorkerCmnds.getmesh;
199 createqueue.Enqueue(repData);
200 }
201 }
202
203 // creates and prepares a mesh to use and calls parameters estimation
204 public bool CreateActorPhysRep(ODEPhysRepData repData)
205 {
206 IMesh mesh = repData.mesh;
207
208 if (mesh != null)
209 {
210 IntPtr vertices, indices;
211 int vertexCount, indexCount;
212 int vertexStride, triStride;
213
214 mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount);
215 mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount);
216
217 if (vertexCount == 0 || indexCount == 0)
218 {
219 m_log.WarnFormat("[PHYSICS]: Invalid mesh data on prim {0} mesh UUID {1}",
220 repData.actor.Name, repData.pbs.SculptTexture.ToString());
221 repData.meshState = MeshState.MeshFailed;
222 repData.hasOBB = false;
223 repData.mesh = null;
224 m_scene.mesher.ReleaseMesh(mesh);
225 }
226 else
227 {
228 repData.OBBOffset = mesh.GetCentroid();
229 repData.OBB = mesh.GetOBB();
230 repData.hasOBB = true;
231 mesh.releaseSourceMeshData();
232 }
233 }
234 CalcVolumeData(repData);
235 return true;
236 }
237
238 public void AssetLoaded(ODEPhysRepData repData)
239 {
240 if (m_scene.haveActor(repData.actor))
241 {
242 if (needsMeshing(repData.pbs)) // no need for pbs now?
243 {
244 repData.comand = meshWorkerCmnds.changefull;
245 createqueue.Enqueue(repData);
246 }
247 }
248 else
249 repData.pbs.SculptData = Utils.EmptyBytes;
250 }
251
252 public void DoRepDataGetMesh(ODEPhysRepData repData)
253 {
254 if (!repData.pbs.SculptEntry)
255 return;
256
257 if (repData.meshState != MeshState.loadingAsset)
258 return;
259
260 if (repData.assetID == null || repData.assetID == UUID.Zero)
261 return;
262
263 if (repData.assetID != repData.pbs.SculptTexture)
264 return;
265
266 // check if it is in cache
267 GetMesh(repData);
268 if (repData.meshState != MeshState.needAsset)
269 {
270 CreateActorPhysRep(repData);
271 m_scene.AddChange(repData.actor, changes.PhysRepData, repData);
272 return;
273 }
274
275 RequestAssetDelegate assetProvider = m_scene.RequestAssetMethod;
276 if (assetProvider == null)
277 return;
278 ODEAssetRequest asr = new ODEAssetRequest(this, assetProvider, repData, m_log);
279 }
280
281
282 /// <summary>
283 /// Routine to figure out if we need to mesh this prim with our mesher
284 /// </summary>
285 /// <param name="pbs"></param>
286 /// <returns></returns>
287 public bool needsMeshing(PrimitiveBaseShape pbs)
288 {
289 // check sculpts or meshs
290 if (pbs.SculptEntry)
291 {
292 if (meshSculptedPrim)
293 return true;
294
295 if (pbs.SculptType == (byte)SculptType.Mesh) // always do meshs
296 return true;
297
298 return false;
299 }
300
301 if (forceSimplePrimMeshing)
302 return true;
303
304 // 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
305
306 if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
307 || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1
308 && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z))
309 {
310
311 if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
312 && pbs.ProfileHollow == 0
313 && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
314 && pbs.PathBegin == 0 && pbs.PathEnd == 0
315 && pbs.PathTaperX == 0 && pbs.PathTaperY == 0
316 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
317 && pbs.PathShearX == 0 && pbs.PathShearY == 0)
318 {
319 return false;
320 }
321 }
322
323 // following code doesn't give meshs to boxes and spheres ever
324 // and it's odd.. so for now just return true if asked to force meshs
325 // hopefully mesher will fail if doesn't suport so things still get basic boxes
326
327 int iPropertiesNotSupportedDefault = 0;
328
329 if (pbs.ProfileHollow != 0)
330 iPropertiesNotSupportedDefault++;
331
332 if ((pbs.PathBegin != 0) || pbs.PathEnd != 0)
333 iPropertiesNotSupportedDefault++;
334
335 if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0))
336 iPropertiesNotSupportedDefault++;
337
338 if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0)
339 iPropertiesNotSupportedDefault++;
340
341 if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100))
342 iPropertiesNotSupportedDefault++;
343
344 if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0))
345 iPropertiesNotSupportedDefault++;
346
347 if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight)
348 iPropertiesNotSupportedDefault++;
349
350 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))
351 iPropertiesNotSupportedDefault++;
352
353 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1)
354 iPropertiesNotSupportedDefault++;
355
356 // test for torus
357 if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
358 {
359 if (pbs.PathCurve == (byte)Extrusion.Curve1)
360 {
361 iPropertiesNotSupportedDefault++;
362 }
363 }
364 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
365 {
366 if (pbs.PathCurve == (byte)Extrusion.Straight)
367 {
368 iPropertiesNotSupportedDefault++;
369 }
370
371 // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
372 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
373 {
374 iPropertiesNotSupportedDefault++;
375 }
376 }
377 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
378 {
379 if (pbs.PathCurve == (byte)Extrusion.Curve1 || pbs.PathCurve == (byte)Extrusion.Curve2)
380 {
381 iPropertiesNotSupportedDefault++;
382 }
383 }
384 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
385 {
386 if (pbs.PathCurve == (byte)Extrusion.Straight)
387 {
388 iPropertiesNotSupportedDefault++;
389 }
390 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
391 {
392 iPropertiesNotSupportedDefault++;
393 }
394 }
395
396 if (iPropertiesNotSupportedDefault == 0)
397 {
398 return false;
399 }
400 return true;
401 }
402
403 // see if we need a mesh and if so if we have a cached one
404 // called with a new repData
405 public void CheckMesh(ODEPhysRepData repData)
406 {
407 PhysicsActor actor = repData.actor;
408 PrimitiveBaseShape pbs = repData.pbs;
409
410 if (!needsMeshing(pbs))
411 {
412 repData.meshState = MeshState.noNeed;
413 return;
414 }
415
416 IMesh mesh = null;
417
418 Vector3 size = repData.size;
419 byte shapetype = repData.shapetype;
420
421 bool convex;
422
423 int clod = (int)LevelOfDetail.High;
424 if (shapetype == 0)
425 convex = false;
426 else
427 {
428 convex = true;
429 if (pbs.SculptType != (byte)SculptType.Mesh)
430 clod = (int)LevelOfDetail.Low;
431 }
432
433 mesh = m_mesher.GetMesh(actor.Name, pbs, size, clod, true, convex);
434
435 if (mesh == null)
436 {
437 if (pbs.SculptEntry)
438 {
439 if (pbs.SculptTexture != null && pbs.SculptTexture != UUID.Zero)
440 {
441 repData.assetID = pbs.SculptTexture;
442 repData.meshState = MeshState.needAsset;
443 }
444 else
445 repData.meshState = MeshState.MeshFailed;
446
447 return;
448 }
449 else
450 {
451 repData.meshState = MeshState.needMesh;
452 mesh = m_mesher.CreateMesh(actor.Name, pbs, size, clod, true, convex, true);
453 if (mesh == null)
454 {
455 repData.meshState = MeshState.MeshFailed;
456 return;
457 }
458 }
459 }
460
461 repData.meshState = MeshState.AssetOK;
462 repData.mesh = mesh;
463
464 if (pbs.SculptEntry)
465 {
466 repData.assetID = pbs.SculptTexture;
467 }
468
469 pbs.SculptData = Utils.EmptyBytes;
470 return ;
471 }
472
473 public void GetMesh(ODEPhysRepData repData)
474 {
475 PhysicsActor actor = repData.actor;
476
477 PrimitiveBaseShape pbs = repData.pbs;
478
479 repData.mesh = null;
480 repData.hasOBB = false;
481
482 if (!needsMeshing(pbs))
483 {
484 repData.meshState = MeshState.noNeed;
485 return;
486 }
487
488 if (repData.meshState == MeshState.MeshFailed)
489 return;
490
491 if (pbs.SculptEntry)
492 {
493 if (repData.meshState == MeshState.AssetFailed)
494 {
495 if (pbs.SculptTexture == repData.assetID)
496 return;
497 }
498 }
499
500 repData.meshState = MeshState.noNeed;
501
502 IMesh mesh = null;
503 Vector3 size = repData.size;
504 byte shapetype = repData.shapetype;
505
506 bool convex;
507 int clod = (int)LevelOfDetail.High;
508 if (shapetype == 0)
509 convex = false;
510 else
511 {
512 convex = true;
513 if (pbs.SculptType != (byte)SculptType.Mesh)
514 clod = (int)LevelOfDetail.Low;
515 }
516
517 mesh = m_mesher.CreateMesh(actor.Name, pbs, size, clod, true, convex, true);
518
519 if (mesh == null)
520 {
521 if (pbs.SculptEntry)
522 {
523 if (pbs.SculptTexture == UUID.Zero)
524 return;
525
526 repData.assetID = pbs.SculptTexture;
527
528 if (pbs.SculptData == null || pbs.SculptData.Length == 0)
529 {
530 repData.meshState = MeshState.needAsset;
531 return;
532 }
533 }
534 }
535
536 repData.mesh = mesh;
537 repData.pbs.SculptData = Utils.EmptyBytes;
538
539 if (mesh == null)
540 {
541 if (pbs.SculptEntry)
542 repData.meshState = MeshState.AssetFailed;
543 else
544 repData.meshState = MeshState.MeshFailed;
545
546 return;
547 }
548
549 repData.meshState = MeshState.AssetOK;
550
551 return;
552 }
553
554 private void CalculateBasicPrimVolume(ODEPhysRepData repData)
555 {
556 PrimitiveBaseShape _pbs = repData.pbs;
557 Vector3 _size = repData.size;
558
559 float volume = _size.X * _size.Y * _size.Z; // default
560 float tmp;
561
562 float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f;
563 float hollowVolume = hollowAmount * hollowAmount;
564
565 switch (_pbs.ProfileShape)
566 {
567 case ProfileShape.Square:
568 // default box
569
570 if (_pbs.PathCurve == (byte)Extrusion.Straight)
571 {
572 if (hollowAmount > 0.0)
573 {
574 switch (_pbs.HollowShape)
575 {
576 case HollowShape.Square:
577 case HollowShape.Same:
578 break;
579
580 case HollowShape.Circle:
581
582 hollowVolume *= 0.78539816339f;
583 break;
584
585 case HollowShape.Triangle:
586
587 hollowVolume *= (0.5f * .5f);
588 break;
589
590 default:
591 hollowVolume = 0;
592 break;
593 }
594 volume *= (1.0f - hollowVolume);
595 }
596 }
597
598 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
599 {
600 //a tube
601
602 volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX);
603 tmp = 1.0f - 2.0e-2f * (float)(200 - _pbs.PathScaleY);
604 volume -= volume * tmp * tmp;
605
606 if (hollowAmount > 0.0)
607 {
608 hollowVolume *= hollowAmount;
609
610 switch (_pbs.HollowShape)
611 {
612 case HollowShape.Square:
613 case HollowShape.Same:
614 break;
615
616 case HollowShape.Circle:
617 hollowVolume *= 0.78539816339f;
618 break;
619
620 case HollowShape.Triangle:
621 hollowVolume *= 0.5f * 0.5f;
622 break;
623 default:
624 hollowVolume = 0;
625 break;
626 }
627 volume *= (1.0f - hollowVolume);
628 }
629 }
630
631 break;
632
633 case ProfileShape.Circle:
634
635 if (_pbs.PathCurve == (byte)Extrusion.Straight)
636 {
637 volume *= 0.78539816339f; // elipse base
638
639 if (hollowAmount > 0.0)
640 {
641 switch (_pbs.HollowShape)
642 {
643 case HollowShape.Same:
644 case HollowShape.Circle:
645 break;
646
647 case HollowShape.Square:
648 hollowVolume *= 0.5f * 2.5984480504799f;
649 break;
650
651 case HollowShape.Triangle:
652 hollowVolume *= .5f * 1.27323954473516f;
653 break;
654
655 default:
656 hollowVolume = 0;
657 break;
658 }
659 volume *= (1.0f - hollowVolume);
660 }
661 }
662
663 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
664 {
665 volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX);
666 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
667 volume *= (1.0f - tmp * tmp);
668
669 if (hollowAmount > 0.0)
670 {
671
672 // calculate the hollow volume by it's shape compared to the prim shape
673 hollowVolume *= hollowAmount;
674
675 switch (_pbs.HollowShape)
676 {
677 case HollowShape.Same:
678 case HollowShape.Circle:
679 break;
680
681 case HollowShape.Square:
682 hollowVolume *= 0.5f * 2.5984480504799f;
683 break;
684
685 case HollowShape.Triangle:
686 hollowVolume *= .5f * 1.27323954473516f;
687 break;
688
689 default:
690 hollowVolume = 0;
691 break;
692 }
693 volume *= (1.0f - hollowVolume);
694 }
695 }
696 break;
697
698 case ProfileShape.HalfCircle:
699 if (_pbs.PathCurve == (byte)Extrusion.Curve1)
700 {
701 volume *= 0.5236f;
702
703 if (hollowAmount > 0.0)
704 {
705 hollowVolume *= hollowAmount;
706
707 switch (_pbs.HollowShape)
708 {
709 case HollowShape.Circle:
710 case HollowShape.Triangle: // diference in sl is minor and odd
711 case HollowShape.Same:
712 break;
713
714 case HollowShape.Square:
715 hollowVolume *= 0.909f;
716 break;
717
718 // case HollowShape.Triangle:
719 // hollowVolume *= .827f;
720 // break;
721 default:
722 hollowVolume = 0;
723 break;
724 }
725 volume *= (1.0f - hollowVolume);
726 }
727
728 }
729 break;
730
731 case ProfileShape.EquilateralTriangle:
732
733 if (_pbs.PathCurve == (byte)Extrusion.Straight)
734 {
735 volume *= 0.32475953f;
736
737 if (hollowAmount > 0.0)
738 {
739
740 // calculate the hollow volume by it's shape compared to the prim shape
741 switch (_pbs.HollowShape)
742 {
743 case HollowShape.Same:
744 case HollowShape.Triangle:
745 hollowVolume *= .25f;
746 break;
747
748 case HollowShape.Square:
749 hollowVolume *= 0.499849f * 3.07920140172638f;
750 break;
751
752 case HollowShape.Circle:
753 // Hollow shape is a perfect cyllinder in respect to the cube's scale
754 // Cyllinder hollow volume calculation
755
756 hollowVolume *= 0.1963495f * 3.07920140172638f;
757 break;
758
759 default:
760 hollowVolume = 0;
761 break;
762 }
763 volume *= (1.0f - hollowVolume);
764 }
765 }
766 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
767 {
768 volume *= 0.32475953f;
769 volume *= 0.01f * (float)(200 - _pbs.PathScaleX);
770 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
771 volume *= (1.0f - tmp * tmp);
772
773 if (hollowAmount > 0.0)
774 {
775
776 hollowVolume *= hollowAmount;
777
778 switch (_pbs.HollowShape)
779 {
780 case HollowShape.Same:
781 case HollowShape.Triangle:
782 hollowVolume *= .25f;
783 break;
784
785 case HollowShape.Square:
786 hollowVolume *= 0.499849f * 3.07920140172638f;
787 break;
788
789 case HollowShape.Circle:
790
791 hollowVolume *= 0.1963495f * 3.07920140172638f;
792 break;
793
794 default:
795 hollowVolume = 0;
796 break;
797 }
798 volume *= (1.0f - hollowVolume);
799 }
800 }
801 break;
802
803 default:
804 break;
805 }
806
807 float taperX1;
808 float taperY1;
809 float taperX;
810 float taperY;
811 float pathBegin;
812 float pathEnd;
813 float profileBegin;
814 float profileEnd;
815
816 if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible)
817 {
818 taperX1 = _pbs.PathScaleX * 0.01f;
819 if (taperX1 > 1.0f)
820 taperX1 = 2.0f - taperX1;
821 taperX = 1.0f - taperX1;
822
823 taperY1 = _pbs.PathScaleY * 0.01f;
824 if (taperY1 > 1.0f)
825 taperY1 = 2.0f - taperY1;
826 taperY = 1.0f - taperY1;
827 }
828 else
829 {
830 taperX = _pbs.PathTaperX * 0.01f;
831 if (taperX < 0.0f)
832 taperX = -taperX;
833 taperX1 = 1.0f - taperX;
834
835 taperY = _pbs.PathTaperY * 0.01f;
836 if (taperY < 0.0f)
837 taperY = -taperY;
838 taperY1 = 1.0f - taperY;
839 }
840
841 volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY);
842
843 pathBegin = (float)_pbs.PathBegin * 2.0e-5f;
844 pathEnd = 1.0f - (float)_pbs.PathEnd * 2.0e-5f;
845 volume *= (pathEnd - pathBegin);
846
847 // this is crude aproximation
848 profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f;
849 profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f;
850 volume *= (profileEnd - profileBegin);
851
852 repData.volume = volume;
853 }
854
855 private void CalcVolumeData(ODEPhysRepData repData)
856 {
857 if (repData.hasOBB)
858 {
859 Vector3 OBB = repData.OBB;
860 }
861 else
862 {
863 Vector3 OBB = repData.size;
864 OBB.X *= 0.5f;
865 OBB.Y *= 0.5f;
866 OBB.Z *= 0.5f;
867
868 repData.OBB = OBB;
869 repData.OBBOffset = Vector3.Zero;
870 }
871
872 CalculateBasicPrimVolume(repData);
873 }
874 }
875
876 public class ODEAssetRequest
877 {
878 ODEMeshWorker m_worker;
879 private ILog m_log;
880 ODEPhysRepData repData;
881
882 public ODEAssetRequest(ODEMeshWorker pWorker, RequestAssetDelegate provider,
883 ODEPhysRepData pRepData, ILog plog)
884 {
885 m_worker = pWorker;
886 m_log = plog;
887 repData = pRepData;
888
889 repData.meshState = MeshState.AssetFailed;
890 if (provider == null)
891 return;
892
893 if (repData.assetID == null)
894 return;
895
896 UUID assetID = (UUID) repData.assetID;
897 if (assetID == UUID.Zero)
898 return;
899
900 repData.meshState = MeshState.loadingAsset;
901 provider(assetID, ODEassetReceived);
902 }
903
904 void ODEassetReceived(AssetBase asset)
905 {
906 repData.meshState = MeshState.AssetFailed;
907 if (asset != null)
908 {
909 if (asset.Data != null && asset.Data.Length > 0)
910 {
911 repData.meshState = MeshState.noNeed;
912
913 if (!repData.pbs.SculptEntry)
914 return;
915 if (repData.pbs.SculptTexture != repData.assetID)
916 return;
917
918// repData.pbs.SculptData = new byte[asset.Data.Length];
919// asset.Data.CopyTo(repData.pbs.SculptData,0);
920 repData.pbs.SculptData = asset.Data;
921 repData.meshState = MeshState.AssetOK;
922 m_worker.AssetLoaded(repData);
923 }
924 else
925 m_log.WarnFormat("[PHYSICS]: asset provider returned invalid mesh data for prim {0} asset UUID {1}.",
926 repData.actor.Name, asset.ID.ToString());
927 }
928 else
929 m_log.WarnFormat("[PHYSICS]: asset provider returned null asset fo mesh of prim {0}.",
930 repData.actor.Name);
931 }
932 }
933}