diff --git a/OpenSim/Region/Environment/Scenes/SceneGraph.cs b/OpenSim/Region/Environment/Scenes/SceneGraph.cs
index b373c09afd..d261e2de06 100644
--- a/OpenSim/Region/Environment/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Environment/Scenes/SceneGraph.cs
@@ -1203,6 +1203,8 @@ namespace OpenSim.Region.Environment.Scenes
///
///
///
+ /// This routine seems to get called when a user changes object settings in the viewer.
+ /// If some one can confirm that, please change the comment according.
protected internal void UpdatePrimFlags(uint localID, bool UsePhysics, bool IsTemporary, bool IsPhantom, IClientAPI remoteClient)
{
SceneObjectGroup group = GetGroupByPrim(localID);
@@ -1210,7 +1212,7 @@ namespace OpenSim.Region.Environment.Scenes
{
if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId))
{
- group.UpdatePrimFlags(localID, UsePhysics, IsTemporary, IsPhantom);
+ group.UpdatePrimFlags(localID, UsePhysics, IsTemporary, IsPhantom, false); // VolumeDetect can't be set via UI and will always be off when a change is made there
}
}
}
diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs
index 545628256b..f4ccc46648 100644
--- a/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs
@@ -1431,21 +1431,45 @@ namespace OpenSim.Region.Environment.Scenes
{
bool IsTemporary = ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0);
bool IsPhantom = ((RootPart.Flags & PrimFlags.Phantom) != 0);
- UpdatePrimFlags(RootPart.LocalId, UsePhysics, IsTemporary, IsPhantom);
+ bool IsVolumeDetect = RootPart.VolumeDetectActive;
+ UpdatePrimFlags(RootPart.LocalId, UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
}
public void ScriptSetTemporaryStatus(bool TemporaryStatus)
{
bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
bool IsPhantom = ((RootPart.Flags & PrimFlags.Phantom) != 0);
- UpdatePrimFlags(RootPart.LocalId, UsePhysics, TemporaryStatus, IsPhantom);
+ bool IsVolumeDetect = RootPart.VolumeDetectActive;
+ UpdatePrimFlags(RootPart.LocalId, UsePhysics, TemporaryStatus, IsPhantom, IsVolumeDetect);
}
public void ScriptSetPhantomStatus(bool PhantomStatus)
{
bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
bool IsTemporary = ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0);
- UpdatePrimFlags(RootPart.LocalId, UsePhysics, IsTemporary, PhantomStatus);
+ bool IsVolumeDetect = RootPart.VolumeDetectActive;
+ UpdatePrimFlags(RootPart.LocalId, UsePhysics, IsTemporary, PhantomStatus, IsVolumeDetect);
+ }
+
+ public void ScriptSetVolumeDetect(bool VDStatus)
+ {
+ bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
+ bool IsTemporary = ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0);
+ bool IsPhantom = ((RootPart.Flags & PrimFlags.Phantom) != 0);
+ UpdatePrimFlags(RootPart.LocalId, UsePhysics, IsTemporary, IsPhantom, VDStatus);
+
+ /*
+ ScriptSetPhantomStatus(false); // What ever it was before, now it's not phantom anymore
+
+ if (PhysActor != null) // Should always be the case now
+ {
+ PhysActor.SetVolumeDetect(param);
+ }
+ if (param != 0)
+ AddFlag(PrimFlags.Phantom);
+
+ ScheduleFullUpdate();
+ */
}
public void applyImpulse(PhysicsVector impulse)
@@ -2251,7 +2275,7 @@ namespace OpenSim.Region.Environment.Scenes
///
///
///
- public void UpdatePrimFlags(uint localID, bool UsePhysics, bool IsTemporary, bool IsPhantom)
+ public void UpdatePrimFlags(uint localID, bool UsePhysics, bool IsTemporary, bool IsPhantom, bool IsVolumeDetect)
{
SceneObjectPart selectionPart = GetChildPart(localID);
@@ -2279,7 +2303,7 @@ namespace OpenSim.Region.Environment.Scenes
foreach (SceneObjectPart part in m_parts.Values)
{
- part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom);
+ part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
}
}
}
diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs
index 6b4d47a08b..0315c929b9 100644
--- a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs
@@ -167,7 +167,11 @@ namespace OpenSim.Region.Environment.Scenes
[XmlIgnore]
public PhysicsVector RotationAxis = new PhysicsVector(1f,1f,1f);
-
+
+ [XmlIgnore]
+ public bool VolumeDetectActive = false; // XmlIgnore set to avoid problems with persistance until I come to care for this
+ // Certainly this must be a persistant setting finally
+
///
/// This part's inventory
///
@@ -2178,6 +2182,16 @@ if (m_shape != null) {
m_parentGroup.ScriptSetPhysicsStatus(UsePhysics);
}
+ public void ScriptSetVolumeDetect(bool SetVD)
+ {
+
+ if (m_parentGroup != null)
+ {
+ m_parentGroup.ScriptSetVolumeDetect(SetVD);
+ }
+ }
+
+
public void SculptTextureCallback(UUID textureID, AssetBase texture)
{
if (m_shape.SculptEntry)
@@ -2484,14 +2498,6 @@ if (m_shape != null) {
}
}
- public void SetVolumeDetect(int param)
- {
- if (PhysActor != null)
- {
- PhysActor.SetVolumeDetect(param);
- }
- }
-
public void SetGroup(UUID groupID, IClientAPI client)
{
_groupID = groupID;
@@ -3184,17 +3190,46 @@ if (m_shape != null) {
}
}
- public void UpdatePrimFlags(bool UsePhysics, bool IsTemporary, bool IsPhantom)
+ public void UpdatePrimFlags(bool UsePhysics, bool IsTemporary, bool IsPhantom, bool IsVD)
{
bool wasUsingPhysics = ((ObjectFlags & (uint) PrimFlags.Physics) != 0);
bool wasTemporary = ((ObjectFlags & (uint)PrimFlags.TemporaryOnRez) != 0);
bool wasPhantom = ((ObjectFlags & (uint)PrimFlags.Phantom) != 0);
+ bool wasVD = VolumeDetectActive;
- if ((UsePhysics == wasUsingPhysics) && (wasTemporary == IsTemporary) && (wasPhantom == IsPhantom))
+ if ((UsePhysics == wasUsingPhysics) && (wasTemporary == IsTemporary) && (wasPhantom == IsPhantom) && (IsVD==wasVD) )
{
return;
}
+ // Special cases for VD. VD can only be called from a script
+ // and can't be combined with changes to other states. So we can rely
+ // that...
+ // ... if VD is changed, all others are not.
+ // ... if one of the others is changed, VD is not.
+ if (IsVD) // VD is active, special logic applies
+ {
+ // State machine logic for VolumeDetect
+ // More logic below
+ bool phanReset = (IsPhantom != wasPhantom) && !IsPhantom;
+
+ if (phanReset) // Phantom changes from on to off switch VD off too
+ {
+ IsVD = false; // Switch it of for the course of this routine
+ VolumeDetectActive = false; // and also permanently
+ if (PhysActor != null)
+ PhysActor.SetVolumeDetect(0); // Let physics know about it too
+ }
+ else
+ {
+ IsPhantom = false;
+ // If volumedetect is active we don't want phantom to be applied.
+ // If this is a new call to VD out of the state "phantom"
+ // this will also cause the prim to be visible to physics
+ }
+
+ }
+
if (UsePhysics)
{
AddFlag(PrimFlags.Physics);
@@ -3222,6 +3257,7 @@ if (m_shape != null) {
}
}
+
if (IsPhantom || IsAttachment)
{
AddFlag(PrimFlags.Phantom);
@@ -3232,11 +3268,13 @@ if (m_shape != null) {
PhysActor = null;
}
}
- else
+ else // Not phantom
{
RemFlag(PrimFlags.Phantom);
+
if (PhysActor == null)
{
+ // It's not phantom anymore. So make sure the physics engine get's knowledge of it
PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape(
Name,
Shape,
@@ -3261,10 +3299,11 @@ if (m_shape != null) {
}
}
}
- else
+ else // it already has a physical representation
{
- PhysActor.IsPhysical = UsePhysics;
- DoPhysicsPropertyUpdate(UsePhysics, false);
+ PhysActor.IsPhysical = UsePhysics;
+
+ DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status. If it's phantom this will remove the prim
if (m_parentGroup != null)
{
if (!m_parentGroup.IsDeleted)
@@ -3278,6 +3317,32 @@ if (m_shape != null) {
}
}
+ if (IsVD)
+ {
+ // If the above logic worked (this is urgent candidate to unit tests!)
+ // we now have a physicsactor.
+ // Defensive programming calls for a check here.
+ // Better would be throwing an exception that could be catched by a unit test as the internal
+ // logic should make sure, this Physactor is always here.
+ if (this.PhysActor != null)
+ {
+ PhysActor.SetVolumeDetect(1);
+ AddFlag(PrimFlags.Phantom); // We set this flag also if VD is active
+ this.VolumeDetectActive = true;
+ }
+
+ }
+ else
+ { // Remove VolumeDetect in any case. Note, it's safe to call SetVolumeDetect as often as you like
+ // (mumbles, well, at least if you have infinte CPU powers :-) )
+ if (this.PhysActor != null)
+ {
+ PhysActor.SetVolumeDetect(0);
+ }
+ this.VolumeDetectActive = false;
+ }
+
+
if (IsTemporary)
{
AddFlag(PrimFlags.TemporaryOnRez);
@@ -3287,6 +3352,7 @@ if (m_shape != null) {
RemFlag(PrimFlags.TemporaryOnRez);
}
// System.Console.WriteLine("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString());
+
ParentGroup.HasGroupChanged = true;
ScheduleFullUpdate();
}
diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
index 6f5abfa6a6..b9c0936953 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
@@ -127,6 +127,8 @@ namespace OpenSim.Region.Physics.OdePlugin
private bool m_isphysical = false;
private bool m_isSelected = false;
+ internal bool m_isVolumeDetect = false; // If true, this prim only detects collisions but doesn't collide actively
+
private bool m_throttleUpdates = false;
private int throttleCounter = 0;
public int m_interpenetrationcount = 0;
@@ -2226,7 +2228,10 @@ namespace OpenSim.Region.Physics.OdePlugin
public override void SetVolumeDetect(int param)
{
-
+ lock (_parent_scene.OdeLock)
+ {
+ m_isVolumeDetect = (param!=0);
+ }
}
public override PhysicsVector CenterOfMass
diff --git a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
index 7589750c5b..c0b4b45934 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
@@ -797,7 +797,25 @@ namespace OpenSim.Region.Physics.OdePlugin
#endregion
- if (contacts[i].depth >= 0f && !checkDupe(contacts[i], p2.PhysicsActorType))
+ // Logic for collision handling
+ // Note, that if *all* contacts are skipped (VolumeDetect)
+ // The prim still detects (and forwards) collision events but
+ // appears to be phantom for the world
+ Boolean skipThisContact = false;
+
+ if (contacts[i].depth < 0f)
+ skipThisContact = true;
+
+ if (checkDupe(contacts[i], p2.PhysicsActorType))
+ skipThisContact = true;
+
+ if ((p1 is OdePrim) && (((OdePrim)p1).m_isVolumeDetect))
+ skipThisContact = true; // No collision on volume detect prims
+
+ if ((p2 is OdePrim) && (((OdePrim)p2).m_isVolumeDetect))
+ skipThisContact = true; // No collision on volume detect prims
+
+ if (!skipThisContact)
{
// If we're colliding against terrain
if (name1 == "Terrain" || name2 == "Terrain")
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index b15189e0b7..5ef94719b2 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -5736,7 +5736,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
if (!m_host.ParentGroup.IsDeleted)
{
- m_host.ParentGroup.RootPart.SetVolumeDetect(detect);
+ m_host.ParentGroup.RootPart.ScriptSetVolumeDetect(detect!=0);
}
}
}