123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919 |
- /*
- * AJLDuarte 2012
- */
- using System;
- using OpenSim.Framework;
- using OpenSim.Region.PhysicsModules.SharedBase;
- using log4net;
- using Nini.Config;
- using OpenMetaverse;
- namespace OpenSim.Region.PhysicsModule.ubOde
- {
- public enum MeshState : byte
- {
- noNeed = 0,
- loadingAsset = 1,
- AssetOK = 0x0f, // 00001111
- NeedMask = 0x30, // 00110000
- needMesh = 0x10, // 00010000
- needAsset = 0x20, // 00100000
- FailMask = 0xC0, // 11000000
- AssetFailed = 0x40, // 01000000
- MeshFailed = 0x80, // 10000000
- MeshNoColide = FailMask | needAsset
- }
- public enum meshWorkerCmnds : byte
- {
- nop = 0,
- addnew,
- changefull,
- changesize,
- changeshapetype,
- getmesh,
- }
- public class ODEPhysRepData
- {
- public PhysicsActor actor;
- public PrimitiveBaseShape pbs;
- public IMesh mesh;
- public Vector3 size;
- public Vector3 OBB;
- public Vector3 OBBOffset;
- public float volume;
- public byte shapetype;
- public bool hasOBB;
- public bool hasMeshVolume;
- public bool isTooSmall;
- public MeshState meshState;
- public UUID? assetID;
- public meshWorkerCmnds comand;
- }
- public class ODEMeshWorker
- {
- private readonly ILog m_log;
- private readonly ODEScene m_scene;
- private readonly IMesher m_mesher;
- public bool meshSculptedPrim = true;
- public float meshSculptLOD = 32;
- public float MeshSculptphysicalLOD = 32;
- public float MinSizeToMeshmerize = 0.1f;
- //private static ObjectJobEngine<ODEPhysRepData> workQueue;
- private ObjectJobEngine workQueue;
- private bool m_running;
- private readonly object m_threadLock = new();
- public ODEMeshWorker(ODEScene pScene, ILog pLog, IMesher pMesher, IConfig pConfig)
- {
- m_scene = pScene;
- m_log = pLog;
- m_mesher = pMesher;
- if (pConfig is not null)
- {
- meshSculptedPrim = pConfig.GetBoolean("mesh_sculpted_prim", meshSculptedPrim);
- meshSculptLOD = pConfig.GetFloat("mesh_lod", meshSculptLOD);
- MinSizeToMeshmerize = pConfig.GetFloat("mesh_min_size", MinSizeToMeshmerize);
- MeshSculptphysicalLOD = pConfig.GetFloat("mesh_physical_lod", MeshSculptphysicalLOD);
- }
- m_running = true;
- Util.FireAndForget(DoCacheExpire, null, "OdeCacheExpire", false);
- lock(m_threadLock)
- {
- workQueue ??= new ObjectJobEngine(DoWork, "OdeMeshWorker");
- }
- }
- private void DoCacheExpire(object o)
- {
- m_mesher.ExpireFileCache();
- }
- private void Enqueue(ODEPhysRepData rep)
- {
- workQueue.Enqueue(rep);
- }
- private void DoWork(object rep)
- {
- if (m_running && rep is ODEPhysRepData nextRep && m_scene.haveActor(nextRep.actor))
- {
- switch (nextRep.comand)
- {
- case meshWorkerCmnds.changefull:
- case meshWorkerCmnds.changeshapetype:
- case meshWorkerCmnds.changesize:
- GetMesh(nextRep);
- if (CreateActorPhysRep(nextRep) && m_scene.haveActor(nextRep.actor))
- m_scene.AddChange(nextRep.actor, changes.PhysRepData, nextRep);
- break;
- case meshWorkerCmnds.getmesh:
- DoRepDataGetMesh(nextRep);
- break;
- }
- }
- }
- public void Stop()
- {
- try
- {
- m_running = false;
- workQueue.Dispose();
- workQueue = null;
- }
- catch
- {
- }
- }
- public void ChangeActorPhysRep(PhysicsActor actor, PrimitiveBaseShape pbs,
- Vector3 size, byte shapetype)
- {
- ODEPhysRepData repData = new()
- {
- actor = actor,
- pbs = pbs,
- size = size,
- shapetype = shapetype
- };
- CheckMesh(repData);
- CalcVolumeData(repData);
- m_scene.AddChange(actor, changes.PhysRepData, repData);
- return;
- }
- public ODEPhysRepData NewActorPhysRep(PhysicsActor actor, PrimitiveBaseShape pbs,
- Vector3 size, byte shapetype)
- {
- ODEPhysRepData repData = new()
- {
- actor = actor,
- pbs = pbs,
- size = size,
- shapetype = shapetype
- };
- CheckMesh(repData);
- CalcVolumeData(repData);
- m_scene.AddChange(actor, changes.AddPhysRep, repData);
- return repData;
- }
- public void RequestMesh(ODEPhysRepData repData)
- {
- repData.mesh = null;
- if (repData.meshState == MeshState.needAsset)
- {
- PrimitiveBaseShape pbs = repData.pbs;
- // check if we got outdated
- if (!pbs.SculptEntry || pbs.SculptTexture.IsZero())
- {
- repData.meshState = MeshState.noNeed;
- return;
- }
- repData.assetID = pbs.SculptTexture;
- repData.meshState = MeshState.loadingAsset;
- repData.comand = meshWorkerCmnds.getmesh;
- Enqueue(repData);
- }
- }
- // creates and prepares a mesh to use and calls parameters estimation
- public bool CreateActorPhysRep(ODEPhysRepData repData)
- {
- IMesh mesh = repData.mesh;
- if (mesh is not null)
- {
- mesh.getVertexListAsPtrToFloatArray(out _, out _, out int vertexCount);
- mesh.getIndexListAsPtrToIntArray(out _, out _, out int indexCount);
- if (vertexCount == 0 || indexCount == 0)
- {
- m_log.WarnFormat("[PHYSICS]: Invalid mesh data on prim {0} mesh UUID {1}",
- repData.actor.Name, repData.pbs.SculptTexture.ToString());
- repData.meshState = MeshState.MeshFailed;
- repData.hasOBB = false;
- repData.mesh = null;
- m_scene.mesher.ReleaseMesh(mesh);
- }
- else
- {
- repData.OBBOffset = mesh.GetCentroid();
- repData.OBB = mesh.GetOBB();
- repData.hasOBB = true;
- mesh.releaseSourceMeshData();
- }
- }
- CalcVolumeData(repData);
- return true;
- }
- public void AssetLoaded(ODEPhysRepData repData)
- {
- if (m_scene.haveActor(repData.actor))
- {
- if (needsMeshing(repData)) // no need for pbs now?
- {
- repData.comand = meshWorkerCmnds.changefull;
- Enqueue(repData);
- }
- }
- else
- repData.pbs.SculptData = Array.Empty<byte>();
- }
- public void DoRepDataGetMesh(ODEPhysRepData repData)
- {
- if (!repData.pbs.SculptEntry)
- return;
- if (repData.meshState != MeshState.loadingAsset)
- return;
- if (repData.assetID is null || repData.assetID.Value.IsZero())
- return;
- if (repData.assetID != repData.pbs.SculptTexture)
- return;
- // check if it is in cache
- GetMesh(repData);
- if (repData.meshState != MeshState.needAsset)
- {
- CreateActorPhysRep(repData);
- m_scene.AddChange(repData.actor, changes.PhysRepData, repData);
- return;
- }
- RequestAssetDelegate assetProvider = m_scene.RequestAssetMethod;
- if (assetProvider is null)
- return;
- ODEAssetRequest asr = new(this, assetProvider, repData, m_log);
- }
- /// <summary>
- /// Routine to figure out if we need to mesh this prim with our mesher
- /// </summary>
- /// <param name="pbs"></param>
- /// <returns></returns>
- public bool needsMeshing(ODEPhysRepData repData)
- {
- PrimitiveBaseShape pbs = repData.pbs;
- // check sculpts or meshs
- Vector3 scale = pbs.Scale;
- if(scale.X <= MinSizeToMeshmerize &&
- scale.Y <= MinSizeToMeshmerize &&
- scale.Z <= MinSizeToMeshmerize)
- {
- repData.isTooSmall = true;
- return false;
- }
- if (pbs.SculptEntry)
- {
- if (meshSculptedPrim)
- return true;
- if (pbs.SculptType == (byte)SculptType.Mesh) // always do meshs
- return true;
- return false;
- }
- // convex shapes have no holes
- ushort profilehollow = pbs.ProfileHollow;
- if(repData.shapetype == 2)
- profilehollow = 0;
- // 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
- if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
- || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1
- && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z))
- {
- if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
- && profilehollow == 0
- && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
- && pbs.PathBegin == 0 && pbs.PathEnd == 0
- && pbs.PathTaperX == 0 && pbs.PathTaperY == 0
- && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
- && pbs.PathShearX == 0 && pbs.PathShearY == 0)
- {
- return false;
- }
- }
- // following code doesn't give meshs to boxes and spheres ever
- // and it's odd.. so for now just return true if asked to force meshs
- // hopefully mesher will fail if doesn't suport so things still get basic boxes
- int iPropertiesNotSupportedDefault = 0;
- if (profilehollow != 0)
- iPropertiesNotSupportedDefault++;
- if ((pbs.PathBegin != 0) || pbs.PathEnd != 0)
- iPropertiesNotSupportedDefault++;
- if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0))
- iPropertiesNotSupportedDefault++;
- if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0)
- iPropertiesNotSupportedDefault++;
- if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100))
- iPropertiesNotSupportedDefault++;
- if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0))
- iPropertiesNotSupportedDefault++;
- if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight)
- iPropertiesNotSupportedDefault++;
- 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))
- iPropertiesNotSupportedDefault++;
- if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1)
- iPropertiesNotSupportedDefault++;
- // test for torus
- if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
- {
- if (pbs.PathCurve == (byte)Extrusion.Curve1)
- {
- iPropertiesNotSupportedDefault++;
- }
- }
- else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
- {
- if (pbs.PathCurve == (byte)Extrusion.Straight)
- {
- iPropertiesNotSupportedDefault++;
- }
- // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
- else if (pbs.PathCurve == (byte)Extrusion.Curve1)
- {
- iPropertiesNotSupportedDefault++;
- }
- }
- else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
- {
- if (pbs.PathCurve == (byte)Extrusion.Curve1 || pbs.PathCurve == (byte)Extrusion.Curve2)
- {
- iPropertiesNotSupportedDefault++;
- }
- }
- else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
- {
- if (pbs.PathCurve == (byte)Extrusion.Straight)
- {
- iPropertiesNotSupportedDefault++;
- }
- else if (pbs.PathCurve == (byte)Extrusion.Curve1)
- {
- iPropertiesNotSupportedDefault++;
- }
- }
- if (iPropertiesNotSupportedDefault == 0)
- {
- return false;
- }
- return true;
- }
- // see if we need a mesh and if so if we have a cached one
- // called with a new repData
- public void CheckMesh(ODEPhysRepData repData)
- {
- PhysicsActor actor = repData.actor;
- PrimitiveBaseShape pbs = repData.pbs;
- if (!needsMeshing(repData))
- {
- repData.meshState = MeshState.noNeed;
- repData.hasOBB = false;
- return;
- }
- Vector3 size = repData.size;
- int clod = (int)LevelOfDetail.High;
- byte shapetype = repData.shapetype;
- bool convex = shapetype == 2;
- IMesh mesh = m_mesher.GetMesh(actor.Name, pbs, size, clod, true, convex);
- if (mesh is null)
- {
- if (pbs.SculptEntry)
- {
- if (pbs.SculptTexture.IsNotZero())
- {
- repData.assetID = pbs.SculptTexture;
- repData.meshState = MeshState.needAsset;
- }
- else
- repData.meshState = MeshState.MeshFailed;
- return;
- }
- else
- {
- repData.meshState = MeshState.needMesh;
- mesh = m_mesher.CreateMesh(actor.Name, pbs, size, clod, true, convex, true);
- if (mesh is null)
- {
- repData.meshState = MeshState.MeshFailed;
- return;
- }
- }
- }
- repData.meshState = MeshState.AssetOK;
- repData.mesh = mesh;
- repData.OBB = mesh.GetOBB();
- repData.OBBOffset = mesh.GetCentroid();
- repData.hasOBB = true;
- if (pbs.SculptEntry)
- {
- repData.assetID = pbs.SculptTexture;
- }
- pbs.SculptData = Array.Empty<byte>();
- return ;
- }
- public void GetMesh(ODEPhysRepData repData)
- {
- PhysicsActor actor = repData.actor;
- PrimitiveBaseShape pbs = repData.pbs;
- repData.mesh = null;
- repData.hasOBB = false;
- if (!needsMeshing(repData))
- {
- repData.meshState = MeshState.noNeed;
- return;
- }
- if (repData.meshState == MeshState.MeshFailed)
- return;
- if (pbs.SculptEntry)
- {
- if (repData.meshState == MeshState.AssetFailed)
- {
- if (pbs.SculptTexture == repData.assetID)
- return;
- }
- }
- repData.meshState = MeshState.noNeed;
- Vector3 size = repData.size;
- byte shapetype = repData.shapetype;
- bool convex;
- int clod = (int)LevelOfDetail.High;
- if (shapetype == 0)
- convex = false;
- else
- {
- convex = true;
- if (pbs.SculptType != (byte)SculptType.Mesh)
- clod = (int)LevelOfDetail.Low;
- }
- IMesh mesh = m_mesher.CreateMesh(actor.Name, pbs, size, clod, true, convex, true);
- if (mesh is null)
- {
- if (pbs.SculptEntry)
- {
- if (pbs.SculptTexture.IsZero())
- return;
- repData.assetID = pbs.SculptTexture;
- if (pbs.SculptData is null || pbs.SculptData.Length == 0)
- {
- repData.meshState = MeshState.needAsset;
- return;
- }
- }
- }
- repData.mesh = mesh;
- repData.pbs.SculptData = Utils.EmptyBytes;
- if (mesh is null)
- {
- if (pbs.SculptEntry)
- repData.meshState = MeshState.AssetFailed;
- else
- repData.meshState = MeshState.MeshFailed;
- return;
- }
- repData.meshState = MeshState.AssetOK;
- return;
- }
- private static void CalculateBasicPrimVolume(ODEPhysRepData repData)
- {
- Vector3 _size = repData.size;
- float volume = _size.X * _size.Y * _size.Z; // default
- if(repData.isTooSmall)
- {
- repData.volume = volume;
- return;
- }
- PrimitiveBaseShape _pbs = repData.pbs;
- float tmp;
- float hollowAmount = ((float)_pbs.ProfileHollow) * 2.0e-5f;
- float hollowVolume = hollowAmount * hollowAmount;
- switch (_pbs.ProfileShape)
- {
- case ProfileShape.Square:
- // default box
- if (_pbs.PathCurve == (byte)Extrusion.Straight)
- {
- if (hollowAmount > 0.0)
- {
- switch (_pbs.HollowShape)
- {
- case HollowShape.Square:
- case HollowShape.Same:
- break;
- case HollowShape.Circle:
- hollowVolume *= 0.78539816339f;
- break;
- case HollowShape.Triangle:
- hollowVolume *= (0.5f * .5f);
- break;
- default:
- hollowVolume = 0;
- break;
- }
- volume *= (1.0f - hollowVolume);
- }
- }
- else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
- {
- //a tube
- volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX);
- tmp = 1.0f - 2.0e-2f * (float)(200 - _pbs.PathScaleY);
- volume -= volume * tmp * tmp;
- if (hollowAmount > 0.0)
- {
- hollowVolume *= hollowAmount;
- switch (_pbs.HollowShape)
- {
- case HollowShape.Square:
- case HollowShape.Same:
- break;
- case HollowShape.Circle:
- hollowVolume *= 0.78539816339f;
- break;
- case HollowShape.Triangle:
- hollowVolume *= 0.5f * 0.5f;
- break;
- default:
- hollowVolume = 0;
- break;
- }
- volume *= (1.0f - hollowVolume);
- }
- }
- break;
- case ProfileShape.Circle:
- if (_pbs.PathCurve == (byte)Extrusion.Straight)
- {
- volume *= 0.78539816339f; // elipse base
- if (hollowAmount > 0.0)
- {
- switch (_pbs.HollowShape)
- {
- case HollowShape.Same:
- case HollowShape.Circle:
- break;
- case HollowShape.Square:
- hollowVolume *= 0.5f * 2.5984480504799f;
- break;
- case HollowShape.Triangle:
- hollowVolume *= .5f * 1.27323954473516f;
- break;
- default:
- hollowVolume = 0;
- break;
- }
- volume *= (1.0f - hollowVolume);
- }
- }
- else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
- {
- volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX);
- tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
- volume *= (1.0f - tmp * tmp);
- if (hollowAmount > 0.0)
- {
- // calculate the hollow volume by it's shape compared to the prim shape
- hollowVolume *= hollowAmount;
- switch (_pbs.HollowShape)
- {
- case HollowShape.Same:
- case HollowShape.Circle:
- break;
- case HollowShape.Square:
- hollowVolume *= 0.5f * 2.5984480504799f;
- break;
- case HollowShape.Triangle:
- hollowVolume *= .5f * 1.27323954473516f;
- break;
- default:
- hollowVolume = 0;
- break;
- }
- volume *= (1.0f - hollowVolume);
- }
- }
- break;
- case ProfileShape.HalfCircle:
- if (_pbs.PathCurve == (byte)Extrusion.Curve1)
- {
- volume *= 0.5236f;
- if (hollowAmount > 0.0)
- {
- hollowVolume *= hollowAmount;
- switch (_pbs.HollowShape)
- {
- case HollowShape.Circle:
- case HollowShape.Triangle: // diference in sl is minor and odd
- case HollowShape.Same:
- break;
- case HollowShape.Square:
- hollowVolume *= 0.909f;
- break;
- //case HollowShape.Triangle:
- // hollowVolume *= .827f;
- // break;
- default:
- hollowVolume = 0;
- break;
- }
- volume *= (1.0f - hollowVolume);
- }
- }
- break;
- case ProfileShape.EquilateralTriangle:
- if (_pbs.PathCurve == (byte)Extrusion.Straight)
- {
- volume *= 0.32475953f;
- if (hollowAmount > 0.0)
- {
- // calculate the hollow volume by it's shape compared to the prim shape
- switch (_pbs.HollowShape)
- {
- case HollowShape.Same:
- case HollowShape.Triangle:
- hollowVolume *= .25f;
- break;
- case HollowShape.Square:
- hollowVolume *= 0.499849f * 3.07920140172638f;
- break;
- case HollowShape.Circle:
- // Hollow shape is a perfect cyllinder in respect to the cube's scale
- // Cyllinder hollow volume calculation
- hollowVolume *= 0.1963495f * 3.07920140172638f;
- break;
- default:
- hollowVolume = 0;
- break;
- }
- volume *= (1.0f - hollowVolume);
- }
- }
- else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
- {
- volume *= 0.32475953f;
- volume *= 0.01f * (float)(200 - _pbs.PathScaleX);
- tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
- volume *= (1.0f - tmp * tmp);
- if (hollowAmount > 0.0)
- {
- hollowVolume *= hollowAmount;
- switch (_pbs.HollowShape)
- {
- case HollowShape.Same:
- case HollowShape.Triangle:
- hollowVolume *= .25f;
- break;
- case HollowShape.Square:
- hollowVolume *= 0.499849f * 3.07920140172638f;
- break;
- case HollowShape.Circle:
- hollowVolume *= 0.1963495f * 3.07920140172638f;
- break;
- default:
- hollowVolume = 0;
- break;
- }
- volume *= (1.0f - hollowVolume);
- }
- }
- break;
- default:
- break;
- }
- float taperX1;
- float taperY1;
- float taperX;
- float taperY;
- float pathBegin;
- float pathEnd;
- float profileBegin;
- float profileEnd;
- if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible)
- {
- taperX1 = _pbs.PathScaleX * 0.01f;
- if (taperX1 > 1.0f)
- taperX1 = 2.0f - taperX1;
- taperX = 1.0f - taperX1;
- taperY1 = _pbs.PathScaleY * 0.01f;
- if (taperY1 > 1.0f)
- taperY1 = 2.0f - taperY1;
- taperY = 1.0f - taperY1;
- }
- else
- {
- taperX = _pbs.PathTaperX * 0.01f;
- if (taperX < 0.0f)
- taperX = -taperX;
- taperX1 = 1.0f - taperX;
- taperY = _pbs.PathTaperY * 0.01f;
- if (taperY < 0.0f)
- taperY = -taperY;
- taperY1 = 1.0f - taperY;
- }
- volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY);
- pathBegin = (float)_pbs.PathBegin * 2.0e-5f;
- pathEnd = 1.0f - (float)_pbs.PathEnd * 2.0e-5f;
- volume *= (pathEnd - pathBegin);
- // this is crude aproximation
- profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f;
- profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f;
- volume *= (profileEnd - profileBegin);
- repData.volume = volume;
- }
- private static void CalcVolumeData(ODEPhysRepData repData)
- {
- if (!repData.hasOBB)
- {
- repData.OBB = repData.size * 0.5f;
- repData.OBBOffset = Vector3.Zero;
- }
- CalculateBasicPrimVolume(repData);
- }
- }
- public class ODEAssetRequest
- {
- private readonly ODEMeshWorker m_worker;
- private readonly ILog m_log;
- private readonly ODEPhysRepData repData;
- public ODEAssetRequest(ODEMeshWorker pWorker, RequestAssetDelegate provider,
- ODEPhysRepData pRepData, ILog plog)
- {
- m_worker = pWorker;
- m_log = plog;
- repData = pRepData;
- repData.meshState = MeshState.loadingAsset;
- provider((UUID)repData.assetID, ODEassetReceived);
- }
- void ODEassetReceived(AssetBase asset)
- {
- repData.meshState = MeshState.AssetFailed;
- if (asset is not null)
- {
- if (asset.Data is not null && asset.Data.Length > 0)
- {
- repData.meshState = MeshState.noNeed;
- if (!repData.pbs.SculptEntry)
- return;
- if (repData.pbs.SculptTexture != repData.assetID)
- return;
- //repData.pbs.SculptData = new byte[asset.Data.Length];
- //asset.Data.CopyTo(repData.pbs.SculptData,0);
- repData.pbs.SculptData = asset.Data;
- repData.meshState = MeshState.AssetOK;
- m_worker.AssetLoaded(repData);
- }
- else
- m_log.WarnFormat("[PHYSICS]: asset provider returned invalid mesh data for prim {0} asset UUID {1}.",
- repData.actor.Name, asset.ID.ToString());
- }
- else
- m_log.WarnFormat("[PHYSICS]: asset provider returned null asset for mesh of prim {0}.",
- repData.actor.Name);
- }
- }
- }
|