OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
ODEMeshWorker.cs
Go to the documentation of this file.
1 /*
2  * AJLDuarte 2012
3  */
4 
5 using System;
6 using System.Threading;
7 using System.Collections.Generic;
8 using System.IO;
9 using System.Reflection;
10 using System.Runtime.InteropServices;
11 using System.Text;
12 using OpenSim.Framework;
13 using OpenSim.Region.PhysicsModules.SharedBase;
14 using OdeAPI;
15 using log4net;
16 using Nini.Config;
17 using OpenMetaverse;
18 
19 namespace 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 
38  }
39 
40  public enum meshWorkerCmnds : byte
41  {
42  nop = 0,
43  addnew,
44  changefull,
45  changesize,
47  getmesh,
48  }
49 
50  public class ODEPhysRepData
51  {
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;
66  public UUID? assetID;
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 
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 
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 
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  repData.hasOBB = false;
414  return;
415  }
416 
417  IMesh mesh = null;
418 
419  Vector3 size = repData.size;
420  byte shapetype = repData.shapetype;
421 
422  bool convex;
423 
424  int clod = (int)LevelOfDetail.High;
425  if (shapetype == 0)
426  convex = false;
427  else
428  {
429  convex = true;
430  if (pbs.SculptType != (byte)SculptType.Mesh)
431  clod = (int)LevelOfDetail.Low;
432  }
433 
434  mesh = m_mesher.GetMesh(actor.Name, pbs, size, clod, true, convex);
435 
436  if (mesh == null)
437  {
438  if (pbs.SculptEntry)
439  {
440  if (pbs.SculptTexture != null && pbs.SculptTexture != UUID.Zero)
441  {
442  repData.assetID = pbs.SculptTexture;
443  repData.meshState = MeshState.needAsset;
444  }
445  else
446  repData.meshState = MeshState.MeshFailed;
447 
448  return;
449  }
450  else
451  {
452  repData.meshState = MeshState.needMesh;
453  mesh = m_mesher.CreateMesh(actor.Name, pbs, size, clod, true, convex, true);
454  if (mesh == null)
455  {
456  repData.meshState = MeshState.MeshFailed;
457  return;
458  }
459  }
460  }
461 
462  repData.meshState = MeshState.AssetOK;
463  repData.mesh = mesh;
464  repData.OBB = mesh.GetOBB();
465  repData.OBBOffset = mesh.GetCentroid();
466  repData.hasOBB = true;
467 
468  if (pbs.SculptEntry)
469  {
470  repData.assetID = pbs.SculptTexture;
471  }
472 
473  pbs.SculptData = Utils.EmptyBytes;
474  return ;
475  }
476 
477  public void GetMesh(ODEPhysRepData repData)
478  {
479  PhysicsActor actor = repData.actor;
480 
481  PrimitiveBaseShape pbs = repData.pbs;
482 
483  repData.mesh = null;
484  repData.hasOBB = false;
485 
486  if (!needsMeshing(pbs))
487  {
488  repData.meshState = MeshState.noNeed;
489  return;
490  }
491 
492  if (repData.meshState == MeshState.MeshFailed)
493  return;
494 
495  if (pbs.SculptEntry)
496  {
497  if (repData.meshState == MeshState.AssetFailed)
498  {
499  if (pbs.SculptTexture == repData.assetID)
500  return;
501  }
502  }
503 
504  repData.meshState = MeshState.noNeed;
505 
506  IMesh mesh = null;
507  Vector3 size = repData.size;
508  byte shapetype = repData.shapetype;
509 
510  bool convex;
511  int clod = (int)LevelOfDetail.High;
512  if (shapetype == 0)
513  convex = false;
514  else
515  {
516  convex = true;
517  if (pbs.SculptType != (byte)SculptType.Mesh)
518  clod = (int)LevelOfDetail.Low;
519  }
520 
521  mesh = m_mesher.CreateMesh(actor.Name, pbs, size, clod, true, convex, true);
522 
523  if (mesh == null)
524  {
525  if (pbs.SculptEntry)
526  {
527  if (pbs.SculptTexture == UUID.Zero)
528  return;
529 
530  repData.assetID = pbs.SculptTexture;
531 
532  if (pbs.SculptData == null || pbs.SculptData.Length == 0)
533  {
534  repData.meshState = MeshState.needAsset;
535  return;
536  }
537  }
538  }
539 
540  repData.mesh = mesh;
541  repData.pbs.SculptData = Utils.EmptyBytes;
542 
543  if (mesh == null)
544  {
545  if (pbs.SculptEntry)
546  repData.meshState = MeshState.AssetFailed;
547  else
548  repData.meshState = MeshState.MeshFailed;
549 
550  return;
551  }
552 
553  repData.meshState = MeshState.AssetOK;
554 
555  return;
556  }
557 
558  private void CalculateBasicPrimVolume(ODEPhysRepData repData)
559  {
560  PrimitiveBaseShape _pbs = repData.pbs;
561  Vector3 _size = repData.size;
562 
563  float volume = _size.X * _size.Y * _size.Z; // default
564  float tmp;
565 
566  float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f;
567  float hollowVolume = hollowAmount * hollowAmount;
568 
569  switch (_pbs.ProfileShape)
570  {
571  case ProfileShape.Square:
572  // default box
573 
574  if (_pbs.PathCurve == (byte)Extrusion.Straight)
575  {
576  if (hollowAmount > 0.0)
577  {
578  switch (_pbs.HollowShape)
579  {
580  case HollowShape.Square:
581  case HollowShape.Same:
582  break;
583 
584  case HollowShape.Circle:
585 
586  hollowVolume *= 0.78539816339f;
587  break;
588 
589  case HollowShape.Triangle:
590 
591  hollowVolume *= (0.5f * .5f);
592  break;
593 
594  default:
595  hollowVolume = 0;
596  break;
597  }
598  volume *= (1.0f - hollowVolume);
599  }
600  }
601 
602  else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
603  {
604  //a tube
605 
606  volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX);
607  tmp = 1.0f - 2.0e-2f * (float)(200 - _pbs.PathScaleY);
608  volume -= volume * tmp * tmp;
609 
610  if (hollowAmount > 0.0)
611  {
612  hollowVolume *= hollowAmount;
613 
614  switch (_pbs.HollowShape)
615  {
616  case HollowShape.Square:
617  case HollowShape.Same:
618  break;
619 
620  case HollowShape.Circle:
621  hollowVolume *= 0.78539816339f;
622  break;
623 
624  case HollowShape.Triangle:
625  hollowVolume *= 0.5f * 0.5f;
626  break;
627  default:
628  hollowVolume = 0;
629  break;
630  }
631  volume *= (1.0f - hollowVolume);
632  }
633  }
634 
635  break;
636 
637  case ProfileShape.Circle:
638 
639  if (_pbs.PathCurve == (byte)Extrusion.Straight)
640  {
641  volume *= 0.78539816339f; // elipse base
642 
643  if (hollowAmount > 0.0)
644  {
645  switch (_pbs.HollowShape)
646  {
647  case HollowShape.Same:
648  case HollowShape.Circle:
649  break;
650 
651  case HollowShape.Square:
652  hollowVolume *= 0.5f * 2.5984480504799f;
653  break;
654 
655  case HollowShape.Triangle:
656  hollowVolume *= .5f * 1.27323954473516f;
657  break;
658 
659  default:
660  hollowVolume = 0;
661  break;
662  }
663  volume *= (1.0f - hollowVolume);
664  }
665  }
666 
667  else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
668  {
669  volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX);
670  tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
671  volume *= (1.0f - tmp * tmp);
672 
673  if (hollowAmount > 0.0)
674  {
675 
676  // calculate the hollow volume by it's shape compared to the prim shape
677  hollowVolume *= hollowAmount;
678 
679  switch (_pbs.HollowShape)
680  {
681  case HollowShape.Same:
682  case HollowShape.Circle:
683  break;
684 
685  case HollowShape.Square:
686  hollowVolume *= 0.5f * 2.5984480504799f;
687  break;
688 
689  case HollowShape.Triangle:
690  hollowVolume *= .5f * 1.27323954473516f;
691  break;
692 
693  default:
694  hollowVolume = 0;
695  break;
696  }
697  volume *= (1.0f - hollowVolume);
698  }
699  }
700  break;
701 
702  case ProfileShape.HalfCircle:
703  if (_pbs.PathCurve == (byte)Extrusion.Curve1)
704  {
705  volume *= 0.5236f;
706 
707  if (hollowAmount > 0.0)
708  {
709  hollowVolume *= hollowAmount;
710 
711  switch (_pbs.HollowShape)
712  {
713  case HollowShape.Circle:
714  case HollowShape.Triangle: // diference in sl is minor and odd
715  case HollowShape.Same:
716  break;
717 
718  case HollowShape.Square:
719  hollowVolume *= 0.909f;
720  break;
721 
722  // case HollowShape.Triangle:
723  // hollowVolume *= .827f;
724  // break;
725  default:
726  hollowVolume = 0;
727  break;
728  }
729  volume *= (1.0f - hollowVolume);
730  }
731 
732  }
733  break;
734 
735  case ProfileShape.EquilateralTriangle:
736 
737  if (_pbs.PathCurve == (byte)Extrusion.Straight)
738  {
739  volume *= 0.32475953f;
740 
741  if (hollowAmount > 0.0)
742  {
743 
744  // calculate the hollow volume by it's shape compared to the prim shape
745  switch (_pbs.HollowShape)
746  {
747  case HollowShape.Same:
748  case HollowShape.Triangle:
749  hollowVolume *= .25f;
750  break;
751 
752  case HollowShape.Square:
753  hollowVolume *= 0.499849f * 3.07920140172638f;
754  break;
755 
756  case HollowShape.Circle:
757  // Hollow shape is a perfect cyllinder in respect to the cube's scale
758  // Cyllinder hollow volume calculation
759 
760  hollowVolume *= 0.1963495f * 3.07920140172638f;
761  break;
762 
763  default:
764  hollowVolume = 0;
765  break;
766  }
767  volume *= (1.0f - hollowVolume);
768  }
769  }
770  else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
771  {
772  volume *= 0.32475953f;
773  volume *= 0.01f * (float)(200 - _pbs.PathScaleX);
774  tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
775  volume *= (1.0f - tmp * tmp);
776 
777  if (hollowAmount > 0.0)
778  {
779 
780  hollowVolume *= hollowAmount;
781 
782  switch (_pbs.HollowShape)
783  {
784  case HollowShape.Same:
785  case HollowShape.Triangle:
786  hollowVolume *= .25f;
787  break;
788 
789  case HollowShape.Square:
790  hollowVolume *= 0.499849f * 3.07920140172638f;
791  break;
792 
793  case HollowShape.Circle:
794 
795  hollowVolume *= 0.1963495f * 3.07920140172638f;
796  break;
797 
798  default:
799  hollowVolume = 0;
800  break;
801  }
802  volume *= (1.0f - hollowVolume);
803  }
804  }
805  break;
806 
807  default:
808  break;
809  }
810 
811  float taperX1;
812  float taperY1;
813  float taperX;
814  float taperY;
815  float pathBegin;
816  float pathEnd;
817  float profileBegin;
818  float profileEnd;
819 
820  if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible)
821  {
822  taperX1 = _pbs.PathScaleX * 0.01f;
823  if (taperX1 > 1.0f)
824  taperX1 = 2.0f - taperX1;
825  taperX = 1.0f - taperX1;
826 
827  taperY1 = _pbs.PathScaleY * 0.01f;
828  if (taperY1 > 1.0f)
829  taperY1 = 2.0f - taperY1;
830  taperY = 1.0f - taperY1;
831  }
832  else
833  {
834  taperX = _pbs.PathTaperX * 0.01f;
835  if (taperX < 0.0f)
836  taperX = -taperX;
837  taperX1 = 1.0f - taperX;
838 
839  taperY = _pbs.PathTaperY * 0.01f;
840  if (taperY < 0.0f)
841  taperY = -taperY;
842  taperY1 = 1.0f - taperY;
843  }
844 
845  volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY);
846 
847  pathBegin = (float)_pbs.PathBegin * 2.0e-5f;
848  pathEnd = 1.0f - (float)_pbs.PathEnd * 2.0e-5f;
849  volume *= (pathEnd - pathBegin);
850 
851  // this is crude aproximation
852  profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f;
853  profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f;
854  volume *= (profileEnd - profileBegin);
855 
856  repData.volume = volume;
857  }
858 
859  private void CalcVolumeData(ODEPhysRepData repData)
860  {
861  if (repData.hasOBB)
862  {
863  Vector3 OBB = repData.OBB;
864  }
865  else
866  {
867  Vector3 OBB = repData.size;
868  OBB.X *= 0.5f;
869  OBB.Y *= 0.5f;
870  OBB.Z *= 0.5f;
871 
872  repData.OBB = OBB;
873  repData.OBBOffset = Vector3.Zero;
874  }
875 
876  CalculateBasicPrimVolume(repData);
877  }
878  }
879 
880  public class ODEAssetRequest
881  {
882  ODEMeshWorker m_worker;
883  private ILog m_log;
884  ODEPhysRepData repData;
885 
887  ODEPhysRepData pRepData, ILog plog)
888  {
889  m_worker = pWorker;
890  m_log = plog;
891  repData = pRepData;
892 
893  repData.meshState = MeshState.AssetFailed;
894  if (provider == null)
895  return;
896 
897  if (repData.assetID == null)
898  return;
899 
900  UUID assetID = (UUID) repData.assetID;
901  if (assetID == UUID.Zero)
902  return;
903 
904  repData.meshState = MeshState.loadingAsset;
905  provider(assetID, ODEassetReceived);
906  }
907 
908  void ODEassetReceived(AssetBase asset)
909  {
910  repData.meshState = MeshState.AssetFailed;
911  if (asset != null)
912  {
913  if (asset.Data != null && asset.Data.Length > 0)
914  {
915  repData.meshState = MeshState.noNeed;
916 
917  if (!repData.pbs.SculptEntry)
918  return;
919  if (repData.pbs.SculptTexture != repData.assetID)
920  return;
921 
922 // repData.pbs.SculptData = new byte[asset.Data.Length];
923 // asset.Data.CopyTo(repData.pbs.SculptData,0);
924  repData.pbs.SculptData = asset.Data;
925  repData.meshState = MeshState.AssetOK;
926  m_worker.AssetLoaded(repData);
927  }
928  else
929  m_log.WarnFormat("[PHYSICS]: asset provider returned invalid mesh data for prim {0} asset UUID {1}.",
930  repData.actor.Name, asset.ID.ToString());
931  }
932  else
933  m_log.WarnFormat("[PHYSICS]: asset provider returned null asset fo mesh of prim {0}.",
934  repData.actor.Name);
935  }
936  }
937 }
bool needsMeshing(PrimitiveBaseShape pbs)
Routine to figure out if we need to mesh this prim with our mesher
ODEAssetRequest(ODEMeshWorker pWorker, RequestAssetDelegate provider, ODEPhysRepData pRepData, ILog plog)
void DoRepDataGetMesh(ODEPhysRepData repData)
ODEPhysRepData NewActorPhysRep(PhysicsActor actor, PrimitiveBaseShape pbs, Vector3 size, byte shapetype)
ODEMeshWorker(ODEScene pScene, ILog pLog, IMesher pMesher, IConfig pConfig)
Asset class. All Assets are reference by this class or a class derived from this class ...
Definition: AssetBase.cs:49
void ChangeActorPhysRep(PhysicsActor actor, PrimitiveBaseShape pbs, Vector3 size, byte shapetype)
OpenSim.Region.OptionalModules.Scripting.Minimodule.Object.SculptType SculptType
Definition: SOPObject.cs:39
delegate void RequestAssetDelegate(UUID assetID, AssetReceivedDelegate callback)
bool CreateActorPhysRep(ODEPhysRepData repData)