diff options
-rw-r--r-- | OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 252 |
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 | } |