Merge branch 'master' of ssh://melanie@3dhosting.de/var/git/careminster into careminster

avinationmerge
Melanie 2012-03-07 00:51:24 +00:00
commit f3e04beb2e
10 changed files with 877 additions and 809 deletions

View File

@ -957,12 +957,12 @@ namespace OpenSim.Region.Framework.Scenes
/// <returns></returns>
public void GetAxisAlignedBoundingBoxRaw(out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ)
{
maxX = -256f;
maxY = -256f;
maxZ = -256f;
minX = 256f;
minY = 256f;
minZ = 8192f;
maxX = float.MinValue;
maxY = float.MinValue;
maxZ = float.MinValue;
minX = float.MaxValue;
minY = float.MaxValue;
minZ = float.MaxValue;
SceneObjectPart[] parts = m_parts.GetArray();
foreach (SceneObjectPart part in parts)
@ -1988,7 +1988,12 @@ namespace OpenSim.Region.Framework.Scenes
/// <param name="cGroupID"></param>
public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
{
SetRootPart(part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed));
// SetRootPart(part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed));
// give newpart a new local ID lettng old part keep same
SceneObjectPart newpart = part.Copy(part.LocalId, OwnerID, GroupID, 0, userExposed);
newpart.LocalId = m_scene.AllocateLocalId();
SetRootPart(newpart);
if (userExposed)
RootPart.Velocity = Vector3.Zero; // In case source is moving
}
@ -2191,7 +2196,10 @@ namespace OpenSim.Region.Framework.Scenes
/// <param name="cGroupID"></param>
public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
{
SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
// give new ID to the new part, letting old keep original
// SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
SceneObjectPart newPart = part.Copy(part.LocalId, OwnerID, GroupID, m_parts.Count, userExposed);
newPart.LocalId = m_scene.AllocateLocalId();
newPart.SetParent(this);
AddPart(newPart);
@ -2485,6 +2493,11 @@ namespace OpenSim.Region.Framework.Scenes
SceneObjectPart linkPart = objectGroup.m_rootPart;
if (m_rootPart.PhysActor != null)
m_rootPart.PhysActor.Building = true;
if (linkPart.PhysActor != null)
linkPart.PhysActor.Building = true;
Vector3 oldGroupPosition = linkPart.GroupPosition;
Quaternion oldRootRotation = linkPart.RotationOffset;
@ -2528,6 +2541,13 @@ namespace OpenSim.Region.Framework.Scenes
linkPart.SetParent(this);
linkPart.CreateSelected = true;
// let physics know
if (linkPart.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical)
{
linkPart.PhysActor.link(m_rootPart.PhysActor);
this.Scene.PhysicsScene.AddPhysicsActorTaint(linkPart.PhysActor);
}
linkPart.LinkNum = linkNum++;
SceneObjectPart[] ogParts = objectGroup.Parts;
@ -2540,7 +2560,15 @@ namespace OpenSim.Region.Framework.Scenes
{
SceneObjectPart part = ogParts[i];
if (part.UUID != objectGroup.m_rootPart.UUID)
{
LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
// let physics know
if (part.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical)
{
part.PhysActor.link(m_rootPart.PhysActor);
this.Scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
}
}
part.ClearUndoState();
}
}
@ -2560,6 +2588,9 @@ namespace OpenSim.Region.Framework.Scenes
// unmoved prims!
ResetChildPrimPhysicsPositions();
if (m_rootPart.PhysActor != null)
m_rootPart.PhysActor.Building = false;
//HasGroupChanged = true;
//ScheduleGroupForFullUpdate();
}
@ -2613,6 +2644,9 @@ namespace OpenSim.Region.Framework.Scenes
// "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}",
// linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID);
if (m_rootPart.PhysActor != null)
m_rootPart.PhysActor.Building = true;
linkPart.ClearUndoState();
Quaternion worldRot = linkPart.GetWorldRotation();
@ -2672,6 +2706,10 @@ namespace OpenSim.Region.Framework.Scenes
// When we delete a group, we currently have to force persist to the database if the object id has changed
// (since delete works by deleting all rows which have a given object id)
if (m_rootPart.PhysActor != null)
m_rootPart.PhysActor.Building = false;
objectGroup.HasGroupChangedDueToDelink = true;
return objectGroup;
@ -3284,6 +3322,10 @@ namespace OpenSim.Region.Framework.Scenes
part.StoreUndoState(false);
part.IgnoreUndoUpdate = true;
// unlock parts position change
if (m_rootPart.PhysActor != null)
m_rootPart.PhysActor.Building = true;
if (part.UUID == m_rootPart.UUID)
{
UpdateRootPosition(pos);
@ -3293,6 +3335,9 @@ namespace OpenSim.Region.Framework.Scenes
part.UpdateOffSet(pos);
}
if (m_rootPart.PhysActor != null)
m_rootPart.PhysActor.Building = false;
HasGroupChanged = true;
part.IgnoreUndoUpdate = false;
}
@ -3434,6 +3479,9 @@ namespace OpenSim.Region.Framework.Scenes
// m_log.DebugFormat(
// "[SCENE OBJECT GROUP]: Updating single rotation of {0} {1} to {2}", part.Name, part.LocalId, rot);
if (m_rootPart.PhysActor != null)
m_rootPart.PhysActor.Building = true;
if (part.UUID == m_rootPart.UUID)
{
UpdateRootRotation(rot);
@ -3442,6 +3490,9 @@ namespace OpenSim.Region.Framework.Scenes
{
part.UpdateRotation(rot);
}
if (m_rootPart.PhysActor != null)
m_rootPart.PhysActor.Building = false;
}
}
@ -3462,6 +3513,9 @@ namespace OpenSim.Region.Framework.Scenes
part.StoreUndoState();
part.IgnoreUndoUpdate = true;
if (m_rootPart.PhysActor != null)
m_rootPart.PhysActor.Building = true;
if (part.UUID == m_rootPart.UUID)
{
UpdateRootRotation(rot);
@ -3482,6 +3536,9 @@ namespace OpenSim.Region.Framework.Scenes
part.OffsetPosition = pos;
}
if (m_rootPart.PhysActor != null)
m_rootPart.PhysActor.Building = false;
part.IgnoreUndoUpdate = false;
}
}

View File

@ -1691,9 +1691,8 @@ namespace OpenSim.Region.Framework.Scenes
if (userExposed)
dupe.UUID = UUID.Random();
//memberwiseclone means it also clones the physics actor reference
// This will make physical prim 'bounce' if not set to null.
if (!userExposed)
// The PhysActor cannot be valid on a copy because the copy is not in the scene yet.
// Null it, the caller has to create a new one once the object is added to a scene
dupe.PhysActor = null;
dupe.OwnerID = AgentID;
@ -1727,8 +1726,6 @@ namespace OpenSim.Region.Framework.Scenes
// Move afterwards ResetIDs as it clears the localID
dupe.LocalId = localID;
if(dupe.PhysActor != null)
dupe.PhysActor.LocalID = localID;
// This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
dupe.LastOwnerID = OwnerID;
@ -1749,6 +1746,9 @@ namespace OpenSim.Region.Framework.Scenes
dupe.DoPhysicsPropertyUpdate(UsePhysics, true);
}
if (dupe.PhysActor != null)
dupe.PhysActor.LocalID = localID;
ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed);
// m_log.DebugFormat("[SCENE OBJECT PART]: Clone of {0} {1} finished", Name, UUID);

View File

@ -121,12 +121,18 @@ namespace OpenSim.Region.OptionalModules
private bool CanObjectEnter(UUID objectID, bool enteringRegion, Vector3 newPoint, Scene scene)
{
if ((newPoint.X > 257f || newPoint.X < -1f || newPoint.Y > 257f || newPoint.Y < -1f))
return true;
SceneObjectPart obj = scene.GetSceneObjectPart(objectID);
Vector3 oldPoint = obj.GroupPosition;
int objectCount = obj.ParentGroup.PrimCount;
ILandObject oldParcel = scene.LandChannel.GetLandObject(oldPoint.X, oldPoint.Y);
ILandObject newParcel = scene.LandChannel.GetLandObject(newPoint.X, newPoint.Y);
if (newParcel == null)
return true;
int usedPrims = newParcel.PrimCounts.Total;
int simulatorCapacity = newParcel.GetSimulatorMaxPrimCount();

View File

@ -163,6 +163,8 @@ namespace OpenSim.Region.Physics.OdePlugin
private bool m_isphysical;
private bool m_isSelected;
private bool m_NoColide; // for now only for internal use for bad meshs
internal bool m_isVolumeDetect; // If true, this prim only detects collisions but doesn't collide actively
private bool m_throttleUpdates;
@ -253,7 +255,7 @@ namespace OpenSim.Region.Physics.OdePlugin
private float m_verticalAttractionEfficiency = 1.0f; // damped
private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor.
SerialControl m_taintserial = null;
// SerialControl m_taintserial = null;
object m_taintvehicledata = null;
public void DoSetVehicle()
@ -309,410 +311,6 @@ namespace OpenSim.Region.Physics.OdePlugin
m_taintvehicledata = vdata;
_parent_scene.AddPhysicsActorTaint(this);
}
public override byte[] Serialize(bool PhysIsRunning)
{
SerialControl sc = new SerialControl();
lock (sc.alock)
{
if (PhysIsRunning)
{
m_taintserial = sc;
if (!Monitor.Wait(sc.alock, 1000))
{
m_log.Error("[chOde] prim data serialization timed out");
m_taintserial = null;
return new byte[0];
}
}
else
DoSerialize(sc);
}
return sc.data;
}
public void DoSerialize(SerialControl sc)
{
wstreamer st = new wstreamer();
Vector3 vtmp;
ushort version = 2;
if (!BitConverter.IsLittleEndian)
version |= 1;
st.Wushort(version); //version lower bit codes endian type for future use
// compact booleans in a ushort
ushort flags = 0;
if (m_isphysical) // this should be true for now
flags |= 1;
if (m_isSelected)
flags |= 2;
if (m_isVolumeDetect)
flags |= 4;
if (m_disabled)
flags |= 8;
if (m_collidesWater)
flags |= 16;
if (m_collidesLand)
flags |= 32;
if (m_usePID)
flags |= 64;
if (m_useAPID)
flags |= 128;
if (m_useHoverPID)
flags |= 256;
if (m_throttleUpdates)
flags |= 512;
st.Wushort(flags);
st.Wvector3(_size);
st.Wint(m_material);
st.Wfloat(m_density);
st.Wfloat(0); // future gravity mod V3
st.Wfloat(0); // future friction V3
st.Wfloat(0); // future bounce V3
// st.Wuint((uint)m_collisionCategories);
// st.Wuint((uint)m_collisionFlags);
if (_parent == null)
{
st.Wvector3(_position); // ??
st.Wquat(_orientation);
}
else // for childs save offsets
{
Quaternion to;
Quaternion ipo = Quaternion.Inverse(_parent.Orientation);
if (m_isphysical && prim_geom != IntPtr.Zero)
{
d.Vector3 dvt;
d.GeomCopyPosition(prim_geom, out dvt);
vtmp.X = dvt.X;
vtmp.Y = dvt.Y;
vtmp.Z = dvt.Z;
d.Quaternion dqt;
d.GeomCopyQuaternion(prim_geom, out dqt);
to.X = dqt.X;
to.Y = dqt.Y;
to.Z = dqt.Z;
to.W = dqt.W; // rotation in world
}
else
{
vtmp = _position;
to = _orientation;
}
vtmp -= _parent.Position; // offset in world
vtmp *= ipo; // offset in local
st.Wvector3(vtmp);
ipo *= to; // own rotation
st.Wquat(ipo);
}
st.Wvector3(_velocity);
st.Wvector3(m_rotationalVelocity);
st.Wvector3(_acceleration);
st.Wvector3(m_rotateEnable);
vtmp = Vector3.Zero;
for (int i = 0; i < m_forcelist.Count; i++)
{
vtmp += (m_forcelist[i] * 100);
}
st.Wvector3(vtmp); // force acc
vtmp = Vector3.Zero;
for (int i = 0; i < m_angularforcelist.Count; i++)
{
vtmp += (m_angularforcelist[i] * 100);
}
st.Wvector3(vtmp); // angular force acc
st.Wvector3(m_PIDTarget);
st.Wfloat(m_PIDTau);
st.Wfloat(PID_D);
st.Wfloat(PID_G);
st.Wquat(m_APIDTarget);
st.Wfloat(m_APIDStrength);
st.Wfloat(m_APIDDamping);
st.Wfloat(m_APIDdamper);
st.Wint((int)m_PIDHoverType);
st.Wfloat(m_PIDHoverHeight);
st.Wfloat(m_PIDHoverTau);
st.Wfloat(m_targetHoverHeight);
st.Wfloat(m_groundHeight);
st.Wfloat(m_waterHeight);
st.Wfloat(m_buoyancy);
// this must be last since type none ends stream
if (m_type == Vehicle.TYPE_NONE)
st.Wint((int)Vehicle.TYPE_NONE);
else
{
st.Wint((int)m_type);
st.Wquat(Quaternion.Identity); //m_referenceFrame
st.Wint((int)m_flags);
st.Wvector3(m_linearMotorDirection);
st.Wfloat(
(float)Math.Sqrt(m_lLinMotorDVel.LengthSquared() / m_linearMotorDirection.LengthSquared()));
st.Wvector3(m_linearFrictionTimescale);
st.Wfloat(m_linearMotorDecayTimescale);
st.Wfloat(m_linearMotorTimescale);
st.Wvector3(new Vector3(0, 0, 0)); //m_linearMotorOffset);
st.Wvector3(m_angularMotorDirection);
st.Wfloat((float)Math.Sqrt(m_angularMotorDVel.LengthSquared() / m_angularMotorDirection.LengthSquared()));
st.Wvector3(m_angularFrictionTimescale);
st.Wfloat(m_angularMotorDecayTimescale);
st.Wfloat(m_angularMotorTimescale);
st.Wfloat(0); //m_linearDeflectionEfficiency);
st.Wfloat(1000); //m_linearDeflectionTimescale);
st.Wfloat(0); //m_angularDeflectionEfficiency);
st.Wfloat(120); //m_angularDeflectionTimescale);
st.Wfloat(0); // m_bankingEfficiency);
st.Wfloat(0); //m_bankingMix);
st.Wfloat(1000); //m_bankingTimescale);
st.Wfloat(m_VhoverHeight);
st.Wfloat(0.5f); //m_VhoverEfficiency);
st.Wfloat(m_VhoverTimescale);
st.Wfloat(m_VehicleBuoyancy);
st.Wfloat(m_verticalAttractionEfficiency);
st.Wfloat(m_verticalAttractionTimescale);
}
sc.data = st.close();
m_taintserial = null;
Monitor.PulseAll(sc.alock);
}
public bool DeSerialize(byte[] data)
{
rstreamer st = new rstreamer(data);
int version =st.Rushort(); //version
// merge booleans in a ushort
ushort flags = st.Rushort();
if ((flags & 1) != 0)
m_isphysical = true;
if ((flags & 2) != 0)
m_taintselected = true;
if ((flags & 4) != 0)
m_isVolumeDetect = true;
if ((flags & 8) != 0)
m_taintdisable = true;
if ((flags & 16) != 0)
m_taintCollidesWater = true;
if ((flags & 32) != 0)
m_collidesLand = true;
if ((flags & 64) != 0)
m_usePID = true;
if ((flags & 128) != 0)
m_useAPID = true;
if ((flags & 256) != 0)
m_useHoverPID = true;
if ((flags & 512) != 0)
m_throttleUpdates = true;
_size = st.Rvector3();
m_taintsize = _size;
m_material= st.Rint();
m_density = st.Rfloat();
st.Rfloat(); // future gravity mod V3
st.Rfloat(); // future friction V3
st.Rfloat(); // future bounce V3
// m_collisionCategories = (CollisionCategories)st.Ruint();
// m_collisionFlags = (CollisionCategories) st.Ruint();
if (m_taintparent == null)
{
st.Rvector3(); // ignore old position sop/sog as to tell the new one
m_taintrot = st.Rquat(); //
_orientation = m_taintrot;
}
else
{
m_taintrot = _parent.Orientation;
m_taintposition = st.Rvector3(); // ??
_position = m_taintposition;
m_taintposition *= m_taintrot;
m_taintposition += _parent.Position;
m_taintrot *= st.Rquat(); //
_orientation = m_taintrot;
}
m_taintVelocity = st.Rvector3();
m_rotationalVelocity = st.Rvector3();
_acceleration = st.Rvector3();
m_rotateEnableRequest = st.Rvector3();
m_rotateEnableUpdate = true;
Vector3 vtmp;
vtmp = st.Rvector3(); // forces acc
m_forcelist.Add(vtmp);
m_taintforce = true;
vtmp = st.Rvector3(); // angular forces acc
m_angularforcelist.Add(vtmp);
m_taintaddangularforce = true;
m_PIDTarget = st.Rvector3();
m_PIDTau = st.Rfloat();
PID_D = st.Rfloat();
PID_G = st.Rfloat();
m_APIDTarget = st.Rquat();
m_APIDStrength = st.Rfloat();
m_APIDDamping = st.Rfloat();
m_APIDdamper = st.Rfloat();
m_PIDHoverType = (PIDHoverType) st.Rint();
m_PIDHoverHeight = st.Rfloat();
m_PIDHoverTau = st.Rfloat();
m_targetHoverHeight = st.Rfloat();
m_groundHeight = st.Rfloat();
m_waterHeight = st.Rfloat();
m_buoyancy = st.Rfloat();
// this must be last since type none ends stream
m_type = (Vehicle) st.Rint();
if (m_type != Vehicle.TYPE_NONE)
{
float ftmp;
st.Rquat(); //m_referenceFrame
m_flags = (VehicleFlag) st.Rint();
m_linearMotorDirection = st.Rvector3();
ftmp = st.Rfloat();
m_lLinMotorDVel = m_linearMotorDirection * ftmp;
m_linearFrictionTimescale = st.Rvector3();
m_linearMotorDecayTimescale = st.Rfloat();
m_linearMotorTimescale = st.Rfloat();
st.Rvector3(); //m_linearMotorOffset);
m_angularMotorDirection = st.Rvector3();
ftmp = st.Rfloat();
m_angularMotorDVel = m_angularMotorDirection * ftmp;
m_angularFrictionTimescale = st.Rvector3();
m_angularMotorDecayTimescale = st.Rfloat();
m_angularMotorTimescale = st.Rfloat();
st.Rfloat(); //m_linearDeflectionEfficiency);
st.Rfloat(); //m_linearDeflectionTimescale);
st.Rfloat(); //m_angularDeflectionEfficiency);
st.Rfloat(); //m_angularDeflectionTimescale);
st.Rfloat(); // m_bankingEfficiency);
st.Rfloat(); //m_bankingMix);
st.Rfloat(); //m_bankingTimescale);
m_VhoverHeight = st.Rfloat();
st.Rfloat(); //m_VhoverEfficiency);
m_VhoverTimescale = st.Rfloat();
m_VehicleBuoyancy = st.Rfloat();
m_verticalAttractionEfficiency = st.Rfloat();
m_verticalAttractionTimescale = st.Rfloat();
}
st.close();
return true;
}
public OdePrim(String primName, OdeScene parent_scene, Vector3 pos, PhysicsActor parent,
PrimitiveBaseShape pbs, CollisionLocker dode, uint localid, byte[] sdata)
{
m_localID = localid;
ode = dode;
if (parent == null)
{
m_taintparent = null;
if (!pos.IsFinite())
{
pos = new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f),
parent_scene.GetTerrainHeightAtXY(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f)) + 0.5f);
m_log.Warn("[PHYSICS]: Got nonFinite Object create Position");
}
_position = pos;
m_taintposition = pos;
}
else
m_taintparent = parent;
body_autodisable_frames = parent_scene.bodyFramesAutoDisable;
prim_geom = IntPtr.Zero;
_mesh = null;
m_meshfailed = false;
_pbs = pbs;
_parent_scene = parent_scene;
m_targetSpace = (IntPtr)0;
if(sdata != null && sdata.Length > 1)
DeSerialize(sdata);
if (m_isphysical)
m_targetSpace = _parent_scene.space;
_triMeshData = IntPtr.Zero;
m_primName = primName;
m_taintserial = null;
m_taintadd = true;
_parent_scene.AddPhysicsActorTaint(this);
// don't do .add() here; old geoms get recycled with the same hash
}
public OdePrim(String primName, OdeScene parent_scene, Vector3 pos, Vector3 size,
Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool pisPhysical, CollisionLocker dode, uint localid)
{
@ -776,8 +374,9 @@ namespace OpenSim.Region.Physics.OdePlugin
}
_triMeshData = IntPtr.Zero;
m_NoColide = false;
m_taintserial = null;
// m_taintserial = null;
m_primName = primName;
m_taintadd = true;
_parent_scene.AddPhysicsActorTaint(this);
@ -814,7 +413,6 @@ namespace OpenSim.Region.Physics.OdePlugin
{
set
{
//Console.WriteLine("Sel {0} {1} {2}", m_primName, value, m_isphysical);
// This only makes the object not collidable if the object
// is physical or the object is modified somehow *IN THE FUTURE*
@ -1077,7 +675,6 @@ namespace OpenSim.Region.Physics.OdePlugin
}
}
public override bool FloatOnWater
{
set
@ -1270,7 +867,6 @@ namespace OpenSim.Region.Physics.OdePlugin
}
}
public void SetGeom(IntPtr geom)
{
if (prim_geom != IntPtr.Zero)
@ -1290,9 +886,25 @@ namespace OpenSim.Region.Physics.OdePlugin
{
_parent_scene.geom_name_map[prim_geom] = this.m_primName;
_parent_scene.actor_name_map[prim_geom] = (PhysicsActor)this;
//Console.WriteLine("**** Create {2} Dicts: actor={0} name={1}", _parent_scene.actor_name_map.Count, _parent_scene.geom_name_map.Count, this.m_primName);
if (m_NoColide)
{
d.GeomSetCategoryBits(prim_geom, 0);
if (m_isphysical)
{
d.GeomSetCollideBits(prim_geom, (int)CollisionCategories.Land);
}
else
{
d.GeomSetCollideBits(prim_geom, 0);
d.GeomDisable(prim_geom);
}
}
else
{
d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
//Console.WriteLine("**** Create {2} Dicts: actor={0} name={1}", _parent_scene.actor_name_map.Count, _parent_scene.geom_name_map.Count, this.m_primName);
}
}
if (childPrim)
@ -1351,11 +963,20 @@ namespace OpenSim.Region.Physics.OdePlugin
myrot.W = _orientation.W;
d.BodySetQuaternion(Body, ref myrot);
d.GeomSetBody(prim_geom, Body);
m_collisionCategories |= CollisionCategories.Body;
m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
if (m_NoColide)
{
d.GeomSetCategoryBits(prim_geom, 0);
d.GeomSetCollideBits(prim_geom, (int)CollisionCategories.Land);
}
else
{
d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
}
d.BodySetAutoDisableFlag(Body, true);
d.BodySetAutoDisableSteps(Body, body_autodisable_frames);
@ -1722,11 +1343,19 @@ namespace OpenSim.Region.Physics.OdePlugin
m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land);
if (prim_geom != IntPtr.Zero)
{
if (m_NoColide)
{
d.GeomSetCategoryBits(prim_geom, 0);
d.GeomSetCollideBits(prim_geom, 0);
d.GeomDisable(prim_geom);
}
else
{
d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
}
}
d.BodyDestroy(Body);
lock (childrenPrim)
@ -1735,6 +1364,13 @@ namespace OpenSim.Region.Physics.OdePlugin
{
foreach (OdePrim prm in childrenPrim)
{
if (prm.m_NoColide && prm.prim_geom != IntPtr.Zero)
{
d.GeomSetCategoryBits(prm.prim_geom, 0);
d.GeomSetCollideBits(prm.prim_geom, 0);
d.GeomDisable(prm.prim_geom);
}
_parent_scene.remActivePrim(prm);
prm.Body = IntPtr.Zero;
}
@ -1751,11 +1387,21 @@ namespace OpenSim.Region.Physics.OdePlugin
m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land);
if (prim_geom != IntPtr.Zero)
{
if (m_NoColide)
{
d.GeomSetCategoryBits(prim_geom, 0);
d.GeomSetCollideBits(prim_geom, 0);
d.GeomDisable(prim_geom);
}
else
{
d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
}
}
Body = IntPtr.Zero;
}
@ -1768,11 +1414,6 @@ namespace OpenSim.Region.Physics.OdePlugin
public bool setMesh(OdeScene parent_scene, IMesh mesh)
{
// This sleeper is there to moderate how long it takes between
// setting up the mesh and pre-processing it when we get rapid fire mesh requests on a single object
//Thread.Sleep(10);
//Kill Body so that mesh can re-make the geom
if (IsPhysical && Body != IntPtr.Zero)
{
@ -1790,14 +1431,6 @@ namespace OpenSim.Region.Physics.OdePlugin
}
}
// do it on caller instead
/*
if (_triMeshData != IntPtr.Zero)
{
d.GeomTriMeshDataDestroy(_triMeshData);
_triMeshData = IntPtr.Zero;
}
*/
IntPtr vertices, indices;
int vertexCount, indexCount;
int vertexStride, triStride;
@ -1809,38 +1442,20 @@ namespace OpenSim.Region.Physics.OdePlugin
if (vertexCount == 0 || indexCount == 0)
{
m_log.WarnFormat("[PHYSICS]: Got invalid mesh on prim {0} at <{1},{2},{3}>. It can be a sculp with alpha channel in map. Replacing it by a small box.", Name, _position.X, _position.Y, _position.Z);
_size.X = 0.05f;
_size.Y = 0.05f;
_size.Z = 0.05f;
m_log.WarnFormat("[PHYSICS]: Got invalid mesh on prim {0} at <{1},{2},{3}>. mesh UUID {4}", Name, _position.X, _position.Y, _position.Z, _pbs.SculptTexture.ToString());
return false;
}
/*
if (m_MeshToTriMeshMap.ContainsKey(mesh))
{
_triMeshData = m_MeshToTriMeshMap[mesh];
}
else
*/
{
_triMeshData = d.GeomTriMeshDataCreate();
d.GeomTriMeshDataBuildSimple(_triMeshData, vertices, vertexStride, vertexCount, indices, indexCount, triStride);
d.GeomTriMeshDataPreprocess(_triMeshData);
// m_MeshToTriMeshMap[mesh] = _triMeshData;
}
_parent_scene.waitForSpaceUnlock(m_targetSpace);
IntPtr geo = IntPtr.Zero;
try
{
// if (prim_geom == IntPtr.Zero) // setGeom takes care of phys engine recreate and prim_geom pointer
// {
// SetGeom(d.CreateTriMesh(m_targetSpace, _triMeshData, parent_scene.triCallback, null, null));
SetGeom(d.CreateTriMesh(m_targetSpace, _triMeshData, null, null, null));
// }
_triMeshData = d.GeomTriMeshDataCreate();
d.GeomTriMeshDataBuildSimple(_triMeshData, vertices, vertexStride, vertexCount, indices, indexCount, triStride);
d.GeomTriMeshDataPreprocess(_triMeshData);
_parent_scene.waitForSpaceUnlock(m_targetSpace);
geo = d.CreateTriMesh(m_targetSpace, _triMeshData, null, null, null);
}
catch (Exception e)
{
@ -1851,21 +1466,11 @@ namespace OpenSim.Region.Physics.OdePlugin
d.GeomTriMeshDataDestroy(_triMeshData);
_triMeshData = IntPtr.Zero;
}
_size.X = 0.05f;
_size.Y = 0.05f;
_size.Z = 0.05f;
return false;
}
SetGeom(geo);
// if (IsPhysical && Body == (IntPtr) 0)
// {
// Recreate the body
// m_interpenetrationcount = 0;
// m_collisionscore = 0;
// enableBody();
// }
return true;
}
@ -1943,18 +1548,21 @@ namespace OpenSim.Region.Physics.OdePlugin
if (m_taintvehicledata != null)
DoSetVehicle();
if (m_taintserial != null)
DoSerialize(m_taintserial);
/* obsolete
if (!m_angularLock.ApproxEquals(m_taintAngularLock,0f))
changeAngularLock(timestep);
*/
}
else
{
m_log.Error("[PHYSICS]: The scene reused a disposed PhysActor! *waves finger*, Don't be evil. A couple of things can cause this. An improper prim breakdown(be sure to set prim_geom to zero after d.GeomDestroy! An improper buildup (creating the geom failed). Or, the Scene Reused a physics actor after disposing it.)");
m_log.Error("[PHYSICS]: prim {0} at <{1},{2},{3}> as invalid geom");
// not sure this will not flame...
m_taintremove = true;
_parent_scene.AddPhysicsActorTaint(this);
}
}
/* obsolete
@ -2058,7 +1666,6 @@ namespace OpenSim.Region.Physics.OdePlugin
}
foreach (OdePrim prm in childrenPrim)
{
prm.m_collisionCategories |= CollisionCategories.Body;
prm.m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
@ -2067,9 +1674,17 @@ namespace OpenSim.Region.Physics.OdePlugin
m_log.Warn("[PHYSICS]: Unable to link one of the linkset elements. No geom yet");
continue;
}
if (prm.m_NoColide)
{
d.GeomSetCategoryBits(prm.prim_geom, 0);
d.GeomSetCollideBits(prm.prim_geom, (int)CollisionCategories.Land);
}
else
{
d.GeomSetCategoryBits(prm.prim_geom, (int)prm.m_collisionCategories);
d.GeomSetCollideBits(prm.prim_geom, (int)prm.m_collisionFlags);
}
d.Quaternion quat = new d.Quaternion();
quat.W = prm._orientation.W;
@ -2098,20 +1713,28 @@ namespace OpenSim.Region.Physics.OdePlugin
m_log.Debug("[PHYSICS]:I ain't got no boooooooooddy, no body");
}
prm.m_interpenetrationcount = 0;
prm.m_collisionscore = 0;
prm.m_disabled = false;
prm.Body = Body;
_parent_scene.addActivePrim(prm);
}
m_collisionCategories |= CollisionCategories.Body;
m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
if (m_NoColide)
{
d.GeomSetCategoryBits(prim_geom, 0);
d.GeomSetCollideBits(prim_geom, (int)CollisionCategories.Land);
}
else
{
d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
}
d.Quaternion quat2 = new d.Quaternion();
quat2.W = _orientation.W;
@ -2134,19 +1757,18 @@ namespace OpenSim.Region.Physics.OdePlugin
d.BodySetAutoDisableFlag(Body, true);
d.BodySetAutoDisableSteps(Body, body_autodisable_frames);
m_interpenetrationcount = 0;
m_collisionscore = 0;
m_disabled = false;
d.BodySetPosition(Body, Position.X, Position.Y, Position.Z);
if (m_type != Vehicle.TYPE_NONE) Enable(Body, _parent_scene);
_parent_scene.addActivePrim(this);
}
}
}
}
}
private void ChildSetGeom(OdePrim odePrim)
@ -2258,6 +1880,8 @@ namespace OpenSim.Region.Physics.OdePlugin
{
d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
if (m_NoColide)
d.GeomDisable(prim_geom);
}
if (m_isphysical)
@ -2276,7 +1900,6 @@ namespace OpenSim.Region.Physics.OdePlugin
else
{
m_collisionCategories = CollisionCategories.Geom;
if (m_isphysical)
m_collisionCategories |= CollisionCategories.Body;
@ -2288,10 +1911,24 @@ namespace OpenSim.Region.Physics.OdePlugin
m_collisionFlags |= CollisionCategories.Water;
if (prim_geom != IntPtr.Zero)
{
if (m_NoColide)
{
d.GeomSetCategoryBits(prim_geom, 0);
if (m_isphysical)
d.GeomSetCollideBits(prim_geom, (int)CollisionCategories.Land);
else
{
d.GeomSetCollideBits(prim_geom, 0);
d.GeomDisable(prim_geom);
}
}
else
{
d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
}
}
if (Body != IntPtr.Zero)
{
d.BodySetLinearVel(Body, 0f, 0f, 0f);
@ -2330,19 +1967,29 @@ namespace OpenSim.Region.Physics.OdePlugin
{
bool gottrimesh = false;
m_NoColide = false; // assume all will go well
if (_triMeshData != IntPtr.Zero)
{
d.GeomTriMeshDataDestroy(_triMeshData);
_triMeshData = IntPtr.Zero;
}
if (_mesh != null) // Special - make mesh
if (_mesh != null)
{
gottrimesh = setMesh(_parent_scene, _mesh);
if (!gottrimesh)
{
// getting a mesh failed,
// lets go on having a basic box or sphere, with prim size but not coliding
// physical colides with land, non with nothing
m_NoColide = true;
}
}
if (!gottrimesh) // not a mesh
{
if (!gottrimesh)
{ // we will have a basic box or sphere
IntPtr geo = IntPtr.Zero;
if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1
@ -2376,14 +2023,17 @@ namespace OpenSim.Region.Physics.OdePlugin
}
}
if (geo == IntPtr.Zero)
if (geo == IntPtr.Zero) // if this happens it must be fixed
{
// if it does lets stop what we can
// not sure this will not flame...
m_taintremove = true;
_parent_scene.AddPhysicsActorTaint(this);
return;
}
SetGeom(geo);
SetGeom(geo); // this processes the m_NoColide
}
}
@ -2415,7 +2065,6 @@ namespace OpenSim.Region.Physics.OdePlugin
}
}
lock (_parent_scene.OdeLock)
{
CreateGeom(m_targetSpace, _mesh);
@ -2518,8 +2167,6 @@ namespace OpenSim.Region.Physics.OdePlugin
m_taintposition = _position;
}
public void rotate(float timestep)
{
d.Quaternion myrot = new d.Quaternion();

View File

@ -1735,7 +1735,7 @@ namespace OpenSim.Region.Physics.OdePlugin
return newPrim;
}
/*
private PhysicsActor AddPrim(String name, Vector3 position, PhysicsActor parent,
PrimitiveBaseShape pbs, uint localid, byte[] sdata)
{
@ -1751,7 +1751,7 @@ namespace OpenSim.Region.Physics.OdePlugin
return newPrim;
}
*/
public void addActivePrim(OdePrim activatePrim)
{
@ -1778,7 +1778,7 @@ namespace OpenSim.Region.Physics.OdePlugin
return result;
}
/*
public override PhysicsActor AddPrimShape(string primName, PhysicsActor parent, PrimitiveBaseShape pbs, Vector3 position,
uint localid, byte[] sdata)
{
@ -1789,7 +1789,7 @@ namespace OpenSim.Region.Physics.OdePlugin
return result;
}
*/
public override float TimeDilation
{
get { return m_timeDilation; }

View File

@ -72,11 +72,13 @@ namespace OpenSim.Region.Physics.Manager
{
public float mu;
public float bounce;
public bool softcolide;
public ContactData(float _mu, float _bounce)
public ContactData(float _mu, float _bounce, bool _softcolide)
{
mu = _mu;
bounce = _bounce;
softcolide = _softcolide;
}
}
/// <summary>
@ -158,9 +160,10 @@ namespace OpenSim.Region.Physics.Manager
public virtual bool Building { get; set; }
public virtual ContactData ContactData
public virtual void getContactData(ref ContactData cdata)
{
get { return new ContactData(0, 0); }
cdata.mu = 0;
cdata.bounce = 0;
}
public abstract bool Stopped { get; }

View File

@ -136,7 +136,8 @@ namespace OpenSim.Region.Physics.OdePlugin
public UUID m_uuid;
public bool bad = false;
public ContactData AvatarContactData = new ContactData(10f, 0.3f);
float mu;
float bounce;
public OdeCharacter(String avName, OdeScene parent_scene, Vector3 pos, Vector3 size, float pid_d, float pid_p, float capsule_radius, float density, float walk_divisor, float rundivisor)
{
@ -168,8 +169,8 @@ namespace OpenSim.Region.Physics.OdePlugin
m_density = density;
m_mass = 80f; // sure we have a default
AvatarContactData.mu = parent_scene.AvatarFriction;
AvatarContactData.bounce = parent_scene.AvatarBounce;
mu = parent_scene.AvatarFriction;
bounce = parent_scene.AvatarBounce;
walkDivisor = walk_divisor;
runDivisor = rundivisor;
@ -190,9 +191,11 @@ namespace OpenSim.Region.Physics.OdePlugin
set { return; }
}
public override ContactData ContactData
public override void getContactData(ref ContactData cdata)
{
get { return AvatarContactData; }
cdata.mu = mu;
cdata.bounce = bounce;
cdata.softcolide = false;
}
public override bool Building { get; set; }

View File

@ -38,7 +38,7 @@
* settings use.
*/
// Ubit 2012
// Extensive change Ubit 2012
using System;
using System.Collections.Generic;
@ -119,7 +119,15 @@ namespace OpenSim.Region.Physics.OdePlugin
// auxiliar
private float m_lmEfect = 0; // current linear motor eficiency
private float m_amEfect = 0; // current angular motor eficiency
private float m_ffactor = 1.0f;
public float FrictionFactor
{
get
{
return m_ffactor;
}
}
public ODEDynamics(OdePrim rootp)
{
@ -127,7 +135,6 @@ namespace OpenSim.Region.Physics.OdePlugin
_pParentScene = rootPrim._parent_scene;
}
public void DoSetVehicle(VehicleData vd)
{
@ -152,6 +159,7 @@ namespace OpenSim.Region.Physics.OdePlugin
m_linearMotorTimescale = vd.m_linearMotorTimescale;
if (m_linearMotorTimescale < timestep) m_linearMotorTimescale = timestep;
m_linearMotorOffset = vd.m_linearMotorOffset;
//Angular properties
@ -201,6 +209,7 @@ namespace OpenSim.Region.Physics.OdePlugin
m_lmEfect = 0;
m_amEfect = 0;
m_ffactor = 1.0f;
}
internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue)
@ -318,6 +327,7 @@ namespace OpenSim.Region.Physics.OdePlugin
if (len > 30.0f)
m_linearMotorDirection *= (30.0f / len);
m_lmEfect = 1.0f; // turn it on
m_ffactor = 0.01f;
if (rootPrim.Body != IntPtr.Zero && !d.BodyIsEnabled(rootPrim.Body)
&& !rootPrim.m_isSelected && !rootPrim.m_disabled)
d.BodyEnable(rootPrim.Body);
@ -368,6 +378,7 @@ namespace OpenSim.Region.Physics.OdePlugin
if (len > 30.0f)
m_linearMotorDirection *= (30.0f / len);
m_lmEfect = 1.0f; // turn it on
m_ffactor = 0.01f;
if (rootPrim.Body != IntPtr.Zero && !d.BodyIsEnabled(rootPrim.Body)
&& !rootPrim.m_isSelected && !rootPrim.m_disabled)
d.BodyEnable(rootPrim.Body);
@ -414,6 +425,7 @@ namespace OpenSim.Region.Physics.OdePlugin
float invtimestep = _pParentScene.ODE_STEPSIZE;
m_lmEfect = 0;
m_amEfect = 0;
m_ffactor = 1f;
m_linearMotorDirection = Vector3.Zero;
m_angularMotorDirection = Vector3.Zero;
@ -591,6 +603,7 @@ namespace OpenSim.Region.Physics.OdePlugin
{
m_lmEfect = 0;
m_amEfect = 0;
m_ffactor = 1f;
}
public static Vector3 Xrot(Quaternion rot)
@ -614,6 +627,7 @@ namespace OpenSim.Region.Physics.OdePlugin
return vec;
}
private const float pi = (float)Math.PI;
private const float halfpi = 0.5f * (float)Math.PI;
public static Vector3 ubitRot2Euler(Quaternion rot)
@ -740,9 +754,14 @@ namespace OpenSim.Region.Physics.OdePlugin
force.Z += tmpV.Z;
}
m_lmEfect *= (1.0f - 1.0f / m_linearMotorDecayTimescale);
m_ffactor = 0.01f + 1e-4f * curVel.LengthSquared();
}
else
{
m_lmEfect = 0;
m_ffactor = 1f;
}
// friction
if (curLocalVel.X != 0 || curLocalVel.Y != 0 || curLocalVel.Z != 0)
@ -884,35 +903,64 @@ namespace OpenSim.Region.Physics.OdePlugin
float ftmp = 1.0f / m_verticalAttractionTimescale / m_verticalAttractionTimescale / _pParentScene.ODE_STEPSIZE;
float ftmp2 = m_verticalAttractionEfficiency / _pParentScene.ODE_STEPSIZE;
if (Math.Abs(roll) > 0.01) // roll
if (roll > halfpi)
roll = pi - roll;
else if (roll < -halfpi)
roll = -pi - roll;
float effroll = pitch / halfpi;
effroll *= effroll;
effroll = 1 - effroll;
effroll *= roll;
if (Math.Abs(effroll) > 0.01) // roll
{
torque.X -= -roll * ftmp + curLocalAngVel.X * ftmp2;
torque.X -= -effroll * ftmp + curLocalAngVel.X * ftmp2;
}
if (Math.Abs(pitch) > 0.01 && ((m_flags & VehicleFlag.LIMIT_ROLL_ONLY) == 0)) // pitch
if ((m_flags & VehicleFlag.LIMIT_ROLL_ONLY) == 0)
{
torque.Y -= -pitch * ftmp + curLocalAngVel.Y * ftmp2;
float effpitch = roll / halfpi;
effpitch *= effpitch;
effpitch = 1 - effpitch;
effpitch *= pitch;
if (Math.Abs(effpitch) > 0.01) // pitch
{
torque.Y -= -effpitch * ftmp + curLocalAngVel.Y * ftmp2;
}
}
if (m_bankingEfficiency != 0 && Math.Abs(roll) > 0.01)
if (m_bankingEfficiency != 0 && Math.Abs(effroll) > 0.01)
{
float broll = roll * m_bankingEfficiency; ;
float broll = effroll;
/*
if (broll > halfpi)
broll = pi - broll;
else if (broll < -halfpi)
broll = -pi - broll;
*/
broll *= m_bankingEfficiency;
if (m_bankingMix != 0)
{
float vfact = Math.Abs(curLocalVel.X) / 10.0f;
if (vfact > 1.0f) vfact = 1.0f;
if (curLocalVel.X >= 0)
broll *= ((1 - m_bankingMix) + vfact);
else
broll *= -((1 - m_bankingMix) + vfact);
}
broll = (broll - curLocalAngVel.Z) / m_bankingTimescale;
// torque.Z += broll;
if (curLocalVel.X >= 0)
broll *= (1 + (vfact - 1) * m_bankingMix);
else
broll *= -(1 + (vfact - 1) * m_bankingMix);
}
// make z rot be in world Z not local as seems to be in sl
tmpV.X = 0;
tmpV.Y = 0;
tmpV.Z = broll;
broll = broll / m_bankingTimescale;
ftmp = -Math.Abs(m_bankingEfficiency) / m_bankingTimescale;
tmpV.X = ftmp * curAngVel.X;
tmpV.Y = ftmp * curAngVel.Y;
tmpV.Z = broll + ftmp * curAngVel.Z;
tmpV *= irotq;
torque.X += tmpV.X;

View File

@ -114,6 +114,9 @@ namespace OpenSim.Region.Physics.OdePlugin
// private bool m_collidesLand = true;
private bool m_collidesWater;
public bool m_returnCollisions;
private bool m_softcolide;
private bool m_NoColide; // for now only for internal use for bad meshs
// Default we're a Geometry
private CollisionCategories m_collisionCategories = (CollisionCategories.Geom);
@ -155,6 +158,8 @@ namespace OpenSim.Region.Physics.OdePlugin
public float m_collisionscore;
int m_colliderfilter = 0;
public IntPtr collide_geom; // for objects: geom if single prim space it linkset
private float m_density = 10.000006836f; // Aluminum g/cm3;
public bool _zeroFlag;
@ -185,7 +190,8 @@ namespace OpenSim.Region.Physics.OdePlugin
public ODEDynamics m_vehicle;
internal int m_material = (int)Material.Wood;
protected ContactData primContactData = new ContactData { mu = 0f, bounce = 0.1f };
private float mu;
private float bounce;
/// <summary>
/// Is this prim subject to physics? Even if not, it's still solid for collision purposes.
@ -216,11 +222,24 @@ namespace OpenSim.Region.Physics.OdePlugin
}
}
public override ContactData ContactData
public override void getContactData(ref ContactData cdata)
{
get
cdata.mu = mu;
cdata.bounce = bounce;
// cdata.softcolide = m_softcolide;
cdata.softcolide = false;
if (m_isphysical)
{
return primContactData;
ODEDynamics veh;
if (_parent != null)
veh = ((OdePrim)_parent).m_vehicle;
else
veh = m_vehicle;
if (veh != null && veh.Type != Vehicle.TYPE_NONE)
cdata.mu *= veh.FrictionFactor;
}
}
@ -290,7 +309,10 @@ namespace OpenSim.Region.Physics.OdePlugin
}
if (m_colliderfilter == 0)
{
m_softcolide = false;
m_iscolliding = false;
}
else
m_iscolliding = true;
}
@ -453,8 +475,6 @@ namespace OpenSim.Region.Physics.OdePlugin
{
get
{
// Averate previous velocity with the new one so
// client object interpolation works a 'little' better
if (_zeroFlag)
return Vector3.Zero;
return _velocity;
@ -733,8 +753,8 @@ namespace OpenSim.Region.Physics.OdePlugin
public override void SetMaterial(int pMaterial)
{
m_material = pMaterial;
primContactData.mu = _parent_scene.m_materialContactsData[pMaterial].mu;
primContactData.bounce = _parent_scene.m_materialContactsData[pMaterial].bounce;
mu = _parent_scene.m_materialContactsData[pMaterial].mu;
bounce = _parent_scene.m_materialContactsData[pMaterial].bounce;
}
public void setPrimForRemoval()
@ -833,6 +853,7 @@ namespace OpenSim.Region.Physics.OdePlugin
body_autodisable_frames = parent_scene.bodyFramesAutoDisable;
prim_geom = IntPtr.Zero;
collide_geom = IntPtr.Zero;
Body = IntPtr.Zero;
if (!size.IsFinite())
@ -847,7 +868,6 @@ namespace OpenSim.Region.Physics.OdePlugin
_size = size;
if (!QuaternionIsFinite(rotation))
{
rotation = Quaternion.Identity;
@ -878,6 +898,8 @@ namespace OpenSim.Region.Physics.OdePlugin
m_iscolliding = false;
m_colliderfilter = 0;
m_softcolide = true;
m_NoColide = false;
hasOOBoffsetFromMesh = false;
_triMeshData = IntPtr.Zero;
@ -886,8 +908,8 @@ namespace OpenSim.Region.Physics.OdePlugin
m_isSelected = false;
m_delaySelect = false;
primContactData.mu = parent_scene.m_materialContactsData[(int)Material.Wood].mu;
primContactData.bounce = parent_scene.m_materialContactsData[(int)Material.Wood].bounce;
mu = parent_scene.m_materialContactsData[(int)Material.Wood].mu;
bounce = parent_scene.m_materialContactsData[(int)Material.Wood].bounce;
CalcPrimBodyData();
@ -1025,34 +1047,42 @@ namespace OpenSim.Region.Physics.OdePlugin
if (vertexCount == 0 || indexCount == 0)
{
m_log.WarnFormat("[PHYSICS]: Got invalid mesh on prim {0} at <{1},{2},{3}>. It can be a sculp with alpha channel in map. Replacing it by a small box.", Name, _position.X, _position.Y, _position.Z);
_size.X = 0.01f;
_size.Y = 0.01f;
_size.Z = 0.01f;
m_log.WarnFormat("[PHYSICS]: Got invalid mesh on prim {0} at <{1},{2},{3}>. mesh UUID {4}",
Name, _position.X, _position.Y, _position.Z, _pbs.SculptTexture.ToString());
mesh.releaseSourceMeshData();
return false;
}
primOOBoffset = mesh.GetCentroid();
hasOOBoffsetFromMesh = true;
mesh.releaseSourceMeshData();
IntPtr geo = IntPtr.Zero;
try
{
_triMeshData = d.GeomTriMeshDataCreate();
d.GeomTriMeshDataBuildSimple(_triMeshData, vertices, vertexStride, vertexCount, indices, indexCount, triStride);
d.GeomTriMeshDataPreprocess(_triMeshData);
mesh.releaseSourceMeshData();
_parent_scene.waitForSpaceUnlock(m_targetSpace);
try
{
SetGeom(d.CreateTriMesh(m_targetSpace, _triMeshData, null, null, null));
geo = d.CreateTriMesh(m_targetSpace, _triMeshData, null, null, null);
}
catch (Exception e)
{
m_log.ErrorFormat("[PHYSICS]: SetGeom Mesh failed for {0} exception: {1}", Name, e);
if (_triMeshData != IntPtr.Zero)
{
d.GeomTriMeshDataDestroy(_triMeshData);
_triMeshData = IntPtr.Zero;
}
return false;
}
SetGeom(geo);
return true;
}
@ -1061,26 +1091,31 @@ namespace OpenSim.Region.Physics.OdePlugin
prim_geom = geom;
//Console.WriteLine("SetGeom to " + prim_geom + " for " + Name);
if (prim_geom != IntPtr.Zero)
{
if (m_NoColide)
{
d.GeomSetCategoryBits(prim_geom, 0);
if (m_isphysical)
{
d.GeomSetCollideBits(prim_geom, (int)CollisionCategories.Land);
}
else
{
d.GeomSetCollideBits(prim_geom, 0);
d.GeomDisable(prim_geom);
}
}
else
{
d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
}
CalcPrimBodyData();
_parent_scene.geom_name_map[prim_geom] = Name;
_parent_scene.actor_name_map[prim_geom] = this;
/*
if (childPrim)
{
if (_parent != null && _parent is OdePrim)
{
OdePrim parent = (OdePrim)_parent;
//Console.WriteLine("SetGeom calls ChildSetGeom");
parent.ChildSetGeom(this);
}
}
*/
}
else
m_log.Warn("Setting bad Geom");
@ -1102,10 +1137,13 @@ namespace OpenSim.Region.Physics.OdePlugin
bool haveMesh = false;
hasOOBoffsetFromMesh = false;
m_NoColide = false;
if (_parent_scene.needsMeshing(_pbs))
{
haveMesh = setMesh(_parent_scene); // this will give a mesh to non trivial known prims
if (!haveMesh)
m_NoColide = true;
}
if (!haveMesh)
@ -1197,12 +1235,46 @@ namespace OpenSim.Region.Physics.OdePlugin
{
if (!childPrim && !m_isSelected)
{
if (m_isphysical && Body != IntPtr.Zero && prim_geom != IntPtr.Zero)
if (m_isphysical && Body != IntPtr.Zero)
{
d.GeomEnable(prim_geom);
foreach (OdePrim prm in childrenPrim)
d.GeomEnable(prm.prim_geom);
m_collisionCategories |= CollisionCategories.Body;
m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
foreach (OdePrim prm in childrenPrim)
{
prm.m_collisionCategories = m_collisionCategories;
prm.m_collisionFlags = m_collisionFlags;
if (prm.prim_geom != IntPtr.Zero)
{
if (prm.m_NoColide)
{
d.GeomSetCategoryBits(prm.prim_geom, 0);
d.GeomSetCollideBits(prm.prim_geom, (int)CollisionCategories.Land);
}
else
{
d.GeomSetCategoryBits(prm.prim_geom, (int)m_collisionCategories);
d.GeomSetCollideBits(prm.prim_geom, (int)m_collisionFlags);
}
d.GeomEnable(prm.prim_geom);
}
}
if (prim_geom != IntPtr.Zero)
{
if (m_NoColide)
{
d.GeomSetCategoryBits(prim_geom, 0);
d.GeomSetCollideBits(prim_geom, (int)CollisionCategories.Land);
}
else
{
d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
}
d.GeomEnable(prim_geom);
}
d.BodyEnable(Body);
}
}
@ -1215,11 +1287,47 @@ namespace OpenSim.Region.Physics.OdePlugin
m_disabled = true;
if (!childPrim)
{
if (m_isphysical && Body != IntPtr.Zero && prim_geom != IntPtr.Zero)
if (m_isphysical && Body != IntPtr.Zero)
{
d.GeomDisable(prim_geom);
m_collisionCategories &= ~CollisionCategories.Body;
m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land);
foreach (OdePrim prm in childrenPrim)
{
prm.m_collisionCategories = m_collisionCategories;
prm.m_collisionFlags = m_collisionFlags;
if (prm.prim_geom != IntPtr.Zero)
{
if (prm.m_NoColide)
{
d.GeomSetCategoryBits(prm.prim_geom, 0);
d.GeomSetCollideBits(prm.prim_geom, 0);
}
else
{
d.GeomSetCategoryBits(prm.prim_geom, (int)m_collisionCategories);
d.GeomSetCollideBits(prm.prim_geom, (int)m_collisionFlags);
}
d.GeomDisable(prm.prim_geom);
}
}
if (prim_geom != IntPtr.Zero)
{
if (m_NoColide)
{
d.GeomSetCategoryBits(prim_geom, 0);
d.GeomSetCollideBits(prim_geom, 0);
}
else
{
d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
}
d.GeomDisable(prim_geom);
}
d.BodyDisable(Body);
}
}
@ -1298,8 +1406,6 @@ namespace OpenSim.Region.Physics.OdePlugin
continue;
}
DMassCopy(ref prm.primdMass, ref tmpdmass);
// apply prim current rotation to inertia
@ -1361,14 +1467,7 @@ namespace OpenSim.Region.Physics.OdePlugin
// d.BodySetAngularDampingThreshold(Body, 0.001f);
d.BodySetDamping(Body, .002f, .002f);
m_collisionCategories |= CollisionCategories.Body;
m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
m_collisionscore = 0;
if (m_targetSpace != _parent_scene.ActiveSpace)
{
if (m_targetSpace != IntPtr.Zero)
{
_parent_scene.waitForSpaceUnlock(m_targetSpace);
@ -1376,9 +1475,22 @@ namespace OpenSim.Region.Physics.OdePlugin
d.SpaceRemove(m_targetSpace, prim_geom);
}
if (childrenPrim.Count == 0)
{
collide_geom = prim_geom;
m_targetSpace = _parent_scene.ActiveSpace;
d.SpaceAdd(m_targetSpace, prim_geom);
}
else
{
m_targetSpace = d.HashSpaceCreate(_parent_scene.ActiveSpace);
d.HashSpaceSetLevels(m_targetSpace, -2, 8);
d.SpaceSetSublevel(m_targetSpace, 3);
d.SpaceSetCleanup(m_targetSpace, false);
d.SpaceAdd(m_targetSpace, prim_geom);
collide_geom = m_targetSpace;
}
lock (childrenPrim)
{
@ -1390,28 +1502,45 @@ namespace OpenSim.Region.Physics.OdePlugin
Vector3 ppos = prm._position;
d.GeomSetOffsetWorldPosition(prm.prim_geom, ppos.X, ppos.Y, ppos.Z); // set relative position
prm.m_collisionCategories |= CollisionCategories.Body;
prm.m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
d.GeomSetCategoryBits(prm.prim_geom, (int)prm.m_collisionCategories);
d.GeomSetCollideBits(prm.prim_geom, (int)prm.m_collisionFlags);
prm.m_collisionscore = 0;
if (prm.m_targetSpace != _parent_scene.ActiveSpace)
if (prm.m_targetSpace != m_targetSpace)
{
if (prm.m_targetSpace != IntPtr.Zero)
{
_parent_scene.waitForSpaceUnlock(m_targetSpace);
_parent_scene.waitForSpaceUnlock(prm.m_targetSpace);
if (d.SpaceQuery(prm.m_targetSpace, prm.prim_geom))
d.SpaceRemove(prm.m_targetSpace, prm.prim_geom);
}
prm.m_targetSpace = _parent_scene.ActiveSpace;
prm.m_targetSpace = m_targetSpace;
d.SpaceAdd(m_targetSpace, prm.prim_geom);
}
if (m_isSelected || m_disabled)
{
prm.m_collisionCategories &= ~CollisionCategories.Body;
prm.m_collisionFlags &= ~(CollisionCategories.Land | CollisionCategories.Wind);
d.GeomDisable(prm.prim_geom);
}
else
{
prm.m_collisionCategories |= CollisionCategories.Body;
prm.m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
}
if (prm.m_NoColide)
{
d.GeomSetCategoryBits(prm.prim_geom, 0);
d.GeomSetCollideBits(prm.prim_geom, (int)CollisionCategories.Land);
}
else
{
d.GeomSetCategoryBits(prm.prim_geom, (int)m_collisionCategories);
d.GeomSetCollideBits(prm.prim_geom, (int)m_collisionFlags);
}
prm.m_collisionscore = 0;
if(!m_disabled)
prm.m_disabled = false;
_parent_scene.addActivePrim(prm);
}
}
@ -1424,11 +1553,37 @@ namespace OpenSim.Region.Physics.OdePlugin
if (m_isSelected || m_disabled)
{
m_collisionCategories &= ~CollisionCategories.Body;
m_collisionFlags &= ~(CollisionCategories.Land | CollisionCategories.Wind);
d.GeomDisable(prim_geom);
d.BodyDisable(Body);
}
else
{
m_collisionCategories |= CollisionCategories.Body;
m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
d.BodySetAngularVel(Body, m_rotationalVelocity.X, m_rotationalVelocity.Y, m_rotationalVelocity.Z);
d.BodySetLinearVel(Body, _velocity.X, _velocity.Y, _velocity.Z);
}
if (m_NoColide)
{
d.GeomSetCategoryBits(prim_geom, 0);
d.GeomSetCollideBits(prim_geom, (int)CollisionCategories.Land);
}
else
{
d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
}
m_collisionscore = 0;
m_softcolide = true;
_parent_scene.addActivePrim(this);
_parent_scene.addActiveGroups(this);
}
private void DestroyBody()
@ -1439,9 +1594,17 @@ namespace OpenSim.Region.Physics.OdePlugin
m_collisionCategories &= ~CollisionCategories.Body;
m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land);
if (prim_geom != IntPtr.Zero)
{
if (m_NoColide)
{
d.GeomSetCategoryBits(prim_geom, 0);
d.GeomSetCollideBits(prim_geom, 0);
}
else
{
d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
}
UpdateDataFromGeom();
d.GeomSetBody(prim_geom, IntPtr.Zero);
SetInStaticSpace(this);
@ -1454,12 +1617,20 @@ namespace OpenSim.Region.Physics.OdePlugin
foreach (OdePrim prm in childrenPrim)
{
_parent_scene.remActivePrim(prm);
prm.m_collisionCategories &= ~CollisionCategories.Body;
prm.m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land);
prm.m_collisionCategories = m_collisionCategories;
prm.m_collisionFlags = m_collisionFlags;
if (prm.prim_geom != IntPtr.Zero)
{
if (prm.m_NoColide)
{
d.GeomSetCategoryBits(prm.prim_geom, 0);
d.GeomSetCollideBits(prm.prim_geom, 0);
}
else
{
d.GeomSetCategoryBits(prm.prim_geom, (int)m_collisionCategories);
d.GeomSetCollideBits(prm.prim_geom, (int)m_collisionFlags);
}
prm.UpdateDataFromGeom();
SetInStaticSpace(prm);
}
@ -1473,6 +1644,7 @@ namespace OpenSim.Region.Physics.OdePlugin
d.JointDestroy(Amotor);
Amotor = IntPtr.Zero;
}
_parent_scene.remActiveGroup(this);
d.BodyDestroy(Body);
}
Body = IntPtr.Zero;
@ -2008,23 +2180,14 @@ namespace OpenSim.Region.Physics.OdePlugin
myrot.Z = _orientation.Z;
myrot.W = _orientation.W;
d.GeomSetQuaternion(prim_geom, ref myrot);
// _parent_scene.actor_name_map[prim_geom] = (PhysicsActor)this;
if (!m_isphysical)
SetInStaticSpace(this);
}
if (m_isphysical && Body == IntPtr.Zero)
{
/*
if (_pbs.SculptEntry && _parent_scene.meshSculptedPrim)
{
changeShape(_pbs);
}
else
{
*/
MakeBody();
// }
}
}
@ -2133,17 +2296,52 @@ namespace OpenSim.Region.Physics.OdePlugin
if (!childPrim && Body != IntPtr.Zero)
d.BodyDisable(Body);
if (m_delaySelect)
if (m_delaySelect || m_isphysical)
{
m_collisionCategories = CollisionCategories.Selected;
m_collisionFlags = (CollisionCategories.Sensor | CollisionCategories.Space);
if (!childPrim)
{
foreach (OdePrim prm in childrenPrim)
{
prm.m_collisionCategories = m_collisionCategories;
prm.m_collisionFlags = m_collisionFlags;
if (prm.prim_geom != null)
{
if (prm.m_NoColide)
{
d.GeomSetCategoryBits(prm.prim_geom, 0);
d.GeomSetCollideBits(prm.prim_geom, 0);
}
else
{
d.GeomSetCategoryBits(prm.prim_geom, (int)m_collisionCategories);
d.GeomSetCollideBits(prm.prim_geom, (int)m_collisionFlags);
}
d.GeomDisable(prm.prim_geom);
}
prm.m_delaySelect = false;
}
}
if (prim_geom != null)
{
if (m_NoColide)
{
d.GeomSetCategoryBits(prim_geom, 0);
d.GeomSetCollideBits(prim_geom, 0);
}
else
{
d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
}
d.GeomDisable(prim_geom);
}
m_delaySelect = false;
}
else
@ -2156,19 +2354,64 @@ namespace OpenSim.Region.Physics.OdePlugin
if (!childPrim && Body != IntPtr.Zero && !m_disabled)
d.BodyEnable(Body);
m_collisionCategories = CollisionCategories.Geom;
if (m_isphysical)
m_collisionCategories |= CollisionCategories.Body;
m_collisionFlags = m_default_collisionFlags | CollisionCategories.Land;
if (m_collidesWater)
m_collisionFlags |= CollisionCategories.Water;
if (!childPrim)
{
foreach (OdePrim prm in childrenPrim)
{
if(!prm.m_disabled)
prm.m_collisionCategories = m_collisionCategories;
prm.m_collisionFlags = m_collisionFlags;
if (!prm.m_disabled && prm.prim_geom != IntPtr.Zero)
{
if (prm.m_NoColide)
{
d.GeomSetCategoryBits(prm.prim_geom, 0);
if (m_isphysical)
d.GeomSetCollideBits(prm.prim_geom, (int)CollisionCategories.Land);
else
d.GeomSetCollideBits(prm.prim_geom, 0);
}
else
{
d.GeomSetCategoryBits(prm.prim_geom, (int)m_collisionCategories);
d.GeomSetCollideBits(prm.prim_geom, (int)m_collisionFlags);
}
d.GeomEnable(prm.prim_geom);
}
prm.m_delaySelect = false;
prm.m_softcolide = true;
}
}
if(!m_disabled)
if (!m_disabled && prim_geom != IntPtr.Zero)
{
if (m_NoColide)
{
d.GeomSetCategoryBits(prim_geom, 0);
if (m_isphysical)
d.GeomSetCollideBits(prim_geom, (int)CollisionCategories.Land);
else
d.GeomSetCollideBits(prim_geom, 0);
}
else
{
d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
}
d.GeomEnable(prim_geom);
}
m_delaySelect = false;
m_softcolide = true;
}
resetCollisionAccounting();
@ -2214,6 +2457,7 @@ namespace OpenSim.Region.Physics.OdePlugin
if (givefakepos < 0)
givefakepos = 0;
// changeSelectedStatus();
m_softcolide = true;
resetCollisionAccounting();
}
@ -2266,6 +2510,7 @@ namespace OpenSim.Region.Physics.OdePlugin
givefakeori--;
if (givefakeori < 0)
givefakeori = 0;
m_softcolide = true;
resetCollisionAccounting();
}
@ -2336,6 +2581,7 @@ namespace OpenSim.Region.Physics.OdePlugin
if (givefakeori < 0)
givefakeori = 0;
m_softcolide = true;
resetCollisionAccounting();
}
@ -2390,8 +2636,8 @@ namespace OpenSim.Region.Physics.OdePlugin
else
*/
DestroyBody();
Stop();
}
Stop();
}
}
@ -2452,6 +2698,7 @@ namespace OpenSim.Region.Physics.OdePlugin
else
MakeBody();
m_softcolide = true;
resetCollisionAccounting();
}
@ -2576,6 +2823,7 @@ namespace OpenSim.Region.Physics.OdePlugin
if ((bool)newbuilding)
{
m_building = true;
if (!childPrim)
DestroyBody();
}
else
@ -2648,12 +2896,95 @@ namespace OpenSim.Region.Physics.OdePlugin
public void Move()
{
if (!childPrim && m_isphysical && Body != IntPtr.Zero &&
!m_disabled && !m_isSelected && d.BodyIsEnabled(Body) && !m_building) // KF: Only move root prims.
!m_disabled && !m_isSelected && d.BodyIsEnabled(Body) && !m_building && !m_outbounds)
// !m_disabled && !m_isSelected && !m_building && !m_outbounds)
{
// if (!d.BodyIsEnabled(Body)) d.BodyEnable(Body); // KF add 161009
float timestep = _parent_scene.ODE_STEPSIZE;
// check outside region
d.Vector3 lpos;
d.GeomCopyPosition(prim_geom, out lpos); // root position that is seem by rest of simulator
if (lpos.Z < -100 || lpos.Z > 100000f)
{
m_outbounds = true;
lpos.Z = Util.Clip(lpos.Z, -100f, 100000f);
_acceleration.X = 0;
_acceleration.Y = 0;
_acceleration.Z = 0;
_velocity.X = 0;
_velocity.Y = 0;
_velocity.Z = 0;
m_rotationalVelocity.X = 0;
m_rotationalVelocity.Y = 0;
m_rotationalVelocity.Z = 0;
d.BodySetLinearVel(Body, 0, 0, 0); // stop it
d.BodySetAngularVel(Body, 0, 0, 0); // stop it
d.BodySetPosition(Body, lpos.X, lpos.Y, lpos.Z); // put it somewhere
m_lastposition = _position;
m_lastorientation = _orientation;
base.RequestPhysicsterseUpdate();
m_throttleUpdates = false;
throttleCounter = 0;
_zeroFlag = true;
disableBodySoft(); // disable it and colisions
base.RaiseOutOfBounds(_position);
return;
}
if (lpos.X < 0f)
{
_position.X = Util.Clip(lpos.X, -2f, -0.1f);
m_outbounds = true;
}
else if(lpos.X > _parent_scene.WorldExtents.X)
{
_position.X = Util.Clip(lpos.X, _parent_scene.WorldExtents.X + 0.1f, _parent_scene.WorldExtents.X + 2f);
m_outbounds = true;
}
if (lpos.Y < 0f)
{
_position.Y = Util.Clip(lpos.Y, -2f, -0.1f);
m_outbounds = true;
}
else if(lpos.Y > _parent_scene.WorldExtents.Y)
{
_position.Y = Util.Clip(lpos.Y, _parent_scene.WorldExtents.Y + 0.1f, _parent_scene.WorldExtents.Y + 2f);
m_outbounds = true;
}
if(m_outbounds)
{
m_lastposition = _position;
m_lastorientation = _orientation;
d.Vector3 dtmp = d.BodyGetAngularVel(Body);
m_rotationalVelocity.X = dtmp.X;
m_rotationalVelocity.Y = dtmp.Y;
m_rotationalVelocity.Z = dtmp.Z;
dtmp = d.BodyGetLinearVel(Body);
_velocity.X = dtmp.X;
_velocity.Y = dtmp.Y;
_velocity.Z = dtmp.Z;
d.BodySetLinearVel(Body, 0, 0, 0); // stop it
d.BodySetAngularVel(Body, 0, 0, 0);
d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
disableBodySoft(); // stop collisions
base.RequestPhysicsterseUpdate();
return;
}
float fx = 0;
float fy = 0;
float fz = 0;
@ -2862,7 +3193,7 @@ namespace OpenSim.Region.Physics.OdePlugin
public void UpdatePositionAndVelocity(float simulatedtime)
{
// no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
if (_parent == null && !m_disabled && !m_building)
if (_parent == null && !m_disabled && !m_building && !m_outbounds)
{
if (Body != IntPtr.Zero)
{
@ -2872,64 +3203,6 @@ namespace OpenSim.Region.Physics.OdePlugin
d.Vector3 lpos;
d.GeomCopyPosition(prim_geom, out lpos); // root position that is seem by rest of simulator
// we need to use root position since that's all the rest of scene uses
if (lpos.X < 0f || lpos.X > _parent_scene.WorldExtents.X
|| lpos.Y < 0f || lpos.Y > _parent_scene.WorldExtents.Y
)
{
// we are outside current region
// we can't let it keeping moving and having colisions
// since it can be stucked between something like terrain and edge
// so lets stop and disable it until something else kicks it
_position.X = Util.Clip(lpos.X, -0.2f, _parent_scene.WorldExtents.X + 0.2f);
_position.Y = Util.Clip(lpos.Y, -0.2f, _parent_scene.WorldExtents.Y + 0.2f);
_position.Z = Util.Clip(lpos.Z, -100f, 50000f);
m_lastposition = _position;
// m_lastorientation = _orientation;
d.BodySetLinearVel(Body, 0, 0, 0); // stop it
// d.BodySetAngularVel(Body, 0, 0, 0);
d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
disableBodySoft(); // stop collisions
m_outbounds = true;
base.RequestPhysicsterseUpdate();
return;
}
if (lpos.Z < -100 || lpos.Z > 100000f)
{
lpos.Z = Util.Clip(lpos.Z, -100f, 50000f);
_acceleration.X = 0;
_acceleration.Y = 0;
_acceleration.Z = 0;
_velocity.X = 0;
_velocity.Y = 0;
_velocity.Z = 0;
m_rotationalVelocity.X = 0;
m_rotationalVelocity.Y = 0;
m_rotationalVelocity.Z = 0;
d.BodySetLinearVel(Body, 0, 0, 0); // stop it
d.BodySetAngularVel(Body, 0, 0, 0); // stop it
d.BodySetPosition(Body, lpos.X, lpos.Y, lpos.Z); // put it somewhere
m_lastposition = _position;
m_lastorientation = _orientation;
base.RequestPhysicsterseUpdate();
m_throttleUpdates = false;
throttleCounter = 0;
_zeroFlag = true;
disableBodySoft(); // disable it and colisions
base.RaiseOutOfBounds(_position);
return;
}
d.Quaternion ori;
d.GeomCopyQuaternion(prim_geom, out ori);

View File

@ -155,7 +155,7 @@ namespace OpenSim.Region.Physics.OdePlugin
private readonly ILog m_log;
// private Dictionary<string, sCollisionData> m_storedCollisions = new Dictionary<string, sCollisionData>();
private int threadid = 0;
// private int threadid = 0;
private Random fluidRandomizer = new Random(Environment.TickCount);
const d.ContactFlags comumContactFlags = d.ContactFlags.SoftERP | d.ContactFlags.SoftCFM |d.ContactFlags.Approx1 | d.ContactFlags.Bounce;
@ -163,12 +163,10 @@ namespace OpenSim.Region.Physics.OdePlugin
const float comumSoftContactERP = 0.1f;
const float comumContactCFM = 0.0001f;
float frictionScale = 1.0f;
float frictionMovementMult = 0.3f;
float TerrainBounce = 0.1f;
float TerrainFriction = 0.1f;
float TerrainFriction = 0.3f;
public float AvatarBounce = 0.3f;
public float AvatarFriction = 0;// 0.9f * 0.5f;
@ -189,8 +187,8 @@ namespace OpenSim.Region.Physics.OdePlugin
internal IntPtr WaterGeom;
public float avPIDD = 3200f; // make it visible
public float avPIDP = 1400f; // make it visible
public float avPIDD = 2200f; // make it visible
public float avPIDP = 900f; // make it visible
private float avCapRadius = 0.37f;
private float avDensity = 3f;
private float avMovementDivisorWalk = 1.3f;
@ -202,7 +200,7 @@ namespace OpenSim.Region.Physics.OdePlugin
public bool forceSimplePrimMeshing = false;
public float meshSculptLOD = 32;
public float MeshSculptphysicalLOD = 16;
public float MeshSculptphysicalLOD = 32;
public float geomDefaultDensity = 10.000006836f;
@ -212,18 +210,18 @@ namespace OpenSim.Region.Physics.OdePlugin
public float bodyPIDD = 35f;
public float bodyPIDG = 25;
public int geomCrossingFailuresBeforeOutofbounds = 6;
// public int geomCrossingFailuresBeforeOutofbounds = 6;
public int bodyFramesAutoDisable = 20;
private float[] _watermap;
private bool m_filterCollisions = true;
private d.NearCallback nearCallback;
private readonly HashSet<OdeCharacter> _characters = new HashSet<OdeCharacter>();
private readonly HashSet<OdePrim> _prims = new HashSet<OdePrim>();
private readonly HashSet<OdePrim> _activeprims = new HashSet<OdePrim>();
private readonly HashSet<OdePrim> _activegroups = new HashSet<OdePrim>();
public OpenSim.Framework.LocklessQueue<ODEchangeitem> ChangesQueue = new OpenSim.Framework.LocklessQueue<ODEchangeitem>();
@ -387,9 +385,6 @@ namespace OpenSim.Region.Physics.OdePlugin
// Defaults
avPIDD = 2200.0f;
avPIDP = 900.0f;
int contactsPerCollision = 80;
if (m_config != null)
@ -397,90 +392,86 @@ namespace OpenSim.Region.Physics.OdePlugin
IConfig physicsconfig = m_config.Configs["ODEPhysicsSettings"];
if (physicsconfig != null)
{
gravityx = physicsconfig.GetFloat("world_gravityx", 0f);
gravityy = physicsconfig.GetFloat("world_gravityy", 0f);
gravityz = physicsconfig.GetFloat("world_gravityz", -9.8f);
gravityx = physicsconfig.GetFloat("world_gravityx", gravityx);
gravityy = physicsconfig.GetFloat("world_gravityy", gravityy);
gravityz = physicsconfig.GetFloat("world_gravityz", gravityz);
metersInSpace = physicsconfig.GetFloat("meters_in_small_space", 29.9f);
metersInSpace = physicsconfig.GetFloat("meters_in_small_space", metersInSpace);
contactsurfacelayer = physicsconfig.GetFloat("world_contact_surface_layer", contactsurfacelayer);
ODE_STEPSIZE = physicsconfig.GetFloat("world_stepsize", 0.020f);
m_physicsiterations = physicsconfig.GetInt("world_internal_steps_without_collisions", 10);
ODE_STEPSIZE = physicsconfig.GetFloat("world_stepsize", ODE_STEPSIZE);
m_physicsiterations = physicsconfig.GetInt("world_internal_steps_without_collisions", m_physicsiterations);
avDensity = physicsconfig.GetFloat("av_density", avDensity);
avMovementDivisorWalk = physicsconfig.GetFloat("av_movement_divisor_walk", 1.3f);
avMovementDivisorRun = physicsconfig.GetFloat("av_movement_divisor_run", 0.8f);
avCapRadius = physicsconfig.GetFloat("av_capsule_radius", 0.37f);
avMovementDivisorWalk = physicsconfig.GetFloat("av_movement_divisor_walk", avMovementDivisorWalk);
avMovementDivisorRun = physicsconfig.GetFloat("av_movement_divisor_run", avMovementDivisorRun);
avCapRadius = physicsconfig.GetFloat("av_capsule_radius", avCapRadius);
contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", 80);
contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", contactsPerCollision);
geomContactPointsStartthrottle = physicsconfig.GetInt("geom_contactpoints_start_throttling", 3);
geomUpdatesPerThrottledUpdate = physicsconfig.GetInt("geom_updates_before_throttled_update", 15);
geomCrossingFailuresBeforeOutofbounds = physicsconfig.GetInt("geom_crossing_failures_before_outofbounds", 5);
// geomCrossingFailuresBeforeOutofbounds = physicsconfig.GetInt("geom_crossing_failures_before_outofbounds", 5);
geomDefaultDensity = physicsconfig.GetFloat("geometry_default_density", 10.000006836f);
bodyFramesAutoDisable = physicsconfig.GetInt("body_frames_auto_disable", 20);
geomDefaultDensity = physicsconfig.GetFloat("geometry_default_density", geomDefaultDensity);
bodyFramesAutoDisable = physicsconfig.GetInt("body_frames_auto_disable", bodyFramesAutoDisable);
bodyPIDD = physicsconfig.GetFloat("body_pid_derivative", 35f);
bodyPIDG = physicsconfig.GetFloat("body_pid_gain", 25f);
bodyPIDD = physicsconfig.GetFloat("body_pid_derivative", bodyPIDD);
bodyPIDG = physicsconfig.GetFloat("body_pid_gain", bodyPIDG);
forceSimplePrimMeshing = physicsconfig.GetBoolean("force_simple_prim_meshing", forceSimplePrimMeshing);
meshSculptedPrim = physicsconfig.GetBoolean("mesh_sculpted_prim", true);
meshSculptLOD = physicsconfig.GetFloat("mesh_lod", 32f);
MeshSculptphysicalLOD = physicsconfig.GetFloat("mesh_physical_lod", 16f);
m_filterCollisions = physicsconfig.GetBoolean("filter_collisions", false);
meshSculptedPrim = physicsconfig.GetBoolean("mesh_sculpted_prim", meshSculptedPrim);
meshSculptLOD = physicsconfig.GetFloat("mesh_lod", meshSculptLOD);
MeshSculptphysicalLOD = physicsconfig.GetFloat("mesh_physical_lod", MeshSculptphysicalLOD);
if (Environment.OSVersion.Platform == PlatformID.Unix)
{
avPIDD = physicsconfig.GetFloat("av_pid_derivative_linux", 2200.0f);
avPIDP = physicsconfig.GetFloat("av_pid_proportional_linux", 900.0f);
avPIDD = physicsconfig.GetFloat("av_pid_derivative_linux", avPIDD);
avPIDP = physicsconfig.GetFloat("av_pid_proportional_linux", avPIDP);
}
else
{
avPIDD = physicsconfig.GetFloat("av_pid_derivative_win", 2200.0f);
avPIDP = physicsconfig.GetFloat("av_pid_proportional_win", 900.0f);
avPIDD = physicsconfig.GetFloat("av_pid_derivative_win", avPIDD);
avPIDP = physicsconfig.GetFloat("av_pid_proportional_win", avPIDP);
}
physics_logging = physicsconfig.GetBoolean("physics_logging", false);
physics_logging_interval = physicsconfig.GetInt("physics_logging_interval", 0);
physics_logging_append_existing_logfile = physicsconfig.GetBoolean("physics_logging_append_existing_logfile", false);
minimumGroundFlightOffset = physicsconfig.GetFloat("minimum_ground_flight_offset", 3f);
maximumMassObject = physicsconfig.GetFloat("maximum_mass_object", 10000.01f);
minimumGroundFlightOffset = physicsconfig.GetFloat("minimum_ground_flight_offset", minimumGroundFlightOffset);
maximumMassObject = physicsconfig.GetFloat("maximum_mass_object", maximumMassObject);
}
}
ContactgeomsArray = Marshal.AllocHGlobal(contactsPerCollision * d.ContactGeom.unmanagedSizeOf);
GlobalContactsArray = GlobalContactsArray = Marshal.AllocHGlobal(maxContactsbeforedeath * d.Contact.unmanagedSizeOf);
m_materialContactsData[(int)Material.Stone].mu = frictionScale * 0.8f;
m_materialContactsData[(int)Material.Stone].mu = 0.8f;
m_materialContactsData[(int)Material.Stone].bounce = 0.4f;
m_materialContactsData[(int)Material.Metal].mu = frictionScale * 0.3f;
m_materialContactsData[(int)Material.Metal].mu = 0.3f;
m_materialContactsData[(int)Material.Metal].bounce = 0.4f;
m_materialContactsData[(int)Material.Glass].mu = frictionScale * 0.2f;
m_materialContactsData[(int)Material.Glass].mu = 0.2f;
m_materialContactsData[(int)Material.Glass].bounce = 0.7f;
m_materialContactsData[(int)Material.Wood].mu = frictionScale * 0.6f;
m_materialContactsData[(int)Material.Wood].mu = 0.6f;
m_materialContactsData[(int)Material.Wood].bounce = 0.5f;
m_materialContactsData[(int)Material.Flesh].mu = frictionScale * 0.9f;
m_materialContactsData[(int)Material.Flesh].mu = 0.9f;
m_materialContactsData[(int)Material.Flesh].bounce = 0.3f;
m_materialContactsData[(int)Material.Plastic].mu = frictionScale * 0.4f;
m_materialContactsData[(int)Material.Plastic].mu = 0.4f;
m_materialContactsData[(int)Material.Plastic].bounce = 0.7f;
m_materialContactsData[(int)Material.Rubber].mu = frictionScale * 0.9f;
m_materialContactsData[(int)Material.Rubber].mu = 0.9f;
m_materialContactsData[(int)Material.Rubber].bounce = 0.95f;
m_materialContactsData[(int)Material.light].mu = 0.0f;
m_materialContactsData[(int)Material.light].bounce = 0.0f;
TerrainFriction *= frictionScale;
// AvatarFriction *= frictionScale;
// Set the gravity,, don't disable things automatically (we set it explicitly on some things)
d.WorldSetGravity(world, gravityx, gravityy, gravityz);
@ -566,13 +557,6 @@ namespace OpenSim.Region.Physics.OdePlugin
}
/// <summary>
/// This is our near callback. A geometry is near a body
/// </summary>
/// <param name="space">The space that contains the geoms. Remember, spaces are also geoms</param>
/// <param name="g1">a geometry or space</param>
/// <param name="g2">another geometry or space</param>
///
private bool GetCurContactGeom(int index, ref d.ContactGeom newcontactgeom)
{
@ -584,7 +568,13 @@ namespace OpenSim.Region.Physics.OdePlugin
return true;
}
/// <summary>
/// This is our near callback. A geometry is near a body
/// </summary>
/// <param name="space">The space that contains the geoms. Remember, spaces are also geoms</param>
/// <param name="g1">a geometry or space</param>
/// <param name="g2">another geometry or space</param>
///
private void near(IntPtr space, IntPtr g1, IntPtr g2)
{
@ -703,8 +693,8 @@ namespace OpenSim.Region.Physics.OdePlugin
// big messy collision analises
float mu = 0;
float bounce = 0;
ContactData contactdata1;
ContactData contactdata2;
ContactData contactdata1 = new ContactData(0, 0, false);
ContactData contactdata2 = new ContactData(0, 0, false);
bool erpSoft = false;
String name = null;
@ -718,8 +708,9 @@ namespace OpenSim.Region.Physics.OdePlugin
switch (p2.PhysicsActorType)
{
case (int)ActorTypes.Agent:
contactdata1 = p1.ContactData;
contactdata2 = p2.ContactData;
p1.getContactData(ref contactdata1);
p2.getContactData(ref contactdata2);
bounce = contactdata1.bounce * contactdata2.bounce;
mu = (float)Math.Sqrt(contactdata1.mu * contactdata2.mu);
@ -727,12 +718,13 @@ namespace OpenSim.Region.Physics.OdePlugin
if ((Math.Abs(p2.Velocity.X - p1.Velocity.X) > 0.1f || Math.Abs(p2.Velocity.Y - p1.Velocity.Y) > 0.1f))
mu *= frictionMovementMult;
erpSoft = contactdata1.softcolide | contactdata2.softcolide;
p1.CollidingObj = true;
p2.CollidingObj = true;
break;
case (int)ActorTypes.Prim:
contactdata1 = p1.ContactData;
contactdata2 = p2.ContactData;
p1.getContactData(ref contactdata1);
p2.getContactData(ref contactdata2);
bounce = contactdata1.bounce * contactdata2.bounce;
mu = (float)Math.Sqrt(contactdata1.mu * contactdata2.mu);
@ -741,6 +733,9 @@ namespace OpenSim.Region.Physics.OdePlugin
mu *= frictionMovementMult;
if (p2.Velocity.LengthSquared() > 0.0f)
p2.CollidingObj = true;
erpSoft = contactdata1.softcolide | contactdata2.softcolide;
dop1foot = true;
break;
default:
@ -753,8 +748,8 @@ namespace OpenSim.Region.Physics.OdePlugin
switch (p2.PhysicsActorType)
{
case (int)ActorTypes.Agent:
contactdata1 = p1.ContactData;
contactdata2 = p2.ContactData;
p1.getContactData(ref contactdata1);
p2.getContactData(ref contactdata2);
bounce = contactdata1.bounce * contactdata2.bounce;
mu = (float)Math.Sqrt(contactdata1.mu * contactdata2.mu);
@ -762,6 +757,7 @@ namespace OpenSim.Region.Physics.OdePlugin
if ((Math.Abs(p2.Velocity.X - p1.Velocity.X) > 0.1f || Math.Abs(p2.Velocity.Y - p1.Velocity.Y) > 0.1f))
mu *= frictionMovementMult;
erpSoft = contactdata1.softcolide | contactdata2.softcolide;
dop2foot = true;
if (p1.Velocity.LengthSquared() > 0.0f)
p1.CollidingObj = true;
@ -772,10 +768,10 @@ namespace OpenSim.Region.Physics.OdePlugin
p1.CollidingObj = true;
p2.CollidingObj = true;
}
contactdata1 = p1.ContactData;
contactdata2 = p2.ContactData;
p1.getContactData(ref contactdata1);
p2.getContactData(ref contactdata2);
bounce = contactdata1.bounce * contactdata2.bounce;
erpSoft = true;
erpSoft = contactdata1.softcolide | contactdata2.softcolide;
mu = (float)Math.Sqrt(contactdata1.mu * contactdata2.mu);
if ((Math.Abs(p2.Velocity.X - p1.Velocity.X) > 0.1f || Math.Abs(p2.Velocity.Y - p1.Velocity.Y) > 0.1f))
@ -787,12 +783,12 @@ namespace OpenSim.Region.Physics.OdePlugin
{
if (name == "Terrain")
{
erpSoft = true;
contactdata1 = p1.ContactData;
p1.getContactData(ref contactdata1);
bounce = contactdata1.bounce * TerrainBounce;
mu = (float)Math.Sqrt(contactdata1.mu * TerrainFriction);
if (Math.Abs(p1.Velocity.X) > 0.1f || Math.Abs(p1.Velocity.Y) > 0.1f)
mu *= frictionMovementMult;
erpSoft = contactdata1.softcolide;
p1.CollidingGround = true;
}
else if (name == "Water")
@ -813,11 +809,11 @@ namespace OpenSim.Region.Physics.OdePlugin
{
if (p2.PhysicsActorType == (int)ActorTypes.Prim)
{
erpSoft = true;
p2.CollidingGround = true;
contactdata2 = p2.ContactData;
p2.getContactData(ref contactdata2);
bounce = contactdata2.bounce * TerrainBounce;
mu = (float)Math.Sqrt(contactdata2.mu * TerrainFriction);
erpSoft = contactdata2.softcolide;
if (Math.Abs(p2.Velocity.X) > 0.1f || Math.Abs(p2.Velocity.Y) > 0.1f)
mu *= frictionMovementMult;
@ -1013,15 +1009,24 @@ namespace OpenSim.Region.Physics.OdePlugin
}
// collide active prims with static enviroment
lock (_activeprims)
{
foreach (OdePrim aprim in _activeprims)
{
aprim.CollisionScore = 0;
aprim.IsColliding = false;
}
}
// collide active prims with static enviroment
lock (_activegroups)
{
try
{
foreach (OdePrim prm in _activeprims)
foreach (OdePrim prm in _activegroups)
{
if (d.BodyIsEnabled(prm.Body))
d.SpaceCollide2(StaticSpace, prm.prim_geom, IntPtr.Zero, nearCallback);
if (d.BodyIsEnabled(prm.Body) && !prm.m_outbounds)
d.SpaceCollide2(StaticSpace, prm.collide_geom, IntPtr.Zero, nearCallback);
}
}
catch (AccessViolationException)
@ -1029,7 +1034,6 @@ namespace OpenSim.Region.Physics.OdePlugin
m_log.Warn("[PHYSICS]: Unable to collide Active prim to static space");
}
}
// finally colide active things amoung them
try
{
@ -1039,7 +1043,6 @@ namespace OpenSim.Region.Physics.OdePlugin
{
m_log.Warn("[PHYSICS]: Unable to collide in Active space");
}
// _perloopContact.Clear();
}
@ -1148,13 +1151,20 @@ namespace OpenSim.Region.Physics.OdePlugin
public void addActivePrim(OdePrim activatePrim)
{
// adds active prim.. (ones that should be iterated over in collisions_optimized
// adds active prim..
lock (_activeprims)
{
if (!_activeprims.Contains(activatePrim))
_activeprims.Add(activatePrim);
//else
// m_log.Warn("[PHYSICS]: Double Entry in _activeprims detected, potential crash immenent");
}
}
public void addActiveGroups(OdePrim activatePrim)
{
lock (_activegroups)
{
if (!_activegroups.Contains(activatePrim))
_activegroups.Add(activatePrim);
}
}
@ -1186,6 +1196,13 @@ namespace OpenSim.Region.Physics.OdePlugin
_activeprims.Remove(deactivatePrim);
}
}
public void remActiveGroup(OdePrim deactivatePrim)
{
lock (_activegroups)
{
_activegroups.Remove(deactivatePrim);
}
}
public override void RemovePrim(PhysicsActor prim)
{
@ -1258,6 +1275,11 @@ namespace OpenSim.Region.Physics.OdePlugin
{
waitForSpaceUnlock(currentspace);
d.SpaceRemove(currentspace, geom);
if (d.SpaceGetSublevel(currentspace) > 2 && d.SpaceGetNumGeoms(currentspace) == 0)
{
d.SpaceDestroy(currentspace);
}
}
else
{
@ -1274,6 +1296,12 @@ namespace OpenSim.Region.Physics.OdePlugin
{
waitForSpaceUnlock(currentspace);
d.SpaceRemove(currentspace, geom);
if (d.SpaceGetSublevel(currentspace) > 2 && d.SpaceGetNumGeoms(currentspace) == 0)
{
d.SpaceDestroy(currentspace);
}
}
}
}
@ -1577,42 +1605,14 @@ namespace OpenSim.Region.Physics.OdePlugin
statchanges += Util.EnvironmentTickCountSubtract(statstart);
// Move characters
lock (_characters)
{
List<OdeCharacter> defects = new List<OdeCharacter>();
foreach (OdeCharacter actor in _characters)
{
if (actor != null)
actor.Move(ODE_STEPSIZE, defects);
}
if (defects.Count != 0)
{
foreach (OdeCharacter defect in defects)
{
RemoveCharacter(defect);
}
}
}
statchmove += Util.EnvironmentTickCountSubtract(statstart);
// Move other active objects
lock (_activeprims)
{
foreach (OdePrim aprim in _activeprims)
{
aprim.CollisionScore = 0;
aprim.IsColliding = false;
aprim.Move();
}
}
statactmove += Util.EnvironmentTickCountSubtract(statstart);
//if ((framecount % m_randomizeWater) == 0)
// randomizeWater(waterlevel);
m_rayCastManager.ProcessQueuedRequests();
statray += Util.EnvironmentTickCountSubtract(statstart);
collision_optimized();
statcol += Util.EnvironmentTickCountSubtract(statstart);
@ -1642,8 +1642,35 @@ namespace OpenSim.Region.Physics.OdePlugin
d.WorldQuickStep(world, ODE_STEPSIZE);
statstep += Util.EnvironmentTickCountSubtract(statstart);
d.JointGroupEmpty(contactgroup);
totjcontact += m_global_contactcount;
// Move characters
lock (_characters)
{
List<OdeCharacter> defects = new List<OdeCharacter>();
foreach (OdeCharacter actor in _characters)
{
if (actor != null)
actor.Move(ODE_STEPSIZE, defects);
}
if (defects.Count != 0)
{
foreach (OdeCharacter defect in defects)
{
RemoveCharacter(defect);
}
}
}
statchmove += Util.EnvironmentTickCountSubtract(statstart);
// Move other active objects
lock (_activegroups)
{
foreach (OdePrim aprim in _activegroups)
{
aprim.Move();
}
}
//ode.dunlock(world);
}
catch (Exception e)
@ -1652,6 +1679,9 @@ namespace OpenSim.Region.Physics.OdePlugin
// ode.dunlock(world);
}
d.JointGroupEmpty(contactgroup);
totjcontact += m_global_contactcount;
step_time -= ODE_STEPSIZE;
nodeframes++;
}
@ -1686,10 +1716,10 @@ namespace OpenSim.Region.Physics.OdePlugin
}
statmovchar = Util.EnvironmentTickCountSubtract(statstart);
lock (_activeprims)
lock (_activegroups)
{
{
foreach (OdePrim actor in _activeprims)
foreach (OdePrim actor in _activegroups)
{
if (actor.IsPhysical)
{
@ -1906,13 +1936,14 @@ namespace OpenSim.Region.Physics.OdePlugin
yy += regionsize;
val = heightMap[yy + xx];
if (val < 0.0f)
val = 0.0f; // no neg terrain as in chode
_heightmap[xt + y] = val;
if (hfmin > val)
hfmin = val;
if (hfmax < val)
hfmax = val;
}
xt += heightmapHeightSamples;
}
@ -1966,7 +1997,7 @@ namespace OpenSim.Region.Physics.OdePlugin
d.RFromAxisAndAngle(out R, v3.X, v3.Y, v3.Z, angle);
d.GeomSetRotation(GroundGeom, ref R);
d.GeomSetPosition(GroundGeom, pOffset.X + (float)Constants.RegionSize * 0.5f - 0.5f, pOffset.Y + (float)Constants.RegionSize * 0.5f - 0.5f, 0);
d.GeomSetPosition(GroundGeom, pOffset.X + (float)Constants.RegionSize * 0.5f, pOffset.Y + (float)Constants.RegionSize * 0.5f, 0);
RegionTerrain.Add(pOffset, GroundGeom, GroundGeom);
// TerrainHeightFieldHeights.Add(GroundGeom, ODElandMap);
TerrainHeightFieldHeights.Add(GroundGeom, _heightmap);