Anonymous | Login | Signup for a new account | 2021-01-26 13:01 PST | ![]() |
Main | My View | View Issues | Change Log | Roadmap | Summary | My Account |
View Issue Details [ Jump to Notes ] | [ Issue History ] [ Print ] | ||||||||
ID | Project | Category | View Status | Date Submitted | Last Update | ||||
0007575 | opensim | [REGION] Script Functions | public | 2015-05-16 14:07 | 2015-05-23 05:20 | ||||
Reporter | Magnuz | ||||||||
Assigned To | nebadon | ||||||||
Priority | normal | Severity | minor | Reproducibility | always | ||||
Status | closed | Resolution | fixed | ||||||
Platform | Intel Core i7 | Operating System | Ubuntu | Operating System Version | 14.04 | ||||
Product Version | master (dev code) | ||||||||
Target Version | Fixed in Version | master (dev code) | |||||||
Summary | 0007575: llCastRay V3 performance improved by mesh caching | ||||||||
Description | llCastRay V3 use much time and resources meshing prims, sculpts and mesh assets. This load can be reduced by caching and re-using meshes, using the same mesh cache physics is using. | ||||||||
Additional Information | Mono 3.12.1 | ||||||||
Tags | No tags attached. | ||||||||
Git Revision or version number | 0.8.2 dev | ||||||||
Run Mode | Grid (1 Region per Sim) | ||||||||
Physics Engine | BulletSim | ||||||||
Script Engine | |||||||||
Environment | Mono / Linux32 | ||||||||
Mono Version | Other | ||||||||
Viewer | Singularity 1.8.6 OS X | ||||||||
Attached Files | ![]() From 5f404f08f682dcca1b92fd245b0896043c0539a8 Mon Sep 17 00:00:00 2001 From: Magnuz Binder <magnuz@magnuz-se.com> Date: Sat, 16 May 2015 21:45:02 +0200 Subject: [PATCH] Use cached meshes in llCastRay V3, dysfunctional. --- .../Shared/Api/Implementation/LSL_Api.cs | 132 +++++++++------------ prebuild.xml | 1 + 2 files changed, 60 insertions(+), 73 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 089a5a8..e0bdc0d 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -51,6 +51,7 @@ using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes.Animation; using OpenSim.Region.Framework.Scenes.Scripting; using OpenSim.Region.Physics.Manager; +using OpenSim.Region.Physics.Meshing; using OpenSim.Region.ScriptEngine.Shared; using OpenSim.Region.ScriptEngine.Shared.Api.Plugins; using OpenSim.Region.ScriptEngine.Shared.ScriptBase; @@ -224,10 +225,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api protected bool m_useCastRayV3 = false; protected float m_floatToleranceInCastRay = 0.000001f; protected float m_floatTolerance2InCastRay = 0.0001f; - protected DetailLevel m_primLodInCastRay = DetailLevel.Medium; - protected DetailLevel m_sculptLodInCastRay = DetailLevel.Medium; - protected DetailLevel m_meshLodInCastRay = DetailLevel.Highest; - protected DetailLevel m_avatarLodInCastRay = DetailLevel.Medium; + protected int m_primLodInCastRay = (int)DetailLevel.Medium; + protected int m_sculptLodInCastRay = (int)DetailLevel.Medium; + protected int m_meshLodInCastRay = (int)DetailLevel.Highest; + protected int m_avatarLodInCastRay = (int)DetailLevel.Medium; protected int m_maxHitsInCastRay = 16; protected int m_maxHitsPerPrimInCastRay = 16; protected int m_maxHitsPerObjectInCastRay = 16; @@ -343,10 +344,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_useCastRayV3 = lslConfig.GetBoolean("UseLlCastRayV3", m_useCastRayV3); m_floatToleranceInCastRay = lslConfig.GetFloat("FloatToleranceInLlCastRay", m_floatToleranceInCastRay); m_floatTolerance2InCastRay = lslConfig.GetFloat("FloatTolerance2InLlCastRay", m_floatTolerance2InCastRay); - m_primLodInCastRay = (DetailLevel)lslConfig.GetInt("PrimDetailLevelInLlCastRay", (int)m_primLodInCastRay); - m_sculptLodInCastRay = (DetailLevel)lslConfig.GetInt("SculptDetailLevelInLlCastRay", (int)m_sculptLodInCastRay); - m_meshLodInCastRay = (DetailLevel)lslConfig.GetInt("MeshDetailLevelInLlCastRay", (int)m_meshLodInCastRay); - m_avatarLodInCastRay = (DetailLevel)lslConfig.GetInt("AvatarDetailLevelInLlCastRay", (int)m_avatarLodInCastRay); + m_primLodInCastRay = lslConfig.GetInt("PrimDetailLevelInLlCastRay", m_primLodInCastRay); + m_sculptLodInCastRay = lslConfig.GetInt("SculptDetailLevelInLlCastRay", m_sculptLodInCastRay); + m_meshLodInCastRay = lslConfig.GetInt("MeshDetailLevelInLlCastRay", m_meshLodInCastRay); + m_avatarLodInCastRay = lslConfig.GetInt("AvatarDetailLevelInLlCastRay", m_avatarLodInCastRay); m_maxHitsInCastRay = lslConfig.GetInt("MaxHitsInLlCastRay", m_maxHitsInCastRay); m_maxHitsPerPrimInCastRay = lslConfig.GetInt("MaxHitsPerPrimInLlCastRay", m_maxHitsPerPrimInCastRay); m_maxHitsPerObjectInCastRay = lslConfig.GetInt("MaxHitsPerObjectInLlCastRay", m_maxHitsPerObjectInCastRay); @@ -9951,7 +9952,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (mesh != null) { // Parse each vertex in mesh - foreach (Vertex vertex in mesh.Vertices) + foreach (OpenMetaverse.Rendering.Vertex vertex in mesh.Vertices) { Vector3 position = vertex.Position; position = position * prim.Scale; @@ -9981,7 +9982,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api foreach (Face face in mesh.Faces) { // Parse each vertex in face - foreach (Vertex vertex in face.Vertices) + foreach (OpenMetaverse.Rendering.Vertex vertex in face.Vertices) { Vector3 position = vertex.Position; position = position * prim.Scale; @@ -14065,14 +14066,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api float rayLength = vecRay.Length(); // Try to get a mesher and return failure if none, degenerate ray, or max 0 hits - IRendering primMesher = null; - List<string> renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory()); - if (renderers.Count < 1 || rayLength < tol || m_maxHitsInCastRay < 1) + IConfigSource config = new IniConfigSource(); + config.AddConfig("Startup"); + config.AddConfig("Mesh"); + config.Configs["Mesh"].Set("UseMeshiesPhysicsMesh", true); + IMesher iMesher = new Meshmerizer(config); + if (iMesher == null || rayLength < tol || m_maxHitsInCastRay < 1) { result.Add(new LSL_Integer(ScriptBaseClass.RCERR_UNKNOWN)); return result; } - primMesher = RenderingLoader.LoadRenderer(renderers[0]); + // Parameters for mesher + Vector3 unitVector = new Vector3(1.0f, 1.0f, 1.0f); + bool meshIsPhysical = true; + bool meshShouldCache = true; // Iterate over all objects/groups and prims/parts in region World.ForEachSOG( @@ -14145,52 +14152,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api rayTrans.Position1RayProj = pos1RayProj; rayTrans.VectorRayProj = pos2RayProj - pos1RayProj; - // Make an OMV prim to be able to mesh part - Primitive omvPrim = part.Shape.ToOmvPrimitive(posPart, rotPart); - byte[] sculptAsset = null; - if (omvPrim.Sculpt != null) - sculptAsset = World.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString()); - FacetedMesh mesh = null; - - // When part is mesh, get mesh and check for hits - if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type == SculptType.Mesh && sculptAsset != null) - { - AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset); - FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, m_meshLodInCastRay, out mesh); - meshAsset = null; - } - - // When part is sculpt, create mesh and check for hits - // Quirk: Generated sculpt mesh is about 2.8% smaller in X and Y than visual sculpt. - else if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type != SculptType.Mesh && sculptAsset != null) - { - IJ2KDecoder imgDecoder = World.RequestModuleInterface<IJ2KDecoder>(); - if (imgDecoder != null) - { - Image sculpt = imgDecoder.DecodeToImage(sculptAsset); - if (sculpt != null) - { - mesh = primMesher.GenerateFacetedSculptMesh(omvPrim, (Bitmap)sculpt, m_sculptLodInCastRay); - sculpt.Dispose(); - } - } - } - - // When part is prim, create mesh and check for hits - else if (omvPrim.Sculpt == null) + // Get detail level depending on type + int lod = 0; + // Mesh detail level + if (part.Shape.SculptEntry && part.Shape.SculptType == (byte)SculptType.Mesh) + lod = m_meshLodInCastRay; + // Sculpt detail level + else if (part.Shape.SculptEntry && part.Shape.SculptType == (byte)SculptType.Mesh) + lod = m_sculptLodInCastRay; + // Prim detail level + else if (!part.Shape.SculptEntry) + lod = m_primLodInCastRay; + // Convert detail level for Meshmerizer + lod = 4 << lod; + + // Get mesh and check for hits + PrimitiveBaseShape shape = part.Shape; + IMesh mesh = iMesher.CreateMesh(part.Name, shape, unitVector, lod, meshIsPhysical, meshShouldCache); + // If no cached sculpt or meshie mesh, try again with asset to create one + if (mesh == null && shape.SculptEntry && shape.SculptData.Length <= 0) { - if ( - omvPrim.PrimData.PathBegin == 0.0 && omvPrim.PrimData.PathEnd == 1.0 && - omvPrim.PrimData.PathTaperX == 0.0 && omvPrim.PrimData.PathTaperY == 0.0 && - omvPrim.PrimData.PathSkew == 0.0 && - omvPrim.PrimData.PathTwist - omvPrim.PrimData.PathTwistBegin == 0.0 - ) - rayTrans.ShapeNeedsEnds = false; - mesh = primMesher.GenerateFacetedMesh(omvPrim, m_primLodInCastRay); + // ERROR!!! This way to try and get asset data appears to cause corrupt mesh and sculpt meshes! + shape.SculptData = World.AssetService.GetData(shape.SculptTexture.ToString()); + mesh = iMesher.CreateMesh(part.Name, shape, unitVector, lod, meshIsPhysical, meshShouldCache); + shape.SculptData = Utils.EmptyBytes; } - - // Check mesh for ray hits - AddRayInFacetedMesh(mesh, rayTrans, ref rayHits); + AddRayInIMesh(mesh, rayTrans, ref rayHits); mesh = null; } } @@ -14236,12 +14223,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api rayTrans.Position1RayProj = pos1RayProj; rayTrans.VectorRayProj = pos2RayProj - pos1RayProj; - // Make OMV prim, create and check mesh + // Get mesh and check for hits PrimitiveBaseShape prim = PrimitiveBaseShape.CreateSphere(); prim.Scale = scalePart; - Primitive omvPrim = prim.ToOmvPrimitive(posPart, rotPart); - FacetedMesh mesh = primMesher.GenerateFacetedMesh(omvPrim, m_meshLodInCastRay); - AddRayInFacetedMesh(mesh, rayTrans, ref rayHits); + int lod = 4 << m_avatarLodInCastRay; + IMesh mesh = iMesher.CreateMesh("AvatarCapsule", prim, unitVector, lod, meshIsPhysical, meshShouldCache); + AddRayInIMesh(mesh, rayTrans, ref rayHits); mesh = null; } } @@ -14440,22 +14427,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } /// <summary> - /// Helper to parse FacetedMesh for ray hits. + /// Helper to parse IMesh for ray hits. /// </summary> - private void AddRayInFacetedMesh(FacetedMesh mesh, RayTrans rayTrans, ref List<RayHit> rayHits) + private void AddRayInIMesh(IMesh mesh, RayTrans rayTrans, ref List<RayHit> rayHits) { if (mesh != null) { - foreach (Face face in mesh.Faces) + List<Vector3> vectors = mesh.getVertexList(); + int[] indices = mesh.getIndexListAsInt(); + for (int i = 0; i < indices.Length; i += 3) { - for (int i = 0; i < face.Indices.Count; i += 3) - { - Tri triangle = new Tri(); - triangle.p1 = face.Vertices[face.Indices[i]].Position; - triangle.p2 = face.Vertices[face.Indices[i + 1]].Position; - triangle.p3 = face.Vertices[face.Indices[i + 2]].Position; - AddRayInTri(triangle, rayTrans, ref rayHits); - } + Tri triangle = new Tri(); + triangle.p1 = vectors[indices[i]]; + triangle.p2 = vectors[indices[i + 1]]; + triangle.p3 = vectors[indices[i + 2]]; + AddRayInTri(triangle, rayTrans, ref rayHits); } } } diff --git a/prebuild.xml b/prebuild.xml index 3c62762..3ded758 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -2271,6 +2271,7 @@ <Reference name="OpenSim.Region.Framework"/> <Reference name="OpenSim.Region.CoreModules"/> <Reference name="OpenSim.Region.Physics.Manager"/> + <Reference name="OpenSim.Region.Physics.Meshing" path="../../../../../../bin/Physics/"/> <Reference name="OpenSim.Services.Interfaces"/> <Reference name="OpenSim.Region.ScriptEngine.Shared"/> <Reference name="OpenSim.Region.ScriptEngine.Shared.Api.Runtime"/> -- 1.9.1 ![]() From a31b0d1df1596806c573c0d37eb51d92b1a93434 Mon Sep 17 00:00:00 2001 From: Magnuz Binder <magnuz@magnuz-se.com> Date: Tue, 19 May 2015 07:33:28 +0200 Subject: [PATCH] Use own mesh cache in llCastRay V3. --- .../Shared/Api/Implementation/LSL_Api.cs | 134 +++++++++++++++------ bin/OpenSimDefaults.ini | 4 +- 2 files changed, 97 insertions(+), 41 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 089a5a8..5c7a55a 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -222,8 +222,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api protected float m_primSafetyCoeffY = 2.414214f; protected float m_primSafetyCoeffZ = 1.618034f; protected bool m_useCastRayV3 = false; - protected float m_floatToleranceInCastRay = 0.000001f; - protected float m_floatTolerance2InCastRay = 0.0001f; + protected float m_floatToleranceInCastRay = 0.00001f; + protected float m_floatTolerance2InCastRay = 0.001f; protected DetailLevel m_primLodInCastRay = DetailLevel.Medium; protected DetailLevel m_sculptLodInCastRay = DetailLevel.Medium; protected DetailLevel m_meshLodInCastRay = DetailLevel.Highest; @@ -234,6 +234,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api protected bool m_detectExitsInCastRay = false; protected bool m_filterPartsInCastRay = false; protected bool m_doAttachmentsInCastRay = false; + protected static Dictionary<ulong, FacetedMesh> m_cachedMeshes = new Dictionary<ulong, FacetedMesh>(); //An array of HTTP/1.1 headers that are not allowed to be used //as custom headers by llHTTPRequest. @@ -14145,50 +14146,81 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api rayTrans.Position1RayProj = pos1RayProj; rayTrans.VectorRayProj = pos2RayProj - pos1RayProj; - // Make an OMV prim to be able to mesh part - Primitive omvPrim = part.Shape.ToOmvPrimitive(posPart, rotPart); - byte[] sculptAsset = null; - if (omvPrim.Sculpt != null) - sculptAsset = World.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString()); + // Get detail level depending on type + int lod = 0; + // Mesh detail level + if (part.Shape.SculptEntry && part.Shape.SculptType == (byte)SculptType.Mesh) + lod = (int)m_meshLodInCastRay; + // Sculpt detail level + else if (part.Shape.SculptEntry && part.Shape.SculptType == (byte)SculptType.Mesh) + lod = (int)m_sculptLodInCastRay; + // Prim detail level + else if (!part.Shape.SculptEntry) + lod = (int)m_primLodInCastRay; + + // Try to get cached mesh + ulong meshKey = part.Shape.GetMeshKey(Vector3.One, (float)(4 << lod)); FacetedMesh mesh = null; - - // When part is mesh, get mesh and check for hits - if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type == SculptType.Mesh && sculptAsset != null) + lock (m_cachedMeshes) { - AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset); - FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, m_meshLodInCastRay, out mesh); - meshAsset = null; + m_cachedMeshes.TryGetValue(meshKey, out mesh); } - // When part is sculpt, create mesh and check for hits - // Quirk: Generated sculpt mesh is about 2.8% smaller in X and Y than visual sculpt. - else if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type != SculptType.Mesh && sculptAsset != null) + // Create mesh if no cached mesh + if (mesh == null) { - IJ2KDecoder imgDecoder = World.RequestModuleInterface<IJ2KDecoder>(); - if (imgDecoder != null) + // Make an OMV prim to be able to mesh part + Primitive omvPrim = part.Shape.ToOmvPrimitive(posPart, rotPart); + byte[] sculptAsset = null; + if (omvPrim.Sculpt != null) + sculptAsset = World.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString()); + + // When part is mesh, get mesh + if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type == SculptType.Mesh && sculptAsset != null) + { + AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset); + FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, m_meshLodInCastRay, out mesh); + meshAsset = null; + } + + // When part is sculpt, create mesh + // Quirk: Generated sculpt mesh is about 2.8% smaller in X and Y than visual sculpt. + else if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type != SculptType.Mesh && sculptAsset != null) { - Image sculpt = imgDecoder.DecodeToImage(sculptAsset); - if (sculpt != null) + IJ2KDecoder imgDecoder = World.RequestModuleInterface<IJ2KDecoder>(); + if (imgDecoder != null) { - mesh = primMesher.GenerateFacetedSculptMesh(omvPrim, (Bitmap)sculpt, m_sculptLodInCastRay); - sculpt.Dispose(); + Image sculpt = imgDecoder.DecodeToImage(sculptAsset); + if (sculpt != null) + { + mesh = primMesher.GenerateFacetedSculptMesh(omvPrim, (Bitmap)sculpt, m_sculptLodInCastRay); + sculpt.Dispose(); + } } + } + + // When part is prim, create mesh + else if (omvPrim.Sculpt == null) + { + if ( + omvPrim.PrimData.PathBegin == 0.0 && omvPrim.PrimData.PathEnd == 1.0 && + omvPrim.PrimData.PathTaperX == 0.0 && omvPrim.PrimData.PathTaperY == 0.0 && + omvPrim.PrimData.PathSkew == 0.0 && + omvPrim.PrimData.PathTwist - omvPrim.PrimData.PathTwistBegin == 0.0 + ) + rayTrans.ShapeNeedsEnds = false; + mesh = primMesher.GenerateFacetedMesh(omvPrim, m_primLodInCastRay); } - } - // When part is prim, create mesh and check for hits - else if (omvPrim.Sculpt == null) - { - if ( - omvPrim.PrimData.PathBegin == 0.0 && omvPrim.PrimData.PathEnd == 1.0 && - omvPrim.PrimData.PathTaperX == 0.0 && omvPrim.PrimData.PathTaperY == 0.0 && - omvPrim.PrimData.PathSkew == 0.0 && - omvPrim.PrimData.PathTwist - omvPrim.PrimData.PathTwistBegin == 0.0 - ) - rayTrans.ShapeNeedsEnds = false; - mesh = primMesher.GenerateFacetedMesh(omvPrim, m_primLodInCastRay); + // Cache mesh + if (mesh != null) + { + lock(m_cachedMeshes) + { + m_cachedMeshes.Add(meshKey, mesh); + } + } } - // Check mesh for ray hits AddRayInFacetedMesh(mesh, rayTrans, ref rayHits); mesh = null; @@ -14236,11 +14268,35 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api rayTrans.Position1RayProj = pos1RayProj; rayTrans.VectorRayProj = pos2RayProj - pos1RayProj; - // Make OMV prim, create and check mesh + // Try to get cached mesh PrimitiveBaseShape prim = PrimitiveBaseShape.CreateSphere(); - prim.Scale = scalePart; - Primitive omvPrim = prim.ToOmvPrimitive(posPart, rotPart); - FacetedMesh mesh = primMesher.GenerateFacetedMesh(omvPrim, m_meshLodInCastRay); + int lod = (int)m_avatarLodInCastRay; + ulong meshKey = prim.GetMeshKey(Vector3.One, (float)(4 << lod)); + FacetedMesh mesh = null; + lock (m_cachedMeshes) + { + m_cachedMeshes.TryGetValue(meshKey, out mesh); + } + + // Create mesh if no cached mesh + if (mesh == null) + { + // Make OMV prim and create mesh + prim.Scale = scalePart; + Primitive omvPrim = prim.ToOmvPrimitive(posPart, rotPart); + mesh = primMesher.GenerateFacetedMesh(omvPrim, m_avatarLodInCastRay); + + // Cache mesh + if (mesh != null) + { + lock(m_cachedMeshes) + { + m_cachedMeshes.Add(meshKey, mesh); + } + } + } + + // Check mesh for ray hits AddRayInFacetedMesh(mesh, rayTrans, ref rayHits); mesh = null; } diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index 2c17022..7298ee0 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -1496,10 +1496,10 @@ UseLlCastRayV3 = false ; Accepted calculation precision error in calculations in llCastRay V3 - FloatToleranceInLlCastRay = 0.000001 + FloatToleranceInLlCastRay = 0.00001 ; Accepted distance difference between duplicate hits in llCastRay V3 - FloatTolerance2InLlCastRay = 0.0001 + FloatTolerance2InLlCastRay = 0.001 ; Detail level when rendering prims in llCastRay V3 ; 0 = Low, 1 = Medium, 2 = High, 3 = Highest, higer level gives better accuracy but slower call -- 1.9.1 ![]() From b1ec214264cb8ecc5d4284b161c377b85e5e7702 Mon Sep 17 00:00:00 2001 From: Magnuz Binder <magnuz@magnuz-se.com> Date: Tue, 19 May 2015 20:44:19 +0200 Subject: [PATCH] Use own mesh cache in llCastRay V3 after throttling. --- .../Shared/Api/Implementation/LSL_Api.cs | 143 +++++++++++++++------ bin/OpenSimDefaults.ini | 8 +- 2 files changed, 110 insertions(+), 41 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 8e277ff..6e4a365 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -223,8 +223,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api protected float m_primSafetyCoeffY = 2.414214f; protected float m_primSafetyCoeffZ = 1.618034f; protected bool m_useCastRayV3 = false; - protected float m_floatToleranceInCastRay = 0.000001f; - protected float m_floatTolerance2InCastRay = 0.0001f; + protected float m_floatToleranceInCastRay = 0.00001f; + protected float m_floatTolerance2InCastRay = 0.001f; protected DetailLevel m_primLodInCastRay = DetailLevel.Medium; protected DetailLevel m_sculptLodInCastRay = DetailLevel.Medium; protected DetailLevel m_meshLodInCastRay = DetailLevel.Highest; @@ -241,6 +241,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api protected int m_msMinInCastRay = 2; protected int m_msMaxInCastRay = 40; protected static List<CastRayCall> m_castRayCalls = new List<CastRayCall>(); + protected bool m_useMeshCacheInCastRay = true; + protected static Dictionary<ulong, FacetedMesh> m_cachedMeshes = new Dictionary<ulong, FacetedMesh>(); //An array of HTTP/1.1 headers that are not allowed to be used //as custom headers by llHTTPRequest. @@ -365,6 +367,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_msPerAvatarInCastRay = lslConfig.GetInt("AvailableTimeInMsPerAvatarInLlCastRay", m_msPerAvatarInCastRay); m_msMinInCastRay = lslConfig.GetInt("RequiredAvailableTimeInMsInLlCastRay", m_msMinInCastRay); m_msMaxInCastRay = lslConfig.GetInt("MaximumAvailableTimeInMsInLlCastRay", m_msMaxInCastRay); + m_useMeshCacheInCastRay = lslConfig.GetBoolean("UseMeshCacheInLlCastRay", m_useMeshCacheInCastRay); } IConfig smtpConfig = seConfigSource.Configs["SMTP"]; @@ -14208,50 +14211,85 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api rayTrans.Position1RayProj = pos1RayProj; rayTrans.VectorRayProj = pos2RayProj - pos1RayProj; - // Make an OMV prim to be able to mesh part - Primitive omvPrim = part.Shape.ToOmvPrimitive(posPart, rotPart); - byte[] sculptAsset = null; - if (omvPrim.Sculpt != null) - sculptAsset = World.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString()); + // Get detail level depending on type + int lod = 0; + // Mesh detail level + if (part.Shape.SculptEntry && part.Shape.SculptType == (byte)SculptType.Mesh) + lod = (int)m_meshLodInCastRay; + // Sculpt detail level + else if (part.Shape.SculptEntry && part.Shape.SculptType == (byte)SculptType.Mesh) + lod = (int)m_sculptLodInCastRay; + // Shape detail level + else if (!part.Shape.SculptEntry) + lod = (int)m_primLodInCastRay; + + // Try to get cached mesh if configured + ulong meshKey = 0; FacetedMesh mesh = null; - - // When part is mesh, get mesh and check for hits - if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type == SculptType.Mesh && sculptAsset != null) + if (m_useMeshCacheInCastRay) { - AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset); - FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, m_meshLodInCastRay, out mesh); - meshAsset = null; + meshKey = part.Shape.GetMeshKey(Vector3.One, (float)(4 << lod)); + lock (m_cachedMeshes) + { + m_cachedMeshes.TryGetValue(meshKey, out mesh); + } } - // When part is sculpt, create mesh and check for hits - // Quirk: Generated sculpt mesh is about 2.8% smaller in X and Y than visual sculpt. - else if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type != SculptType.Mesh && sculptAsset != null) + // Create mesh if no cached mesh + if (mesh == null) { - IJ2KDecoder imgDecoder = World.RequestModuleInterface<IJ2KDecoder>(); - if (imgDecoder != null) + // Make an OMV prim to be able to mesh part + Primitive omvPrim = part.Shape.ToOmvPrimitive(posPart, rotPart); + byte[] sculptAsset = null; + if (omvPrim.Sculpt != null) + sculptAsset = World.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString()); + + // When part is mesh, get mesh + if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type == SculptType.Mesh && sculptAsset != null) { - Image sculpt = imgDecoder.DecodeToImage(sculptAsset); - if (sculpt != null) + AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset); + FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, m_meshLodInCastRay, out mesh); + meshAsset = null; + } + + // When part is sculpt, create mesh + // Quirk: Generated sculpt mesh is about 2.8% smaller in X and Y than visual sculpt. + else if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type != SculptType.Mesh && sculptAsset != null) + { + IJ2KDecoder imgDecoder = World.RequestModuleInterface<IJ2KDecoder>(); + if (imgDecoder != null) { - mesh = primMesher.GenerateFacetedSculptMesh(omvPrim, (Bitmap)sculpt, m_sculptLodInCastRay); - sculpt.Dispose(); + Image sculpt = imgDecoder.DecodeToImage(sculptAsset); + if (sculpt != null) + { + mesh = primMesher.GenerateFacetedSculptMesh(omvPrim, (Bitmap)sculpt, m_sculptLodInCastRay); + sculpt.Dispose(); + } } + } + + // When part is shape, create mesh + else if (omvPrim.Sculpt == null) + { + if ( + omvPrim.PrimData.PathBegin == 0.0 && omvPrim.PrimData.PathEnd == 1.0 && + omvPrim.PrimData.PathTaperX == 0.0 && omvPrim.PrimData.PathTaperY == 0.0 && + omvPrim.PrimData.PathSkew == 0.0 && + omvPrim.PrimData.PathTwist - omvPrim.PrimData.PathTwistBegin == 0.0 + ) + rayTrans.ShapeNeedsEnds = false; + mesh = primMesher.GenerateFacetedMesh(omvPrim, m_primLodInCastRay); } - } - // When part is prim, create mesh and check for hits - else if (omvPrim.Sculpt == null) - { - if ( - omvPrim.PrimData.PathBegin == 0.0 && omvPrim.PrimData.PathEnd == 1.0 && - omvPrim.PrimData.PathTaperX == 0.0 && omvPrim.PrimData.PathTaperY == 0.0 && - omvPrim.PrimData.PathSkew == 0.0 && - omvPrim.PrimData.PathTwist - omvPrim.PrimData.PathTwistBegin == 0.0 - ) - rayTrans.ShapeNeedsEnds = false; - mesh = primMesher.GenerateFacetedMesh(omvPrim, m_primLodInCastRay); + // Cache mesh if configured + if (m_useMeshCacheInCastRay && mesh != null) + { + lock(m_cachedMeshes) + { + m_cachedMeshes.Add(meshKey, mesh); + } + } } - // Check mesh for ray hits AddRayInFacetedMesh(mesh, rayTrans, ref rayHits); mesh = null; @@ -14299,11 +14337,38 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api rayTrans.Position1RayProj = pos1RayProj; rayTrans.VectorRayProj = pos2RayProj - pos1RayProj; - // Make OMV prim, create and check mesh + // Try to get cached mesh if configured PrimitiveBaseShape prim = PrimitiveBaseShape.CreateSphere(); - prim.Scale = scalePart; - Primitive omvPrim = prim.ToOmvPrimitive(posPart, rotPart); - FacetedMesh mesh = primMesher.GenerateFacetedMesh(omvPrim, m_meshLodInCastRay); + int lod = (int)m_avatarLodInCastRay; + ulong meshKey = prim.GetMeshKey(Vector3.One, (float)(4 << lod)); + FacetedMesh mesh = null; + if (m_useMeshCacheInCastRay) + { + lock (m_cachedMeshes) + { + m_cachedMeshes.TryGetValue(meshKey, out mesh); + } + } + + // Create mesh if no cached mesh + if (mesh == null) + { + // Make OMV prim and create mesh + prim.Scale = scalePart; + Primitive omvPrim = prim.ToOmvPrimitive(posPart, rotPart); + mesh = primMesher.GenerateFacetedMesh(omvPrim, m_avatarLodInCastRay); + + // Cache mesh if configured + if (m_useMeshCacheInCastRay && mesh != null) + { + lock(m_cachedMeshes) + { + m_cachedMeshes.Add(meshKey, mesh); + } + } + } + + // Check mesh for ray hits AddRayInFacetedMesh(mesh, rayTrans, ref rayHits); mesh = null; } diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index e66ac6d..9ed6d68 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -1496,10 +1496,10 @@ UseLlCastRayV3 = false ; Accepted calculation precision error in calculations in llCastRay V3 - FloatToleranceInLlCastRay = 0.000001 + FloatToleranceInLlCastRay = 0.00001 ; Accepted distance difference between duplicate hits in llCastRay V3 - FloatTolerance2InLlCastRay = 0.0001 + FloatTolerance2InLlCastRay = 0.001 ; Detail level when rendering prims in llCastRay V3 ; 0 = Low, 1 = Medium, 2 = High, 3 = Highest, higer level gives better accuracy but slower call @@ -1551,6 +1551,10 @@ ; Maximum available time in ms possible in llCastRay V3, not to get too high values with varregions MaximumAvailableTimeInMsInLlCastRay = 40 + ; Use cached meshes in llCastRay V3 if true + ; Improves performance but uses more memory + UseMeshCacheInLlCastRay = true + [DataSnapshot] ; The following set of configs pertains to search. -- 1.9.1 | ||||||||
![]() |
||||||||||||||||
|
![]() |
|
(0028385) Magnuz (reporter) 2015-05-16 14:08 |
DON'T APPLY THIS DYSFUNCTIONAL PATCH 0001-Use-cached-meshes-in-llCastRay-V3-dysfunctional.patch Patch attempting to use cached meshes in llCastRay V3. Thanks to dahlia making the physics mesh cache available for this. The first time a new shape, sculpt or mesh is encountered, the overhead of processing and caching it is 40-50% higher than without caching, on both a high-end server and an ordinary laptop in my performance tests. However, on renewed encounters, the caching saves about 55-60% call time on a high-end server and 60-70% on an ordinary laptop. This first, dysfunctional version do prims right, but appears to get corrupt data when trying to mesh sculpts and meshes from assets. The error is probably at line 14176: shape.SculptData = World.AssetService.GetData(shape.SculptTexture.ToString()); I'm lost at how to load and use the assets in a correct way though, so any suggestions are welcome. The other possibility is a bug in the mesher used, but I can't find anything obvious in the code so I find that less likely. |
(0028399) Magnuz (reporter) 2015-05-18 22:58 |
The new patch 0001-Use-own-mesh-cache-in-llCastRay-V3.patch is fully functional. It sets up an own mesh cache optimized for llCastRay V3 and uses libopenmetaverse mesher instead of Meshmerizer. It works fully with sculpts and meshes again, eliminates the 40-50% overhead on first encounter with a shape, sculpt or mesh, increases the time save when using cached geometries to about 65% on a high-end server and 75% on an ordinary laptop in my performance tests. Since the physics mesh cache isn't populated by BulletSim and llCastRay V3 stores and uses geometries without scaling and rotation, it's really not much use to use the un-optimized physics mesh cache in particular for llCastRay V3. This patch also includes a minor fix where calculation errors sometimes made hits fall outside triangle bounding boxes and be discarded, especially when triangle planes are parallel with the local XY, XZ or YZ plane. To deal with this, error tolerances were increased by a factor of 10. (Old tolerance 0.000001, actual calculation error 0.000003-0.000004, new tolerance 0.00001.) |
(0028401) Magnuz (reporter) 2015-05-19 10:58 |
The patch 0001-Use-own-mesh-cache-in-llCastRay-V3.patch won't apply after the patch 0001-Throttle-llCastRay-V3.patch from Mantis 7568. The new patch 0001-Use-own-mesh-cache-in-llCastRay-V3-after-throttling.patch will apply after the patch 0001-Throttle-llCastRay-V3.patch from Mantis 7568. It also makes the caching optional by configuration, since the caching increases memory usage, which may be undesirable in some situations. |
(0028422) nebadon (administrator) 2015-05-21 22:49 |
patch applied : http://opensimulator.org/viewgit/?a=commit&p=opensim&h=fdc383a843c0a0218c194f7f51ef5d8fe774b520 [^] |
(0028435) Magnuz (reporter) 2015-05-22 14:34 |
Verified code and function, so closing. |
![]() |
|||
Date Modified | Username | Field | Change |
2015-05-16 14:07 | Magnuz | New Issue | |
2015-05-16 14:07 | Magnuz | File Added: 0001-Use-cached-meshes-in-llCastRay-V3-dysfunctional.patch | |
2015-05-16 14:08 | Magnuz | Note Added: 0028385 | |
2015-05-16 14:08 | Magnuz | Status | new => patch included |
2015-05-16 14:09 | Magnuz | Relationship added | related to 0007546 |
2015-05-16 14:09 | Magnuz | Relationship added | related to 0007568 |
2015-05-18 22:56 | Magnuz | File Added: 0001-Use-own-mesh-cache-in-llCastRay-V3.patch | |
2015-05-18 22:58 | Magnuz | Note Added: 0028399 | |
2015-05-19 10:53 | Magnuz | File Added: 0001-Use-own-mesh-cache-in-llCastRay-V3-after-throttling.patch | |
2015-05-19 10:58 | Magnuz | Note Added: 0028401 | |
2015-05-19 11:47 | Magnuz | File Deleted: 0001-Use-own-mesh-cache-in-llCastRay-V3-after-throttling.patch | |
2015-05-19 11:47 | Magnuz | File Added: 0001-Use-own-mesh-cache-in-llCastRay-V3-after-throttling.patch | |
2015-05-21 22:49 | nebadon | Note Added: 0028422 | |
2015-05-21 22:49 | nebadon | Status | patch included => resolved |
2015-05-21 22:49 | nebadon | Resolution | open => fixed |
2015-05-21 22:49 | nebadon | Assigned To | => nebadon |
2015-05-22 14:34 | Magnuz | Note Added: 0028435 | |
2015-05-22 14:34 | Magnuz | Status | resolved => closed |
2015-05-22 14:34 | Magnuz | Fixed in Version | => master (dev code) |
2015-05-23 05:20 | Magnuz | Relationship added | related to 0007587 |
Copyright © 2000 - 2012 MantisBT Group |