aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine
diff options
context:
space:
mode:
authorMagnuz Binder2015-05-10 20:01:50 +0200
committerdahlia2015-05-12 15:40:42 -0700
commitd348f871612c5f241f33885604391d1f30a416bc (patch)
treeb163a65e5fa6337877f9848024bd6760e37108b4 /OpenSim/Region/ScriptEngine
parentDisable the "show threadpool calls active" console command for now. (diff)
downloadopensim-SC_OLD-d348f871612c5f241f33885604391d1f30a416bc.zip
opensim-SC_OLD-d348f871612c5f241f33885604391d1f30a416bc.tar.gz
opensim-SC_OLD-d348f871612c5f241f33885604391d1f30a416bc.tar.bz2
opensim-SC_OLD-d348f871612c5f241f33885604391d1f30a416bc.tar.xz
Patch llCastRay fully simplified to V3.
Diffstat (limited to 'OpenSim/Region/ScriptEngine')
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs429
1 files changed, 217 insertions, 212 deletions
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index c90f015..089a5a8 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -221,15 +221,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
221 protected float m_primSafetyCoeffX = 2.414214f; 221 protected float m_primSafetyCoeffX = 2.414214f;
222 protected float m_primSafetyCoeffY = 2.414214f; 222 protected float m_primSafetyCoeffY = 2.414214f;
223 protected float m_primSafetyCoeffZ = 1.618034f; 223 protected float m_primSafetyCoeffZ = 1.618034f;
224 protected bool m_useCastRayV3 = false;
224 protected float m_floatToleranceInCastRay = 0.000001f; 225 protected float m_floatToleranceInCastRay = 0.000001f;
225 protected float m_floatTolerance2InCastRay = 0.0001f; 226 protected float m_floatTolerance2InCastRay = 0.0001f;
227 protected DetailLevel m_primLodInCastRay = DetailLevel.Medium;
228 protected DetailLevel m_sculptLodInCastRay = DetailLevel.Medium;
229 protected DetailLevel m_meshLodInCastRay = DetailLevel.Highest;
230 protected DetailLevel m_avatarLodInCastRay = DetailLevel.Medium;
226 protected int m_maxHitsInCastRay = 16; 231 protected int m_maxHitsInCastRay = 16;
227 protected int m_maxHitsPerPrimInCastRay = 16; 232 protected int m_maxHitsPerPrimInCastRay = 16;
228 protected int m_maxHitsPerObjectInCastRay = 16; 233 protected int m_maxHitsPerObjectInCastRay = 16;
229 protected bool m_detectExitsInCastRay = false; 234 protected bool m_detectExitsInCastRay = false;
230 protected bool m_filterPartsInCastRay = false; 235 protected bool m_filterPartsInCastRay = false;
231 protected bool m_doAttachmentsInCastRay = false; 236 protected bool m_doAttachmentsInCastRay = false;
232 protected bool m_useCastRayV1 = true;
233 237
234 //An array of HTTP/1.1 headers that are not allowed to be used 238 //An array of HTTP/1.1 headers that are not allowed to be used
235 //as custom headers by llHTTPRequest. 239 //as custom headers by llHTTPRequest.
@@ -336,15 +340,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
336 m_primSafetyCoeffX = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientX", m_primSafetyCoeffX); 340 m_primSafetyCoeffX = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientX", m_primSafetyCoeffX);
337 m_primSafetyCoeffY = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientY", m_primSafetyCoeffY); 341 m_primSafetyCoeffY = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientY", m_primSafetyCoeffY);
338 m_primSafetyCoeffZ = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientZ", m_primSafetyCoeffZ); 342 m_primSafetyCoeffZ = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientZ", m_primSafetyCoeffZ);
343 m_useCastRayV3 = lslConfig.GetBoolean("UseLlCastRayV3", m_useCastRayV3);
339 m_floatToleranceInCastRay = lslConfig.GetFloat("FloatToleranceInLlCastRay", m_floatToleranceInCastRay); 344 m_floatToleranceInCastRay = lslConfig.GetFloat("FloatToleranceInLlCastRay", m_floatToleranceInCastRay);
340 m_floatTolerance2InCastRay = lslConfig.GetFloat("FloatTolerance2InLlCastRay", m_floatTolerance2InCastRay); 345 m_floatTolerance2InCastRay = lslConfig.GetFloat("FloatTolerance2InLlCastRay", m_floatTolerance2InCastRay);
346 m_primLodInCastRay = (DetailLevel)lslConfig.GetInt("PrimDetailLevelInLlCastRay", (int)m_primLodInCastRay);
347 m_sculptLodInCastRay = (DetailLevel)lslConfig.GetInt("SculptDetailLevelInLlCastRay", (int)m_sculptLodInCastRay);
348 m_meshLodInCastRay = (DetailLevel)lslConfig.GetInt("MeshDetailLevelInLlCastRay", (int)m_meshLodInCastRay);
349 m_avatarLodInCastRay = (DetailLevel)lslConfig.GetInt("AvatarDetailLevelInLlCastRay", (int)m_avatarLodInCastRay);
341 m_maxHitsInCastRay = lslConfig.GetInt("MaxHitsInLlCastRay", m_maxHitsInCastRay); 350 m_maxHitsInCastRay = lslConfig.GetInt("MaxHitsInLlCastRay", m_maxHitsInCastRay);
342 m_maxHitsPerPrimInCastRay = lslConfig.GetInt("MaxHitsPerPrimInLlCastRay", m_maxHitsPerPrimInCastRay); 351 m_maxHitsPerPrimInCastRay = lslConfig.GetInt("MaxHitsPerPrimInLlCastRay", m_maxHitsPerPrimInCastRay);
343 m_maxHitsPerObjectInCastRay = lslConfig.GetInt("MaxHitsPerObjectInLlCastRay", m_maxHitsPerObjectInCastRay); 352 m_maxHitsPerObjectInCastRay = lslConfig.GetInt("MaxHitsPerObjectInLlCastRay", m_maxHitsPerObjectInCastRay);
344 m_detectExitsInCastRay = lslConfig.GetBoolean("DetectExitHitsInLlCastRay", m_detectExitsInCastRay); 353 m_detectExitsInCastRay = lslConfig.GetBoolean("DetectExitHitsInLlCastRay", m_detectExitsInCastRay);
345 m_filterPartsInCastRay = lslConfig.GetBoolean("FilterPartsInLlCastRay", m_filterPartsInCastRay); 354 m_filterPartsInCastRay = lslConfig.GetBoolean("FilterPartsInLlCastRay", m_filterPartsInCastRay);
346 m_doAttachmentsInCastRay = lslConfig.GetBoolean("DoAttachmentsInLlCastRay", m_doAttachmentsInCastRay); 355 m_doAttachmentsInCastRay = lslConfig.GetBoolean("DoAttachmentsInLlCastRay", m_doAttachmentsInCastRay);
347 m_useCastRayV1 = lslConfig.GetBoolean("UseLlCastRayV1", m_useCastRayV1);
348 } 356 }
349 357
350 IConfig smtpConfig = seConfigSource.Configs["SMTP"]; 358 IConfig smtpConfig = seConfigSource.Configs["SMTP"];
@@ -13811,8 +13819,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13811 return contacts[0]; 13819 return contacts[0];
13812 } 13820 }
13813 13821
13814 public LSL_List llCastRayV1(LSL_Vector start, LSL_Vector end, LSL_List options) 13822 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options)
13815 { 13823 {
13824 // Use llCastRay V3 if configured
13825 if (m_useCastRayV3)
13826 return llCastRayV3(start, end, options);
13827
13816 LSL_List list = new LSL_List(); 13828 LSL_List list = new LSL_List();
13817 13829
13818 m_host.AddScriptLPS(1); 13830 m_host.AddScriptLPS(1);
@@ -14003,29 +14015,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
14003 } 14015 }
14004 14016
14005 /// <summary> 14017 /// <summary>
14006 /// Full implementation of llCastRay similar to SL 2015-04-21. 14018 /// Implementation of llCastRay similar to SL 2015-04-21.
14007 /// http://wiki.secondlife.com/wiki/LlCastRay 14019 /// http://wiki.secondlife.com/wiki/LlCastRay
14008 /// Uses pure geometry, bounding shapes, meshing and no physics 14020 /// Uses pure geometry, bounding shapes, meshing and no physics
14009 /// for prims, sculpts, meshes, avatars and terrain. 14021 /// for prims, sculpts, meshes, avatars and terrain.
14010 /// Implements all flags, reject types and data flags. 14022 /// Implements all flags, reject types and data flags.
14011 /// Can handle both objects/groups and prims/parts, by config. 14023 /// Can handle both objects/groups and prims/parts, by config.
14012 /// May give poor results with multi-part meshes where "root" 14024 /// May sometimes be inaccurate owing to calculation precision,
14013 /// part doesn't dominate, owing to "guessed" bounding boxes. 14025 /// meshing detail level and a bug in libopenmetaverse PrimMesher.
14014 /// May sometimes be inaccurate owing to calculation precision
14015 /// and a bug in libopenmetaverse PrimMesher.
14016 /// </summary> 14026 /// </summary>
14017 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) 14027 public LSL_List llCastRayV3(LSL_Vector start, LSL_Vector end, LSL_List options)
14018 { 14028 {
14019 // Use llCastRay v1 if configured
14020 if (m_useCastRayV1)
14021 return llCastRayV1(start, end, options);
14022
14023 // Initialize 14029 // Initialize
14024 m_host.AddScriptLPS(1); 14030 m_host.AddScriptLPS(1);
14025 List<RayHit> rayHits = new List<RayHit>(); 14031 List<RayHit> rayHits = new List<RayHit>();
14026 LSL_List result = new LSL_List(); 14032 LSL_List result = new LSL_List();
14027 float tol = m_floatToleranceInCastRay; 14033 float tol = m_floatToleranceInCastRay;
14028 float tol2 = m_floatTolerance2InCastRay; 14034 Vector3 pos1Ray = start;
14035 Vector3 pos2Ray = end;
14029 14036
14030 // Get input options 14037 // Get input options
14031 int rejectTypes = 0; 14038 int rejectTypes = 0;
@@ -14054,25 +14061,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
14054 bool getLinkNum = ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) != 0); 14061 bool getLinkNum = ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) != 0);
14055 14062
14056 // Calculate some basic parameters 14063 // Calculate some basic parameters
14057 Vector3 ray = end - start; 14064 Vector3 vecRay = pos2Ray - pos1Ray;
14058 float rayLength = ray.Length(); 14065 float rayLength = vecRay.Length();
14059 14066
14060 // Try to get a mesher and return failure if none or degenerate ray 14067 // Try to get a mesher and return failure if none, degenerate ray, or max 0 hits
14061 IRendering primMesher = null; 14068 IRendering primMesher = null;
14062 List<string> renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory()); 14069 List<string> renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory());
14063 if (renderers.Count < 1 || rayLength < tol) 14070 if (renderers.Count < 1 || rayLength < tol || m_maxHitsInCastRay < 1)
14064 { 14071 {
14065 result.Add(new LSL_Integer(ScriptBaseClass.RCERR_UNKNOWN)); 14072 result.Add(new LSL_Integer(ScriptBaseClass.RCERR_UNKNOWN));
14066 return result; 14073 return result;
14067 } 14074 }
14068 primMesher = RenderingLoader.LoadRenderer(renderers[0]); 14075 primMesher = RenderingLoader.LoadRenderer(renderers[0]);
14069 14076
14070 // Used to translate and rotate world so ray is along negative Z axis from origo and
14071 // calculations mostly simplified to a 2D projecttion on the X-Y plane
14072 Vector3 posProj = new Vector3(-start);
14073 Quaternion rotProj = Vector3.RotationBetween(ray, new Vector3(0.0f, 0.0f, -1.0f));
14074 Quaternion rotBack = Quaternion.Inverse(rotProj);
14075
14076 // Iterate over all objects/groups and prims/parts in region 14077 // Iterate over all objects/groups and prims/parts in region
14077 World.ForEachSOG( 14078 World.ForEachSOG(
14078 delegate(SceneObjectGroup group) 14079 delegate(SceneObjectGroup group)
@@ -14115,51 +14116,51 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
14115 if (!doPart) 14116 if (!doPart)
14116 continue; 14117 continue;
14117 } 14118 }
14118 // Parse prim/part if passed filters
14119 14119
14120 // Estimate bounding box from size box 14120 // Parse prim/part and project ray if passed filters
14121 Vector3 scaleSafe = part.Scale; 14121 Vector3 scalePart = part.Scale;
14122 if (!part.Shape.SculptEntry) 14122 Vector3 posPart = part.GetWorldPosition();
14123 scaleSafe = scaleSafe * (new Vector3(m_primSafetyCoeffX, m_primSafetyCoeffY, m_primSafetyCoeffZ)); 14123 Quaternion rotPart = part.GetWorldRotation();
14124 Quaternion rotPartInv = Quaternion.Inverse(rotPart);
14125 Vector3 pos1RayProj = ((pos1Ray - posPart) * rotPartInv) / scalePart;
14126 Vector3 pos2RayProj = ((pos2Ray - posPart) * rotPartInv) / scalePart;
14124 14127
14125 // Filter parts by bounding shapes 14128 // Filter parts by shape bounding boxes
14126 Vector3 posPartRel = part.GetWorldPosition() + posProj; 14129 Vector3 shapeBoxMax = new Vector3(0.5f, 0.5f, 0.5f);
14127 Vector3 posPartProj = posPartRel * rotProj; 14130 if (!part.Shape.SculptEntry)
14128 if (InBoundingShapes(ray, rayLength, scaleSafe, posPartRel, posPartProj, rotProj)) 14131 shapeBoxMax = shapeBoxMax * (new Vector3(m_primSafetyCoeffX, m_primSafetyCoeffY, m_primSafetyCoeffZ));
14132 shapeBoxMax = shapeBoxMax + (new Vector3(tol, tol, tol));
14133 if (RayIntersectsShapeBox(pos1RayProj, pos2RayProj, shapeBoxMax))
14129 { 14134 {
14130 // Prepare data needed to check for ray hits 14135 // Prepare data needed to check for ray hits
14131 RayTrans rayTrans = new RayTrans(); 14136 RayTrans rayTrans = new RayTrans();
14132 rayTrans.PartId = part.UUID; 14137 rayTrans.PartId = part.UUID;
14133 rayTrans.GroupId = part.ParentGroup.UUID; 14138 rayTrans.GroupId = part.ParentGroup.UUID;
14134 rayTrans.Link = group.PrimCount > 1 ? part.LinkNum : 0; 14139 rayTrans.Link = group.PrimCount > 1 ? part.LinkNum : 0;
14135 rayTrans.Scale = part.Scale; 14140 rayTrans.ScalePart = scalePart;
14136 rayTrans.PositionPartProj = posPartProj; 14141 rayTrans.PositionPart = posPart;
14137 rayTrans.PositionProj = posProj; 14142 rayTrans.RotationPart = rotPart;
14138 rayTrans.RotationPartProj = rotProj * part.GetWorldRotation(); 14143 rayTrans.ShapeNeedsEnds = true;
14139 rayTrans.RotationBack = rotBack; 14144 rayTrans.Position1Ray = pos1Ray;
14140 rayTrans.NeedsEnds = true; 14145 rayTrans.Position1RayProj = pos1RayProj;
14141 rayTrans.RayLength = rayLength; 14146 rayTrans.VectorRayProj = pos2RayProj - pos1RayProj;
14142 rayTrans.Tolerance = tol;
14143 rayTrans.Tolerance2 = tol2;
14144 14147
14145 // Make an OMV prim to be able to mesh part 14148 // Make an OMV prim to be able to mesh part
14146 Primitive omvPrim = part.Shape.ToOmvPrimitive(posPartProj, rayTrans.RotationPartProj); 14149 Primitive omvPrim = part.Shape.ToOmvPrimitive(posPart, rotPart);
14147 byte[] sculptAsset = null; 14150 byte[] sculptAsset = null;
14148 if (omvPrim.Sculpt != null) 14151 if (omvPrim.Sculpt != null)
14149 sculptAsset = World.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString()); 14152 sculptAsset = World.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString());
14153 FacetedMesh mesh = null;
14150 14154
14151 // When part is mesh, get and check mesh 14155 // When part is mesh, get mesh and check for hits
14152 if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type == SculptType.Mesh && sculptAsset != null) 14156 if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type == SculptType.Mesh && sculptAsset != null)
14153 { 14157 {
14154 AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset); 14158 AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset);
14155 FacetedMesh mesh = null; 14159 FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, m_meshLodInCastRay, out mesh);
14156 FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, DetailLevel.Highest, out mesh);
14157 meshAsset = null; 14160 meshAsset = null;
14158 AddRayInFacetedMesh(mesh, rayTrans, ref rayHits);
14159 mesh = null;
14160 } 14161 }
14161 14162
14162 // When part is sculpt, create and check mesh 14163 // When part is sculpt, create mesh and check for hits
14163 // Quirk: Generated sculpt mesh is about 2.8% smaller in X and Y than visual sculpt. 14164 // Quirk: Generated sculpt mesh is about 2.8% smaller in X and Y than visual sculpt.
14164 else if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type != SculptType.Mesh && sculptAsset != null) 14165 else if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type != SculptType.Mesh && sculptAsset != null)
14165 { 14166 {
@@ -14169,15 +14170,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
14169 Image sculpt = imgDecoder.DecodeToImage(sculptAsset); 14170 Image sculpt = imgDecoder.DecodeToImage(sculptAsset);
14170 if (sculpt != null) 14171 if (sculpt != null)
14171 { 14172 {
14172 SimpleMesh mesh = primMesher.GenerateSimpleSculptMesh(omvPrim, (Bitmap)sculpt, DetailLevel.Medium); 14173 mesh = primMesher.GenerateFacetedSculptMesh(omvPrim, (Bitmap)sculpt, m_sculptLodInCastRay);
14173 sculpt.Dispose(); 14174 sculpt.Dispose();
14174 AddRayInSimpleMesh(mesh, rayTrans, ref rayHits);
14175 mesh = null;
14176 } 14175 }
14177 } 14176 }
14178 } 14177 }
14179 14178
14180 // When part is prim, create and check mesh 14179 // When part is prim, create mesh and check for hits
14181 else if (omvPrim.Sculpt == null) 14180 else if (omvPrim.Sculpt == null)
14182 { 14181 {
14183 if ( 14182 if (
@@ -14186,12 +14185,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
14186 omvPrim.PrimData.PathSkew == 0.0 && 14185 omvPrim.PrimData.PathSkew == 0.0 &&
14187 omvPrim.PrimData.PathTwist - omvPrim.PrimData.PathTwistBegin == 0.0 14186 omvPrim.PrimData.PathTwist - omvPrim.PrimData.PathTwistBegin == 0.0
14188 ) 14187 )
14189 rayTrans.NeedsEnds = false; 14188 rayTrans.ShapeNeedsEnds = false;
14190 SimpleMesh mesh = primMesher.GenerateSimpleMesh(omvPrim, DetailLevel.Medium); 14189 mesh = primMesher.GenerateFacetedMesh(omvPrim, m_primLodInCastRay);
14191 AddRayInSimpleMesh(mesh, rayTrans, ref rayHits);
14192 mesh = null;
14193 } 14190 }
14194 14191
14192 // Check mesh for ray hits
14193 AddRayInFacetedMesh(mesh, rayTrans, ref rayHits);
14194 mesh = null;
14195 } 14195 }
14196 } 14196 }
14197 } 14197 }
@@ -14205,38 +14205,43 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
14205 World.ForEachRootScenePresence( 14205 World.ForEachRootScenePresence(
14206 delegate (ScenePresence sp) 14206 delegate (ScenePresence sp)
14207 { 14207 {
14208 // Parse avatar
14209
14210 // Get bounding box 14208 // Get bounding box
14211 Vector3 lower; 14209 Vector3 lower;
14212 Vector3 upper; 14210 Vector3 upper;
14213 BoundingBoxOfScenePresence(sp, out lower, out upper); 14211 BoundingBoxOfScenePresence(sp, out lower, out upper);
14214 Vector3 scale = upper - lower; 14212 // Parse avatar
14215 14213 Vector3 scalePart = upper - lower;
14216 // Filter avatars by bounding shapes 14214 Vector3 posPart = sp.AbsolutePosition;
14217 Vector3 posPartRel = sp.AbsolutePosition + posProj + (lower + upper) * 0.5f * sp.Rotation; 14215 Quaternion rotPart = sp.GetWorldRotation();
14218 Vector3 posPartProj = posPartRel * rotProj; 14216 Quaternion rotPartInv = Quaternion.Inverse(rotPart);
14219 if (InBoundingShapes(ray, rayLength, scale, posPartRel, posPartProj, rotProj)) 14217 posPart = posPart + (lower + upper) * 0.5f * rotPart;
14218 // Project ray
14219 Vector3 pos1RayProj = ((pos1Ray - posPart) * rotPartInv) / scalePart;
14220 Vector3 pos2RayProj = ((pos2Ray - posPart) * rotPartInv) / scalePart;
14221
14222 // Filter avatars by shape bounding boxes
14223 Vector3 shapeBoxMax = new Vector3(0.5f + tol, 0.5f + tol, 0.5f + tol);
14224 if (RayIntersectsShapeBox(pos1RayProj, pos2RayProj, shapeBoxMax))
14220 { 14225 {
14221 // Prepare data needed to check for ray hits 14226 // Prepare data needed to check for ray hits
14222 RayTrans rayTrans = new RayTrans(); 14227 RayTrans rayTrans = new RayTrans();
14223 rayTrans.PartId = sp.UUID; 14228 rayTrans.PartId = sp.UUID;
14224 rayTrans.GroupId = sp.ParentPart != null ? sp.ParentPart.ParentGroup.UUID : sp.UUID; 14229 rayTrans.GroupId = sp.ParentPart != null ? sp.ParentPart.ParentGroup.UUID : sp.UUID;
14225 rayTrans.Link = sp.ParentPart != null ? UUID2LinkNumber(sp.ParentPart, sp.UUID) : 0; 14230 rayTrans.Link = sp.ParentPart != null ? UUID2LinkNumber(sp.ParentPart, sp.UUID) : 0;
14226 rayTrans.Scale = scale; 14231 rayTrans.ScalePart = scalePart;
14227 rayTrans.PositionPartProj = posPartProj; 14232 rayTrans.PositionPart = posPart;
14228 rayTrans.PositionProj = posProj; 14233 rayTrans.RotationPart = rotPart;
14229 rayTrans.RotationPartProj = rotProj * sp.Rotation; 14234 rayTrans.ShapeNeedsEnds = false;
14230 rayTrans.RotationBack = rotBack; 14235 rayTrans.Position1Ray = pos1Ray;
14231 rayTrans.NeedsEnds = false; 14236 rayTrans.Position1RayProj = pos1RayProj;
14232 rayTrans.RayLength = rayLength; 14237 rayTrans.VectorRayProj = pos2RayProj - pos1RayProj;
14233 rayTrans.Tolerance = tol;
14234 rayTrans.Tolerance2 = tol2;
14235 14238
14236 // Make OMV prim, create and check mesh 14239 // Make OMV prim, create and check mesh
14237 Primitive omvPrim = MakeOpenMetaversePrim(scale, posPartProj, rayTrans.RotationPartProj, ScriptBaseClass.PRIM_TYPE_SPHERE); 14240 PrimitiveBaseShape prim = PrimitiveBaseShape.CreateSphere();
14238 SimpleMesh mesh = primMesher.GenerateSimpleMesh(omvPrim, DetailLevel.Medium); 14241 prim.Scale = scalePart;
14239 AddRayInSimpleMesh(mesh, rayTrans, ref rayHits); 14242 Primitive omvPrim = prim.ToOmvPrimitive(posPart, rotPart);
14243 FacetedMesh mesh = primMesher.GenerateFacetedMesh(omvPrim, m_meshLodInCastRay);
14244 AddRayInFacetedMesh(mesh, rayTrans, ref rayHits);
14240 mesh = null; 14245 mesh = null;
14241 } 14246 }
14242 } 14247 }
@@ -14248,32 +14253,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
14248 { 14253 {
14249 // Parse terrain 14254 // Parse terrain
14250 14255
14251 // Mesh terrain and check projected bounding box 14256 // Mesh terrain and check bounding box
14252 Vector3 posPartProj = posProj * rotProj;
14253 Quaternion rotPartProj = rotProj;
14254 Vector3 lower; 14257 Vector3 lower;
14255 Vector3 upper; 14258 Vector3 upper;
14256 List<Tri> triangles = TrisFromHeightmapUnderRay(start, end, out lower, out upper); 14259 List<Tri> triangles = TrisFromHeightmapUnderRay(pos1Ray, pos2Ray, out lower, out upper);
14257 Vector3 lowerBox = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue); 14260 lower.Z -= tol;
14258 Vector3 upperBox = new Vector3(float.MinValue, float.MinValue, float.MinValue); 14261 upper.Z += tol;
14259 int dummy = 0; 14262 if ((pos1Ray.Z >= lower.Z || pos2Ray.Z >= lower.Z) && (pos1Ray.Z <= upper.Z || pos2Ray.Z <= upper.Z))
14260 AddBoundingBoxOfSimpleBox(lower, upper, posPartProj, rotPartProj, true, ref lowerBox, ref upperBox, ref dummy);
14261 if (lowerBox.X <= tol && lowerBox.Y <= tol && lowerBox.Z <= tol && upperBox.X >= -tol && upperBox.Y >= -tol && upperBox.Z >= -rayLength - tol)
14262 { 14263 {
14263 // Prepare data needed to check for ray hits 14264 // Prepare data needed to check for ray hits
14264 RayTrans rayTrans = new RayTrans(); 14265 RayTrans rayTrans = new RayTrans();
14265 rayTrans.PartId = UUID.Zero; 14266 rayTrans.PartId = UUID.Zero;
14266 rayTrans.GroupId = UUID.Zero; 14267 rayTrans.GroupId = UUID.Zero;
14267 rayTrans.Link = 0; 14268 rayTrans.Link = 0;
14268 rayTrans.Scale = new Vector3 (1.0f, 1.0f, 1.0f); 14269 rayTrans.ScalePart = new Vector3 (1.0f, 1.0f, 1.0f);
14269 rayTrans.PositionPartProj = posPartProj; 14270 rayTrans.PositionPart = Vector3.Zero;
14270 rayTrans.PositionProj = posProj; 14271 rayTrans.RotationPart = Quaternion.Identity;
14271 rayTrans.RotationPartProj = rotPartProj; 14272 rayTrans.ShapeNeedsEnds = true;
14272 rayTrans.RotationBack = rotBack; 14273 rayTrans.Position1Ray = pos1Ray;
14273 rayTrans.NeedsEnds = true; 14274 rayTrans.Position1RayProj = pos1Ray;
14274 rayTrans.RayLength = rayLength; 14275 rayTrans.VectorRayProj = vecRay;
14275 rayTrans.Tolerance = tol;
14276 rayTrans.Tolerance2 = tol2;
14277 14276
14278 // Check mesh 14277 // Check mesh
14279 AddRayInTris(triangles, rayTrans, ref rayHits); 14278 AddRayInTris(triangles, rayTrans, ref rayHits);
@@ -14358,15 +14357,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
14358 public UUID PartId; 14357 public UUID PartId;
14359 public UUID GroupId; 14358 public UUID GroupId;
14360 public int Link; 14359 public int Link;
14361 public Vector3 Scale; 14360 public Vector3 ScalePart;
14362 public Vector3 PositionPartProj; 14361 public Vector3 PositionPart;
14363 public Vector3 PositionProj; 14362 public Quaternion RotationPart;
14364 public Quaternion RotationPartProj; 14363 public bool ShapeNeedsEnds;
14365 public Quaternion RotationBack; 14364 public Vector3 Position1Ray;
14366 public bool NeedsEnds; 14365 public Vector3 Position1RayProj;
14367 public float RayLength; 14366 public Vector3 VectorRayProj;
14368 public float Tolerance;
14369 public float Tolerance2;
14370 } 14367 }
14371 14368
14372 /// <summary> 14369 /// <summary>
@@ -14383,21 +14380,63 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
14383 } 14380 }
14384 14381
14385 /// <summary> 14382 /// <summary>
14386 /// Helper to parse SimpleMesh for ray hits. 14383 /// Helper to check if a ray intersects a shape bounding box.
14387 /// </summary> 14384 /// </summary>
14388 private void AddRayInSimpleMesh(SimpleMesh mesh, RayTrans rayTrans, ref List<RayHit> rayHits) 14385 private bool RayIntersectsShapeBox(Vector3 pos1RayProj, Vector3 pos2RayProj, Vector3 shapeBoxMax)
14389 { 14386 {
14390 if (mesh != null) 14387 // Skip if ray can't intersect bounding box;
14388 Vector3 rayBoxProjMin = Vector3.Min(pos1RayProj, pos2RayProj);
14389 Vector3 rayBoxProjMax = Vector3.Max(pos1RayProj, pos2RayProj);
14390 if (
14391 rayBoxProjMin.X > shapeBoxMax.X || rayBoxProjMin.Y > shapeBoxMax.Y || rayBoxProjMin.Z > shapeBoxMax.Z ||
14392 rayBoxProjMax.X < -shapeBoxMax.X || rayBoxProjMax.Y < -shapeBoxMax.Y || rayBoxProjMax.Z < -shapeBoxMax.Z
14393 )
14394 return false;
14395
14396 // Check if ray intersect any bounding box side
14397 int sign = 0;
14398 float dist = 0.0f;
14399 Vector3 posProj = Vector3.Zero;
14400 Vector3 vecRayProj = pos2RayProj - pos1RayProj;
14401
14402 // Check both X sides unless ray is parallell to them
14403 if (Math.Abs(vecRayProj.X) > m_floatToleranceInCastRay)
14404 {
14405 for (sign = -1; sign <= 1; sign += 2)
14406 {
14407 dist = ((float)sign * shapeBoxMax.X - pos1RayProj.X) / vecRayProj.X;
14408 posProj = pos1RayProj + vecRayProj * dist;
14409 if (Math.Abs(posProj.Y) <= shapeBoxMax.Y && Math.Abs(posProj.Z) <= shapeBoxMax.Z)
14410 return true;
14411 }
14412 }
14413
14414 // Check both Y sides unless ray is parallell to them
14415 if (Math.Abs(vecRayProj.Y) > m_floatToleranceInCastRay)
14391 { 14416 {
14392 for (int i = 0; i < mesh.Indices.Count; i += 3) 14417 for (sign = -1; sign <= 1; sign += 2)
14393 { 14418 {
14394 Tri triangle = new Tri(); 14419 dist = ((float)sign * shapeBoxMax.Y - pos1RayProj.Y) / vecRayProj.Y;
14395 triangle.p1 = mesh.Vertices[mesh.Indices[i]].Position; 14420 posProj = pos1RayProj + vecRayProj * dist;
14396 triangle.p2 = mesh.Vertices[mesh.Indices[i + 1]].Position; 14421 if (Math.Abs(posProj.X) <= shapeBoxMax.X && Math.Abs(posProj.Z) <= shapeBoxMax.Z)
14397 triangle.p3 = mesh.Vertices[mesh.Indices[i + 2]].Position; 14422 return true;
14398 AddRayInTri(triangle, rayTrans, ref rayHits);
14399 } 14423 }
14400 } 14424 }
14425
14426 // Check both Z sides unless ray is parallell to them
14427 if (Math.Abs(vecRayProj.Z) > m_floatToleranceInCastRay)
14428 {
14429 for (sign = -1; sign <= 1; sign += 2)
14430 {
14431 dist = ((float)sign * shapeBoxMax.Z - pos1RayProj.Z) / vecRayProj.Z;
14432 posProj = pos1RayProj + vecRayProj * dist;
14433 if (Math.Abs(posProj.X) <= shapeBoxMax.X && Math.Abs(posProj.Y) <= shapeBoxMax.Y)
14434 return true;
14435 }
14436 }
14437
14438 // No hits on bounding box so return false
14439 return false;
14401 } 14440 }
14402 14441
14403 /// <summary> 14442 /// <summary>
@@ -14409,7 +14448,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
14409 { 14448 {
14410 foreach (Face face in mesh.Faces) 14449 foreach (Face face in mesh.Faces)
14411 { 14450 {
14412 for (int i = 0; i <face.Indices.Count; i += 3) 14451 for (int i = 0; i < face.Indices.Count; i += 3)
14413 { 14452 {
14414 Tri triangle = new Tri(); 14453 Tri triangle = new Tri();
14415 triangle.p1 = face.Vertices[face.Indices[i]].Position; 14454 triangle.p1 = face.Vertices[face.Indices[i]].Position;
@@ -14435,23 +14474,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
14435 /// <summary> 14474 /// <summary>
14436 /// Helper to add ray hit in a Tri (triangle). 14475 /// Helper to add ray hit in a Tri (triangle).
14437 /// </summary> 14476 /// </summary>
14438 private void AddRayInTri(Tri triangle, RayTrans rayTrans, ref List<RayHit> rayHits) 14477 private void AddRayInTri(Tri triProj, RayTrans rayTrans, ref List<RayHit> rayHits)
14439 { 14478 {
14440 // Check for hit in triangle 14479 // Check for hit in triangle
14441 float distance; 14480 Vector3 posHitProj;
14442 Vector3 posHit; 14481 Vector3 normalProj;
14443 Vector3 normal; 14482 if (HitRayInTri(triProj, rayTrans.Position1RayProj, rayTrans.VectorRayProj, out posHitProj, out normalProj))
14444 if (HitRayInTri(triangle, rayTrans, out distance, out posHit, out normal)) 14483 {
14445 { 14484 // Hack to circumvent ghost face bug in PrimMesher by removing hits in (ghost) face plane through shape center
14446 // Project hit part back to normal coordinate system 14485 if (Math.Abs(Vector3.Dot(posHitProj, normalProj)) < m_floatToleranceInCastRay && !rayTrans.ShapeNeedsEnds)
14447 Vector3 posPart = rayTrans.PositionPartProj * rayTrans.RotationBack - rayTrans.PositionProj;
14448 // Hack to circumvent ghost face bug in PrimMesher by removing hits in (ghost) faces plane through shape center
14449 if (Math.Abs(Vector3.Dot(posPart, normal) - Vector3.Dot(posHit, normal)) < rayTrans.Tolerance && !rayTrans.NeedsEnds)
14450 return; 14486 return;
14451 // Remove duplicate hits at triangle edges and intersections 14487
14488 // Transform hit and normal to region coordinate system
14489 Vector3 posHit = rayTrans.PositionPart + (posHitProj * rayTrans.ScalePart) * rayTrans.RotationPart;
14490 Vector3 normal = Vector3.Normalize((normalProj * rayTrans.ScalePart) * rayTrans.RotationPart);
14491
14492 // Remove duplicate hits at triangle intersections
14493 float distance = Vector3.Distance(rayTrans.Position1Ray, posHit);
14452 for (int i = rayHits.Count - 1; i >= 0; i--) 14494 for (int i = rayHits.Count - 1; i >= 0; i--)
14453 { 14495 {
14454 if (rayHits[i].PartId == rayTrans.PartId && Math.Abs(rayHits[i].Distance - distance) < rayTrans.Tolerance2) 14496 if (rayHits[i].PartId != rayTrans.PartId)
14497 break;
14498 if (Math.Abs(rayHits[i].Distance - distance) < m_floatTolerance2InCastRay)
14455 return; 14499 return;
14456 } 14500 }
14457 14501
@@ -14468,76 +14512,56 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
14468 } 14512 }
14469 14513
14470 /// <summary> 14514 /// <summary>
14471 /// Helper to find ray hit in a Tri (triangle). 14515 /// Helper to find ray hit in triangle
14472 /// </summary> 14516 /// </summary>
14473 private bool HitRayInTri(Tri triangle, RayTrans rayTrans, out float distance, out Vector3 posHit, out Vector3 normal) 14517 bool HitRayInTri(Tri triProj, Vector3 pos1RayProj, Vector3 vecRayProj, out Vector3 posHitProj, out Vector3 normalProj)
14474 { 14518 {
14475 // Initialize 14519 float tol = m_floatToleranceInCastRay;
14476 distance = 0.0f; 14520 posHitProj = Vector3.Zero;
14477 posHit = Vector3.Zero; 14521
14478 normal = Vector3.Zero; 14522 // Calculate triangle edge vectors
14479 float tol = rayTrans.Tolerance; 14523 Vector3 vec1Proj = triProj.p2 - triProj.p1;
14480 14524 Vector3 vec2Proj = triProj.p3 - triProj.p2;
14481 // Project triangle on X-Y plane 14525 Vector3 vec3Proj = triProj.p1 - triProj.p3;
14482 Vector3 pos1 = triangle.p1 * rayTrans.Scale * rayTrans.RotationPartProj + rayTrans.PositionPartProj;
14483 Vector3 pos2 = triangle.p2 * rayTrans.Scale * rayTrans.RotationPartProj + rayTrans.PositionPartProj;
14484 Vector3 pos3 = triangle.p3 * rayTrans.Scale * rayTrans.RotationPartProj + rayTrans.PositionPartProj;
14485
14486 // Check if ray/origo inside triangle bounding rectangle
14487 Vector3 lower = Vector3.Min(pos1, Vector3.Min(pos2, pos3));
14488 Vector3 upper = Vector3.Max(pos1, Vector3.Max(pos2, pos3));
14489 if (lower.X > tol || lower.Y > tol || lower.Z > tol || upper.X < -tol || upper.Y < -tol || upper.Z < -rayTrans.RayLength - tol)
14490 return false;
14491 14526
14492 // Check if ray/origo inside every edge or reverse "outside" every edge on exit 14527 // Calculate triangle normal
14493 float dist; 14528 normalProj = Vector3.Cross(vec1Proj, vec2Proj);
14494 bool inside = true; 14529
14495 bool outside = true; 14530 // Skip if degenerate triangle or ray parallell with triangle plane
14496 Vector3 vec1 = pos2 - pos1; 14531 float divisor = Vector3.Dot(vecRayProj, normalProj);
14497 dist = pos1.X * vec1.Y - pos1.Y * vec1.X; 14532 if (Math.Abs(divisor) < tol)
14498 if (dist < -tol)
14499 inside = false;
14500 if (dist > tol)
14501 outside = false;
14502 Vector3 vec2 = pos3 - pos2;
14503 dist = pos2.X * vec2.Y - pos2.Y * vec2.X;
14504 if (dist < -tol)
14505 inside = false;
14506 if (dist > tol)
14507 outside = false;
14508 Vector3 vec3 = pos1 - pos3;
14509 dist = pos3.X * vec3.Y - pos3.Y * vec3.X;
14510 if (dist < -tol)
14511 inside = false;
14512 if (dist > tol)
14513 outside = false;
14514
14515 // Skip if ray/origo outside
14516 if (!inside && !(outside && m_detectExitsInCastRay))
14517 return false; 14533 return false;
14518 14534
14519 // Calculate normal 14535 // Skip if exit and not configured to detect
14520 Vector3 normalProj = Vector3.Cross(vec1, vec2); 14536 if (divisor > tol && !m_detectExitsInCastRay)
14521 float normalLength = normalProj.Length();
14522 // Skip if degenerate triangle
14523 if (normalLength < tol)
14524 return false; 14537 return false;
14525 normalProj = normalProj / normalLength; 14538
14526 // Skip if ray parallell to triangle plane 14539 // Skip if outside ray ends
14527 if (Math.Abs(normalProj.Z) < tol) 14540 float distanceProj = Vector3.Dot(triProj.p1 - pos1RayProj, normalProj) / divisor;
14541 if (distanceProj < -tol || distanceProj > 1 + tol)
14528 return false; 14542 return false;
14529 14543
14530 // Calculate distance 14544 // Calculate hit position in triangle
14531 distance = Vector3.Dot(normalProj, pos2) / normalProj.Z * -1.0f; 14545 posHitProj = pos1RayProj + vecRayProj * distanceProj;
14532 // Skip if outside ray 14546
14533 if (distance < -tol || distance > rayTrans.RayLength + tol) 14547 // Skip if outside triangle bounding box
14548 Vector3 triProjMin = Vector3.Min(Vector3.Min(triProj.p1, triProj.p2), triProj.p3);
14549 Vector3 triProjMax = Vector3.Max(Vector3.Max(triProj.p1, triProj.p2), triProj.p3);
14550 if (
14551 posHitProj.X < triProjMin.X - tol || posHitProj.Y < triProjMin.Y - tol || posHitProj.Z < triProjMin.Z - tol ||
14552 posHitProj.X > triProjMax.X + tol || posHitProj.Y > triProjMax.Y + tol || posHitProj.Z > triProjMax.Z + tol
14553 )
14534 return false; 14554 return false;
14535 14555
14536 // Calculate projected hit position 14556 // Skip if outside triangle
14537 Vector3 posHitProj = new Vector3(0.0f, 0.0f, -distance); 14557 if (
14538 // Project hit back to normal coordinate system 14558 Vector3.Dot(Vector3.Cross(vec1Proj, normalProj), posHitProj - triProj.p1) > tol ||
14539 posHit = posHitProj * rayTrans.RotationBack - rayTrans.PositionProj; 14559 Vector3.Dot(Vector3.Cross(vec2Proj, normalProj), posHitProj - triProj.p2) > tol ||
14540 normal = normalProj * rayTrans.RotationBack; 14560 Vector3.Dot(Vector3.Cross(vec3Proj, normalProj), posHitProj - triProj.p3) > tol
14561 )
14562 return false;
14563
14564 // Return hit
14541 return true; 14565 return true;
14542 } 14566 }
14543 14567
@@ -14660,24 +14684,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
14660 y = Util.Clamp<int>(yInt+1, 0, World.Heightmap.Height - 1); 14684 y = Util.Clamp<int>(yInt+1, 0, World.Heightmap.Height - 1);
14661 Vector3 pos2 = new Vector3(x, y, (float)World.Heightmap[x, y]); 14685 Vector3 pos2 = new Vector3(x, y, (float)World.Heightmap[x, y]);
14662 // Adjust bounding box 14686 // Adjust bounding box
14663 zLower = Math.Min(zLower, pos1.Z); 14687 zLower = Math.Min(zLower, pos2.Z);
14664 zUpper = Math.Max(zUpper, pos1.Z); 14688 zUpper = Math.Max(zUpper, pos2.Z);
14665 14689
14666 // Corner 3 of 1x1 rectangle 14690 // Corner 3 of 1x1 rectangle
14667 x = Util.Clamp<int>(xInt, 0, World.Heightmap.Width - 1); 14691 x = Util.Clamp<int>(xInt, 0, World.Heightmap.Width - 1);
14668 y = Util.Clamp<int>(yInt, 0, World.Heightmap.Height - 1); 14692 y = Util.Clamp<int>(yInt, 0, World.Heightmap.Height - 1);
14669 Vector3 pos3 = new Vector3(x, y, (float)World.Heightmap[x, y]); 14693 Vector3 pos3 = new Vector3(x, y, (float)World.Heightmap[x, y]);
14670 // Adjust bounding box 14694 // Adjust bounding box
14671 zLower = Math.Min(zLower, pos1.Z); 14695 zLower = Math.Min(zLower, pos3.Z);
14672 zUpper = Math.Max(zUpper, pos1.Z); 14696 zUpper = Math.Max(zUpper, pos3.Z);
14673 14697
14674 // Corner 4 of 1x1 rectangle 14698 // Corner 4 of 1x1 rectangle
14675 x = Util.Clamp<int>(xInt+1, 0, World.Heightmap.Width - 1); 14699 x = Util.Clamp<int>(xInt+1, 0, World.Heightmap.Width - 1);
14676 y = Util.Clamp<int>(yInt, 0, World.Heightmap.Height - 1); 14700 y = Util.Clamp<int>(yInt, 0, World.Heightmap.Height - 1);
14677 Vector3 pos4 = new Vector3(x, y, (float)World.Heightmap[x, y]); 14701 Vector3 pos4 = new Vector3(x, y, (float)World.Heightmap[x, y]);
14678 // Adjust bounding box 14702 // Adjust bounding box
14679 zLower = Math.Min(zLower, pos1.Z); 14703 zLower = Math.Min(zLower, pos4.Z);
14680 zUpper = Math.Max(zUpper, pos1.Z); 14704 zUpper = Math.Max(zUpper, pos4.Z);
14681 14705
14682 // Add triangle 1 14706 // Add triangle 1
14683 Tri triangle1 = new Tri(); 14707 Tri triangle1 = new Tri();
@@ -14695,25 +14719,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
14695 } 14719 }
14696 14720
14697 /// <summary> 14721 /// <summary>
14698 /// Helper to check if a ray intersects bounding shapes.
14699 /// </summary>
14700 private bool InBoundingShapes(Vector3 ray, float rayLength, Vector3 scale, Vector3 posPartRel, Vector3 posPartProj, Quaternion rotProj)
14701 {
14702 float tol = m_floatToleranceInCastRay;
14703
14704 // Check if ray intersects projected bounding box
14705 Vector3 lowerBox = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
14706 Vector3 upperBox = new Vector3(float.MinValue, float.MinValue, float.MinValue);
14707 int dummy = 0;
14708 AddBoundingBoxOfSimpleBox(scale * -0.5f, scale * 0.5f, posPartProj, rotProj, true, ref lowerBox, ref upperBox, ref dummy);
14709 if (lowerBox.X > tol || lowerBox.Y > tol || lowerBox.Z > tol || upperBox.X < -tol || upperBox.Y < -tol || upperBox.Z < -rayLength - tol)
14710 return false;
14711
14712 // Passed bounding shape filters, so return true
14713 return true;
14714 }
14715
14716 /// <summary>
14717 /// Helper to get link number for a UUID. 14722 /// Helper to get link number for a UUID.
14718 /// </summary> 14723 /// </summary>
14719 private int UUID2LinkNumber(SceneObjectPart part, UUID id) 14724 private int UUID2LinkNumber(SceneObjectPart part, UUID id)