aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs252
1 files changed, 127 insertions, 125 deletions
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 7efdc62..eeaec42 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -15010,7 +15010,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
15010 int rejectTypes = 0; 15010 int rejectTypes = 0;
15011 int dataFlags = 0; 15011 int dataFlags = 0;
15012 int maxHits = 1; 15012 int maxHits = 1;
15013 bool detectPhantom = false; 15013 bool notdetectPhantom = true;
15014 for (int i = 0; i < options.Length; i += 2) 15014 for (int i = 0; i < options.Length; i += 2)
15015 { 15015 {
15016 if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES) 15016 if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES)
@@ -15020,7 +15020,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
15020 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS) 15020 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS)
15021 maxHits = options.GetLSLIntegerItem(i + 1); 15021 maxHits = options.GetLSLIntegerItem(i + 1);
15022 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM) 15022 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM)
15023 detectPhantom = (options.GetLSLIntegerItem(i + 1) != 0); 15023 notdetectPhantom = (options.GetLSLIntegerItem(i + 1) == 0);
15024 } 15024 }
15025 if (maxHits > m_maxHitsInCastRay) 15025 if (maxHits > m_maxHitsInCastRay)
15026 maxHits = m_maxHitsInCastRay; 15026 maxHits = m_maxHitsInCastRay;
@@ -15050,157 +15050,159 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
15050 World.ForEachSOG( 15050 World.ForEachSOG(
15051 delegate(SceneObjectGroup group) 15051 delegate(SceneObjectGroup group)
15052 { 15052 {
15053 if(group.IsDeleted || group.RootPart == null)
15054 return;
15053 // Check group filters unless part filters are configured 15055 // Check group filters unless part filters are configured
15054 bool isPhysical = (group.RootPart != null && group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical); 15056 bool isPhysical = (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical);
15055 bool isNonphysical = !isPhysical; 15057 bool isNonphysical = !isPhysical;
15056 bool isPhantom = group.IsPhantom || group.IsVolumeDetect; 15058 bool isPhantom = group.IsPhantom || group.IsVolumeDetect;
15057 bool isAttachment = group.IsAttachment; 15059 bool isAttachment = group.IsAttachment;
15058 bool doGroup = true;
15059 if (isPhysical && rejectPhysical) 15060 if (isPhysical && rejectPhysical)
15060 doGroup = false; 15061 return;
15061 if (isNonphysical && rejectNonphysical) 15062 if (isNonphysical && rejectNonphysical)
15062 doGroup = false; 15063 return;
15063 if (isPhantom && detectPhantom) 15064 if (isPhantom && notdetectPhantom)
15064 doGroup = true; 15065 return;
15065 if (m_filterPartsInCastRay) 15066 if (m_filterPartsInCastRay)
15066 doGroup = true; 15067 return;
15067 if (isAttachment && !m_doAttachmentsInCastRay) 15068 if (isAttachment && !m_doAttachmentsInCastRay)
15068 doGroup = false; 15069 return;
15070
15069 // Parse object/group if passed filters 15071 // Parse object/group if passed filters
15070 if (doGroup) 15072 // Iterate over all prims/parts in object/group
15073 foreach(SceneObjectPart part in group.Parts)
15071 { 15074 {
15072 // Iterate over all prims/parts in object/group 15075 // Check part filters if configured
15073 foreach(SceneObjectPart part in group.Parts) 15076 if (m_filterPartsInCastRay)
15074 { 15077 {
15075 // Check part filters if configured 15078 // ignore PhysicsShapeType.None as physics engines do
15076 if (m_filterPartsInCastRay) 15079 // or we will get into trouble in future
15080 if(part.PhysicsShapeType == (byte)PhysicsShapeType.None)
15081 continue;
15082 isPhysical = (part.PhysActor != null && part.PhysActor.IsPhysical);
15083 isNonphysical = !isPhysical;
15084 isPhantom = ((part.Flags & PrimFlags.Phantom) != 0) ||
15085 (part.VolumeDetectActive);
15086
15087 if (isPhysical && rejectPhysical)
15088 continue;
15089 if (isNonphysical && rejectNonphysical)
15090 continue;
15091 if (isPhantom && notdetectPhantom)
15092 continue;
15093 }
15094
15095 // Parse prim/part and project ray if passed filters
15096 Vector3 scalePart = part.Scale;
15097 Vector3 posPart = part.GetWorldPosition();
15098 Quaternion rotPart = part.GetWorldRotation();
15099 Quaternion rotPartInv = Quaternion.Inverse(rotPart);
15100 Vector3 pos1RayProj = ((pos1Ray - posPart) * rotPartInv) / scalePart;
15101 Vector3 pos2RayProj = ((pos2Ray - posPart) * rotPartInv) / scalePart;
15102
15103 // Filter parts by shape bounding boxes
15104 Vector3 shapeBoxMax = new Vector3(0.5f, 0.5f, 0.5f);
15105 if (!part.Shape.SculptEntry)
15106 shapeBoxMax = shapeBoxMax * (new Vector3(m_primSafetyCoeffX, m_primSafetyCoeffY, m_primSafetyCoeffZ));
15107 shapeBoxMax = shapeBoxMax + (new Vector3(tol, tol, tol));
15108 if (RayIntersectsShapeBox(pos1RayProj, pos2RayProj, shapeBoxMax))
15109 {
15110 // Prepare data needed to check for ray hits
15111 RayTrans rayTrans = new RayTrans();
15112 rayTrans.PartId = part.UUID;
15113 rayTrans.GroupId = part.ParentGroup.UUID;
15114 rayTrans.Link = group.PrimCount > 1 ? part.LinkNum : 0;
15115 rayTrans.ScalePart = scalePart;
15116 rayTrans.PositionPart = posPart;
15117 rayTrans.RotationPart = rotPart;
15118 rayTrans.ShapeNeedsEnds = true;
15119 rayTrans.Position1Ray = pos1Ray;
15120 rayTrans.Position1RayProj = pos1RayProj;
15121 rayTrans.VectorRayProj = pos2RayProj - pos1RayProj;
15122
15123 // Get detail level depending on type
15124 int lod = 0;
15125 // Mesh detail level
15126 if (part.Shape.SculptEntry && part.Shape.SculptType == (byte)SculptType.Mesh)
15127 lod = (int)m_meshLodInCastRay;
15128 // Sculpt detail level
15129 else if (part.Shape.SculptEntry && part.Shape.SculptType == (byte)SculptType.Mesh)
15130 lod = (int)m_sculptLodInCastRay;
15131 // Shape detail level
15132 else if (!part.Shape.SculptEntry)
15133 lod = (int)m_primLodInCastRay;
15134
15135 // Try to get cached mesh if configured
15136 ulong meshKey = 0;
15137 FacetedMesh mesh = null;
15138 if (m_useMeshCacheInCastRay)
15077 { 15139 {
15078 isPhysical = (part.PhysActor != null && part.PhysActor.IsPhysical); 15140 meshKey = part.Shape.GetMeshKey(Vector3.One, (float)(4 << lod));
15079 isNonphysical = !isPhysical; 15141 lock (m_cachedMeshes)
15080 isPhantom = ((part.Flags & PrimFlags.Phantom) != 0) || (part.VolumeDetectActive); 15142 {
15081 bool doPart = true; 15143 m_cachedMeshes.TryGetValue(meshKey, out mesh);
15082 if (isPhysical && rejectPhysical) 15144 }
15083 doPart = false;
15084 if (isNonphysical && rejectNonphysical)
15085 doPart = false;
15086 if (isPhantom && detectPhantom)
15087 doPart = true;
15088 if (!doPart)
15089 continue;
15090 } 15145 }
15091 15146
15092 // Parse prim/part and project ray if passed filters 15147 // Create mesh if no cached mesh
15093 Vector3 scalePart = part.Scale; 15148 if (mesh == null)
15094 Vector3 posPart = part.GetWorldPosition();
15095 Quaternion rotPart = part.GetWorldRotation();
15096 Quaternion rotPartInv = Quaternion.Inverse(rotPart);
15097 Vector3 pos1RayProj = ((pos1Ray - posPart) * rotPartInv) / scalePart;
15098 Vector3 pos2RayProj = ((pos2Ray - posPart) * rotPartInv) / scalePart;
15099
15100 // Filter parts by shape bounding boxes
15101 Vector3 shapeBoxMax = new Vector3(0.5f, 0.5f, 0.5f);
15102 if (!part.Shape.SculptEntry)
15103 shapeBoxMax = shapeBoxMax * (new Vector3(m_primSafetyCoeffX, m_primSafetyCoeffY, m_primSafetyCoeffZ));
15104 shapeBoxMax = shapeBoxMax + (new Vector3(tol, tol, tol));
15105 if (RayIntersectsShapeBox(pos1RayProj, pos2RayProj, shapeBoxMax))
15106 { 15149 {
15107 // Prepare data needed to check for ray hits 15150 // Make an OMV prim to be able to mesh part
15108 RayTrans rayTrans = new RayTrans(); 15151 Primitive omvPrim = part.Shape.ToOmvPrimitive(posPart, rotPart);
15109 rayTrans.PartId = part.UUID; 15152 byte[] sculptAsset = null;
15110 rayTrans.GroupId = part.ParentGroup.UUID; 15153 if (omvPrim.Sculpt != null)
15111 rayTrans.Link = group.PrimCount > 1 ? part.LinkNum : 0; 15154 sculptAsset = World.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString());
15112 rayTrans.ScalePart = scalePart; 15155
15113 rayTrans.PositionPart = posPart; 15156 // When part is mesh, get mesh
15114 rayTrans.RotationPart = rotPart; 15157 if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type == SculptType.Mesh && sculptAsset != null)
15115 rayTrans.ShapeNeedsEnds = true;
15116 rayTrans.Position1Ray = pos1Ray;
15117 rayTrans.Position1RayProj = pos1RayProj;
15118 rayTrans.VectorRayProj = pos2RayProj - pos1RayProj;
15119
15120 // Get detail level depending on type
15121 int lod = 0;
15122 // Mesh detail level
15123 if (part.Shape.SculptEntry && part.Shape.SculptType == (byte)SculptType.Mesh)
15124 lod = (int)m_meshLodInCastRay;
15125 // Sculpt detail level
15126 else if (part.Shape.SculptEntry && part.Shape.SculptType == (byte)SculptType.Mesh)
15127 lod = (int)m_sculptLodInCastRay;
15128 // Shape detail level
15129 else if (!part.Shape.SculptEntry)
15130 lod = (int)m_primLodInCastRay;
15131
15132 // Try to get cached mesh if configured
15133 ulong meshKey = 0;
15134 FacetedMesh mesh = null;
15135 if (m_useMeshCacheInCastRay)
15136 { 15158 {
15137 meshKey = part.Shape.GetMeshKey(Vector3.One, (float)(4 << lod)); 15159 AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset);
15138 lock (m_cachedMeshes) 15160 FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, m_meshLodInCastRay, out mesh);
15139 { 15161 meshAsset = null;
15140 m_cachedMeshes.TryGetValue(meshKey, out mesh);
15141 }
15142 } 15162 }
15143 15163
15144 // Create mesh if no cached mesh 15164 // When part is sculpt, create mesh
15145 if (mesh == null) 15165 // Quirk: Generated sculpt mesh is about 2.8% smaller in X and Y than visual sculpt.
15166 else if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type != SculptType.Mesh && sculptAsset != null)
15146 { 15167 {
15147 // Make an OMV prim to be able to mesh part 15168 IJ2KDecoder imgDecoder = World.RequestModuleInterface<IJ2KDecoder>();
15148 Primitive omvPrim = part.Shape.ToOmvPrimitive(posPart, rotPart); 15169 if (imgDecoder != null)
15149 byte[] sculptAsset = null;
15150 if (omvPrim.Sculpt != null)
15151 sculptAsset = World.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString());
15152
15153 // When part is mesh, get mesh
15154 if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type == SculptType.Mesh && sculptAsset != null)
15155 {
15156 AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset);
15157 FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, m_meshLodInCastRay, out mesh);
15158 meshAsset = null;
15159 }
15160
15161 // When part is sculpt, create mesh
15162 // Quirk: Generated sculpt mesh is about 2.8% smaller in X and Y than visual sculpt.
15163 else if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type != SculptType.Mesh && sculptAsset != null)
15164 { 15170 {
15165 IJ2KDecoder imgDecoder = World.RequestModuleInterface<IJ2KDecoder>(); 15171 Image sculpt = imgDecoder.DecodeToImage(sculptAsset);
15166 if (imgDecoder != null) 15172 if (sculpt != null)
15167 { 15173 {
15168 Image sculpt = imgDecoder.DecodeToImage(sculptAsset); 15174 mesh = primMesher.GenerateFacetedSculptMesh(omvPrim, (Bitmap)sculpt, m_sculptLodInCastRay);
15169 if (sculpt != null) 15175 sculpt.Dispose();
15170 {
15171 mesh = primMesher.GenerateFacetedSculptMesh(omvPrim, (Bitmap)sculpt, m_sculptLodInCastRay);
15172 sculpt.Dispose();
15173 }
15174 } 15176 }
15175 }
15176
15177 // When part is shape, create mesh
15178 else if (omvPrim.Sculpt == null)
15179 {
15180 if (
15181 omvPrim.PrimData.PathBegin == 0.0 && omvPrim.PrimData.PathEnd == 1.0 &&
15182 omvPrim.PrimData.PathTaperX == 0.0 && omvPrim.PrimData.PathTaperY == 0.0 &&
15183 omvPrim.PrimData.PathSkew == 0.0 &&
15184 omvPrim.PrimData.PathTwist - omvPrim.PrimData.PathTwistBegin == 0.0
15185 )
15186 rayTrans.ShapeNeedsEnds = false;
15187 mesh = primMesher.GenerateFacetedMesh(omvPrim, m_primLodInCastRay);
15188 } 15177 }
15178 }
15189 15179
15190 // Cache mesh if configured 15180 // When part is shape, create mesh
15191 if (m_useMeshCacheInCastRay && mesh != null) 15181 else if (omvPrim.Sculpt == null)
15182 {
15183 if (
15184 omvPrim.PrimData.PathBegin == 0.0 && omvPrim.PrimData.PathEnd == 1.0 &&
15185 omvPrim.PrimData.PathTaperX == 0.0 && omvPrim.PrimData.PathTaperY == 0.0 &&
15186 omvPrim.PrimData.PathSkew == 0.0 &&
15187 omvPrim.PrimData.PathTwist - omvPrim.PrimData.PathTwistBegin == 0.0
15188 )
15189 rayTrans.ShapeNeedsEnds = false;
15190 mesh = primMesher.GenerateFacetedMesh(omvPrim, m_primLodInCastRay);
15191 }
15192
15193 // Cache mesh if configured
15194 if (m_useMeshCacheInCastRay && mesh != null)
15195 {
15196 lock(m_cachedMeshes)
15192 { 15197 {
15193 lock(m_cachedMeshes) 15198 if (!m_cachedMeshes.ContainsKey(meshKey))
15194 { 15199 m_cachedMeshes.Add(meshKey, mesh);
15195 if (!m_cachedMeshes.ContainsKey(meshKey))
15196 m_cachedMeshes.Add(meshKey, mesh);
15197 }
15198 } 15200 }
15199 } 15201 }
15200 // Check mesh for ray hits
15201 AddRayInFacetedMesh(mesh, rayTrans, ref rayHits);
15202 mesh = null;
15203 } 15202 }
15203 // Check mesh for ray hits
15204 AddRayInFacetedMesh(mesh, rayTrans, ref rayHits);
15205 mesh = null;
15204 } 15206 }
15205 } 15207 }
15206 } 15208 }