Merge branch 'ubitwork'

Conflicts:
	OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs
	OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs
avinationmerge
Melanie 2012-02-19 20:08:01 +01:00
commit 96409cc2ee
29 changed files with 13346 additions and 1080 deletions

View File

@ -417,7 +417,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
so.AttachedAvatar = UUID.Zero;
rootPart.SetParentLocalId(0);
so.ClearPartAttachmentData();
rootPart.ApplyPhysics(rootPart.GetEffectiveObjectFlags(), rootPart.VolumeDetectActive);
rootPart.ApplyPhysics(rootPart.GetEffectiveObjectFlags(), rootPart.VolumeDetectActive,false);
so.HasGroupChanged = true;
rootPart.Rezzed = DateTime.Now;
rootPart.RemFlag(PrimFlags.TemporaryOnRez);

View File

@ -0,0 +1,487 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Region.Physics.Manager;
using System.Xml;
using OpenSim.Framework.Serialization;
using OpenSim.Framework.Serialization.External;
using OpenSim.Region.Framework.Scenes.Serialization;
namespace OpenSim.Region.Framework.Scenes
{
public class SOPVehicle
{
public VehicleData vd;
public Vehicle Type
{
get { return vd.m_type; }
}
public SOPVehicle()
{
vd = new VehicleData();
ProcessTypeChange(Vehicle.TYPE_NONE); // is needed?
}
public void ProcessFloatVehicleParam(Vehicle pParam, float pValue)
{
float len;
float timestep = 0.01f;
switch (pParam)
{
case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
if (pValue < 0f) pValue = 0f;
if (pValue > 1f) pValue = 1f;
vd.m_angularDeflectionEfficiency = pValue;
break;
case Vehicle.ANGULAR_DEFLECTION_TIMESCALE:
if (pValue < timestep) pValue = timestep;
vd.m_angularDeflectionTimescale = pValue;
break;
case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE:
if (pValue < timestep) pValue = timestep;
else if (pValue > 120) pValue = 120;
vd.m_angularMotorDecayTimescale = pValue;
break;
case Vehicle.ANGULAR_MOTOR_TIMESCALE:
if (pValue < timestep) pValue = timestep;
vd.m_angularMotorTimescale = pValue;
break;
case Vehicle.BANKING_EFFICIENCY:
if (pValue < -1f) pValue = -1f;
if (pValue > 1f) pValue = 1f;
vd.m_bankingEfficiency = pValue;
break;
case Vehicle.BANKING_MIX:
if (pValue < 0f) pValue = 0f;
if (pValue > 1f) pValue = 1f;
vd.m_bankingMix = pValue;
break;
case Vehicle.BANKING_TIMESCALE:
if (pValue < timestep) pValue = timestep;
vd.m_bankingTimescale = pValue;
break;
case Vehicle.BUOYANCY:
if (pValue < -1f) pValue = -1f;
if (pValue > 1f) pValue = 1f;
vd.m_VehicleBuoyancy = pValue;
break;
case Vehicle.HOVER_EFFICIENCY:
if (pValue < 0f) pValue = 0f;
if (pValue > 1f) pValue = 1f;
vd.m_VhoverEfficiency = pValue;
break;
case Vehicle.HOVER_HEIGHT:
vd.m_VhoverHeight = pValue;
break;
case Vehicle.HOVER_TIMESCALE:
if (pValue < timestep) pValue = timestep;
vd.m_VhoverTimescale = pValue;
break;
case Vehicle.LINEAR_DEFLECTION_EFFICIENCY:
if (pValue < 0f) pValue = 0f;
if (pValue > 1f) pValue = 1f;
vd.m_linearDeflectionEfficiency = pValue;
break;
case Vehicle.LINEAR_DEFLECTION_TIMESCALE:
if (pValue < timestep) pValue = timestep;
vd.m_linearDeflectionTimescale = pValue;
break;
case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE:
// if (pValue < timestep) pValue = timestep;
// try to make impulses to work a bit better
if (pValue < timestep) pValue = timestep;
else if (pValue > 120) pValue = 120;
vd.m_linearMotorDecayTimescale = pValue;
break;
case Vehicle.LINEAR_MOTOR_TIMESCALE:
if (pValue < timestep) pValue = timestep;
vd.m_linearMotorTimescale = pValue;
break;
case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY:
if (pValue < 0f) pValue = 0f;
if (pValue > 1f) pValue = 1f;
vd.m_verticalAttractionEfficiency = pValue;
break;
case Vehicle.VERTICAL_ATTRACTION_TIMESCALE:
if (pValue < timestep) pValue = timestep;
vd.m_verticalAttractionTimescale = pValue;
break;
// These are vector properties but the engine lets you use a single float value to
// set all of the components to the same value
case Vehicle.ANGULAR_FRICTION_TIMESCALE:
if (pValue < timestep) pValue = timestep;
vd.m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue);
break;
case Vehicle.ANGULAR_MOTOR_DIRECTION:
vd.m_angularMotorDirection = new Vector3(pValue, pValue, pValue);
len = vd.m_angularMotorDirection.Length();
if (len > 12.566f)
vd.m_angularMotorDirection *= (12.566f / len);
break;
case Vehicle.LINEAR_FRICTION_TIMESCALE:
if (pValue < timestep) pValue = timestep;
vd.m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue);
break;
case Vehicle.LINEAR_MOTOR_DIRECTION:
vd.m_linearMotorDirection = new Vector3(pValue, pValue, pValue);
len = vd.m_linearMotorDirection.Length();
if (len > 30.0f)
vd.m_linearMotorDirection *= (30.0f / len);
break;
case Vehicle.LINEAR_MOTOR_OFFSET:
vd.m_linearMotorOffset = new Vector3(pValue, pValue, pValue);
len = vd.m_linearMotorOffset.Length();
if (len > 100.0f)
vd.m_linearMotorOffset *= (100.0f / len);
break;
}
}//end ProcessFloatVehicleParam
public void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue)
{
float len;
float timestep = 0.01f;
switch (pParam)
{
case Vehicle.ANGULAR_FRICTION_TIMESCALE:
if (pValue.X < timestep) pValue.X = timestep;
if (pValue.Y < timestep) pValue.Y = timestep;
if (pValue.Z < timestep) pValue.Z = timestep;
vd.m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
break;
case Vehicle.ANGULAR_MOTOR_DIRECTION:
vd.m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
// Limit requested angular speed to 2 rps= 4 pi rads/sec
len = vd.m_angularMotorDirection.Length();
if (len > 12.566f)
vd.m_angularMotorDirection *= (12.566f / len);
break;
case Vehicle.LINEAR_FRICTION_TIMESCALE:
if (pValue.X < timestep) pValue.X = timestep;
if (pValue.Y < timestep) pValue.Y = timestep;
if (pValue.Z < timestep) pValue.Z = timestep;
vd.m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
break;
case Vehicle.LINEAR_MOTOR_DIRECTION:
vd.m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
len = vd.m_linearMotorDirection.Length();
if (len > 30.0f)
vd.m_linearMotorDirection *= (30.0f / len);
break;
case Vehicle.LINEAR_MOTOR_OFFSET:
vd.m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z);
len = vd.m_linearMotorOffset.Length();
if (len > 100.0f)
vd.m_linearMotorOffset *= (100.0f / len);
break;
}
}//end ProcessVectorVehicleParam
public void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue)
{
switch (pParam)
{
case Vehicle.REFERENCE_FRAME:
vd.m_referenceFrame = Quaternion.Inverse(pValue);
break;
}
}//end ProcessRotationVehicleParam
public void ProcessVehicleFlags(int pParam, bool remove)
{
if (remove)
{
vd.m_flags &= ~((VehicleFlag)pParam);
}
else
{
vd.m_flags |= (VehicleFlag)pParam;
}
}//end ProcessVehicleFlags
public void ProcessTypeChange(Vehicle pType)
{
vd.m_linearMotorDirection = Vector3.Zero;
vd.m_angularMotorDirection = Vector3.Zero;
vd.m_linearMotorOffset = Vector3.Zero;
vd.m_referenceFrame = Quaternion.Identity;
// Set Defaults For Type
vd.m_type = pType;
switch (pType)
{
case Vehicle.TYPE_NONE:
vd.m_linearFrictionTimescale = new Vector3(1000, 1000, 1000);
vd.m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
vd.m_linearMotorTimescale = 1000;
vd.m_linearMotorDecayTimescale = 120;
vd.m_angularMotorTimescale = 1000;
vd.m_angularMotorDecayTimescale = 1000;
vd.m_VhoverHeight = 0;
vd.m_VhoverEfficiency = 1;
vd.m_VhoverTimescale = 1000;
vd.m_VehicleBuoyancy = 0;
vd.m_linearDeflectionEfficiency = 0;
vd.m_linearDeflectionTimescale = 1000;
vd.m_angularDeflectionEfficiency = 0;
vd.m_angularDeflectionTimescale = 1000;
vd.m_bankingEfficiency = 0;
vd.m_bankingMix = 1;
vd.m_bankingTimescale = 1000;
vd.m_verticalAttractionEfficiency = 0;
vd.m_verticalAttractionTimescale = 1000;
vd.m_flags = (VehicleFlag)0;
break;
case Vehicle.TYPE_SLED:
vd.m_linearFrictionTimescale = new Vector3(30, 1, 1000);
vd.m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
vd.m_linearMotorTimescale = 1000;
vd.m_linearMotorDecayTimescale = 120;
vd.m_angularMotorTimescale = 1000;
vd.m_angularMotorDecayTimescale = 120;
vd.m_VhoverHeight = 0;
vd.m_VhoverEfficiency = 1;
vd.m_VhoverTimescale = 10;
vd.m_VehicleBuoyancy = 0;
vd.m_linearDeflectionEfficiency = 1;
vd.m_linearDeflectionTimescale = 1;
vd.m_angularDeflectionEfficiency = 0;
vd.m_angularDeflectionTimescale = 1000;
vd.m_bankingEfficiency = 0;
vd.m_bankingMix = 1;
vd.m_bankingTimescale = 10;
vd.m_flags &=
~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
vd.m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
break;
case Vehicle.TYPE_CAR:
vd.m_linearFrictionTimescale = new Vector3(100, 2, 1000);
vd.m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
vd.m_linearMotorTimescale = 1;
vd.m_linearMotorDecayTimescale = 60;
vd.m_angularMotorTimescale = 1;
vd.m_angularMotorDecayTimescale = 0.8f;
vd.m_VhoverHeight = 0;
vd.m_VhoverEfficiency = 0;
vd.m_VhoverTimescale = 1000;
vd.m_VehicleBuoyancy = 0;
vd.m_linearDeflectionEfficiency = 1;
vd.m_linearDeflectionTimescale = 2;
vd.m_angularDeflectionEfficiency = 0;
vd.m_angularDeflectionTimescale = 10;
vd.m_verticalAttractionEfficiency = 1f;
vd.m_verticalAttractionTimescale = 10f;
vd.m_bankingEfficiency = -0.2f;
vd.m_bankingMix = 1;
vd.m_bankingTimescale = 1;
vd.m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT);
vd.m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY |
VehicleFlag.LIMIT_MOTOR_UP | VehicleFlag.HOVER_UP_ONLY);
break;
case Vehicle.TYPE_BOAT:
vd.m_linearFrictionTimescale = new Vector3(10, 3, 2);
vd.m_angularFrictionTimescale = new Vector3(10, 10, 10);
vd.m_linearMotorTimescale = 5;
vd.m_linearMotorDecayTimescale = 60;
vd.m_angularMotorTimescale = 4;
vd.m_angularMotorDecayTimescale = 4;
vd.m_VhoverHeight = 0;
vd.m_VhoverEfficiency = 0.5f;
vd.m_VhoverTimescale = 2;
vd.m_VehicleBuoyancy = 1;
vd.m_linearDeflectionEfficiency = 0.5f;
vd.m_linearDeflectionTimescale = 3;
vd.m_angularDeflectionEfficiency = 0.5f;
vd.m_angularDeflectionTimescale = 5;
vd.m_verticalAttractionEfficiency = 0.5f;
vd.m_verticalAttractionTimescale = 5f;
vd.m_bankingEfficiency = -0.3f;
vd.m_bankingMix = 0.8f;
vd.m_bankingTimescale = 1;
vd.m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY |
VehicleFlag.HOVER_GLOBAL_HEIGHT |
VehicleFlag.HOVER_UP_ONLY |
VehicleFlag.LIMIT_ROLL_ONLY);
vd.m_flags |= (VehicleFlag.NO_DEFLECTION_UP |
VehicleFlag.LIMIT_MOTOR_UP |
VehicleFlag.HOVER_WATER_ONLY);
break;
case Vehicle.TYPE_AIRPLANE:
vd.m_linearFrictionTimescale = new Vector3(200, 10, 5);
vd.m_angularFrictionTimescale = new Vector3(20, 20, 20);
vd.m_linearMotorTimescale = 2;
vd.m_linearMotorDecayTimescale = 60;
vd.m_angularMotorTimescale = 4;
vd.m_angularMotorDecayTimescale = 8;
vd.m_VhoverHeight = 0;
vd.m_VhoverEfficiency = 0.5f;
vd.m_VhoverTimescale = 1000;
vd.m_VehicleBuoyancy = 0;
vd.m_linearDeflectionEfficiency = 0.5f;
vd.m_linearDeflectionTimescale = 0.5f;
vd.m_angularDeflectionEfficiency = 1;
vd.m_angularDeflectionTimescale = 2;
vd.m_verticalAttractionEfficiency = 0.9f;
vd.m_verticalAttractionTimescale = 2f;
vd.m_bankingEfficiency = 1;
vd.m_bankingMix = 0.7f;
vd.m_bankingTimescale = 2;
vd.m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY |
VehicleFlag.HOVER_TERRAIN_ONLY |
VehicleFlag.HOVER_GLOBAL_HEIGHT |
VehicleFlag.HOVER_UP_ONLY |
VehicleFlag.NO_DEFLECTION_UP |
VehicleFlag.LIMIT_MOTOR_UP);
vd.m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
break;
case Vehicle.TYPE_BALLOON:
vd.m_linearFrictionTimescale = new Vector3(5, 5, 5);
vd.m_angularFrictionTimescale = new Vector3(10, 10, 10);
vd.m_linearMotorTimescale = 5;
vd.m_linearMotorDecayTimescale = 60;
vd.m_angularMotorTimescale = 6;
vd.m_angularMotorDecayTimescale = 10;
vd.m_VhoverHeight = 5;
vd.m_VhoverEfficiency = 0.8f;
vd.m_VhoverTimescale = 10;
vd.m_VehicleBuoyancy = 1;
vd.m_linearDeflectionEfficiency = 0;
vd.m_linearDeflectionTimescale = 5;
vd.m_angularDeflectionEfficiency = 0;
vd.m_angularDeflectionTimescale = 5;
vd.m_verticalAttractionEfficiency = 0f;
vd.m_verticalAttractionTimescale = 1000f;
vd.m_bankingEfficiency = 0;
vd.m_bankingMix = 0.7f;
vd.m_bankingTimescale = 5;
vd.m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY |
VehicleFlag.HOVER_TERRAIN_ONLY |
VehicleFlag.HOVER_UP_ONLY |
VehicleFlag.NO_DEFLECTION_UP |
VehicleFlag.LIMIT_MOTOR_UP);
vd.m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY |
VehicleFlag.HOVER_GLOBAL_HEIGHT);
break;
}
}
public void SetVehicle(PhysicsActor ph)
{
if (ph == null)
return;
ph.SetVehicle(vd);
}
private XmlTextWriter writer;
private void XWint(string name, int i)
{
writer.WriteElementString(name, i.ToString());
}
private void XWfloat(string name, float f)
{
writer.WriteElementString(name, f.ToString(Utils.EnUsCulture));
}
private void XWVector(string name, Vector3 vec)
{
writer.WriteStartElement(name);
writer.WriteElementString("X", vec.X.ToString(Utils.EnUsCulture));
writer.WriteElementString("Y", vec.Y.ToString(Utils.EnUsCulture));
writer.WriteElementString("Z", vec.Z.ToString(Utils.EnUsCulture));
writer.WriteEndElement();
}
private void XWQuat(string name, Quaternion quat)
{
writer.WriteStartElement(name);
writer.WriteElementString("X", quat.X.ToString(Utils.EnUsCulture));
writer.WriteElementString("Y", quat.Y.ToString(Utils.EnUsCulture));
writer.WriteElementString("Z", quat.Z.ToString(Utils.EnUsCulture));
writer.WriteElementString("W", quat.W.ToString(Utils.EnUsCulture));
writer.WriteEndElement();
}
public void ToXml2(XmlTextWriter twriter)
{
writer = twriter;
writer.WriteStartElement("SOGVehicle");
XWint("TYPE", (int)vd.m_type);
XWint("FLAGS", (int)vd.m_flags);
// Linear properties
XWVector("LMDIR", vd.m_linearMotorDirection);
XWVector("LMFTIME", vd.m_linearFrictionTimescale);
XWfloat("LMDTIME", vd.m_linearMotorDecayTimescale);
XWfloat("LMTIME", vd.m_linearMotorTimescale);
XWVector("LMOFF", vd.m_linearMotorOffset);
//Angular properties
XWVector("AMDIR", vd.m_angularMotorDirection);
XWfloat("AMTIME", vd.m_angularMotorTimescale);
XWfloat("AMDTIME", vd.m_angularMotorDecayTimescale);
XWVector("AMFTIME", vd.m_angularFrictionTimescale);
//Deflection properties
XWfloat("ADEFF", vd.m_angularDeflectionEfficiency);
XWfloat("ADTIME", vd.m_angularDeflectionTimescale);
XWfloat("LDEFF", vd.m_linearDeflectionEfficiency);
XWfloat("LDTIME", vd.m_linearDeflectionTimescale);
//Banking properties
XWfloat("BEFF", vd.m_bankingEfficiency);
XWfloat("BMIX", vd.m_bankingMix);
XWfloat("BTIME", vd.m_bankingTimescale);
//Hover and Buoyancy properties
XWfloat("HHEI", vd.m_VhoverHeight);
XWfloat("HEFF", vd.m_VhoverEfficiency);
XWfloat("HTIME", vd.m_VhoverTimescale);
XWfloat("VBUO", vd.m_VehicleBuoyancy);
//Attractor properties
XWfloat("VAEFF", vd.m_verticalAttractionEfficiency);
XWfloat("VATIME", vd.m_verticalAttractionTimescale);
XWQuat("REF_FRAME", vd.m_referenceFrame);
writer.WriteEndElement();
writer = null;
}
}
}

View File

@ -4792,7 +4792,7 @@ Environment.Exit(1);
bool wasUsingPhysics = ((jointProxyObject.Flags & PrimFlags.Physics) != 0);
if (wasUsingPhysics)
{
jointProxyObject.UpdatePrimFlags(false, false, true, false); // FIXME: possible deadlock here; check to make sure all the scene alterations set into motion here won't deadlock
jointProxyObject.UpdatePrimFlags(false, false, true, false,false); // FIXME: possible deadlock here; check to make sure all the scene alterations set into motion here won't deadlock
}
}

View File

@ -43,6 +43,7 @@ using OpenSim.Region.Framework.Scenes.Serialization;
namespace OpenSim.Region.Framework.Scenes
{
[Flags]
public enum scriptEvents
{
@ -1378,7 +1379,8 @@ namespace OpenSim.Region.Framework.Scenes
m_rootPart.SetParentLocalId(0);
AttachmentPoint = (byte)0;
m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive);
// must check if buildind should be true or false here
m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive,false);
HasGroupChanged = true;
RootPart.Rezzed = DateTime.Now;
RootPart.RemFlag(PrimFlags.TemporaryOnRez);
@ -1677,22 +1679,32 @@ namespace OpenSim.Region.Framework.Scenes
/// </summary>
public void ApplyPhysics()
{
// Apply physics to the root prim
m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive);
// Apply physics to child prims
SceneObjectPart[] parts = m_parts.GetArray();
if (parts.Length > 1)
{
ResetChildPrimPhysicsPositions();
// Apply physics to the root prim
m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, true);
for (int i = 0; i < parts.Length; i++)
{
SceneObjectPart part = parts[i];
if (part.LocalId != m_rootPart.LocalId)
part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive);
part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, true);
}
// Hack to get the physics scene geometries in the right spot
ResetChildPrimPhysicsPositions();
// ResetChildPrimPhysicsPositions();
if (m_rootPart.PhysActor != null)
{
m_rootPart.PhysActor.Building = false;
}
}
else
{
// Apply physics to the root prim
m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, false);
}
}
@ -1863,6 +1875,7 @@ namespace OpenSim.Region.Framework.Scenes
/// <returns></returns>
public SceneObjectGroup Copy(bool userExposed)
{
m_dupeInProgress = true;
SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone();
dupe.m_isBackedUp = false;
dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>();
@ -1926,13 +1939,16 @@ namespace OpenSim.Region.Framework.Scenes
pbs,
newPart.AbsolutePosition,
newPart.Scale,
newPart.RotationOffset,
//newPart.RotationOffset,
newPart.GetWorldRotation(),
part.PhysActor.IsPhysical,
newPart.LocalId);
newPart.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true);
}
}
if (dupe.m_rootPart.PhysActor != null && userExposed)
dupe.m_rootPart.PhysActor.Building = false; // tell physics to finish building
if (userExposed)
{
@ -1943,6 +1959,7 @@ namespace OpenSim.Region.Framework.Scenes
ScheduleGroupForFullUpdate();
}
m_dupeInProgress = false;
return dupe;
}
@ -2950,12 +2967,31 @@ namespace OpenSim.Region.Framework.Scenes
}
}
/*
RootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect);
for (int i = 0; i < parts.Length; i++)
{
if (parts[i] != RootPart)
parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect);
}
*/
if (parts.Length > 1)
{
m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, true);
for (int i = 0; i < parts.Length; i++)
{
if (parts[i].UUID != m_rootPart.UUID)
parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, true);
}
if (m_rootPart.PhysActor != null)
m_rootPart.PhysActor.Building = false;
}
else
m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, false);
}
}

View File

@ -310,6 +310,9 @@ namespace OpenSim.Region.Framework.Scenes
private UUID m_collisionSound;
private float m_collisionSoundVolume;
private SOPVehicle m_vehicle = null;
#endregion Fields
// ~SceneObjectPart()
@ -1506,7 +1509,8 @@ namespace OpenSim.Region.Framework.Scenes
/// </summary>
/// <param name="rootObjectFlags"></param>
/// <param name="VolumeDetectActive"></param>
public void ApplyPhysics(uint rootObjectFlags, bool VolumeDetectActive)
// public void ApplyPhysics(uint rootObjectFlags, bool VolumeDetectActive)
public void ApplyPhysics(uint rootObjectFlags, bool VolumeDetectActive, bool building)
{
if (!ParentGroup.Scene.CollidablePrims)
return;
@ -1542,7 +1546,8 @@ namespace OpenSim.Region.Framework.Scenes
Shape,
AbsolutePosition,
Scale,
RotationOffset,
// RotationOffset,
GetWorldRotation(), // physics wants world rotation
RigidBody,
m_localId);
}
@ -1557,8 +1562,16 @@ namespace OpenSim.Region.Framework.Scenes
{
PhysActor.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info
PhysActor.SetMaterial(Material);
// if root part apply vehicle
if (m_vehicle != null && LocalId == ParentGroup.RootPart.LocalId)
m_vehicle.SetVehicle(PhysActor);
DoPhysicsPropertyUpdate(RigidBody, true);
PhysActor.SetVolumeDetect(VolumeDetectActive ? 1 : 0);
if (!building)
PhysActor.Building = false;
}
}
}
@ -1794,6 +1807,10 @@ namespace OpenSim.Region.Framework.Scenes
if (!isNew)
ParentGroup.Scene.RemovePhysicalPrim(1);
Velocity = new Vector3(0, 0, 0);
Acceleration = new Vector3(0, 0, 0);
AngularVelocity = new Vector3(0, 0, 0);
PhysActor.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate;
PhysActor.OnOutOfBounds -= PhysicsOutOfBounds;
PhysActor.delink();
@ -3163,17 +3180,61 @@ namespace OpenSim.Region.Framework.Scenes
}
}
public int VehicleType
{
get
{
if (m_vehicle == null)
return (int)Vehicle.TYPE_NONE;
else
return (int)m_vehicle.Type;
}
set
{
SetVehicleType(value);
}
}
public void SetVehicleType(int type)
{
if (PhysActor != null)
m_vehicle = null;
if (type == (int)Vehicle.TYPE_NONE)
{
if (_parentID ==0 && PhysActor != null)
PhysActor.VehicleType = (int)Vehicle.TYPE_NONE;
return;
}
m_vehicle = new SOPVehicle();
m_vehicle.ProcessTypeChange((Vehicle)type);
{
if (_parentID ==0 && PhysActor != null)
PhysActor.VehicleType = type;
return;
}
}
public void SetVehicleFlags(int param, bool remove)
{
if (m_vehicle == null)
return;
m_vehicle.ProcessVehicleFlags(param, remove);
if (_parentID ==0 && PhysActor != null)
{
PhysActor.VehicleType = type;
PhysActor.VehicleFlags(param, remove);
}
}
public void SetVehicleFloatParam(int param, float value)
{
if (PhysActor != null)
if (m_vehicle == null)
return;
m_vehicle.ProcessFloatVehicleParam((Vehicle)param, value);
if (_parentID == 0 && PhysActor != null)
{
PhysActor.VehicleFloatParam(param, value);
}
@ -3181,7 +3242,12 @@ namespace OpenSim.Region.Framework.Scenes
public void SetVehicleVectorParam(int param, Vector3 value)
{
if (PhysActor != null)
if (m_vehicle == null)
return;
m_vehicle.ProcessVectorVehicleParam((Vehicle)param, value);
if (_parentID == 0 && PhysActor != null)
{
PhysActor.VehicleVectorParam(param, value);
}
@ -3189,7 +3255,12 @@ namespace OpenSim.Region.Framework.Scenes
public void SetVehicleRotationParam(int param, Quaternion rotation)
{
if (PhysActor != null)
if (m_vehicle == null)
return;
m_vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation);
if (_parentID == 0 && PhysActor != null)
{
PhysActor.VehicleRotationParam(param, rotation);
}
@ -3376,13 +3447,6 @@ namespace OpenSim.Region.Framework.Scenes
hasProfileCut = hasDimple; // is it the same thing?
}
public void SetVehicleFlags(int param, bool remove)
{
if (PhysActor != null)
{
PhysActor.VehicleFlags(param, remove);
}
}
public void SetGroup(UUID groupID, IClientAPI client)
{
@ -4270,7 +4334,8 @@ namespace OpenSim.Region.Framework.Scenes
/// <param name="SetTemporary"></param>
/// <param name="SetPhantom"></param>
/// <param name="SetVD"></param>
public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD)
// public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD)
public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD, bool building)
{
bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0);
bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0);
@ -4288,6 +4353,9 @@ namespace OpenSim.Region.Framework.Scenes
// that...
// ... if VD is changed, all others are not.
// ... if one of the others is changed, VD is not.
// do this first
if (building && PhysActor != null && PhysActor.Building != building)
PhysActor.Building = building;
if (SetVD) // VD is active, special logic applies
{
// State machine logic for VolumeDetect
@ -4369,11 +4437,17 @@ namespace OpenSim.Region.Framework.Scenes
Shape,
AbsolutePosition,
Scale,
RotationOffset,
// RotationOffset,
GetWorldRotation(), //physics wants world rotation like all other functions send
UsePhysics,
m_localId);
PhysActor.SetMaterial(Material);
// if root part apply vehicle
if (m_vehicle != null && LocalId == ParentGroup.RootPart.LocalId)
m_vehicle.SetVehicle(PhysActor);
DoPhysicsPropertyUpdate(UsePhysics, true);
if (!ParentGroup.IsDeleted)
@ -4449,6 +4523,9 @@ namespace OpenSim.Region.Framework.Scenes
}
// m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString());
// and last in case we have a new actor and not building
if (PhysActor != null && PhysActor.Building != building)
PhysActor.Building = building;
if (ParentGroup != null)
{
ParentGroup.HasGroupChanged = true;

View File

@ -1843,8 +1843,11 @@ namespace OpenSim.Region.Framework.Scenes
// m_log.DebugFormat("[SCENE PRESENCE]: StandUp() for {0}", Name);
SitGround = false;
/* move this down so avatar gets physical in the new position and not where it is siting
if (PhysicsActor == null)
AddToPhysicalScene(false);
*/
if (ParentID != 0)
{
@ -1879,6 +1882,10 @@ namespace OpenSim.Region.Framework.Scenes
ParentPosition = Vector3.Zero;
ParentID = 0;
if (PhysicsActor == null)
AddToPhysicalScene(false);
SendAvatarDataToAllAgents();
m_requestedSitTargetID = 0;
@ -1886,6 +1893,9 @@ namespace OpenSim.Region.Framework.Scenes
part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
}
else if (PhysicsActor == null)
AddToPhysicalScene(false);
Animator.TrySetMovementAnimation("STAND");
}

File diff suppressed because it is too large Load Diff

View File

@ -1736,6 +1736,23 @@ namespace OpenSim.Region.Physics.OdePlugin
return newPrim;
}
private PhysicsActor AddPrim(String name, Vector3 position, PhysicsActor parent,
PrimitiveBaseShape pbs, uint localid, byte[] sdata)
{
Vector3 pos = position;
OdePrim newPrim;
lock (OdeLock)
{
newPrim = new OdePrim(name, this, pos, parent, pbs, ode, localid, sdata);
lock (_prims)
_prims.Add(newPrim);
}
return newPrim;
}
public void addActivePrim(OdePrim activatePrim)
{
// adds active prim.. (ones that should be iterated over in collisions_optimized
@ -1762,6 +1779,17 @@ namespace OpenSim.Region.Physics.OdePlugin
return result;
}
public override PhysicsActor AddPrimShape(string primName, PhysicsActor parent, PrimitiveBaseShape pbs, Vector3 position,
uint localid, byte[] sdata)
{
PhysicsActor result;
result = AddPrim(primName, position, parent,
pbs, localid, sdata);
return result;
}
public override float TimeDilation
{
get { return m_timeDilation; }
@ -3412,15 +3440,15 @@ namespace OpenSim.Region.Physics.OdePlugin
int regionsize = (int) Constants.RegionSize; // visible region size eg. 256(M)
int heightmapWidth = regionsize + 2; // ODE map size 257 x 257 (Meters) (1 extra
int heightmapWidth = regionsize + 2; // ODE map size 258 x 258 (Meters) (1 extra each side)
int heightmapHeight = regionsize + 2;
int heightmapWidthSamples = (int)regionsize + 2; // Sample file size, 258 x 258 samples
int heightmapHeightSamples = (int)regionsize + 2;
int heightmapWidthSamples = (int)regionsize + 3; // to have 258m we need 259 samples
int heightmapHeightSamples = (int)regionsize + 3;
// Array of height samples for ODE
float[] _heightmap;
_heightmap = new float[(heightmapWidthSamples * heightmapHeightSamples)]; // loaded samples 258 x 258
_heightmap = new float[(heightmapWidthSamples * heightmapHeightSamples)]; // loaded samples 259 x 259
// Other ODE parameters
const float scale = 1.0f;

View File

@ -0,0 +1,353 @@
/* Ubit 2012
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// no endian conversion. So can't be use to pass information around diferent cpus with diferent endian
using System;
using System.IO;
using OpenMetaverse;
namespace OpenSim.Region.Physics.OdePlugin
{
unsafe public class wstreamer
{
byte[] buf;
int index;
byte* src;
public wstreamer()
{
buf = new byte[1024];
index = 0;
}
public wstreamer(int size)
{
buf = new byte[size];
index = 0;
}
public byte[] close()
{
byte[] data = new byte[index];
Buffer.BlockCopy(buf, 0, data, 0, index);
return data;
}
public void Seek(int pos)
{
index = pos;
}
public void Seekrel(int pos)
{
index += pos;
}
public void Wbyte(byte value)
{
buf[index++] = value;
}
public void Wshort(short value)
{
src = (byte*)&value;
buf[index++] = *src++;
buf[index++] = *src;
}
public void Wushort(ushort value)
{
src = (byte*)&value;
buf[index++] = *src++;
buf[index++] = *src;
}
public void Wint(int value)
{
src = (byte*)&value;
buf[index++] = *src++;
buf[index++] = *src++;
buf[index++] = *src++;
buf[index++] = *src;
}
public void Wuint(uint value)
{
src = (byte*)&value;
buf[index++] = *src++;
buf[index++] = *src++;
buf[index++] = *src++;
buf[index++] = *src;
}
public void Wlong(long value)
{
src = (byte*)&value;
buf[index++] = *src++;
buf[index++] = *src++;
buf[index++] = *src++;
buf[index++] = *src++;
buf[index++] = *src++;
buf[index++] = *src++;
buf[index++] = *src++;
buf[index++] = *src;
}
public void Wulong(ulong value)
{
src = (byte*)&value;
buf[index++] = *src++;
buf[index++] = *src++;
buf[index++] = *src++;
buf[index++] = *src++;
buf[index++] = *src++;
buf[index++] = *src++;
buf[index++] = *src++;
buf[index++] = *src;
}
public void Wfloat(float value)
{
src = (byte*)&value;
buf[index++] = *src++;
buf[index++] = *src++;
buf[index++] = *src++;
buf[index++] = *src;
}
public void Wdouble(double value)
{
src = (byte*)&value;
buf[index++] = *src++;
buf[index++] = *src++;
buf[index++] = *src++;
buf[index++] = *src++;
buf[index++] = *src++;
buf[index++] = *src++;
buf[index++] = *src++;
buf[index++] = *src;
}
public void Wvector3(Vector3 value)
{
src = (byte*)&value.X;
buf[index++] = *src++;
buf[index++] = *src++;
buf[index++] = *src++;
buf[index++] = *src;
src = (byte*)&value.Y; // it may have padding ??
buf[index++] = *src++;
buf[index++] = *src++;
buf[index++] = *src++;
buf[index++] = *src;
src = (byte*)&value.Z;
buf[index++] = *src++;
buf[index++] = *src++;
buf[index++] = *src++;
buf[index++] = *src;
}
public void Wquat(Quaternion value)
{
src = (byte*)&value.X;
buf[index++] = *src++;
buf[index++] = *src++;
buf[index++] = *src++;
buf[index++] = *src;
src = (byte*)&value.Y; // it may have padding ??
buf[index++] = *src++;
buf[index++] = *src++;
buf[index++] = *src++;
buf[index++] = *src;
src = (byte*)&value.Z;
buf[index++] = *src++;
buf[index++] = *src++;
buf[index++] = *src++;
buf[index++] = *src;
src = (byte*)&value.W;
buf[index++] = *src++;
buf[index++] = *src++;
buf[index++] = *src++;
buf[index++] = *src;
}
}
unsafe public class rstreamer
{
private byte[] rbuf;
private int ptr;
private byte* dst;
public rstreamer(byte[] data)
{
rbuf = data;
ptr = 0;
}
public void close()
{
}
public void Seek(int pos)
{
ptr = pos;
}
public void Seekrel(int pos)
{
ptr += pos;
}
public byte Rbyte()
{
return (byte)rbuf[ptr++];
}
public short Rshort()
{
short v;
dst = (byte*)&v;
*dst++ = rbuf[ptr++];
*dst = rbuf[ptr++];
return v;
}
public ushort Rushort()
{
ushort v;
dst = (byte*)&v;
*dst++ = rbuf[ptr++];
*dst = rbuf[ptr++];
return v;
}
public int Rint()
{
int v;
dst = (byte*)&v;
*dst++ = rbuf[ptr++];
*dst++ = rbuf[ptr++];
*dst++ = rbuf[ptr++];
*dst = rbuf[ptr++];
return v;
}
public uint Ruint()
{
uint v;
dst = (byte*)&v;
*dst++ = rbuf[ptr++];
*dst++ = rbuf[ptr++];
*dst++ = rbuf[ptr++];
*dst = rbuf[ptr++];
return v;
}
public long Rlong()
{
long v;
dst = (byte*)&v;
*dst++ = rbuf[ptr++];
*dst++ = rbuf[ptr++];
*dst++ = rbuf[ptr++];
*dst++ = rbuf[ptr++];
*dst++ = rbuf[ptr++];
*dst++ = rbuf[ptr++];
*dst++ = rbuf[ptr++];
*dst = rbuf[ptr++];
return v;
}
public ulong Rulong()
{
ulong v;
dst = (byte*)&v;
*dst++ = rbuf[ptr++];
*dst++ = rbuf[ptr++];
*dst++ = rbuf[ptr++];
*dst++ = rbuf[ptr++];
*dst++ = rbuf[ptr++];
*dst++ = rbuf[ptr++];
*dst++ = rbuf[ptr++];
*dst = rbuf[ptr++];
return v;
}
public float Rfloat()
{
float v;
dst = (byte*)&v;
*dst++ = rbuf[ptr++];
*dst++ = rbuf[ptr++];
*dst++ = rbuf[ptr++];
*dst = rbuf[ptr++];
return v;
}
public double Rdouble()
{
double v;
dst = (byte*)&v;
*dst++ = rbuf[ptr++];
*dst++ = rbuf[ptr++];
*dst++ = rbuf[ptr++];
*dst++ = rbuf[ptr++];
*dst++ = rbuf[ptr++];
*dst++ = rbuf[ptr++];
*dst++ = rbuf[ptr++];
*dst = rbuf[ptr++];
return v;
}
public Vector3 Rvector3()
{
Vector3 v;
dst = (byte*)&v.X;
*dst++ = rbuf[ptr++];
*dst++ = rbuf[ptr++];
*dst++ = rbuf[ptr++];
*dst = rbuf[ptr++];
dst = (byte*)&v.Y;
*dst++ = rbuf[ptr++];
*dst++ = rbuf[ptr++];
*dst++ = rbuf[ptr++];
*dst = rbuf[ptr++];
dst = (byte*)&v.Z;
*dst++ = rbuf[ptr++];
*dst++ = rbuf[ptr++];
*dst++ = rbuf[ptr++];
*dst = rbuf[ptr++];
return v;
}
public Quaternion Rquat()
{
Quaternion v;
dst = (byte*)&v.X;
*dst++ = rbuf[ptr++];
*dst++ = rbuf[ptr++];
*dst++ = rbuf[ptr++];
*dst = rbuf[ptr++];
dst = (byte*)&v.Y;
*dst++ = rbuf[ptr++];
*dst++ = rbuf[ptr++];
*dst++ = rbuf[ptr++];
*dst = rbuf[ptr++];
dst = (byte*)&v.Z;
*dst++ = rbuf[ptr++];
*dst++ = rbuf[ptr++];
*dst++ = rbuf[ptr++];
*dst = rbuf[ptr++];
dst = (byte*)&v.W;
*dst++ = rbuf[ptr++];
*dst++ = rbuf[ptr++];
*dst++ = rbuf[ptr++];
*dst = rbuf[ptr++];
return v;
}
}
}

View File

@ -65,5 +65,6 @@ namespace OpenSim.Region.Physics.Manager
void releasePinned();
void Append(IMesh newMesh);
void TransformLinear(float[,] matrix, float[] offset);
Vector3 GetCentroid();
}
}

View File

@ -68,6 +68,17 @@ namespace OpenSim.Region.Physics.Manager
}
}
public struct ContactData
{
public float mu;
public float bounce;
public ContactData(float _mu, float _bounce)
{
mu = _mu;
bounce = _bounce;
}
}
/// <summary>
/// Used to pass collision information to OnCollisionUpdate listeners.
/// </summary>
@ -135,6 +146,8 @@ namespace OpenSim.Region.Physics.Manager
/// </summary>
public event CollisionUpdate OnCollisionUpdate;
public virtual void SetVehicle(object vdata) { }
public event OutOfBounds OnOutOfBounds;
#pragma warning restore 67
@ -142,6 +155,13 @@ namespace OpenSim.Region.Physics.Manager
{
get { return new NullPhysicsActor(); }
}
public virtual bool Building { get; set; }
public virtual ContactData ContactData
{
get { return new ContactData(0, 0); }
}
public abstract bool Stopped { get; }
@ -195,6 +215,11 @@ namespace OpenSim.Region.Physics.Manager
}
}
public virtual byte[] Serialize(bool PhysIsRunning)
{
return new byte[0];
}
public virtual void RaiseOutOfBounds(Vector3 pos)
{
// Make a temporary copy of the event to avoid possibility of
@ -554,5 +579,6 @@ namespace OpenSim.Region.Physics.Manager
{
return false;
}
}
}

View File

@ -128,6 +128,12 @@ namespace OpenSim.Region.Physics.Manager
public abstract PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
Vector3 size, Quaternion rotation, bool isPhysical, uint localid);
public virtual PhysicsActor AddPrimShape(string primName, PhysicsActor parent, PrimitiveBaseShape pbs, Vector3 position,
uint localid, byte[] sdata)
{
return null;
}
public virtual float TimeDilation
{
get { return 1.0f; }
@ -225,7 +231,7 @@ namespace OpenSim.Region.Physics.Manager
}
public virtual void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents) {}
public virtual void CombineTerrain(float[] heightMap, Vector3 pOffset) {}
public virtual void UnCombine(PhysicsScene pScene) {}
/// <summary>
@ -263,5 +269,13 @@ namespace OpenSim.Region.Physics.Manager
{
return new List<ContactResult>();
}
public virtual void RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, RaycastCallback retMethod){}
public virtual void RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, int Count, RayCallback retMethod) { }
public virtual List<ContactResult> RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, int Count)
{
return new List<ContactResult>();
}
}
}

View File

@ -26,6 +26,7 @@
*/
using System;
using OpenMetaverse;
namespace OpenSim.Region.Physics.Manager
{
@ -117,5 +118,47 @@ namespace OpenSim.Region.Physics.Manager
NO_DEFLECTION = 16392,
LOCK_ROTATION = 32784
}
public struct VehicleData
{
public Vehicle m_type;
public VehicleFlag m_flags;
// Linear properties
public Vector3 m_linearMotorDirection;
public Vector3 m_linearFrictionTimescale;
public float m_linearMotorDecayTimescale;
public float m_linearMotorTimescale;
public Vector3 m_linearMotorOffset;
//Angular properties
public Vector3 m_angularMotorDirection;
public float m_angularMotorTimescale;
public float m_angularMotorDecayTimescale;
public Vector3 m_angularFrictionTimescale;
//Deflection properties
public float m_angularDeflectionEfficiency;
public float m_angularDeflectionTimescale;
public float m_linearDeflectionEfficiency;
public float m_linearDeflectionTimescale;
//Banking properties
public float m_bankingEfficiency;
public float m_bankingMix;
public float m_bankingTimescale;
//Hover and Buoyancy properties
public float m_VhoverHeight;
public float m_VhoverEfficiency;
public float m_VhoverTimescale;
public float m_VehicleBuoyancy;
//Attractor properties
public float m_verticalAttractionEfficiency;
public float m_verticalAttractionTimescale;
// Axis
public Quaternion m_referenceFrame;
}
}

View File

@ -46,11 +46,36 @@ namespace OpenSim.Region.Physics.Meshing
IntPtr m_indicesPtr = IntPtr.Zero;
int m_indexCount = 0;
public float[] m_normals;
Vector3 _centroid;
int _centroidDiv;
private class vertexcomp : IEqualityComparer<Vertex>
{
public bool Equals(Vertex v1, Vertex v2)
{
if (v1.X == v2.X && v1.Y == v2.Y && v1.Z == v2.Z)
return true;
else
return false;
}
public int GetHashCode(Vertex v)
{
int a = v.X.GetHashCode();
int b = v.Y.GetHashCode();
int c = v.Z.GetHashCode();
return (a << 16) ^ (b << 8) ^ c;
}
}
public Mesh()
{
m_vertices = new Dictionary<Vertex, int>();
vertexcomp vcomp = new vertexcomp();
m_vertices = new Dictionary<Vertex, int>(vcomp);
m_triangles = new List<Triangle>();
_centroid = Vector3.Zero;
_centroidDiv = 0;
}
public Mesh Clone()
@ -61,7 +86,8 @@ namespace OpenSim.Region.Physics.Meshing
{
result.Add(new Triangle(t.v1.Clone(), t.v2.Clone(), t.v3.Clone()));
}
result._centroid = _centroid;
result._centroidDiv = _centroidDiv;
return result;
}
@ -71,15 +97,57 @@ namespace OpenSim.Region.Physics.Meshing
throw new NotSupportedException("Attempt to Add to a pinned Mesh");
// If a vertex of the triangle is not yet in the vertices list,
// add it and set its index to the current index count
// vertex == seems broken
// skip colapsed triangles
if ((triangle.v1.X == triangle.v2.X && triangle.v1.Y == triangle.v2.Y && triangle.v1.Z == triangle.v2.Z)
|| (triangle.v1.X == triangle.v3.X && triangle.v1.Y == triangle.v3.Y && triangle.v1.Z == triangle.v3.Z)
|| (triangle.v2.X == triangle.v3.X && triangle.v2.Y == triangle.v3.Y && triangle.v2.Z == triangle.v3.Z)
)
{
return;
}
if (m_vertices.Count == 0)
{
_centroidDiv = 0;
_centroid = Vector3.Zero;
}
if (!m_vertices.ContainsKey(triangle.v1))
{
m_vertices[triangle.v1] = m_vertices.Count;
_centroid.X += triangle.v1.X;
_centroid.Y += triangle.v1.Y;
_centroid.Z += triangle.v1.Z;
_centroidDiv++;
}
if (!m_vertices.ContainsKey(triangle.v2))
{
m_vertices[triangle.v2] = m_vertices.Count;
_centroid.X += triangle.v2.X;
_centroid.Y += triangle.v2.Y;
_centroid.Z += triangle.v2.Z;
_centroidDiv++;
}
if (!m_vertices.ContainsKey(triangle.v3))
{
m_vertices[triangle.v3] = m_vertices.Count;
_centroid.X += triangle.v3.X;
_centroid.Y += triangle.v3.Y;
_centroid.Z += triangle.v3.Z;
_centroidDiv++;
}
m_triangles.Add(triangle);
}
public Vector3 GetCentroid()
{
if (_centroidDiv > 0)
return new Vector3(_centroid.X / _centroidDiv, _centroid.Y / _centroidDiv, _centroid.Z / _centroidDiv);
else
return Vector3.Zero;
}
public void CalcNormals()
{
int iTriangles = m_triangles.Count;

View File

@ -74,6 +74,8 @@ namespace OpenSim.Region.Physics.Meshing
#endif
private bool cacheSculptMaps = true;
private bool cacheSculptAlphaMaps = true;
private string decodedSculptMapPath = null;
private bool useMeshiesPhysicsMesh = false;
@ -87,7 +89,16 @@ namespace OpenSim.Region.Physics.Meshing
IConfig mesh_config = config.Configs["Mesh"];
decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache");
cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps);
if (Environment.OSVersion.Platform == PlatformID.Unix)
{
cacheSculptAlphaMaps = false;
}
else
cacheSculptAlphaMaps = cacheSculptMaps;
if(mesh_config != null)
useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh);
@ -268,15 +279,18 @@ namespace OpenSim.Region.Physics.Meshing
{
if (!GenerateCoordsAndFacesFromPrimSculptData(primName, primShape, size, lod, out coords, out faces))
return null;
// Remove the reference to any JPEG2000 sculpt data so it can be GCed
// don't loose it
// primShape.SculptData = Utils.EmptyBytes;
}
// primShape.SculptDataLoaded = true;
}
else
{
if (!GenerateCoordsAndFacesFromPrimShapeData(primName, primShape, size, lod, out coords, out faces))
return null;
}
// Remove the reference to any JPEG2000 sculpt data so it can be GCed
// keep compatible
primShape.SculptData = Utils.EmptyBytes;
int numCoords = coords.Count;
@ -482,7 +496,8 @@ namespace OpenSim.Region.Physics.Meshing
//idata = CSJ2K.J2kImage.FromBytes(primShape.SculptData);
if (cacheSculptMaps)
if (cacheSculptMaps && (cacheSculptAlphaMaps || (((ImageFlags)(idata.Flags) & ImageFlags.HasAlpha) ==0)))
// don't cache images with alpha channel in linux since mono can't load them correctly)
{
try { idata.Save(decodedSculptFileName, ImageFormat.MemoryBmp); }
catch (Exception e) { m_log.Error("[SCULPT]: unable to cache sculpt map " + decodedSculptFileName + " " + e.Message); }

View File

@ -58,28 +58,24 @@ namespace PrimMesher
if (bmW == 0 || bmH == 0)
throw new Exception("SculptMap: bitmap has no data");
int numLodPixels = lod * 2 * lod * 2; // (32 * 2)^2 = 64^2 pixels for default sculpt map image
int numLodPixels = lod * lod; // (32 * 2)^2 = 64^2 pixels for default sculpt map image
bool smallMap = bmW * bmH <= numLodPixels;
bool needsScaling = false;
bool smallMap = bmW * bmH <= lod * lod;
width = bmW;
height = bmH;
while (width * height > numLodPixels)
while (width * height > numLodPixels * 4)
{
width >>= 1;
height >>= 1;
needsScaling = true;
}
try
{
if (needsScaling)
bm = ScaleImage(bm, width, height,
System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor);
bm = ScaleImage(bm, width, height);
}
catch (Exception e)
@ -87,7 +83,7 @@ namespace PrimMesher
throw new Exception("Exception in ScaleImage(): e: " + e.ToString());
}
if (width * height > lod * lod)
if (width * height > numLodPixels)
{
width >>= 1;
height >>= 1;
@ -144,15 +140,17 @@ namespace PrimMesher
int rowNdx, colNdx;
int smNdx = 0;
for (rowNdx = 0; rowNdx < numRows; rowNdx++)
{
List<Coord> row = new List<Coord>(numCols);
for (colNdx = 0; colNdx < numCols; colNdx++)
{
if (mirror)
row.Add(new Coord(-(redBytes[smNdx] * pixScale - 0.5f), (greenBytes[smNdx] * pixScale - 0.5f), blueBytes[smNdx] * pixScale - 0.5f));
row.Add(new Coord(-((float)redBytes[smNdx] * pixScale - 0.5f), ((float)greenBytes[smNdx] * pixScale - 0.5f), (float)blueBytes[smNdx] * pixScale - 0.5f));
else
row.Add(new Coord(redBytes[smNdx] * pixScale - 0.5f, greenBytes[smNdx] * pixScale - 0.5f, blueBytes[smNdx] * pixScale - 0.5f));
row.Add(new Coord((float)redBytes[smNdx] * pixScale - 0.5f, (float)greenBytes[smNdx] * pixScale - 0.5f, (float)blueBytes[smNdx] * pixScale - 0.5f));
++smNdx;
}
@ -161,23 +159,39 @@ namespace PrimMesher
return rows;
}
private Bitmap ScaleImage(Bitmap srcImage, int destWidth, int destHeight,
System.Drawing.Drawing2D.InterpolationMode interpMode)
private Bitmap ScaleImage(Bitmap srcImage, int destWidth, int destHeight)
{
Bitmap scaledImage = new Bitmap(srcImage, destWidth, destHeight);
scaledImage.SetResolution(96.0f, 96.0f);
Graphics grPhoto = Graphics.FromImage(scaledImage);
grPhoto.InterpolationMode = interpMode;
Bitmap scaledImage = new Bitmap(destWidth, destHeight, PixelFormat.Format24bppRgb);
Color c;
float xscale = srcImage.Width / destWidth;
float yscale = srcImage.Height / destHeight;
float sy = 0.5f;
for (int y = 0; y < destHeight; y++)
{
float sx = 0.5f;
for (int x = 0; x < destWidth; x++)
{
try
{
c = srcImage.GetPixel((int)(sx), (int)(sy));
scaledImage.SetPixel(x, y, Color.FromArgb(c.R, c.G, c.B));
}
catch (IndexOutOfRangeException)
{
}
grPhoto.DrawImage(srcImage,
new Rectangle(0, 0, destWidth, destHeight),
new Rectangle(0, 0, srcImage.Width, srcImage.Height),
GraphicsUnit.Pixel);
grPhoto.Dispose();
sx += xscale;
}
sy += yscale;
}
srcImage.Dispose();
return scaledImage;
}
}
}
}
#endif

View File

@ -0,0 +1,58 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System.Reflection;
using System.Runtime.InteropServices;
// Information about this assembly is defined by the following
// attributes.
//
// change them to the information which is associated with the assembly
// you compile.
[assembly : AssemblyTitle("OdePlugin")]
[assembly : AssemblyDescription("Ubit Variation")]
[assembly : AssemblyConfiguration("")]
[assembly : AssemblyCompany("http://opensimulator.org")]
[assembly : AssemblyProduct("OdePlugin")]
[assembly : AssemblyCopyright("Copyright (c) OpenSimulator.org Developers 2007-2009")]
[assembly : AssemblyTrademark("")]
[assembly : AssemblyCulture("")]
// This sets the default COM visibility of types in the assembly to invisible.
// If you need to expose a type to COM, use [ComVisible(true)] on that type.
[assembly : ComVisible(false)]
// The assembly version has following format :
//
// Major.Minor.Build.Revision
//
// You can specify all values by your own or you can build default build and revision
// numbers with the '*' character (the default):
[assembly : AssemblyVersion("0.6.5.*")]

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,849 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* Revised Aug, Sept 2009 by Kitto Flora. ODEDynamics.cs replaces
* ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised:
* ODEPrim.cs contains methods dealing with Prim editing, Prim
* characteristics and Kinetic motion.
* ODEDynamics.cs contains methods dealing with Prim Physical motion
* (dynamics) and the associated settings. Old Linear and angular
* motors for dynamic motion have been replace with MoveLinear()
* and MoveAngular(); 'Physical' is used only to switch ODE dynamic
* simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_<other> is to
* switch between 'VEHICLE' parameter use and general dynamics
* settings use.
*/
// Ubit 2012
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.InteropServices;
using log4net;
using OpenMetaverse;
using OdeAPI;
using OpenSim.Framework;
using OpenSim.Region.Physics.Manager;
namespace OpenSim.Region.Physics.OdePlugin
{
public class ODEDynamics
{
public Vehicle Type
{
get { return m_type; }
}
private OdePrim rootPrim;
private OdeScene _pParentScene;
// Vehicle properties
private Quaternion m_referenceFrame = Quaternion.Identity; // Axis modifier
private Quaternion m_RollreferenceFrame = Quaternion.Identity; // what hell is this ?
private Vehicle m_type = Vehicle.TYPE_NONE; // If a 'VEHICLE', and what kind
private VehicleFlag m_flags = (VehicleFlag) 0; // Boolean settings:
// HOVER_TERRAIN_ONLY
// HOVER_GLOBAL_HEIGHT
// NO_DEFLECTION_UP
// HOVER_WATER_ONLY
// HOVER_UP_ONLY
// LIMIT_MOTOR_UP
// LIMIT_ROLL_ONLY
private Vector3 m_BlockingEndPoint = Vector3.Zero; // not sl
// Linear properties
private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time
private Vector3 m_linearFrictionTimescale = new Vector3(1000, 1000, 1000);
private float m_linearMotorDecayTimescale = 120;
private float m_linearMotorTimescale = 1000;
private Vector3 m_lastLinearVelocityVector = Vector3.Zero;
private Vector3 m_linearMotorOffset = Vector3.Zero;
//Angular properties
private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor
private float m_angularMotorTimescale = 1000; // motor angular velocity ramp up rate
private float m_angularMotorDecayTimescale = 120; // motor angular velocity decay rate
private Vector3 m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); // body angular velocity decay rate
private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body
//Deflection properties
private float m_angularDeflectionEfficiency = 0;
private float m_angularDeflectionTimescale = 1000;
private float m_linearDeflectionEfficiency = 0;
private float m_linearDeflectionTimescale = 1000;
//Banking properties
private float m_bankingEfficiency = 0;
private float m_bankingMix = 0;
private float m_bankingTimescale = 0;
//Hover and Buoyancy properties
private float m_VhoverHeight = 0f;
private float m_VhoverEfficiency = 0f;
private float m_VhoverTimescale = 1000f;
private float m_VehicleBuoyancy = 0f; //KF: m_VehicleBuoyancy is set by VEHICLE_BUOYANCY for a vehicle.
// Modifies gravity. Slider between -1 (double-gravity) and 1 (full anti-gravity)
// KF: So far I have found no good method to combine a script-requested .Z velocity and gravity.
// Therefore only m_VehicleBuoyancy=1 (0g) will use the script-requested .Z velocity.
//Attractor properties
private float m_verticalAttractionEfficiency = 1.0f; // damped
private float m_verticalAttractionTimescale = 1000f; // Timescale > 300 means no vert attractor.
// auxiliar
private Vector3 m_dir = Vector3.Zero; // velocity applied to body
private float m_lmEfect = 0; // current linear motor eficiency
private float m_amEfect = 0; // current angular motor eficiency
public ODEDynamics(OdePrim rootp)
{
rootPrim = rootp;
_pParentScene = rootPrim._parent_scene;
}
internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue)
{
float len;
float invtimestep = 1.0f / _pParentScene.ODE_STEPSIZE;
float timestep = _pParentScene.ODE_STEPSIZE;
switch (pParam)
{
case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
if (pValue < 0f) pValue = 0f;
if (pValue > 1f) pValue = 1f;
m_angularDeflectionEfficiency = pValue;
break;
case Vehicle.ANGULAR_DEFLECTION_TIMESCALE:
if (pValue < timestep) pValue = timestep;
m_angularDeflectionTimescale = pValue;
break;
case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE:
// if (pValue < timestep) pValue = timestep;
// try to make impulses to work a bit better
if (pValue < 0.5f) pValue = 0.5f;
else if (pValue > 120) pValue = 120;
m_angularMotorDecayTimescale = pValue * invtimestep;
break;
case Vehicle.ANGULAR_MOTOR_TIMESCALE:
if (pValue < timestep) pValue = timestep;
m_angularMotorTimescale = pValue;
break;
case Vehicle.BANKING_EFFICIENCY:
if (pValue < -1f) pValue = -1f;
if (pValue > 1f) pValue = 1f;
m_bankingEfficiency = pValue;
break;
case Vehicle.BANKING_MIX:
if (pValue < 0f) pValue = 0f;
if (pValue > 1f) pValue = 1f;
m_bankingMix = pValue;
break;
case Vehicle.BANKING_TIMESCALE:
if (pValue < timestep) pValue = timestep;
m_bankingTimescale = pValue;
break;
case Vehicle.BUOYANCY:
if (pValue < -1f) pValue = -1f;
if (pValue > 1f) pValue = 1f;
m_VehicleBuoyancy = pValue;
break;
case Vehicle.HOVER_EFFICIENCY:
if (pValue < 0f) pValue = 0f;
if (pValue > 1f) pValue = 1f;
m_VhoverEfficiency = pValue;
break;
case Vehicle.HOVER_HEIGHT:
m_VhoverHeight = pValue;
break;
case Vehicle.HOVER_TIMESCALE:
if (pValue < timestep) pValue = timestep;
m_VhoverTimescale = pValue;
break;
case Vehicle.LINEAR_DEFLECTION_EFFICIENCY:
if (pValue < 0f) pValue = 0f;
if (pValue > 1f) pValue = 1f;
m_linearDeflectionEfficiency = pValue;
break;
case Vehicle.LINEAR_DEFLECTION_TIMESCALE:
if (pValue < timestep) pValue = timestep;
m_linearDeflectionTimescale = pValue;
break;
case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE:
// if (pValue < timestep) pValue = timestep;
// try to make impulses to work a bit better
if (pValue < 0.5f) pValue = 0.5f;
else if (pValue > 120) pValue = 120;
m_linearMotorDecayTimescale = pValue * invtimestep;
break;
case Vehicle.LINEAR_MOTOR_TIMESCALE:
if (pValue < timestep) pValue = timestep;
m_linearMotorTimescale = pValue;
break;
case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY:
if (pValue < 0f) pValue = 0f;
if (pValue > 1f) pValue = 1f;
m_verticalAttractionEfficiency = pValue;
break;
case Vehicle.VERTICAL_ATTRACTION_TIMESCALE:
if (pValue < timestep) pValue = timestep;
m_verticalAttractionTimescale = pValue;
break;
// These are vector properties but the engine lets you use a single float value to
// set all of the components to the same value
case Vehicle.ANGULAR_FRICTION_TIMESCALE:
if (pValue < timestep) pValue = timestep;
m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue);
break;
case Vehicle.ANGULAR_MOTOR_DIRECTION:
m_angularMotorDirection = new Vector3(pValue, pValue, pValue);
len = m_angularMotorDirection.Length();
if (len > 12.566f)
m_angularMotorDirection *= (12.566f / len);
m_amEfect = 1.0f; // turn it on
break;
case Vehicle.LINEAR_FRICTION_TIMESCALE:
if (pValue < timestep) pValue = timestep;
m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue);
break;
case Vehicle.LINEAR_MOTOR_DIRECTION:
m_linearMotorDirection = new Vector3(pValue, pValue, pValue);
len = m_linearMotorDirection.Length();
if (len > 30.0f)
m_linearMotorDirection *= (30.0f / len);
m_lmEfect = 1.0f; // turn it on
break;
case Vehicle.LINEAR_MOTOR_OFFSET:
m_linearMotorOffset = new Vector3(pValue, pValue, pValue);
len = m_linearMotorOffset.Length();
if (len > 100.0f)
m_linearMotorOffset *= (100.0f / len);
break;
}
}//end ProcessFloatVehicleParam
internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue)
{
float len;
float invtimestep = 1.0f / _pParentScene.ODE_STEPSIZE;
float timestep = _pParentScene.ODE_STEPSIZE;
switch (pParam)
{
case Vehicle.ANGULAR_FRICTION_TIMESCALE:
if (pValue.X < timestep) pValue.X = timestep;
if (pValue.Y < timestep) pValue.Y = timestep;
if (pValue.Z < timestep) pValue.Z = timestep;
m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
break;
case Vehicle.ANGULAR_MOTOR_DIRECTION:
m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
// Limit requested angular speed to 2 rps= 4 pi rads/sec
len = m_angularMotorDirection.Length();
if (len > 12.566f)
m_angularMotorDirection *= (12.566f / len);
m_amEfect = 1.0f; // turn it on
break;
case Vehicle.LINEAR_FRICTION_TIMESCALE:
if (pValue.X < timestep) pValue.X = timestep;
if (pValue.Y < timestep) pValue.Y = timestep;
if (pValue.Z < timestep) pValue.Z = timestep;
m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
break;
case Vehicle.LINEAR_MOTOR_DIRECTION:
m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
len = m_linearMotorDirection.Length();
if (len > 30.0f)
m_linearMotorDirection *= (30.0f / len);
m_lmEfect = 1.0f; // turn it on
break;
case Vehicle.LINEAR_MOTOR_OFFSET:
m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z);
len = m_linearMotorOffset.Length();
if (len > 100.0f)
m_linearMotorOffset *= (100.0f / len);
break;
case Vehicle.BLOCK_EXIT:
m_BlockingEndPoint = new Vector3(pValue.X, pValue.Y, pValue.Z);
break;
}
}//end ProcessVectorVehicleParam
internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue)
{
switch (pParam)
{
case Vehicle.REFERENCE_FRAME:
m_referenceFrame = Quaternion.Inverse(pValue);
break;
case Vehicle.ROLL_FRAME:
m_RollreferenceFrame = pValue;
break;
}
}//end ProcessRotationVehicleParam
internal void ProcessVehicleFlags(int pParam, bool remove)
{
if (remove)
{
m_flags &= ~((VehicleFlag)pParam);
}
else
{
m_flags |= (VehicleFlag)pParam;
}
}//end ProcessVehicleFlags
internal void ProcessTypeChange(Vehicle pType)
{
float invtimestep = _pParentScene.ODE_STEPSIZE;
m_lmEfect = 0;
m_amEfect = 0;
m_linearMotorDirection = Vector3.Zero;
m_angularMotorDirection = Vector3.Zero;
m_BlockingEndPoint = Vector3.Zero;
m_RollreferenceFrame = Quaternion.Identity;
m_linearMotorOffset = Vector3.Zero;
m_referenceFrame = Quaternion.Identity;
// Set Defaults For Type
m_type = pType;
switch (pType)
{
case Vehicle.TYPE_NONE:
m_linearFrictionTimescale = new Vector3(1000, 1000, 1000);
m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
m_linearMotorTimescale = 1000;
m_linearMotorDecayTimescale = 120 * invtimestep;
m_angularMotorTimescale = 1000;
m_angularMotorDecayTimescale = 1000 * invtimestep;
m_VhoverHeight = 0;
m_VhoverTimescale = 1000;
m_VehicleBuoyancy = 0;
m_flags = (VehicleFlag)0;
break;
case Vehicle.TYPE_SLED:
m_linearFrictionTimescale = new Vector3(30, 1, 1000);
m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
m_linearMotorTimescale = 1000;
m_linearMotorDecayTimescale = 120 * invtimestep;
m_angularMotorTimescale = 1000;
m_angularMotorDecayTimescale = 120 * invtimestep;
m_VhoverHeight = 0;
m_VhoverEfficiency = 1;
m_VhoverTimescale = 10;
m_VehicleBuoyancy = 0;
m_linearDeflectionEfficiency = 1;
m_linearDeflectionTimescale = 1;
m_angularDeflectionEfficiency = 0;
m_angularDeflectionTimescale = 1000;
m_bankingEfficiency = 0;
m_bankingMix = 1;
m_bankingTimescale = 10;
m_flags &=
~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
break;
case Vehicle.TYPE_CAR:
m_linearFrictionTimescale = new Vector3(100, 2, 1000);
m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
m_linearMotorTimescale = 1;
m_linearMotorDecayTimescale = 60 * invtimestep;
m_angularMotorTimescale = 1;
m_angularMotorDecayTimescale = 0.8f * invtimestep;
m_VhoverHeight = 0;
m_VhoverEfficiency = 0;
m_VhoverTimescale = 1000;
m_VehicleBuoyancy = 0;
m_linearDeflectionEfficiency = 1;
m_linearDeflectionTimescale = 2;
m_angularDeflectionEfficiency = 0;
m_angularDeflectionTimescale = 10;
m_verticalAttractionEfficiency = 1f;
m_verticalAttractionTimescale = 10f;
m_bankingEfficiency = -0.2f;
m_bankingMix = 1;
m_bankingTimescale = 1;
m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT);
m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY |
VehicleFlag.LIMIT_MOTOR_UP | VehicleFlag.HOVER_UP_ONLY);
break;
case Vehicle.TYPE_BOAT:
m_linearFrictionTimescale = new Vector3(10, 3, 2);
m_angularFrictionTimescale = new Vector3(10, 10, 10);
m_linearMotorTimescale = 5;
m_linearMotorDecayTimescale = 60 * invtimestep;
m_angularMotorTimescale = 4;
m_angularMotorDecayTimescale = 4 * invtimestep;
m_VhoverHeight = 0;
m_VhoverEfficiency = 0.5f;
m_VhoverTimescale = 2;
m_VehicleBuoyancy = 1;
m_linearDeflectionEfficiency = 0.5f;
m_linearDeflectionTimescale = 3;
m_angularDeflectionEfficiency = 0.5f;
m_angularDeflectionTimescale = 5;
m_verticalAttractionEfficiency = 0.5f;
m_verticalAttractionTimescale = 5f;
m_bankingEfficiency = -0.3f;
m_bankingMix = 0.8f;
m_bankingTimescale = 1;
m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY |
VehicleFlag.HOVER_GLOBAL_HEIGHT |
VehicleFlag.HOVER_UP_ONLY |
VehicleFlag.LIMIT_ROLL_ONLY);
m_flags |= (VehicleFlag.NO_DEFLECTION_UP |
VehicleFlag.LIMIT_MOTOR_UP |
VehicleFlag.HOVER_WATER_ONLY);
break;
case Vehicle.TYPE_AIRPLANE:
m_linearFrictionTimescale = new Vector3(200, 10, 5);
m_angularFrictionTimescale = new Vector3(20, 20, 20);
m_linearMotorTimescale = 2;
m_linearMotorDecayTimescale = 60 * invtimestep;
m_angularMotorTimescale = 4;
m_angularMotorDecayTimescale = 8 * invtimestep;
m_VhoverHeight = 0;
m_VhoverEfficiency = 0.5f;
m_VhoverTimescale = 1000;
m_VehicleBuoyancy = 0;
m_linearDeflectionEfficiency = 0.5f;
m_linearDeflectionTimescale = 0.5f;
m_angularDeflectionEfficiency = 1;
m_angularDeflectionTimescale = 2;
m_verticalAttractionEfficiency = 0.9f;
m_verticalAttractionTimescale = 2f;
m_bankingEfficiency = 1;
m_bankingMix = 0.7f;
m_bankingTimescale = 2;
m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY |
VehicleFlag.HOVER_TERRAIN_ONLY |
VehicleFlag.HOVER_GLOBAL_HEIGHT |
VehicleFlag.HOVER_UP_ONLY |
VehicleFlag.NO_DEFLECTION_UP |
VehicleFlag.LIMIT_MOTOR_UP);
m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
break;
case Vehicle.TYPE_BALLOON:
m_linearFrictionTimescale = new Vector3(5, 5, 5);
m_angularFrictionTimescale = new Vector3(10, 10, 10);
m_linearMotorTimescale = 5;
m_linearMotorDecayTimescale = 60 * invtimestep;
m_angularMotorTimescale = 6;
m_angularMotorDecayTimescale = 10 * invtimestep;
m_VhoverHeight = 5;
m_VhoverEfficiency = 0.8f;
m_VhoverTimescale = 10;
m_VehicleBuoyancy = 1;
m_linearDeflectionEfficiency = 0;
m_linearDeflectionTimescale = 5 * invtimestep;
m_angularDeflectionEfficiency = 0;
m_angularDeflectionTimescale = 5;
m_verticalAttractionEfficiency = 0f;
m_verticalAttractionTimescale = 1000f;
m_bankingEfficiency = 0;
m_bankingMix = 0.7f;
m_bankingTimescale = 5;
m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY |
VehicleFlag.HOVER_TERRAIN_ONLY |
VehicleFlag.HOVER_UP_ONLY |
VehicleFlag.NO_DEFLECTION_UP |
VehicleFlag.LIMIT_MOTOR_UP);
m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY |
VehicleFlag.HOVER_GLOBAL_HEIGHT);
break;
}
}//end SetDefaultsForType
internal void Stop()
{
m_lmEfect = 0;
m_amEfect = 0;
}
public static Vector3 Xrot(Quaternion rot)
{
Vector3 vec;
rot.Normalize(); // just in case
vec.X = 2 * (rot.X * rot.X + rot.W * rot.W) - 1;
vec.Y = 2 * (rot.X * rot.Y + rot.Z * rot.W);
vec.Z = 2 * (rot.X * rot.Z - rot.Y * rot.W);
return vec;
}
public static Vector3 Zrot(Quaternion rot)
{
Vector3 vec;
rot.Normalize(); // just in case
vec.X = 2 * (rot.X * rot.Z + rot.Y * rot.W);
vec.Y = 2 * (rot.Y * rot.Z - rot.X * rot.W);
vec.Z = 2 * (rot.Z * rot.Z + rot.W * rot.W) - 1;
return vec;
}
private const float halfpi = 0.5f * (float)Math.PI;
public static Vector3 ubitRot2Euler(Quaternion rot)
{
// returns roll in X
// pitch in Y
// yaw in Z
Vector3 vec;
// assuming rot is normalised
// rot.Normalize();
float zX = rot.X * rot.Z + rot.Y * rot.W;
if (zX < -0.49999f)
{
vec.X = 0;
vec.Y = -halfpi;
vec.Z = (float)(-2d * Math.Atan(rot.X / rot.W));
}
else if (zX > 0.49999f)
{
vec.X = 0;
vec.Y = halfpi;
vec.Z = (float)(2d * Math.Atan(rot.X / rot.W));
}
else
{
vec.Y = (float)Math.Asin(2 * zX);
float sqw = rot.W * rot.W;
float minuszY = rot.X * rot.W - rot.Y * rot.Z;
float zZ = rot.Z * rot.Z + sqw - 0.5f;
vec.X = (float)Math.Atan2(minuszY, zZ);
float yX = rot.Z * rot.W - rot.X * rot.Y; //( have negative ?)
float yY = rot.X * rot.X + sqw - 0.5f;
vec.Z = (float)Math.Atan2(yX, yY);
}
return vec;
}
public static void GetRollPitch(Quaternion rot, out float roll, out float pitch)
{
// assuming rot is normalised
// rot.Normalize();
float zX = rot.X * rot.Z + rot.Y * rot.W;
if (zX < -0.49999f)
{
roll = 0;
pitch = -halfpi;
}
else if (zX > 0.49999f)
{
roll = 0;
pitch = halfpi;
}
else
{
pitch = (float)Math.Asin(2 * zX);
float minuszY = rot.X * rot.W - rot.Y * rot.Z;
float zZ = rot.Z * rot.Z + rot.W * rot.W - 0.5f;
roll = (float)Math.Atan2(minuszY, zZ);
}
return ;
}
internal void Step()//float pTimestep)
{
IntPtr Body = rootPrim.Body;
d.Quaternion rot = d.BodyGetQuaternion(Body);
Quaternion objrotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object
Quaternion rotq = objrotq; // rotq = rotation of object
rotq *= m_referenceFrame; // rotq is now rotation in vehicle reference frame
Quaternion irotq = Quaternion.Inverse(rotq);
d.Vector3 dvtmp;
Vector3 tmpV;
Vector3 curVel; // velocity in world
Vector3 curAngVel; // angular velocity in world
Vector3 force = Vector3.Zero; // actually linear aceleration until mult by mass in world frame
Vector3 torque = Vector3.Zero;// actually angular aceleration until mult by Inertia in vehicle frame
d.Vector3 dtorque = new d.Vector3();
dvtmp = d.BodyGetLinearVel(Body);
curVel.X = dvtmp.X;
curVel.Y = dvtmp.Y;
curVel.Z = dvtmp.Z;
Vector3 curLocalVel = curVel * irotq; // current velocity in local
dvtmp = d.BodyGetAngularVel(Body);
curAngVel.X = dvtmp.X;
curAngVel.Y = dvtmp.Y;
curAngVel.Z = dvtmp.Z;
Vector3 curLocalAngVel = curAngVel * irotq; // current angular velocity in local
// linear motor
if (m_lmEfect > 0.01 && m_linearMotorTimescale < 1000)
{
tmpV = m_linearMotorDirection - curLocalVel; // velocity error
tmpV *= m_lmEfect / m_linearMotorTimescale; // error to correct in this timestep
tmpV *= rotq; // to world
if ((m_flags & VehicleFlag.LIMIT_MOTOR_UP) != 0)
tmpV.Z = 0;
if (m_linearMotorOffset.X != 0 || m_linearMotorOffset.Y != 0 || m_linearMotorOffset.Z != 0)
{
// have offset, do it now
tmpV *= rootPrim.Mass;
d.BodyAddForceAtRelPos(Body, tmpV.X, tmpV.Y, tmpV.Z, m_linearMotorOffset.X, m_linearMotorOffset.Y, m_linearMotorOffset.Z);
}
else
{
force.X += tmpV.X;
force.Y += tmpV.Y;
force.Z += tmpV.Z;
}
m_lmEfect *= (1.0f - 1.0f / m_linearMotorDecayTimescale);
}
else
m_lmEfect = 0;
// friction
if (curLocalVel.X != 0 || curLocalVel.Y != 0 || curLocalVel.Z != 0)
{
tmpV.X = -curLocalVel.X / m_linearFrictionTimescale.X;
tmpV.Y = -curLocalVel.Y / m_linearFrictionTimescale.Y;
tmpV.Z = -curLocalVel.Z / m_linearFrictionTimescale.Z;
tmpV *= rotq; // to world
force.X += tmpV.X;
force.Y += tmpV.Y;
force.Z += tmpV.Z;
}
// hover
if (m_VhoverTimescale < 300)
{
d.Vector3 pos = d.BodyGetPosition(Body);
// default to global
float perr = m_VhoverHeight - pos.Z;;
if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0)
{
perr += _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y);
}
else if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0)
{
perr += _pParentScene.GetWaterLevel();
}
else if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) == 0)
{
float t = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y);
float w = _pParentScene.GetWaterLevel();
if (t > w)
perr += t;
else
perr += w;
}
if ((m_flags & VehicleFlag.HOVER_UP_ONLY) == 0 || perr > 0)
{
force.Z += (perr / m_VhoverTimescale / m_VhoverTimescale - curVel.Z * m_VhoverEfficiency) / _pParentScene.ODE_STEPSIZE;
force.Z += _pParentScene.gravityz * (1f - m_VehicleBuoyancy);
}
else // no buoyancy
force.Z += _pParentScene.gravityz;
}
else
{
// default gravity and buoancy
force.Z += _pParentScene.gravityz * (1f - m_VehicleBuoyancy);
}
// linear deflection
if (m_linearDeflectionEfficiency > 0)
{
float len = curVel.Length();
Vector3 atAxis;
atAxis = Xrot(rotq); // where are we pointing to
atAxis *= len; // make it same size as world velocity vector
tmpV = -atAxis; // oposite direction
atAxis -= curVel; // error to one direction
len = atAxis.LengthSquared();
tmpV -= curVel; // error to oposite
float lens = tmpV.LengthSquared();
if (len > 0.01 || lens > 0.01) // do nothing if close enougth
{
if (len < lens)
tmpV = atAxis;
tmpV *= (m_linearDeflectionEfficiency / m_linearDeflectionTimescale); // error to correct in this timestep
force.X += tmpV.X;
force.Y += tmpV.Y;
if ((m_flags & VehicleFlag.NO_DEFLECTION_UP) == 0)
force.Z += tmpV.Z;
}
}
// angular motor
if (m_amEfect > 0.01 && m_angularMotorTimescale < 1000)
{
tmpV = m_angularMotorDirection - curLocalAngVel; // velocity error
tmpV *= m_amEfect / m_angularMotorTimescale; // error to correct in this timestep
torque.X += tmpV.X;
torque.Y += tmpV.Y;
torque.Z += tmpV.Z;
m_amEfect *= (1 - 1.0f / m_angularMotorDecayTimescale);
}
else
m_amEfect = 0;
// angular friction
if (curLocalAngVel.X != 0 || curLocalAngVel.Y != 0 || curLocalAngVel.Z != 0)
{
torque.X -= curLocalAngVel.X / m_angularFrictionTimescale.X;
torque.Y -= curLocalAngVel.Y / m_angularFrictionTimescale.Y;
torque.Z -= curLocalAngVel.Z / m_angularFrictionTimescale.Z;
}
// angular deflection
if (m_angularDeflectionEfficiency > 0)
{
Vector3 dirv;
if (curLocalVel.X > 0.01f)
dirv = curLocalVel;
else if (curLocalVel.X < -0.01f)
// use oposite
dirv = -curLocalVel;
else
{
// make it fall into small positive x case
dirv.X = 0.01f;
dirv.Y = curLocalVel.Y;
dirv.Z = curLocalVel.Z;
}
float ftmp = m_angularDeflectionEfficiency / m_angularDeflectionTimescale;
if (Math.Abs(dirv.Z) > 0.01)
{
torque.Y += - (float)Math.Atan2(dirv.Z, dirv.X) * ftmp;
}
if (Math.Abs(dirv.Y) > 0.01)
{
torque.Z += (float)Math.Atan2(dirv.Y, dirv.X) * ftmp;
}
}
// vertical atractor
if (m_verticalAttractionTimescale < 300)
{
float roll;
float pitch;
GetRollPitch(irotq, out roll, out pitch);
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
{
torque.X -= -roll * ftmp + curLocalAngVel.X * ftmp2;
}
if (Math.Abs(pitch) > 0.01 && ((m_flags & VehicleFlag.LIMIT_ROLL_ONLY) == 0)) // pitch
{
torque.Y -= -pitch * ftmp + curLocalAngVel.Y * ftmp2;
}
if (m_bankingEfficiency != 0 && Math.Abs(roll) > 0.01)
{
float broll = roll * 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;
// make z rot be in world Z not local as seems to be in sl
tmpV.X = 0;
tmpV.Y = 0;
tmpV.Z = broll;
tmpV *= irotq;
torque.X += tmpV.X;
torque.Y += tmpV.Y;
torque.Z += tmpV.Z;
}
}
d.Mass dmass;
d.BodyGetMass(Body,out dmass);
if (force.X != 0 || force.Y != 0 || force.Z != 0)
{
force *= dmass.mass;
d.BodySetForce(Body, force.X, force.Y, force.Z);
}
if (torque.X != 0 || torque.Y != 0 || torque.Z != 0)
{
torque *= m_referenceFrame; // to object frame
dtorque.X = torque.X;
dtorque.Y = torque.Y;
dtorque.Z = torque.Z;
d.MultiplyM3V3(out dvtmp, ref dmass.I, ref dtorque);
d.BodyAddRelTorque(Body, dvtmp.X, dvtmp.Y, dvtmp.Z); // add torque in object frame
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,443 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using OpenMetaverse;
using OpenSim.Region.Physics.Manager;
using OdeAPI;
using log4net;
namespace OpenSim.Region.Physics.OdePlugin
{
/// <summary>
/// Processes raycast requests as ODE is in a state to be able to do them.
/// This ensures that it's thread safe and there will be no conflicts.
/// Requests get returned by a different thread then they were requested by.
/// </summary>
public class ODERayCastRequestManager
{
/// <summary>
/// Pending ray requests
/// </summary>
protected OpenSim.Framework.LocklessQueue<ODERayRequest> m_PendingRequests = new OpenSim.Framework.LocklessQueue<ODERayRequest>();
/// <summary>
/// Scene that created this object.
/// </summary>
private OdeScene m_scene;
IntPtr ray;
private const int ColisionContactGeomsPerTest = 5;
/// <summary>
/// ODE near callback delegate
/// </summary>
private d.NearCallback nearCallback;
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private List<ContactResult> m_contactResults = new List<ContactResult>();
public ODERayCastRequestManager(OdeScene pScene)
{
m_scene = pScene;
nearCallback = near;
ray = d.CreateRay(IntPtr.Zero, 1.0f);
}
/// <summary>
/// Queues a raycast
/// </summary>
/// <param name="position">Origin of Ray</param>
/// <param name="direction">Ray normal</param>
/// <param name="length">Ray length</param>
/// <param name="retMethod">Return method to send the results</param>
public void QueueRequest(Vector3 position, Vector3 direction, float length, RayCallback retMethod)
{
ODERayRequest req = new ODERayRequest();
req.geom = IntPtr.Zero;
req.callbackMethod = retMethod;
req.Count = 0;
req.length = length;
req.Normal = direction;
req.Origin = position;
m_PendingRequests.Enqueue(req);
}
public void QueueRequest(IntPtr geom, Vector3 position, Vector3 direction, float length, RayCallback retMethod)
{
ODERayRequest req = new ODERayRequest();
req.geom = geom;
req.callbackMethod = retMethod;
req.length = length;
req.Normal = direction;
req.Origin = position;
req.Count = 0;
m_PendingRequests.Enqueue(req);
}
public void QueueRequest(Vector3 position, Vector3 direction, float length, RaycastCallback retMethod)
{
ODERayRequest req = new ODERayRequest();
req.geom = IntPtr.Zero;
req.callbackMethod = retMethod;
req.Count = 0;
req.length = length;
req.Normal = direction;
req.Origin = position;
m_PendingRequests.Enqueue(req);
}
public void QueueRequest(IntPtr geom, Vector3 position, Vector3 direction, float length, RaycastCallback retMethod)
{
ODERayRequest req = new ODERayRequest();
req.geom = geom;
req.callbackMethod = retMethod;
req.length = length;
req.Normal = direction;
req.Origin = position;
req.Count = 0;
m_PendingRequests.Enqueue(req);
}
/// <summary>
/// Queues a raycast
/// </summary>
/// <param name="position">Origin of Ray</param>
/// <param name="direction">Ray normal</param>
/// <param name="length">Ray length</param>
/// <param name="count"></param>
/// <param name="retMethod">Return method to send the results</param>
public void QueueRequest(Vector3 position, Vector3 direction, float length, int count, RayCallback retMethod)
{
ODERayRequest req = new ODERayRequest();
req.geom = IntPtr.Zero;
req.callbackMethod = retMethod;
req.length = length;
req.Normal = direction;
req.Origin = position;
req.Count = count;
m_PendingRequests.Enqueue(req);
}
public void QueueRequest(IntPtr geom, Vector3 position, Vector3 direction, float length, int count, RayCallback retMethod)
{
ODERayRequest req = new ODERayRequest();
req.geom = geom;
req.callbackMethod = retMethod;
req.length = length;
req.Normal = direction;
req.Origin = position;
req.Count = count;
m_PendingRequests.Enqueue(req);
}
public void QueueRequest(Vector3 position, Vector3 direction, float length, int count, RaycastCallback retMethod)
{
ODERayRequest req = new ODERayRequest();
req.geom = IntPtr.Zero;
req.callbackMethod = retMethod;
req.length = length;
req.Normal = direction;
req.Origin = position;
req.Count = count;
m_PendingRequests.Enqueue(req);
}
public void QueueRequest(IntPtr geom, Vector3 position, Vector3 direction, float length, int count, RaycastCallback retMethod)
{
ODERayRequest req = new ODERayRequest();
req.geom = geom;
req.callbackMethod = retMethod;
req.length = length;
req.Normal = direction;
req.Origin = position;
req.Count = count;
m_PendingRequests.Enqueue(req);
}
/// <summary>
/// Process all queued raycast requests
/// </summary>
/// <returns>Time in MS the raycasts took to process.</returns>
public int ProcessQueuedRequests()
{
int time = System.Environment.TickCount;
if (m_PendingRequests.Count <= 0)
return 0;
if (m_scene.ContactgeomsArray == IntPtr.Zero) // oops something got wrong or scene isn't ready still
{
m_PendingRequests.Clear();
return 0;
}
ODERayRequest req;
int i = 50; // arbitary limit of processed tests per frame
while(m_PendingRequests.Dequeue(out req))
{
if (req.geom == IntPtr.Zero)
doSpaceRay(req);
else
doGeomRay(req);
if(--i < 0)
break;
}
lock (m_contactResults)
m_contactResults.Clear();
return System.Environment.TickCount - time;
}
/// <summary>
/// Method that actually initiates the raycast with full top space
/// </summary>
/// <param name="req"></param>
private void doSpaceRay(ODERayRequest req)
{
// Create the ray
// IntPtr ray = d.CreateRay(m_scene.TopSpace, req.length);
d.GeomRaySetLength(ray, req.length);
d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z);
// Collide test
d.SpaceCollide2(m_scene.TopSpace, ray, IntPtr.Zero, nearCallback);
// Remove Ray
// d.GeomDestroy(ray);
if (req.callbackMethod == null)
return;
if (req.callbackMethod is RaycastCallback)
{
// Define default results
bool hitYN = false;
uint hitConsumerID = 0;
float distance = 999999999999f;
Vector3 closestcontact = new Vector3(99999f, 99999f, 99999f);
Vector3 snormal = Vector3.Zero;
// Find closest contact and object.
lock (m_contactResults)
{
foreach (ContactResult cResult in m_contactResults)
{
if (Vector3.Distance(req.Origin, cResult.Pos) < Vector3.Distance(req.Origin, closestcontact))
{
closestcontact = cResult.Pos;
hitConsumerID = cResult.ConsumerID;
distance = cResult.Depth;
hitYN = true;
snormal = cResult.Normal;
}
}
m_contactResults.Clear();
}
((RaycastCallback)req.callbackMethod)(hitYN, closestcontact, hitConsumerID, distance, snormal);
}
else
{
((RayCallback)req.callbackMethod)(m_contactResults);
lock (m_PendingRequests)
m_contactResults.Clear();
}
}
/// <summary>
/// Method that actually initiates the raycast with a geom
/// </summary>
/// <param name="req"></param>
private void doGeomRay(ODERayRequest req)
{
// Create the ray
// IntPtr ray = d.CreateRay(m_scene.TopSpace, req.length);
d.GeomRaySetLength(ray, req.length);
d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z);
// Collide test
d.SpaceCollide2(req.geom, ray, IntPtr.Zero, nearCallback); // still do this to have full AABB pre test
// Remove Ray
// d.GeomDestroy(ray);
if (req.callbackMethod == null)
return;
if (req.callbackMethod is RaycastCallback)
{
// Define default results
bool hitYN = false;
uint hitConsumerID = 0;
float distance = 999999999999f;
Vector3 closestcontact = new Vector3(99999f, 99999f, 99999f);
Vector3 snormal = Vector3.Zero;
// Find closest contact and object.
lock (m_contactResults)
{
foreach (ContactResult cResult in m_contactResults)
{
if (Vector3.Distance(req.Origin, cResult.Pos) < Vector3.Distance(req.Origin, closestcontact))
{
closestcontact = cResult.Pos;
hitConsumerID = cResult.ConsumerID;
distance = cResult.Depth;
hitYN = true;
snormal = cResult.Normal;
}
}
m_contactResults.Clear();
}
((RaycastCallback)req.callbackMethod)(hitYN, closestcontact, hitConsumerID, distance, snormal);
}
else
{
((RayCallback)req.callbackMethod)(m_contactResults);
lock (m_PendingRequests)
m_contactResults.Clear();
}
}
private bool GetCurContactGeom(int index, ref d.ContactGeom newcontactgeom)
{
IntPtr ContactgeomsArray = m_scene.ContactgeomsArray;
if (ContactgeomsArray == IntPtr.Zero || index >= ColisionContactGeomsPerTest)
return false;
IntPtr contactptr = new IntPtr(ContactgeomsArray.ToInt64() + (Int64)(index * d.ContactGeom.unmanagedSizeOf));
newcontactgeom = (d.ContactGeom)Marshal.PtrToStructure(contactptr, typeof(d.ContactGeom));
return true;
}
// This is the standard Near. g2 is the ray
private void near(IntPtr space, IntPtr g1, IntPtr g2)
{
//Don't test against heightfield Geom, or you'll be sorry!
// Exclude heightfield geom
if (g1 == IntPtr.Zero || g1 == g2)
return;
if (d.GeomGetClass(g1) == d.GeomClassID.HeightfieldClass)
return;
// Raytest against AABBs of spaces first, then dig into the spaces it hits for actual geoms.
if (d.GeomIsSpace(g1))
{
try
{
d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback);
}
catch (Exception e)
{
m_log.WarnFormat("[PHYSICS Ray]: Unable to Space collide test an object: {0}", e.Message);
}
return;
}
int count = 0;
try
{
count = d.CollidePtr(g1, g2, ColisionContactGeomsPerTest, m_scene.ContactgeomsArray, d.ContactGeom.unmanagedSizeOf);
}
catch (SEHException)
{
m_log.Error("[PHYSICS Ray]: The Operating system shut down ODE because of corrupt memory. This could be a result of really irregular terrain. If this repeats continuously, restart using Basic Physics and terrain fill your terrain. Restarting the sim.");
}
catch (Exception e)
{
m_log.WarnFormat("[PHYSICS Ray]: Unable to collide test an object: {0}", e.Message);
return;
}
if (count == 0)
return;
PhysicsActor p1 = null;
if (g1 != IntPtr.Zero)
m_scene.actor_name_map.TryGetValue(g1, out p1);
d.ContactGeom curcontact = new d.ContactGeom();
// Loop over contacts, build results.
for (int i = 0; i < count; i++)
{
if (!GetCurContactGeom(i, ref curcontact))
break;
if (p1 != null) {
if (p1 is OdePrim)
{
ContactResult collisionresult = new ContactResult();
collisionresult.ConsumerID = ((OdePrim)p1).m_localID;
collisionresult.Pos = new Vector3(curcontact.pos.X, curcontact.pos.Y, curcontact.pos.Z);
collisionresult.Depth = curcontact.depth;
collisionresult.Normal = new Vector3(curcontact.normal.X, curcontact.normal.Y,
curcontact.normal.Z);
lock (m_contactResults)
m_contactResults.Add(collisionresult);
}
}
}
}
/// <summary>
/// Dereference the creator scene so that it can be garbage collected if needed.
/// </summary>
internal void Dispose()
{
m_scene = null;
}
}
public struct ODERayRequest
{
public IntPtr geom;
public Vector3 Origin;
public Vector3 Normal;
public int Count;
public float length;
public object callbackMethod;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,86 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
using System.IO;
using System.Diagnostics;
using log4net;
using Nini.Config;
using OdeAPI;
using OpenSim.Framework;
using OpenSim.Region.Physics.Manager;
using OpenMetaverse;
namespace OpenSim.Region.Physics.OdePlugin
{
/// <summary>
/// ODE plugin
/// </summary>
public class OdePlugin : IPhysicsPlugin
{
//private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private OdeScene m_scene;
public bool Init()
{
if (d.InitODE2(0) != 0)
{
if (d.AllocateODEDataForThread(~0U) == 0)
{
d.CloseODE();
return false;
}
return true;
}
return false;
}
public PhysicsScene GetScene(String sceneIdentifier)
{
if (m_scene == null)
{
m_scene = new OdeScene(sceneIdentifier);
}
return (m_scene);
}
public string GetName()
{
return ("UbitODE");
}
public void Dispose()
{
d.CloseODE();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,7 @@
<configuration>
<dllmap os="osx" dll="ode" target="libode.dylib" />
<dllmap os="!windows,osx" cpu="x86-64,ia64" dll="ode" target="libode-x86_64" />
<dllmap os="!windows,osx" cpu="x86" dll="ode" target="libode" />
<dllmap os="!windows,osx" cpu="ppc64" dll="ode" target="libode-ppc64" />
<dllmap os="!windows,osx" cpu="s390x" dll="ode" target="libode-s390x" />
</configuration>

Binary file not shown.

BIN
bin/Physics/libode.so Normal file

Binary file not shown.

View File

@ -6,7 +6,7 @@
<CompilerDefines>TRACE;DEBUG</CompilerDefines>
<OptimizeCode>false</OptimizeCode>
<CheckUnderflowOverflow>false</CheckUnderflowOverflow>
<AllowUnsafe>false</AllowUnsafe>
<AllowUnsafe>true</AllowUnsafe>
<WarningLevel>4</WarningLevel>
<WarningsAsErrors>false</WarningsAsErrors>
<SuppressWarnings/>
@ -606,6 +606,36 @@
</Files>
</Project>
<Project frameworkVersion="v3_5" name="OpenSim.Region.Physics.UbitOdePlugin" path="OpenSim/Region/Physics/UbitOdePlugin" type="Library">
<Configuration name="Debug">
<Options>
<OutputPath>../../../../bin/Physics/</OutputPath>
</Options>
</Configuration>
<Configuration name="Release">
<Options>
<OutputPath>../../../../bin/Physics/</OutputPath>
</Options>
</Configuration>
<ReferencePath>../../../../bin/</ReferencePath>
<Reference name="System"/>
<Reference name="System.Core"/>
<Reference name="OpenMetaverseTypes" path="../../../../bin/"/>
<Reference name="Nini" path="../../../../bin/"/>
<Reference name="OpenSim.Framework"/>
<Reference name="OpenSim.Framework.Console"/>
<Reference name="OpenSim.Region.Physics.Manager"/>
<Reference name="log4net" path="../../../../bin/"/>
<Files>
<Match pattern="*.cs" recurse="true">
<Exclude name="Tests" pattern="Tests"/>
</Match>
</Files>
</Project>
<Project frameworkVersion="v3_5" name="OpenSim.Region.Physics.ConvexDecompositionDotNet" path="OpenSim/Region/Physics/ConvexDecompositionDotNet" type="Library">
<Configuration name="Debug">
<Options>
@ -3316,16 +3346,12 @@
<Reference name="OpenMetaverse.StructuredData" path="../../../bin/"/>
<Reference name="XMLRPC" path="../../../bin/"/>
<Reference name="OpenSim.Framework"/>
<Reference name="OpenSim.Framework.Communications"/>
<Reference name="OpenSim.Framework.Console"/>
<Reference name="OpenSim.Framework.Servers.HttpServer"/>
<Reference name="OpenSim.Region.CoreModules"/>
<Reference name="OpenSim.Region.Framework"/>
<Reference name="OpenSim.Region.OptionalModules"/>
<Reference name="OpenSim.Region.ScriptEngine.Shared"/>
<Reference name="OpenSim.Region.ScriptEngine.XEngine"/>
<Reference name="OpenSim.Services.Interfaces"/>
<Reference name="OpenSim.Services.AvatarService"/>
<Reference name="OpenSim.Region.ScriptEngine.Shared"/>
<Reference name="OpenSim.Tests.Common"/>
<Files>
<Match pattern="*.cs" recurse="false"/>

View File

@ -1,4 +1,4 @@
bin\Prebuild.exe /target nant
bin\Prebuild.exe /target vs2008
echo C:\WINDOWS\Microsoft.NET\Framework\v3.5\msbuild opensim.sln > compile.bat
echo C:\WINDOWS\Microsoft.NET\Framework\v3.5\msbuild OpenSim.sln > compile.bat