ODEMeshWorker.cs 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943
  1. /*
  2. * AJLDuarte 2012
  3. */
  4. using System;
  5. using System.Threading;
  6. using System.Collections.Generic;
  7. using System.IO;
  8. using System.Reflection;
  9. using System.Runtime.InteropServices;
  10. using System.Text;
  11. using OpenSim.Framework;
  12. using OpenSim.Region.PhysicsModules.SharedBase;
  13. using OdeAPI;
  14. using log4net;
  15. using Nini.Config;
  16. using OpenMetaverse;
  17. namespace OpenSim.Region.PhysicsModule.ubOde
  18. {
  19. public enum MeshState : byte
  20. {
  21. noNeed = 0,
  22. loadingAsset = 1,
  23. AssetOK = 0x0f, // 00001111
  24. NeedMask = 0x30, // 00110000
  25. needMesh = 0x10, // 00010000
  26. needAsset = 0x20, // 00100000
  27. FailMask = 0xC0, // 11000000
  28. AssetFailed = 0x40, // 01000000
  29. MeshFailed = 0x80, // 10000000
  30. MeshNoColide = FailMask | needAsset
  31. }
  32. public enum meshWorkerCmnds : byte
  33. {
  34. nop = 0,
  35. addnew,
  36. changefull,
  37. changesize,
  38. changeshapetype,
  39. getmesh,
  40. }
  41. public class ODEPhysRepData
  42. {
  43. public PhysicsActor actor;
  44. public PrimitiveBaseShape pbs;
  45. public IMesh mesh;
  46. public Vector3 size;
  47. public Vector3 OBB;
  48. public Vector3 OBBOffset;
  49. public float volume;
  50. public byte shapetype;
  51. public bool hasOBB;
  52. public bool hasMeshVolume;
  53. public MeshState meshState;
  54. public UUID? assetID;
  55. public meshWorkerCmnds comand;
  56. }
  57. public class ODEMeshWorker
  58. {
  59. private ILog m_log;
  60. private ODEScene m_scene;
  61. private IMesher m_mesher;
  62. public bool meshSculptedPrim = true;
  63. public bool forceSimplePrimMeshing = false;
  64. public float meshSculptLOD = 32;
  65. public float MeshSculptphysicalLOD = 32;
  66. private OpenSim.Framework.BlockingQueue<ODEPhysRepData> workQueue = new OpenSim.Framework.BlockingQueue<ODEPhysRepData>();
  67. private bool m_running;
  68. private Thread m_thread;
  69. public ODEMeshWorker(ODEScene pScene, ILog pLog, IMesher pMesher, IConfig pConfig)
  70. {
  71. m_scene = pScene;
  72. m_log = pLog;
  73. m_mesher = pMesher;
  74. if (pConfig != null)
  75. {
  76. forceSimplePrimMeshing = pConfig.GetBoolean("force_simple_prim_meshing", forceSimplePrimMeshing);
  77. meshSculptedPrim = pConfig.GetBoolean("mesh_sculpted_prim", meshSculptedPrim);
  78. meshSculptLOD = pConfig.GetFloat("mesh_lod", meshSculptLOD);
  79. MeshSculptphysicalLOD = pConfig.GetFloat("mesh_physical_lod", MeshSculptphysicalLOD);
  80. }
  81. m_running = true;
  82. m_thread = new Thread(DoWork);
  83. m_thread.Name = "OdeMeshWorker";
  84. m_thread.Start();
  85. }
  86. private void DoWork()
  87. {
  88. m_mesher.ExpireFileCache();
  89. while(m_running)
  90. {
  91. ODEPhysRepData nextRep = workQueue.Dequeue();
  92. if(!m_running)
  93. return;
  94. if (nextRep == null)
  95. continue;
  96. if (m_scene.haveActor(nextRep.actor))
  97. {
  98. switch (nextRep.comand)
  99. {
  100. case meshWorkerCmnds.changefull:
  101. case meshWorkerCmnds.changeshapetype:
  102. case meshWorkerCmnds.changesize:
  103. GetMesh(nextRep);
  104. if (CreateActorPhysRep(nextRep) && m_scene.haveActor(nextRep.actor))
  105. m_scene.AddChange(nextRep.actor, changes.PhysRepData, nextRep);
  106. break;
  107. case meshWorkerCmnds.getmesh:
  108. DoRepDataGetMesh(nextRep);
  109. break;
  110. }
  111. }
  112. }
  113. }
  114. public void Stop()
  115. {
  116. try
  117. {
  118. m_thread.Abort();
  119. workQueue.Clear();
  120. }
  121. catch
  122. {
  123. }
  124. }
  125. public void ChangeActorPhysRep(PhysicsActor actor, PrimitiveBaseShape pbs,
  126. Vector3 size, byte shapetype)
  127. {
  128. ODEPhysRepData repData = new ODEPhysRepData();
  129. repData.actor = actor;
  130. repData.pbs = pbs;
  131. repData.size = size;
  132. repData.shapetype = shapetype;
  133. CheckMesh(repData);
  134. CalcVolumeData(repData);
  135. m_scene.AddChange(actor, changes.PhysRepData, repData);
  136. return;
  137. }
  138. public ODEPhysRepData NewActorPhysRep(PhysicsActor actor, PrimitiveBaseShape pbs,
  139. Vector3 size, byte shapetype)
  140. {
  141. ODEPhysRepData repData = new ODEPhysRepData();
  142. repData.actor = actor;
  143. repData.pbs = pbs;
  144. repData.size = size;
  145. repData.shapetype = shapetype;
  146. CheckMesh(repData);
  147. CalcVolumeData(repData);
  148. m_scene.AddChange(actor, changes.AddPhysRep, repData);
  149. return repData;
  150. }
  151. public void RequestMesh(ODEPhysRepData repData)
  152. {
  153. repData.mesh = null;
  154. if (repData.meshState == MeshState.needAsset)
  155. {
  156. PrimitiveBaseShape pbs = repData.pbs;
  157. // check if we got outdated
  158. if (!pbs.SculptEntry || pbs.SculptTexture == UUID.Zero)
  159. {
  160. repData.meshState = MeshState.noNeed;
  161. return;
  162. }
  163. repData.assetID = pbs.SculptTexture;
  164. repData.meshState = MeshState.loadingAsset;
  165. repData.comand = meshWorkerCmnds.getmesh;
  166. workQueue.Enqueue(repData);
  167. }
  168. }
  169. // creates and prepares a mesh to use and calls parameters estimation
  170. public bool CreateActorPhysRep(ODEPhysRepData repData)
  171. {
  172. IMesh mesh = repData.mesh;
  173. if (mesh != null)
  174. {
  175. IntPtr vertices, indices;
  176. int vertexCount, indexCount;
  177. int vertexStride, triStride;
  178. mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount);
  179. mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount);
  180. if (vertexCount == 0 || indexCount == 0)
  181. {
  182. m_log.WarnFormat("[PHYSICS]: Invalid mesh data on prim {0} mesh UUID {1}",
  183. repData.actor.Name, repData.pbs.SculptTexture.ToString());
  184. repData.meshState = MeshState.MeshFailed;
  185. repData.hasOBB = false;
  186. repData.mesh = null;
  187. m_scene.mesher.ReleaseMesh(mesh);
  188. }
  189. else
  190. {
  191. repData.OBBOffset = mesh.GetCentroid();
  192. repData.OBB = mesh.GetOBB();
  193. repData.hasOBB = true;
  194. mesh.releaseSourceMeshData();
  195. }
  196. }
  197. CalcVolumeData(repData);
  198. return true;
  199. }
  200. public void AssetLoaded(ODEPhysRepData repData)
  201. {
  202. if (m_scene.haveActor(repData.actor))
  203. {
  204. if (needsMeshing(repData)) // no need for pbs now?
  205. {
  206. repData.comand = meshWorkerCmnds.changefull;
  207. workQueue.Enqueue(repData);
  208. }
  209. }
  210. else
  211. repData.pbs.SculptData = Utils.EmptyBytes;
  212. }
  213. public void DoRepDataGetMesh(ODEPhysRepData repData)
  214. {
  215. if (!repData.pbs.SculptEntry)
  216. return;
  217. if (repData.meshState != MeshState.loadingAsset)
  218. return;
  219. if (repData.assetID == null || repData.assetID == UUID.Zero)
  220. return;
  221. if (repData.assetID != repData.pbs.SculptTexture)
  222. return;
  223. // check if it is in cache
  224. GetMesh(repData);
  225. if (repData.meshState != MeshState.needAsset)
  226. {
  227. CreateActorPhysRep(repData);
  228. m_scene.AddChange(repData.actor, changes.PhysRepData, repData);
  229. return;
  230. }
  231. RequestAssetDelegate assetProvider = m_scene.RequestAssetMethod;
  232. if (assetProvider == null)
  233. return;
  234. ODEAssetRequest asr = new ODEAssetRequest(this, assetProvider, repData, m_log);
  235. }
  236. /// <summary>
  237. /// Routine to figure out if we need to mesh this prim with our mesher
  238. /// </summary>
  239. /// <param name="pbs"></param>
  240. /// <returns></returns>
  241. public bool needsMeshing(ODEPhysRepData repData)
  242. {
  243. PrimitiveBaseShape pbs = repData.pbs;
  244. // check sculpts or meshs
  245. if (pbs.SculptEntry)
  246. {
  247. if (meshSculptedPrim)
  248. return true;
  249. if (pbs.SculptType == (byte)SculptType.Mesh) // always do meshs
  250. return true;
  251. return false;
  252. }
  253. if (forceSimplePrimMeshing)
  254. return true;
  255. // convex shapes have no holes
  256. ushort profilehollow = pbs.ProfileHollow;
  257. if(repData.shapetype == 2)
  258. profilehollow = 0;
  259. // 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
  260. if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
  261. || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1
  262. && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z))
  263. {
  264. if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
  265. && profilehollow == 0
  266. && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
  267. && pbs.PathBegin == 0 && pbs.PathEnd == 0
  268. && pbs.PathTaperX == 0 && pbs.PathTaperY == 0
  269. && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
  270. && pbs.PathShearX == 0 && pbs.PathShearY == 0)
  271. {
  272. return false;
  273. }
  274. }
  275. // following code doesn't give meshs to boxes and spheres ever
  276. // and it's odd.. so for now just return true if asked to force meshs
  277. // hopefully mesher will fail if doesn't suport so things still get basic boxes
  278. int iPropertiesNotSupportedDefault = 0;
  279. if (profilehollow != 0)
  280. iPropertiesNotSupportedDefault++;
  281. if ((pbs.PathBegin != 0) || pbs.PathEnd != 0)
  282. iPropertiesNotSupportedDefault++;
  283. if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0))
  284. iPropertiesNotSupportedDefault++;
  285. if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0)
  286. iPropertiesNotSupportedDefault++;
  287. if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100))
  288. iPropertiesNotSupportedDefault++;
  289. if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0))
  290. iPropertiesNotSupportedDefault++;
  291. if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight)
  292. iPropertiesNotSupportedDefault++;
  293. 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))
  294. iPropertiesNotSupportedDefault++;
  295. if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1)
  296. iPropertiesNotSupportedDefault++;
  297. // test for torus
  298. if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
  299. {
  300. if (pbs.PathCurve == (byte)Extrusion.Curve1)
  301. {
  302. iPropertiesNotSupportedDefault++;
  303. }
  304. }
  305. else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
  306. {
  307. if (pbs.PathCurve == (byte)Extrusion.Straight)
  308. {
  309. iPropertiesNotSupportedDefault++;
  310. }
  311. // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
  312. else if (pbs.PathCurve == (byte)Extrusion.Curve1)
  313. {
  314. iPropertiesNotSupportedDefault++;
  315. }
  316. }
  317. else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
  318. {
  319. if (pbs.PathCurve == (byte)Extrusion.Curve1 || pbs.PathCurve == (byte)Extrusion.Curve2)
  320. {
  321. iPropertiesNotSupportedDefault++;
  322. }
  323. }
  324. else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
  325. {
  326. if (pbs.PathCurve == (byte)Extrusion.Straight)
  327. {
  328. iPropertiesNotSupportedDefault++;
  329. }
  330. else if (pbs.PathCurve == (byte)Extrusion.Curve1)
  331. {
  332. iPropertiesNotSupportedDefault++;
  333. }
  334. }
  335. if (iPropertiesNotSupportedDefault == 0)
  336. {
  337. return false;
  338. }
  339. return true;
  340. }
  341. // see if we need a mesh and if so if we have a cached one
  342. // called with a new repData
  343. public void CheckMesh(ODEPhysRepData repData)
  344. {
  345. PhysicsActor actor = repData.actor;
  346. PrimitiveBaseShape pbs = repData.pbs;
  347. if (!needsMeshing(repData))
  348. {
  349. repData.meshState = MeshState.noNeed;
  350. repData.hasOBB = false;
  351. return;
  352. }
  353. IMesh mesh = null;
  354. Vector3 size = repData.size;
  355. int clod = (int)LevelOfDetail.High;
  356. bool convex;
  357. byte shapetype = repData.shapetype;
  358. if (shapetype == 0)
  359. convex = false;
  360. else
  361. {
  362. convex = true;
  363. // sculpts pseudo convex
  364. if (pbs.SculptEntry && pbs.SculptType != (byte)SculptType.Mesh)
  365. clod = (int)LevelOfDetail.Low;
  366. }
  367. mesh = m_mesher.GetMesh(actor.Name, pbs, size, clod, true, convex);
  368. if (mesh == null)
  369. {
  370. if (pbs.SculptEntry)
  371. {
  372. if (pbs.SculptTexture != null && pbs.SculptTexture != UUID.Zero)
  373. {
  374. repData.assetID = pbs.SculptTexture;
  375. repData.meshState = MeshState.needAsset;
  376. }
  377. else
  378. repData.meshState = MeshState.MeshFailed;
  379. return;
  380. }
  381. else
  382. {
  383. repData.meshState = MeshState.needMesh;
  384. mesh = m_mesher.CreateMesh(actor.Name, pbs, size, clod, true, convex, true);
  385. if (mesh == null)
  386. {
  387. repData.meshState = MeshState.MeshFailed;
  388. return;
  389. }
  390. }
  391. }
  392. repData.meshState = MeshState.AssetOK;
  393. repData.mesh = mesh;
  394. repData.OBB = mesh.GetOBB();
  395. repData.OBBOffset = mesh.GetCentroid();
  396. repData.hasOBB = true;
  397. if (pbs.SculptEntry)
  398. {
  399. repData.assetID = pbs.SculptTexture;
  400. }
  401. pbs.SculptData = Utils.EmptyBytes;
  402. return ;
  403. }
  404. public void GetMesh(ODEPhysRepData repData)
  405. {
  406. PhysicsActor actor = repData.actor;
  407. PrimitiveBaseShape pbs = repData.pbs;
  408. repData.mesh = null;
  409. repData.hasOBB = false;
  410. if (!needsMeshing(repData))
  411. {
  412. repData.meshState = MeshState.noNeed;
  413. return;
  414. }
  415. if (repData.meshState == MeshState.MeshFailed)
  416. return;
  417. if (pbs.SculptEntry)
  418. {
  419. if (repData.meshState == MeshState.AssetFailed)
  420. {
  421. if (pbs.SculptTexture == repData.assetID)
  422. return;
  423. }
  424. }
  425. repData.meshState = MeshState.noNeed;
  426. IMesh mesh = null;
  427. Vector3 size = repData.size;
  428. byte shapetype = repData.shapetype;
  429. bool convex;
  430. int clod = (int)LevelOfDetail.High;
  431. if (shapetype == 0)
  432. convex = false;
  433. else
  434. {
  435. convex = true;
  436. if (pbs.SculptType != (byte)SculptType.Mesh)
  437. clod = (int)LevelOfDetail.Low;
  438. }
  439. mesh = m_mesher.CreateMesh(actor.Name, pbs, size, clod, true, convex, true);
  440. if (mesh == null)
  441. {
  442. if (pbs.SculptEntry)
  443. {
  444. if (pbs.SculptTexture == UUID.Zero)
  445. return;
  446. repData.assetID = pbs.SculptTexture;
  447. if (pbs.SculptData == null || pbs.SculptData.Length == 0)
  448. {
  449. repData.meshState = MeshState.needAsset;
  450. return;
  451. }
  452. }
  453. }
  454. repData.mesh = mesh;
  455. repData.pbs.SculptData = Utils.EmptyBytes;
  456. if (mesh == null)
  457. {
  458. if (pbs.SculptEntry)
  459. repData.meshState = MeshState.AssetFailed;
  460. else
  461. repData.meshState = MeshState.MeshFailed;
  462. return;
  463. }
  464. repData.meshState = MeshState.AssetOK;
  465. return;
  466. }
  467. private void CalculateBasicPrimVolume(ODEPhysRepData repData)
  468. {
  469. PrimitiveBaseShape _pbs = repData.pbs;
  470. Vector3 _size = repData.size;
  471. float volume = _size.X * _size.Y * _size.Z; // default
  472. float tmp;
  473. float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f;
  474. float hollowVolume = hollowAmount * hollowAmount;
  475. switch (_pbs.ProfileShape)
  476. {
  477. case ProfileShape.Square:
  478. // default box
  479. if (_pbs.PathCurve == (byte)Extrusion.Straight)
  480. {
  481. if (hollowAmount > 0.0)
  482. {
  483. switch (_pbs.HollowShape)
  484. {
  485. case HollowShape.Square:
  486. case HollowShape.Same:
  487. break;
  488. case HollowShape.Circle:
  489. hollowVolume *= 0.78539816339f;
  490. break;
  491. case HollowShape.Triangle:
  492. hollowVolume *= (0.5f * .5f);
  493. break;
  494. default:
  495. hollowVolume = 0;
  496. break;
  497. }
  498. volume *= (1.0f - hollowVolume);
  499. }
  500. }
  501. else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
  502. {
  503. //a tube
  504. volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX);
  505. tmp = 1.0f - 2.0e-2f * (float)(200 - _pbs.PathScaleY);
  506. volume -= volume * tmp * tmp;
  507. if (hollowAmount > 0.0)
  508. {
  509. hollowVolume *= hollowAmount;
  510. switch (_pbs.HollowShape)
  511. {
  512. case HollowShape.Square:
  513. case HollowShape.Same:
  514. break;
  515. case HollowShape.Circle:
  516. hollowVolume *= 0.78539816339f;
  517. break;
  518. case HollowShape.Triangle:
  519. hollowVolume *= 0.5f * 0.5f;
  520. break;
  521. default:
  522. hollowVolume = 0;
  523. break;
  524. }
  525. volume *= (1.0f - hollowVolume);
  526. }
  527. }
  528. break;
  529. case ProfileShape.Circle:
  530. if (_pbs.PathCurve == (byte)Extrusion.Straight)
  531. {
  532. volume *= 0.78539816339f; // elipse base
  533. if (hollowAmount > 0.0)
  534. {
  535. switch (_pbs.HollowShape)
  536. {
  537. case HollowShape.Same:
  538. case HollowShape.Circle:
  539. break;
  540. case HollowShape.Square:
  541. hollowVolume *= 0.5f * 2.5984480504799f;
  542. break;
  543. case HollowShape.Triangle:
  544. hollowVolume *= .5f * 1.27323954473516f;
  545. break;
  546. default:
  547. hollowVolume = 0;
  548. break;
  549. }
  550. volume *= (1.0f - hollowVolume);
  551. }
  552. }
  553. else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
  554. {
  555. volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX);
  556. tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
  557. volume *= (1.0f - tmp * tmp);
  558. if (hollowAmount > 0.0)
  559. {
  560. // calculate the hollow volume by it's shape compared to the prim shape
  561. hollowVolume *= hollowAmount;
  562. switch (_pbs.HollowShape)
  563. {
  564. case HollowShape.Same:
  565. case HollowShape.Circle:
  566. break;
  567. case HollowShape.Square:
  568. hollowVolume *= 0.5f * 2.5984480504799f;
  569. break;
  570. case HollowShape.Triangle:
  571. hollowVolume *= .5f * 1.27323954473516f;
  572. break;
  573. default:
  574. hollowVolume = 0;
  575. break;
  576. }
  577. volume *= (1.0f - hollowVolume);
  578. }
  579. }
  580. break;
  581. case ProfileShape.HalfCircle:
  582. if (_pbs.PathCurve == (byte)Extrusion.Curve1)
  583. {
  584. volume *= 0.5236f;
  585. if (hollowAmount > 0.0)
  586. {
  587. hollowVolume *= hollowAmount;
  588. switch (_pbs.HollowShape)
  589. {
  590. case HollowShape.Circle:
  591. case HollowShape.Triangle: // diference in sl is minor and odd
  592. case HollowShape.Same:
  593. break;
  594. case HollowShape.Square:
  595. hollowVolume *= 0.909f;
  596. break;
  597. // case HollowShape.Triangle:
  598. // hollowVolume *= .827f;
  599. // break;
  600. default:
  601. hollowVolume = 0;
  602. break;
  603. }
  604. volume *= (1.0f - hollowVolume);
  605. }
  606. }
  607. break;
  608. case ProfileShape.EquilateralTriangle:
  609. if (_pbs.PathCurve == (byte)Extrusion.Straight)
  610. {
  611. volume *= 0.32475953f;
  612. if (hollowAmount > 0.0)
  613. {
  614. // calculate the hollow volume by it's shape compared to the prim shape
  615. switch (_pbs.HollowShape)
  616. {
  617. case HollowShape.Same:
  618. case HollowShape.Triangle:
  619. hollowVolume *= .25f;
  620. break;
  621. case HollowShape.Square:
  622. hollowVolume *= 0.499849f * 3.07920140172638f;
  623. break;
  624. case HollowShape.Circle:
  625. // Hollow shape is a perfect cyllinder in respect to the cube's scale
  626. // Cyllinder hollow volume calculation
  627. hollowVolume *= 0.1963495f * 3.07920140172638f;
  628. break;
  629. default:
  630. hollowVolume = 0;
  631. break;
  632. }
  633. volume *= (1.0f - hollowVolume);
  634. }
  635. }
  636. else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
  637. {
  638. volume *= 0.32475953f;
  639. volume *= 0.01f * (float)(200 - _pbs.PathScaleX);
  640. tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
  641. volume *= (1.0f - tmp * tmp);
  642. if (hollowAmount > 0.0)
  643. {
  644. hollowVolume *= hollowAmount;
  645. switch (_pbs.HollowShape)
  646. {
  647. case HollowShape.Same:
  648. case HollowShape.Triangle:
  649. hollowVolume *= .25f;
  650. break;
  651. case HollowShape.Square:
  652. hollowVolume *= 0.499849f * 3.07920140172638f;
  653. break;
  654. case HollowShape.Circle:
  655. hollowVolume *= 0.1963495f * 3.07920140172638f;
  656. break;
  657. default:
  658. hollowVolume = 0;
  659. break;
  660. }
  661. volume *= (1.0f - hollowVolume);
  662. }
  663. }
  664. break;
  665. default:
  666. break;
  667. }
  668. float taperX1;
  669. float taperY1;
  670. float taperX;
  671. float taperY;
  672. float pathBegin;
  673. float pathEnd;
  674. float profileBegin;
  675. float profileEnd;
  676. if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible)
  677. {
  678. taperX1 = _pbs.PathScaleX * 0.01f;
  679. if (taperX1 > 1.0f)
  680. taperX1 = 2.0f - taperX1;
  681. taperX = 1.0f - taperX1;
  682. taperY1 = _pbs.PathScaleY * 0.01f;
  683. if (taperY1 > 1.0f)
  684. taperY1 = 2.0f - taperY1;
  685. taperY = 1.0f - taperY1;
  686. }
  687. else
  688. {
  689. taperX = _pbs.PathTaperX * 0.01f;
  690. if (taperX < 0.0f)
  691. taperX = -taperX;
  692. taperX1 = 1.0f - taperX;
  693. taperY = _pbs.PathTaperY * 0.01f;
  694. if (taperY < 0.0f)
  695. taperY = -taperY;
  696. taperY1 = 1.0f - taperY;
  697. }
  698. volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY);
  699. pathBegin = (float)_pbs.PathBegin * 2.0e-5f;
  700. pathEnd = 1.0f - (float)_pbs.PathEnd * 2.0e-5f;
  701. volume *= (pathEnd - pathBegin);
  702. // this is crude aproximation
  703. profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f;
  704. profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f;
  705. volume *= (profileEnd - profileBegin);
  706. repData.volume = volume;
  707. }
  708. private void CalcVolumeData(ODEPhysRepData repData)
  709. {
  710. if (repData.hasOBB)
  711. {
  712. Vector3 OBB = repData.OBB;
  713. }
  714. else
  715. {
  716. Vector3 OBB = repData.size;
  717. OBB.X *= 0.5f;
  718. OBB.Y *= 0.5f;
  719. OBB.Z *= 0.5f;
  720. repData.OBB = OBB;
  721. repData.OBBOffset = Vector3.Zero;
  722. }
  723. CalculateBasicPrimVolume(repData);
  724. }
  725. }
  726. public class ODEAssetRequest
  727. {
  728. ODEMeshWorker m_worker;
  729. private ILog m_log;
  730. ODEPhysRepData repData;
  731. public ODEAssetRequest(ODEMeshWorker pWorker, RequestAssetDelegate provider,
  732. ODEPhysRepData pRepData, ILog plog)
  733. {
  734. m_worker = pWorker;
  735. m_log = plog;
  736. repData = pRepData;
  737. repData.meshState = MeshState.AssetFailed;
  738. if (provider == null)
  739. return;
  740. if (repData.assetID == null)
  741. return;
  742. UUID assetID = (UUID) repData.assetID;
  743. if (assetID == UUID.Zero)
  744. return;
  745. repData.meshState = MeshState.loadingAsset;
  746. provider(assetID, ODEassetReceived);
  747. }
  748. void ODEassetReceived(AssetBase asset)
  749. {
  750. repData.meshState = MeshState.AssetFailed;
  751. if (asset != null)
  752. {
  753. if (asset.Data != null && asset.Data.Length > 0)
  754. {
  755. repData.meshState = MeshState.noNeed;
  756. if (!repData.pbs.SculptEntry)
  757. return;
  758. if (repData.pbs.SculptTexture != repData.assetID)
  759. return;
  760. // repData.pbs.SculptData = new byte[asset.Data.Length];
  761. // asset.Data.CopyTo(repData.pbs.SculptData,0);
  762. repData.pbs.SculptData = asset.Data;
  763. repData.meshState = MeshState.AssetOK;
  764. m_worker.AssetLoaded(repData);
  765. }
  766. else
  767. m_log.WarnFormat("[PHYSICS]: asset provider returned invalid mesh data for prim {0} asset UUID {1}.",
  768. repData.actor.Name, asset.ID.ToString());
  769. }
  770. else
  771. m_log.WarnFormat("[PHYSICS]: asset provider returned null asset for mesh of prim {0}.",
  772. repData.actor.Name);
  773. }
  774. }
  775. }