Merge branch 'master' of ssh://TOR/var/git/careminster

avinationmerge
CasperW 2009-12-23 14:15:27 +01:00
commit c54e0953d0
38 changed files with 10872 additions and 245 deletions

View File

@ -46,7 +46,7 @@ namespace OpenSim.Framework.Capabilities
public delegate UUID UpdateItem(UUID itemID, byte[] data);
public delegate void UpdateTaskScript(UUID itemID, UUID primID, bool isScriptRunning, byte[] data);
public delegate void UpdateTaskScript(UUID itemID, UUID primID, bool isScriptRunning, byte[] data, ref ArrayList errors);
public delegate void NewInventoryItem(UUID userID, InventoryItemBase item);
@ -54,7 +54,7 @@ namespace OpenSim.Framework.Capabilities
public delegate UUID ItemUpdatedCallback(UUID userID, UUID itemID, byte[] data);
public delegate void TaskScriptUpdatedCallback(UUID userID, UUID itemID, UUID primID,
public delegate ArrayList TaskScriptUpdatedCallback(UUID userID, UUID itemID, UUID primID,
bool isScriptRunning, byte[] data);
public delegate InventoryCollection FetchInventoryDescendentsCAPS(UUID agentID, UUID folderID, UUID ownerID,
@ -940,11 +940,13 @@ namespace OpenSim.Framework.Capabilities
/// <param name="primID">Prim containing item to update</param>
/// <param name="isScriptRunning">Signals whether the script to update is currently running</param>
/// <param name="data">New asset data</param>
public void TaskScriptUpdated(UUID itemID, UUID primID, bool isScriptRunning, byte[] data)
public void TaskScriptUpdated(UUID itemID, UUID primID, bool isScriptRunning, byte[] data, ref ArrayList errors)
{
if (TaskScriptUpdatedCall != null)
{
TaskScriptUpdatedCall(m_agentID, itemID, primID, isScriptRunning, data);
ArrayList e = TaskScriptUpdatedCall(m_agentID, itemID, primID, isScriptRunning, data);
foreach (Object item in e)
errors.Add(item);
}
}
@ -1174,17 +1176,20 @@ namespace OpenSim.Framework.Capabilities
// data, path, param));
string res = String.Empty;
LLSDTaskInventoryUploadComplete uploadComplete = new LLSDTaskInventoryUploadComplete();
LLSDTaskScriptUploadComplete uploadComplete = new LLSDTaskScriptUploadComplete();
ArrayList errors = new ArrayList();
handlerUpdateTaskScript = OnUpLoad;
if (handlerUpdateTaskScript != null)
{
handlerUpdateTaskScript(inventoryItemID, primID, isScriptRunning, data);
handlerUpdateTaskScript(inventoryItemID, primID, isScriptRunning, data, ref errors);
}
uploadComplete.item_id = inventoryItemID;
uploadComplete.task_id = primID;
uploadComplete.new_asset = inventoryItemID;
uploadComplete.compiled = errors.Count > 0 ? false : true;
uploadComplete.state = "complete";
uploadComplete.errors = new OSDArray();
uploadComplete.errors.Array = errors;
res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);

View File

@ -0,0 +1,54 @@
/*
* 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 OpenMetaverse;
using System;
using System.Collections;
namespace OpenSim.Framework.Capabilities
{
[OSDMap]
public class LLSDTaskScriptUploadComplete
{
/// <summary>
/// The task inventory item that was updated
/// </summary>
public UUID new_asset;
/// <summary>
/// Was it compiled?
/// </summary>
public bool compiled;
/// <summary>
/// State of the upload. So far have only even seen this set to "complete"
/// </summary>
public string state;
public OSDArray errors;
}
}

View File

@ -171,6 +171,7 @@ namespace OpenSim.Framework.Communications.Cache
item.NextPermissions = (uint)config.GetLong("nextPermissions", 0x7FFFFFFF);
item.EveryOnePermissions = (uint)config.GetLong("everyonePermissions", 0x7FFFFFFF);
item.BasePermissions = (uint)config.GetLong("basePermissions", 0x7FFFFFFF);
item.Flags = (uint)config.GetInt("flags", 0);
if (libraryFolders.ContainsKey(item.Folder))
{

View File

@ -142,6 +142,7 @@ namespace OpenSim.Framework.Communications.Cache
if (userProfile != null)
{
if ((userProfile.UserAssetURI == null || userProfile.UserAssetURI == "") && m_commsManager.NetworkServersInfo != null)
userProfile.UserAssetURI = m_commsManager.NetworkServersInfo.AssetURL;
if ((userProfile.UserInventoryURI == null || userProfile.UserInventoryURI == "") && m_commsManager.NetworkServersInfo != null)
@ -177,6 +178,7 @@ namespace OpenSim.Framework.Communications.Cache
UserProfileData userProfile = m_commsManager.UserService.GetUserProfile(userID);
if (userProfile != null)
{
if ((userProfile.UserAssetURI == null || userProfile.UserAssetURI == "") && m_commsManager.NetworkServersInfo != null)
userProfile.UserAssetURI = m_commsManager.NetworkServersInfo.AssetURL;
if ((userProfile.UserInventoryURI == null || userProfile.UserInventoryURI == "") && m_commsManager.NetworkServersInfo != null)

View File

@ -56,6 +56,17 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
private ISessionAuthInventoryService m_HGService;
private string m_LocalGridInventoryURI = string.Empty;
private string LocalGridInventory
{
get
{
if (m_LocalGridInventoryURI == null || m_LocalGridInventoryURI == "")
m_LocalGridInventoryURI = m_Scene.CommsManager.NetworkServersInfo.InventoryURL;
return m_LocalGridInventoryURI;
}
}
public Type ReplaceableInterface
{
get { return null; }
@ -533,7 +544,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
string userInventoryServerURI = Util.ServerURI(uinfo.UserProfile.UserInventoryURI);
string uri = m_LocalGridInventoryURI.TrimEnd('/');
string uri = LocalGridInventory.TrimEnd('/');
if ((userInventoryServerURI == uri) || (userInventoryServerURI == ""))
{
@ -545,7 +556,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
private string GetUserInventoryURI(UUID userID)
{
string invURI = m_LocalGridInventoryURI;
string invURI = LocalGridInventory;
CachedUserInfo uinfo = m_UserProfileService.GetUserDetails(userID);
if ((uinfo == null) || (uinfo.UserProfile == null))

View File

@ -26,6 +26,7 @@
*/
using System.Collections.Generic;
using System.Collections;
using OpenMetaverse;
using OpenSim.Framework;
@ -71,6 +72,7 @@ namespace OpenSim.Region.Framework.Interfaces
/// Start all the scripts contained in this entity's inventory
/// </summary>
void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource);
ArrayList GetScriptErrors(UUID itemID);
/// <summary>
/// Stop all the scripts in this entity.

View File

@ -26,6 +26,7 @@
*/
using System;
using System.Collections;
using OpenMetaverse;
namespace OpenSim.Region.Framework.Interfaces
@ -39,5 +40,7 @@ namespace OpenSim.Region.Framework.Interfaces
bool PostScriptEvent(UUID itemID, string name, Object[] args);
bool PostObjectEvent(UUID itemID, string name, Object[] args);
ArrayList GetScriptErrors(UUID itemID);
}
}

View File

@ -27,6 +27,7 @@
using System;
using System.Collections.Generic;
using System.Collections;
using System.Reflection;
using System.Text;
using System.Timers;
@ -215,13 +216,13 @@ namespace OpenSim.Region.Framework.Scenes
/// <param name="primID">The prim which contains the item to update</param>
/// <param name="isScriptRunning">Indicates whether the script to update is currently running</param>
/// <param name="data"></param>
public void CapsUpdateTaskInventoryScriptAsset(IClientAPI remoteClient, UUID itemId,
public ArrayList CapsUpdateTaskInventoryScriptAsset(IClientAPI remoteClient, UUID itemId,
UUID primId, bool isScriptRunning, byte[] data)
{
if (!Permissions.CanEditScript(itemId, primId, remoteClient.AgentId))
{
remoteClient.SendAgentAlertMessage("Insufficient permissions to edit script", false);
return;
return new ArrayList();
}
// Retrieve group
@ -234,7 +235,7 @@ namespace OpenSim.Region.Framework.Scenes
"Prim inventory update requested for item ID {0} in prim ID {1} but this prim does not exist",
itemId, primId);
return;
return new ArrayList();
}
// Retrieve item
@ -247,7 +248,7 @@ namespace OpenSim.Region.Framework.Scenes
+ " but the item does not exist in this inventory",
itemId, part.Name, part.UUID);
return;
return new ArrayList();
}
AssetBase asset = CreateAsset(item.Name, item.Description, (sbyte)AssetType.LSLText, data);
@ -264,29 +265,33 @@ namespace OpenSim.Region.Framework.Scenes
part.GetProperties(remoteClient);
// Trigger rerunning of script (use TriggerRezScript event, see RezScript)
ArrayList errors = new ArrayList();
if (isScriptRunning)
{
// Needs to determine which engine was running it and use that
//
part.Inventory.CreateScriptInstance(item.ItemID, 0, false, DefaultScriptEngine, 0);
errors = part.Inventory.GetScriptErrors(item.ItemID);
}
else
{
remoteClient.SendAgentAlertMessage("Script saved", false);
}
return errors;
}
/// <summary>
/// <see>CapsUpdateTaskInventoryScriptAsset(IClientAPI, UUID, UUID, bool, byte[])</see>
/// </summary>
public void CapsUpdateTaskInventoryScriptAsset(UUID avatarId, UUID itemId,
public ArrayList CapsUpdateTaskInventoryScriptAsset(UUID avatarId, UUID itemId,
UUID primId, bool isScriptRunning, byte[] data)
{
ScenePresence avatar;
if (TryGetAvatar(avatarId, out avatar))
{
CapsUpdateTaskInventoryScriptAsset(
return CapsUpdateTaskInventoryScriptAsset(
avatar.ControllingClient, itemId, primId, isScriptRunning, data);
}
else
@ -295,6 +300,7 @@ namespace OpenSim.Region.Framework.Scenes
"[PRIM INVENTORY]: " +
"Avatar {0} cannot be found to update its prim item asset",
avatarId);
return new ArrayList();
}
}

View File

@ -542,6 +542,18 @@ namespace OpenSim.Region.Framework.Scenes
if (group.GetFromItemID() == itemID)
{
m_parentScene.SendAttachEvent(group.LocalId, itemID, UUID.Zero);
bool hasScripts = false;
foreach (SceneObjectPart part in group.Children.Values)
{
if (part.Inventory.ContainsScripts())
{
hasScripts = true;
break;
}
}
if (hasScripts) // Allow the object to execute the attach(NULL_KEY) event
System.Threading.Thread.Sleep(100);
group.DetachToInventoryPrep();
m_log.Debug("[DETACH]: Saving attachpoint: " +
((uint)group.GetAttachmentPoint()).ToString());

View File

@ -1880,6 +1880,7 @@ namespace OpenSim.Region.Framework.Scenes
}
}
}
public void stopLookAt()
{
SceneObjectPart rootpart = m_rootPart;

View File

@ -29,6 +29,7 @@ using System;
using System.Xml;
using System.IO;
using System.Collections.Generic;
using System.Collections;
using System.Reflection;
using OpenMetaverse;
using log4net;
@ -210,6 +211,27 @@ namespace OpenSim.Region.Framework.Scenes
}
}
public ArrayList GetScriptErrors(UUID itemID)
{
ArrayList ret = new ArrayList();
IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
if (engines == null) // No engine at all
return ret;
foreach (IScriptModule e in engines)
{
if (e != null)
{
ArrayList errors = e.GetScriptErrors(itemID);
foreach (Object line in errors)
ret.Add(line);
}
}
return ret;
}
/// <summary>
/// Stop all the scripts in this prim.
/// </summary>
@ -345,6 +367,7 @@ namespace OpenSim.Region.Framework.Scenes
break;
}
}
m_part.ParentGroup.m_savedScriptState.Remove(oldID);
}
}

View File

@ -258,26 +258,50 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule
public Vector3 SitTarget
{
get { throw new System.NotImplementedException(); }
set { throw new System.NotImplementedException(); }
get { return GetSOP().SitTargetPosition; }
set
{
if (CanEdit())
{
GetSOP().SitTargetPosition = value;
}
}
}
public string SitTargetText
{
get { throw new System.NotImplementedException(); }
set { throw new System.NotImplementedException(); }
get { return GetSOP().SitName; }
set
{
if (CanEdit())
{
GetSOP().SitName = value;
}
}
}
public string TouchText
{
get { throw new System.NotImplementedException(); }
set { throw new System.NotImplementedException(); }
get { return GetSOP().TouchName; }
set
{
if (CanEdit())
{
GetSOP().TouchName = value;
}
}
}
public string Text
{
get { throw new System.NotImplementedException(); }
set { throw new System.NotImplementedException(); }
get { return GetSOP().Text; }
set
{
if (CanEdit())
{
GetSOP().SetText(value,new Vector3(1.0f,1.0f,1.0f),1.0f);
}
}
}
public bool IsRotationLockedX

View File

@ -620,11 +620,25 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin
set { return; }
}
public override Quaternion APIDTarget { set { return; } }
public override bool APIDActive { set { return; } }
public override float APIDStrength { set { return; } }
public override float APIDDamping { set { return; } }
public override Quaternion APIDTarget
{
set { return; }
}
public override bool APIDActive
{
set { return; }
}
public override float APIDStrength
{
set { return; }
}
public override float APIDDamping
{
set { return; }
}
/// <summary>
/// Adds the force supplied to the Target Velocity

View File

@ -570,7 +570,6 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin
public override float APIDStrength { set { return; } }
public override float APIDDamping { set { return; } }
public override void AddForce(Vector3 force, bool pushforce)
{
m_forcelist.Add(force);

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("")]
[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,630 @@
/*
* Revised August 26 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.
*
* 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 log4net;
using OpenMetaverse;
using Ode.NET;
using OpenSim.Framework;
using OpenSim.Region.Physics.Manager;
namespace OpenSim.Region.Physics.OdePlugin
{
public class ODEDynamics
{
public Vehicle Type
{
get { return m_type; }
}
public IntPtr Body
{
get { return m_body; }
}
private int frcount = 0; // Used to limit dynamics debug output to
// every 100th frame
// private OdeScene m_parentScene = null;
private IntPtr m_body = IntPtr.Zero;
private IntPtr m_jointGroup = IntPtr.Zero;
private IntPtr m_aMotor = IntPtr.Zero;
// Vehicle properties
private Vehicle m_type = Vehicle.TYPE_NONE; // If a 'VEHICLE', and what kind
// private Quaternion m_referenceFrame = Quaternion.Identity; // Axis modifier
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
// Linear properties
private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time
private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL
private Vector3 m_dir = Vector3.Zero; // velocity applied to body
private Vector3 m_linearFrictionTimescale = Vector3.Zero;
private float m_linearMotorDecayTimescale = 0;
private float m_linearMotorTimescale = 0;
private Vector3 m_lastLinearVelocityVector = Vector3.Zero;
// private bool m_LinearMotorSetLastFrame = false;
// private Vector3 m_linearMotorOffset = Vector3.Zero;
//Angular properties
private Vector3 m_angularMotorDirection = Vector3.Zero;
private Vector3 m_angularMotorDirectionLASTSET = Vector3.Zero;
private Vector3 m_angularFrictionTimescale = Vector3.Zero;
private float m_angularMotorDecayTimescale = 0;
private float m_angularMotorTimescale = 0;
private Vector3 m_lastAngularVelocityVector = Vector3.Zero;
//Deflection properties
// private float m_angularDeflectionEfficiency = 0;
// private float m_angularDeflectionTimescale = 0;
// private float m_linearDeflectionEfficiency = 0;
// private float m_linearDeflectionTimescale = 0;
//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 = 0f;
private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height
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 = 0;
private float m_verticalAttractionTimescale = 0;
internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue)
{
switch (pParam)
{
case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
if (pValue < 0.01f) pValue = 0.01f;
// m_angularDeflectionEfficiency = pValue;
break;
case Vehicle.ANGULAR_DEFLECTION_TIMESCALE:
if (pValue < 0.01f) pValue = 0.01f;
// m_angularDeflectionTimescale = pValue;
break;
case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE:
if (pValue < 0.01f) pValue = 0.01f;
m_angularMotorDecayTimescale = pValue;
break;
case Vehicle.ANGULAR_MOTOR_TIMESCALE:
if (pValue < 0.01f) pValue = 0.01f;
m_angularMotorTimescale = pValue;
break;
case Vehicle.BANKING_EFFICIENCY:
if (pValue < 0.01f) pValue = 0.01f;
// m_bankingEfficiency = pValue;
break;
case Vehicle.BANKING_MIX:
if (pValue < 0.01f) pValue = 0.01f;
// m_bankingMix = pValue;
break;
case Vehicle.BANKING_TIMESCALE:
if (pValue < 0.01f) pValue = 0.01f;
// 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 < 0.01f) pValue = 0.01f;
m_VhoverTimescale = pValue;
break;
case Vehicle.LINEAR_DEFLECTION_EFFICIENCY:
if (pValue < 0.01f) pValue = 0.01f;
// m_linearDeflectionEfficiency = pValue;
break;
case Vehicle.LINEAR_DEFLECTION_TIMESCALE:
if (pValue < 0.01f) pValue = 0.01f;
// m_linearDeflectionTimescale = pValue;
break;
case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE:
if (pValue < 0.01f) pValue = 0.01f;
m_linearMotorDecayTimescale = pValue;
break;
case Vehicle.LINEAR_MOTOR_TIMESCALE:
if (pValue < 0.01f) pValue = 0.01f;
m_linearMotorTimescale = pValue;
break;
case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY:
if (pValue < 0.0f) pValue = 0.0f;
if (pValue > 1.0f) pValue = 1.0f;
m_verticalAttractionEfficiency = pValue;
break;
case Vehicle.VERTICAL_ATTRACTION_TIMESCALE:
if (pValue < 0.01f) pValue = 0.01f;
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:
m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue);
break;
case Vehicle.ANGULAR_MOTOR_DIRECTION:
m_angularMotorDirection = new Vector3(pValue, pValue, pValue);
m_angularMotorDirectionLASTSET = new Vector3(pValue, pValue, pValue);
break;
case Vehicle.LINEAR_FRICTION_TIMESCALE:
m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue);
break;
case Vehicle.LINEAR_MOTOR_DIRECTION:
m_linearMotorDirection = new Vector3(pValue, pValue, pValue);
m_linearMotorDirectionLASTSET = new Vector3(pValue, pValue, pValue);
break;
case Vehicle.LINEAR_MOTOR_OFFSET:
// m_linearMotorOffset = new Vector3(pValue, pValue, pValue);
break;
}
}//end ProcessFloatVehicleParam
internal void ProcessVectorVehicleParam(Vehicle pParam, PhysicsVector pValue)
{
switch (pParam)
{
case Vehicle.ANGULAR_FRICTION_TIMESCALE:
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);
m_angularMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z);
break;
case Vehicle.LINEAR_FRICTION_TIMESCALE:
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);
m_linearMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z);
break;
case Vehicle.LINEAR_MOTOR_OFFSET:
// m_linearMotorOffset = 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 = pValue;
break;
}
}//end ProcessRotationVehicleParam
internal void ProcessTypeChange(Vehicle pType)
{
Console.WriteLine("ProcessTypeChange to " + pType);
// Set Defaults For Type
m_type = pType;
switch (pType)
{
case Vehicle.TYPE_SLED:
m_linearFrictionTimescale = new Vector3(30, 1, 1000);
m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
m_linearMotorDirection = Vector3.Zero;
m_linearMotorTimescale = 1000;
m_linearMotorDecayTimescale = 120;
m_angularMotorDirection = Vector3.Zero;
m_angularMotorTimescale = 1000;
m_angularMotorDecayTimescale = 120;
m_VhoverHeight = 0;
m_VhoverEfficiency = 1;
m_VhoverTimescale = 10;
m_VehicleBuoyancy = 0;
// m_linearDeflectionEfficiency = 1;
// m_linearDeflectionTimescale = 1;
// m_angularDeflectionEfficiency = 1;
// m_angularDeflectionTimescale = 1000;
// m_bankingEfficiency = 0;
// m_bankingMix = 1;
// m_bankingTimescale = 10;
// m_referenceFrame = Quaternion.Identity;
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_linearMotorDirection = Vector3.Zero;
m_linearMotorTimescale = 1;
m_linearMotorDecayTimescale = 60;
m_angularMotorDirection = Vector3.Zero;
m_angularMotorTimescale = 1;
m_angularMotorDecayTimescale = 0.8f;
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 = 1;
m_verticalAttractionTimescale = 10;
// m_bankingEfficiency = -0.2f;
// m_bankingMix = 1;
// m_bankingTimescale = 1;
// m_referenceFrame = Quaternion.Identity;
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.HOVER_UP_ONLY |
VehicleFlag.LIMIT_MOTOR_UP);
break;
case Vehicle.TYPE_BOAT:
m_linearFrictionTimescale = new Vector3(10, 3, 2);
m_angularFrictionTimescale = new Vector3(10,10,10);
m_linearMotorDirection = Vector3.Zero;
m_linearMotorTimescale = 5;
m_linearMotorDecayTimescale = 60;
m_angularMotorDirection = Vector3.Zero;
m_angularMotorTimescale = 4;
m_angularMotorDecayTimescale = 4;
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 = 5;
// m_bankingEfficiency = -0.3f;
// m_bankingMix = 0.8f;
// m_bankingTimescale = 1;
// m_referenceFrame = Quaternion.Identity;
m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.LIMIT_ROLL_ONLY |
VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY |
VehicleFlag.LIMIT_MOTOR_UP);
break;
case Vehicle.TYPE_AIRPLANE:
m_linearFrictionTimescale = new Vector3(200, 10, 5);
m_angularFrictionTimescale = new Vector3(20, 20, 20);
m_linearMotorDirection = Vector3.Zero;
m_linearMotorTimescale = 2;
m_linearMotorDecayTimescale = 60;
m_angularMotorDirection = Vector3.Zero;
m_angularMotorTimescale = 4;
m_angularMotorDecayTimescale = 4;
m_VhoverHeight = 0;
m_VhoverEfficiency = 0.5f;
m_VhoverTimescale = 1000;
m_VehicleBuoyancy = 0;
// m_linearDeflectionEfficiency = 0.5f;
// m_linearDeflectionTimescale = 3;
// m_angularDeflectionEfficiency = 1;
// m_angularDeflectionTimescale = 2;
m_verticalAttractionEfficiency = 0.9f;
m_verticalAttractionTimescale = 2;
// m_bankingEfficiency = 1;
// m_bankingMix = 0.7f;
// m_bankingTimescale = 2;
// m_referenceFrame = Quaternion.Identity;
m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY | 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_linearMotorDirection = Vector3.Zero;
m_linearMotorTimescale = 5;
m_linearMotorDecayTimescale = 60;
m_angularMotorDirection = Vector3.Zero;
m_angularMotorTimescale = 6;
m_angularMotorDecayTimescale = 10;
m_VhoverHeight = 5;
m_VhoverEfficiency = 0.8f;
m_VhoverTimescale = 10;
m_VehicleBuoyancy = 1;
// m_linearDeflectionEfficiency = 0;
// m_linearDeflectionTimescale = 5;
// m_angularDeflectionEfficiency = 0;
// m_angularDeflectionTimescale = 5;
m_verticalAttractionEfficiency = 1;
m_verticalAttractionTimescale = 1000;
// m_bankingEfficiency = 0;
// m_bankingMix = 0.7f;
// m_bankingTimescale = 5;
// m_referenceFrame = Quaternion.Identity;
m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
VehicleFlag.HOVER_UP_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT);
break;
}
}//end SetDefaultsForType
internal void Enable(IntPtr pBody, OdeScene pParentScene)
{
//Console.WriteLine("Enable m_type=" + m_type + " m_VehicleBuoyancy=" + m_VehicleBuoyancy);
if (m_type == Vehicle.TYPE_NONE)
return;
m_body = pBody;
//KF: This used to set up the linear and angular joints
}
internal void Step(float pTimestep, OdeScene pParentScene)
{
if (m_body == IntPtr.Zero || m_type == Vehicle.TYPE_NONE)
return;
frcount++; // used to limit debug comment output
if (frcount > 100)
frcount = 0;
MoveLinear(pTimestep, pParentScene);
MoveAngular(pTimestep);
}// end Step
private void MoveLinear(float pTimestep, OdeScene _pParentScene)
{
if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f)) // requested m_linearMotorDirection is significant
{
if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body);
// add drive to body
Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale/pTimestep);
m_lastLinearVelocityVector += (addAmount*10); // lastLinearVelocityVector is the current body velocity vector?
// This will work temporarily, but we really need to compare speed on an axis
// KF: Limit body velocity to applied velocity?
if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X))
m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X;
if (Math.Abs(m_lastLinearVelocityVector.Y) > Math.Abs(m_linearMotorDirectionLASTSET.Y))
m_lastLinearVelocityVector.Y = m_linearMotorDirectionLASTSET.Y;
if (Math.Abs(m_lastLinearVelocityVector.Z) > Math.Abs(m_linearMotorDirectionLASTSET.Z))
m_lastLinearVelocityVector.Z = m_linearMotorDirectionLASTSET.Z;
// decay applied velocity
Vector3 decayfraction = ((Vector3.One/(m_linearMotorDecayTimescale/pTimestep)));
//Console.WriteLine("decay: " + decayfraction);
m_linearMotorDirection -= m_linearMotorDirection * decayfraction;
//Console.WriteLine("actual: " + m_linearMotorDirection);
}
else
{ // requested is not significant
// if what remains of applied is small, zero it.
if (m_lastLinearVelocityVector.ApproxEquals(Vector3.Zero, 0.01f))
m_lastLinearVelocityVector = Vector3.Zero;
}
// convert requested object velocity to world-referenced vector
m_dir = m_lastLinearVelocityVector;
d.Quaternion rot = d.BodyGetQuaternion(Body);
Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object
m_dir *= rotq; // apply obj rotation to velocity vector
// add Gravity andBuoyancy
// KF: So far I have found no good method to combine a script-requested
// .Z velocity and gravity. Therefore only 0g will used script-requested
// .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only.
Vector3 grav = Vector3.Zero;
if(m_VehicleBuoyancy < 1.0f)
{
// There is some gravity, make a gravity force vector
// that is applied after object velocity.
d.Mass objMass;
d.BodyGetMass(Body, out objMass);
// m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
grav.Z = _pParentScene.gravityz * objMass.mass * (1f - m_VehicleBuoyancy);
// Preserve the current Z velocity
d.Vector3 vel_now = d.BodyGetLinearVel(Body);
m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity
} // else its 1.0, no gravity.
// Check if hovering
if( (m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0)
{
// We should hover, get the target height
d.Vector3 pos = d.BodyGetPosition(Body);
if((m_flags & VehicleFlag.HOVER_WATER_ONLY) == VehicleFlag.HOVER_WATER_ONLY)
{
m_VhoverTargetHeight = _pParentScene.GetWaterLevel() + m_VhoverHeight;
}
else if((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) == VehicleFlag.HOVER_TERRAIN_ONLY)
{
m_VhoverTargetHeight = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight;
}
else if((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) == VehicleFlag.HOVER_GLOBAL_HEIGHT)
{
m_VhoverTargetHeight = m_VhoverHeight;
}
if((m_flags & VehicleFlag.HOVER_UP_ONLY) == VehicleFlag.HOVER_UP_ONLY)
{
// If body is aready heigher, use its height as target height
if(pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z;
}
// m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped
// m_VhoverTimescale = 0f; // time to acheive height
// pTimestep is time since last frame,in secs
float herr0 = pos.Z - m_VhoverTargetHeight;
//if(frcount == 0) Console.WriteLine("herr0=" + herr0);
// Replace Vertical speed with correction figure if significant
if(Math.Abs(herr0) > 0.01f )
{
d.Mass objMass;
d.BodyGetMass(Body, out objMass);
m_dir.Z = - ( (herr0 * pTimestep * 50.0f) / m_VhoverTimescale);
// m_VhoverEfficiency is not yet implemented
}
else
{
m_dir.Z = 0f;
}
}
// Apply velocity
d.BodySetLinearVel(Body, m_dir.X, m_dir.Y, m_dir.Z);
//if(frcount == 0) Console.WriteLine("Move " + Body + ":"+ m_dir.X + " " + m_dir.Y + " " + m_dir.Z);
// apply gravity force
d.BodyAddForce(Body, grav.X, grav.Y, grav.Z);
//if(frcount == 0) Console.WriteLine("Force " + Body + ":" + grav.X + " " + grav.Y + " " + grav.Z);
// apply friction
Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep);
m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount;
} // end MoveLinear()
private void MoveAngular(float pTimestep)
{
// m_angularMotorDirection is the latest value from the script, and is decayed here
// m_angularMotorDirectionLASTSET is the latest value from the script
// m_lastAngularVelocityVector is what is being applied to the Body, varied up and down here
if (!m_angularMotorDirection.ApproxEquals(Vector3.Zero, 0.01f))
{
if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body);
// ramp up to new value
Vector3 addAmount = m_angularMotorDirection / (m_angularMotorTimescale / pTimestep);
m_lastAngularVelocityVector += (addAmount * 10f);
//if(frcount == 0) Console.WriteLine("add: " + addAmount);
// limit applied value to what was set by script
// This will work temporarily, but we really need to compare speed on an axis
if (Math.Abs(m_lastAngularVelocityVector.X) > Math.Abs(m_angularMotorDirectionLASTSET.X))
m_lastAngularVelocityVector.X = m_angularMotorDirectionLASTSET.X;
if (Math.Abs(m_lastAngularVelocityVector.Y) > Math.Abs(m_angularMotorDirectionLASTSET.Y))
m_lastAngularVelocityVector.Y = m_angularMotorDirectionLASTSET.Y;
if (Math.Abs(m_lastAngularVelocityVector.Z) > Math.Abs(m_angularMotorDirectionLASTSET.Z))
m_lastAngularVelocityVector.Z = m_angularMotorDirectionLASTSET.Z;
// decay the requested value
Vector3 decayfraction = ((Vector3.One / (m_angularMotorDecayTimescale / pTimestep)));
//Console.WriteLine("decay: " + decayfraction);
m_angularMotorDirection -= m_angularMotorDirection * decayfraction;
//Console.WriteLine("actual: " + m_linearMotorDirection);
}
// KF: m_lastAngularVelocityVector is rotational speed in rad/sec ?
// Vertical attractor section
// d.Mass objMass;
// d.BodyGetMass(Body, out objMass);
// float servo = 100f * objMass.mass * m_verticalAttractionEfficiency / (m_verticalAttractionTimescale * pTimestep);
float servo = 0.1f * m_verticalAttractionEfficiency / (m_verticalAttractionTimescale * pTimestep);
// get present body rotation
d.Quaternion rot = d.BodyGetQuaternion(Body);
Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W);
// make a vector pointing up
Vector3 verterr = Vector3.Zero;
verterr.Z = 1.0f;
// rotate it to Body Angle
verterr = verterr * rotq;
// verterr.X and .Y are the World error ammounts. They are 0 when there is no error (Vehicle Body is 'vertical'), and .Z will be 1.
// As the body leans to its side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall and .Z will go
// negative. Similar for tilt and |.Y|. .X and .Y must be modulated to prevent a stable inverted body.
if (verterr.Z < 0.0f)
{
verterr.X = 2.0f - verterr.X;
verterr.Y = 2.0f - verterr.Y;
}
// Error is 0 (no error) to +/- 2 (max error)
// scale it by servo
verterr = verterr * servo;
// rotate to object frame
// verterr = verterr * rotq;
// As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so
// Change Body angular velocity X based on Y, and Y based on X. Z is not changed.
m_lastAngularVelocityVector.X += verterr.Y;
m_lastAngularVelocityVector.Y -= verterr.X;
/*
if(frcount == 0)
{
// Console.WriteLine("AngleMotor " + m_lastAngularVelocityVector);
Console.WriteLine(String.Format("VA Body:{0} servo:{1} err:<{2},{3},{4}> VAE:{5}",
Body, servo, verterr.X, verterr.Y, verterr.Z, m_verticalAttractionEfficiency));
}
*/
d.BodySetAngularVel (Body, m_lastAngularVelocityVector.X, m_lastAngularVelocityVector.Y, m_lastAngularVelocityVector.Z);
// apply friction
Vector3 decayamount = Vector3.One / (m_angularFrictionTimescale / pTimestep);
m_lastAngularVelocityVector -= m_lastAngularVelocityVector * decayamount;
} //end MoveAngular
}
}

View File

@ -0,0 +1,673 @@
/*
* 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.
*
*/
/* 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.
*/
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.InteropServices;
using log4net;
using OpenMetaverse;
using Ode.NET;
using OpenSim.Framework;
using OpenSim.Region.Physics.Manager;
namespace OpenSim.Region.Physics.OdePlugin
{
public class ODEDynamics
{
public Vehicle Type
{
get { return m_type; }
}
public IntPtr Body
{
get { return m_body; }
}
private int frcount = 0; // Used to limit dynamics debug output to
// every 100th frame
// private OdeScene m_parentScene = null;
private IntPtr m_body = IntPtr.Zero;
// private IntPtr m_jointGroup = IntPtr.Zero;
// private IntPtr m_aMotor = IntPtr.Zero;
// Vehicle properties
private Vehicle m_type = Vehicle.TYPE_NONE; // If a 'VEHICLE', and what kind
// private Quaternion m_referenceFrame = Quaternion.Identity; // Axis modifier
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
// Linear properties
private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time
private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL
private Vector3 m_dir = Vector3.Zero; // velocity applied to body
private Vector3 m_linearFrictionTimescale = Vector3.Zero;
private float m_linearMotorDecayTimescale = 0;
private float m_linearMotorTimescale = 0;
private Vector3 m_lastLinearVelocityVector = Vector3.Zero;
// private bool m_LinearMotorSetLastFrame = false;
// private Vector3 m_linearMotorOffset = Vector3.Zero;
//Angular properties
private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor
private int m_angularMotorApply = 0; // application frame counter
private Vector3 m_angularMotorVelocity = Vector3.Zero; // current angular motor velocity
private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate
private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate
private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate
private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body
// private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body
//Deflection properties
// private float m_angularDeflectionEfficiency = 0;
// private float m_angularDeflectionTimescale = 0;
// private float m_linearDeflectionEfficiency = 0;
// private float m_linearDeflectionTimescale = 0;
//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 = 0f;
private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height
private float m_VehicleBuoyancy = 0f; // 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 = 500f; // Timescale > 300 means no vert attractor.
internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue)
{
switch (pParam)
{
case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
if (pValue < 0.01f) pValue = 0.01f;
// m_angularDeflectionEfficiency = pValue;
break;
case Vehicle.ANGULAR_DEFLECTION_TIMESCALE:
if (pValue < 0.01f) pValue = 0.01f;
// m_angularDeflectionTimescale = pValue;
break;
case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE:
if (pValue < 0.01f) pValue = 0.01f;
m_angularMotorDecayTimescale = pValue;
break;
case Vehicle.ANGULAR_MOTOR_TIMESCALE:
if (pValue < 0.01f) pValue = 0.01f;
m_angularMotorTimescale = pValue;
break;
case Vehicle.BANKING_EFFICIENCY:
if (pValue < 0.01f) pValue = 0.01f;
// m_bankingEfficiency = pValue;
break;
case Vehicle.BANKING_MIX:
if (pValue < 0.01f) pValue = 0.01f;
// m_bankingMix = pValue;
break;
case Vehicle.BANKING_TIMESCALE:
if (pValue < 0.01f) pValue = 0.01f;
// 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 < 0.01f) pValue = 0.01f;
m_VhoverTimescale = pValue;
break;
case Vehicle.LINEAR_DEFLECTION_EFFICIENCY:
if (pValue < 0.01f) pValue = 0.01f;
// m_linearDeflectionEfficiency = pValue;
break;
case Vehicle.LINEAR_DEFLECTION_TIMESCALE:
if (pValue < 0.01f) pValue = 0.01f;
// m_linearDeflectionTimescale = pValue;
break;
case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE:
if (pValue < 0.01f) pValue = 0.01f;
m_linearMotorDecayTimescale = pValue;
break;
case Vehicle.LINEAR_MOTOR_TIMESCALE:
if (pValue < 0.01f) pValue = 0.01f;
m_linearMotorTimescale = pValue;
break;
case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY:
if (pValue < 0.1f) pValue = 0.1f; // Less goes unstable
if (pValue > 1.0f) pValue = 1.0f;
m_verticalAttractionEfficiency = pValue;
break;
case Vehicle.VERTICAL_ATTRACTION_TIMESCALE:
if (pValue < 0.01f) pValue = 0.01f;
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:
m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue);
break;
case Vehicle.ANGULAR_MOTOR_DIRECTION:
m_angularMotorDirection = new Vector3(pValue, pValue, pValue);
m_angularMotorApply = 10;
break;
case Vehicle.LINEAR_FRICTION_TIMESCALE:
m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue);
break;
case Vehicle.LINEAR_MOTOR_DIRECTION:
m_linearMotorDirection = new Vector3(pValue, pValue, pValue);
m_linearMotorDirectionLASTSET = new Vector3(pValue, pValue, pValue);
break;
case Vehicle.LINEAR_MOTOR_OFFSET:
// m_linearMotorOffset = new Vector3(pValue, pValue, pValue);
break;
}
}//end ProcessFloatVehicleParam
internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue)
{
switch (pParam)
{
case Vehicle.ANGULAR_FRICTION_TIMESCALE:
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
if(m_angularMotorDirection.X > 12.56f) m_angularMotorDirection.X = 12.56f;
if(m_angularMotorDirection.X < - 12.56f) m_angularMotorDirection.X = - 12.56f;
if(m_angularMotorDirection.Y > 12.56f) m_angularMotorDirection.Y = 12.56f;
if(m_angularMotorDirection.Y < - 12.56f) m_angularMotorDirection.Y = - 12.56f;
if(m_angularMotorDirection.Z > 12.56f) m_angularMotorDirection.Z = 12.56f;
if(m_angularMotorDirection.Z < - 12.56f) m_angularMotorDirection.Z = - 12.56f;
m_angularMotorApply = 10;
break;
case Vehicle.LINEAR_FRICTION_TIMESCALE:
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);
m_linearMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z);
break;
case Vehicle.LINEAR_MOTOR_OFFSET:
// m_linearMotorOffset = 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 = pValue;
break;
}
}//end ProcessRotationVehicleParam
internal void ProcessTypeChange(Vehicle pType)
{
// Set Defaults For Type
m_type = pType;
switch (pType)
{
case Vehicle.TYPE_SLED:
m_linearFrictionTimescale = new Vector3(30, 1, 1000);
m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
m_linearMotorDirection = Vector3.Zero;
m_linearMotorTimescale = 1000;
m_linearMotorDecayTimescale = 120;
m_angularMotorDirection = Vector3.Zero;
m_angularMotorTimescale = 1000;
m_angularMotorDecayTimescale = 120;
m_VhoverHeight = 0;
// m_VhoverEfficiency = 1;
m_VhoverTimescale = 10;
m_VehicleBuoyancy = 0;
// m_linearDeflectionEfficiency = 1;
// m_linearDeflectionTimescale = 1;
// m_angularDeflectionEfficiency = 1;
// m_angularDeflectionTimescale = 1000;
// m_bankingEfficiency = 0;
// m_bankingMix = 1;
// m_bankingTimescale = 10;
// m_referenceFrame = Quaternion.Identity;
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_linearMotorDirection = Vector3.Zero;
m_linearMotorTimescale = 1;
m_linearMotorDecayTimescale = 60;
m_angularMotorDirection = Vector3.Zero;
m_angularMotorTimescale = 1;
m_angularMotorDecayTimescale = 0.8f;
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_referenceFrame = Quaternion.Identity;
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.HOVER_UP_ONLY |
VehicleFlag.LIMIT_MOTOR_UP);
break;
case Vehicle.TYPE_BOAT:
m_linearFrictionTimescale = new Vector3(10, 3, 2);
m_angularFrictionTimescale = new Vector3(10,10,10);
m_linearMotorDirection = Vector3.Zero;
m_linearMotorTimescale = 5;
m_linearMotorDecayTimescale = 60;
m_angularMotorDirection = Vector3.Zero;
m_angularMotorTimescale = 4;
m_angularMotorDecayTimescale = 4;
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_referenceFrame = Quaternion.Identity;
m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.LIMIT_ROLL_ONLY |
VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY |
VehicleFlag.LIMIT_MOTOR_UP);
break;
case Vehicle.TYPE_AIRPLANE:
m_linearFrictionTimescale = new Vector3(200, 10, 5);
m_angularFrictionTimescale = new Vector3(20, 20, 20);
m_linearMotorDirection = Vector3.Zero;
m_linearMotorTimescale = 2;
m_linearMotorDecayTimescale = 60;
m_angularMotorDirection = Vector3.Zero;
m_angularMotorTimescale = 4;
m_angularMotorDecayTimescale = 4;
m_VhoverHeight = 0;
// m_VhoverEfficiency = 0.5f;
m_VhoverTimescale = 1000;
m_VehicleBuoyancy = 0;
// m_linearDeflectionEfficiency = 0.5f;
// m_linearDeflectionTimescale = 3;
// m_angularDeflectionEfficiency = 1;
// m_angularDeflectionTimescale = 2;
m_verticalAttractionEfficiency = 0.9f;
m_verticalAttractionTimescale = 2f;
// m_bankingEfficiency = 1;
// m_bankingMix = 0.7f;
// m_bankingTimescale = 2;
// m_referenceFrame = Quaternion.Identity;
m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY | 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_linearMotorDirection = Vector3.Zero;
m_linearMotorTimescale = 5;
m_linearMotorDecayTimescale = 60;
m_angularMotorDirection = Vector3.Zero;
m_angularMotorTimescale = 6;
m_angularMotorDecayTimescale = 10;
m_VhoverHeight = 5;
// m_VhoverEfficiency = 0.8f;
m_VhoverTimescale = 10;
m_VehicleBuoyancy = 1;
// m_linearDeflectionEfficiency = 0;
// m_linearDeflectionTimescale = 5;
// m_angularDeflectionEfficiency = 0;
// m_angularDeflectionTimescale = 5;
m_verticalAttractionEfficiency = 1f;
m_verticalAttractionTimescale = 100f;
// m_bankingEfficiency = 0;
// m_bankingMix = 0.7f;
// m_bankingTimescale = 5;
// m_referenceFrame = Quaternion.Identity;
m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
VehicleFlag.HOVER_UP_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT);
break;
}
}//end SetDefaultsForType
internal void Enable(IntPtr pBody, OdeScene pParentScene)
{
if (m_type == Vehicle.TYPE_NONE)
return;
m_body = pBody;
}
internal void Step(float pTimestep, OdeScene pParentScene)
{
if (m_body == IntPtr.Zero || m_type == Vehicle.TYPE_NONE)
return;
frcount++; // used to limit debug comment output
if (frcount > 100)
frcount = 0;
MoveLinear(pTimestep, pParentScene);
MoveAngular(pTimestep);
}// end Step
private void MoveLinear(float pTimestep, OdeScene _pParentScene)
{
if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f)) // requested m_linearMotorDirection is significant
{
if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body);
// add drive to body
Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale/pTimestep);
m_lastLinearVelocityVector += (addAmount*10); // lastLinearVelocityVector is the current body velocity vector?
// This will work temporarily, but we really need to compare speed on an axis
// KF: Limit body velocity to applied velocity?
if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X))
m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X;
if (Math.Abs(m_lastLinearVelocityVector.Y) > Math.Abs(m_linearMotorDirectionLASTSET.Y))
m_lastLinearVelocityVector.Y = m_linearMotorDirectionLASTSET.Y;
if (Math.Abs(m_lastLinearVelocityVector.Z) > Math.Abs(m_linearMotorDirectionLASTSET.Z))
m_lastLinearVelocityVector.Z = m_linearMotorDirectionLASTSET.Z;
// decay applied velocity
Vector3 decayfraction = ((Vector3.One/(m_linearMotorDecayTimescale/pTimestep)));
//Console.WriteLine("decay: " + decayfraction);
m_linearMotorDirection -= m_linearMotorDirection * decayfraction * 0.5f;
//Console.WriteLine("actual: " + m_linearMotorDirection);
}
else
{ // requested is not significant
// if what remains of applied is small, zero it.
if (m_lastLinearVelocityVector.ApproxEquals(Vector3.Zero, 0.01f))
m_lastLinearVelocityVector = Vector3.Zero;
}
// convert requested object velocity to world-referenced vector
m_dir = m_lastLinearVelocityVector;
d.Quaternion rot = d.BodyGetQuaternion(Body);
Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object
m_dir *= rotq; // apply obj rotation to velocity vector
// add Gravity and Buoyancy
// KF: So far I have found no good method to combine a script-requested
// .Z velocity and gravity. Therefore only 0g will used script-requested
// .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only.
Vector3 grav = Vector3.Zero;
if(m_VehicleBuoyancy < 1.0f)
{
// There is some gravity, make a gravity force vector
// that is applied after object velocity.
d.Mass objMass;
d.BodyGetMass(Body, out objMass);
// m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
grav.Z = _pParentScene.gravityz * objMass.mass * (1f - m_VehicleBuoyancy);
// Preserve the current Z velocity
d.Vector3 vel_now = d.BodyGetLinearVel(Body);
m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity
} // else its 1.0, no gravity.
// Check if hovering
if( (m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0)
{
// We should hover, get the target height
d.Vector3 pos = d.BodyGetPosition(Body);
if((m_flags & VehicleFlag.HOVER_WATER_ONLY) == VehicleFlag.HOVER_WATER_ONLY)
{
m_VhoverTargetHeight = _pParentScene.GetWaterLevel() + m_VhoverHeight;
}
else if((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) == VehicleFlag.HOVER_TERRAIN_ONLY)
{
m_VhoverTargetHeight = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight;
}
else if((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) == VehicleFlag.HOVER_GLOBAL_HEIGHT)
{
m_VhoverTargetHeight = m_VhoverHeight;
}
if((m_flags & VehicleFlag.HOVER_UP_ONLY) == VehicleFlag.HOVER_UP_ONLY)
{
// If body is aready heigher, use its height as target height
if(pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z;
}
// m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped
// m_VhoverTimescale = 0f; // time to acheive height
// pTimestep is time since last frame,in secs
float herr0 = pos.Z - m_VhoverTargetHeight;
// Replace Vertical speed with correction figure if significant
if(Math.Abs(herr0) > 0.01f )
{
d.Mass objMass;
d.BodyGetMass(Body, out objMass);
m_dir.Z = - ( (herr0 * pTimestep * 50.0f) / m_VhoverTimescale);
//KF: m_VhoverEfficiency is not yet implemented
}
else
{
m_dir.Z = 0f;
}
}
// Apply velocity
d.BodySetLinearVel(Body, m_dir.X, m_dir.Y, m_dir.Z);
// apply gravity force
d.BodyAddForce(Body, grav.X, grav.Y, grav.Z);
// apply friction
Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep);
m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount;
} // end MoveLinear()
private void MoveAngular(float pTimestep)
{
/*
private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor
private int m_angularMotorApply = 0; // application frame counter
private float m_angularMotorVelocity = 0; // current angular motor velocity (ramps up and down)
private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate
private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate
private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate
private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body
*/
//if(frcount == 0) Console.WriteLine("MoveAngular ");
// Get what the body is doing, this includes 'external' influences
d.Vector3 angularVelocity = d.BodyGetAngularVel(Body);
// Vector3 angularVelocity = Vector3.Zero;
if (m_angularMotorApply > 0)
{
// ramp up to new value
// current velocity += error / ( time to get there / step interval )
// requested speed - last motor speed
m_angularMotorVelocity.X += (m_angularMotorDirection.X - m_angularMotorVelocity.X) / (m_angularMotorTimescale / pTimestep);
m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep);
m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep);
m_angularMotorApply--; // This is done so that if script request rate is less than phys frame rate the expected
// velocity may still be acheived.
}
else
{
// no motor recently applied, keep the body velocity
/* m_angularMotorVelocity.X = angularVelocity.X;
m_angularMotorVelocity.Y = angularVelocity.Y;
m_angularMotorVelocity.Z = angularVelocity.Z; */
// and decay the velocity
m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / pTimestep);
} // end motor section
// Vertical attractor section
Vector3 vertattr = Vector3.Zero;
if(m_verticalAttractionTimescale < 300)
{
float VAservo = 0.2f / (m_verticalAttractionTimescale * pTimestep);
// get present body rotation
d.Quaternion rot = d.BodyGetQuaternion(Body);
Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W);
// make a vector pointing up
Vector3 verterr = Vector3.Zero;
verterr.Z = 1.0f;
// rotate it to Body Angle
verterr = verterr * rotq;
// verterr.X and .Y are the World error ammounts. They are 0 when there is no error (Vehicle Body is 'vertical'), and .Z will be 1.
// As the body leans to its side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall and .Z will go
// negative. Similar for tilt and |.Y|. .X and .Y must be modulated to prevent a stable inverted body.
if (verterr.Z < 0.0f)
{
verterr.X = 2.0f - verterr.X;
verterr.Y = 2.0f - verterr.Y;
}
// Error is 0 (no error) to +/- 2 (max error)
// scale it by VAservo
verterr = verterr * VAservo;
//if(frcount == 0) Console.WriteLine("VAerr=" + verterr);
// As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so
// Change Body angular velocity X based on Y, and Y based on X. Z is not changed.
vertattr.X = verterr.Y;
vertattr.Y = - verterr.X;
vertattr.Z = 0f;
// scaling appears better usingsquare-law
float bounce = 1.0f - (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency);
vertattr.X += bounce * angularVelocity.X;
vertattr.Y += bounce * angularVelocity.Y;
} // else vertical attractor is off
// m_lastVertAttractor = vertattr;
// Bank section tba
// Deflection section tba
// Sum velocities
m_lastAngularVelocity = m_angularMotorVelocity + vertattr; // tba: + bank + deflection
if (!m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f))
{
if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body);
}
else
{
m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero.
}
// apply friction
Vector3 decayamount = Vector3.One / (m_angularFrictionTimescale / pTimestep);
m_lastAngularVelocity -= m_lastAngularVelocity * decayamount;
// Apply to the body
d.BodySetAngularVel (Body, m_lastAngularVelocity.X, m_lastAngularVelocity.Y, m_lastAngularVelocity.Z);
} //end MoveAngular
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,375 @@
/*
* 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 Ode.NET;
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 Raycast Requests
/// </summary>
protected List<ODERayCastRequest> m_PendingRequests = new List<ODERayCastRequest>();
/// <summary>
/// Scene that created this object.
/// </summary>
private OdeScene m_scene;
/// <summary>
/// ODE contact array to be filled by the collision testing
/// </summary>
d.ContactGeom[] contacts = new d.ContactGeom[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;
}
/// <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, RaycastCallback retMethod)
{
lock (m_PendingRequests)
{
ODERayCastRequest req = new ODERayCastRequest();
req.callbackMethod = retMethod;
req.length = length;
req.Normal = direction;
req.Origin = position;
m_PendingRequests.Add(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;
lock (m_PendingRequests)
{
if (m_PendingRequests.Count > 0)
{
ODERayCastRequest[] reqs = m_PendingRequests.ToArray();
for (int i = 0; i < reqs.Length; i++)
{
if (reqs[i].callbackMethod != null) // quick optimization here, don't raycast
RayCast(reqs[i]); // if there isn't anyone to send results
}
/*
foreach (ODERayCastRequest req in m_PendingRequests)
{
if (req.callbackMethod != null) // quick optimization here, don't raycast
RayCast(req); // if there isn't anyone to send results to
}
*/
m_PendingRequests.Clear();
}
}
lock (m_contactResults)
m_contactResults.Clear();
return System.Environment.TickCount - time;
}
/// <summary>
/// Method that actually initiates the raycast
/// </summary>
/// <param name="req"></param>
private void RayCast(ODERayCastRequest req)
{
// Create the ray
IntPtr ray = d.CreateRay(m_scene.space, 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.space, ray, IntPtr.Zero, nearCallback);
// Remove Ray
d.GeomDestroy(ray);
// 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();
}
// Return results
if (req.callbackMethod != null)
req.callbackMethod(hitYN, closestcontact, hitConsumerID, distance, snormal);
}
// This is the standard Near. Uses space AABBs to speed up detection.
private void near(IntPtr space, IntPtr g1, IntPtr g2)
{
//Don't test against heightfield Geom, or you'll be sorry!
/*
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
Stacktrace:
at (wrapper managed-to-native) Ode.NET.d.Collide (intptr,intptr,int,Ode.NET.d/ContactGeom[],int) <0x00004>
at (wrapper managed-to-native) Ode.NET.d.Collide (intptr,intptr,int,Ode.NET.d/ContactGeom[],int) <0xffffffff>
at OpenSim.Region.Physics.OdePlugin.ODERayCastRequestManager.near (intptr,intptr,intptr) <0x00280>
at (wrapper native-to-managed) OpenSim.Region.Physics.OdePlugin.ODERayCastRequestManager.near (intptr,intptr,intptr) <0xfff
fffff>
at (wrapper managed-to-native) Ode.NET.d.SpaceCollide2 (intptr,intptr,intptr,Ode.NET.d/NearCallback) <0x00004>
at (wrapper managed-to-native) Ode.NET.d.SpaceCollide2 (intptr,intptr,intptr,Ode.NET.d/NearCallback) <0xffffffff>
at OpenSim.Region.Physics.OdePlugin.ODERayCastRequestManager.RayCast (OpenSim.Region.Physics.OdePlugin.ODERayCastRequest) <
0x00114>
at OpenSim.Region.Physics.OdePlugin.ODERayCastRequestManager.ProcessQueuedRequests () <0x000eb>
at OpenSim.Region.Physics.OdePlugin.OdeScene.Simulate (single) <0x017e6>
at OpenSim.Region.Framework.Scenes.SceneGraph.UpdatePhysics (double) <0x00042>
at OpenSim.Region.Framework.Scenes.Scene.Update () <0x0039e>
at OpenSim.Region.Framework.Scenes.Scene.Heartbeat (object) <0x00019>
at (wrapper runtime-invoke) object.runtime_invoke_void__this___object (object,intptr,intptr,intptr) <0xffffffff>
Native stacktrace:
mono [0x80d2a42]
[0xb7f5840c]
/lib/i686/cmov/libc.so.6(abort+0x188) [0xb7d1a018]
/usr/lib/libstdc++.so.6(_ZN9__gnu_cxx27__verbose_terminate_handlerEv+0x158) [0xb45fc988]
/usr/lib/libstdc++.so.6 [0xb45fa865]
/usr/lib/libstdc++.so.6 [0xb45fa8a2]
/usr/lib/libstdc++.so.6 [0xb45fa9da]
/usr/lib/libstdc++.so.6(_Znwj+0x83) [0xb45fb033]
/usr/lib/libstdc++.so.6(_Znaj+0x1d) [0xb45fb11d]
libode.so(_ZN13dxHeightfield23dCollideHeightfieldZoneEiiiiP6dxGeomiiP12dContactGeomi+0xd04) [0xb46678e4]
libode.so(_Z19dCollideHeightfieldP6dxGeomS0_iP12dContactGeomi+0x54b) [0xb466832b]
libode.so(dCollide+0x102) [0xb46571b2]
[0x95cfdec9]
[0x8ea07fe1]
[0xab260146]
libode.so [0xb465a5c4]
libode.so(_ZN11dxHashSpace8collide2EPvP6dxGeomPFvS0_S2_S2_E+0x75) [0xb465bcf5]
libode.so(dSpaceCollide2+0x177) [0xb465ac67]
[0x95cf978e]
[0x8ea07945]
[0x95cf2bbc]
[0xab2787e7]
[0xab419fb3]
[0xab416657]
[0xab415bda]
[0xb609b08e]
mono(mono_runtime_delegate_invoke+0x34) [0x8192534]
mono [0x81a2f0f]
mono [0x81d28b6]
mono [0x81ea2c6]
/lib/i686/cmov/libpthread.so.0 [0xb7e744c0]
/lib/i686/cmov/libc.so.6(clone+0x5e) [0xb7dcd6de]
*/
// Exclude heightfield geom
if (g1 == IntPtr.Zero || g2 == IntPtr.Zero)
return;
if (d.GeomGetClass(g1) == d.GeomClassID.HeightfieldClass || d.GeomGetClass(g2) == d.GeomClassID.HeightfieldClass)
return;
// Raytest against AABBs of spaces first, then dig into the spaces it hits for actual geoms.
if (d.GeomIsSpace(g1) || d.GeomIsSpace(g2))
{
if (g1 == IntPtr.Zero || g2 == IntPtr.Zero)
return;
// Separating static prim geometry spaces.
// We'll be calling near recursivly if one
// of them is a space to find all of the
// contact points in the space
try
{
d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback);
}
catch (AccessViolationException)
{
m_log.Warn("[PHYSICS]: Unable to collide test a space");
return;
}
//Colliding a space or a geom with a space or a geom. so drill down
//Collide all geoms in each space..
//if (d.GeomIsSpace(g1)) d.SpaceCollide(g1, IntPtr.Zero, nearCallback);
//if (d.GeomIsSpace(g2)) d.SpaceCollide(g2, IntPtr.Zero, nearCallback);
return;
}
if (g1 == IntPtr.Zero || g2 == IntPtr.Zero)
return;
int count = 0;
try
{
if (g1 == g2)
return; // Can't collide with yourself
lock (contacts)
{
count = d.Collide(g1, g2, contacts.GetLength(0), contacts, d.ContactGeom.SizeOf);
}
}
catch (SEHException)
{
m_log.Error("[PHYSICS]: 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]: Unable to collide test an object: {0}", e.Message);
return;
}
PhysicsActor p1 = null;
PhysicsActor p2 = null;
if (g1 != IntPtr.Zero)
m_scene.actor_name_map.TryGetValue(g1, out p1);
if (g2 != IntPtr.Zero)
m_scene.actor_name_map.TryGetValue(g1, out p2);
// Loop over contacts, build results.
for (int i = 0; i < count; i++)
{
if (p1 != null) {
if (p1 is OdePrim)
{
ContactResult collisionresult = new ContactResult();
collisionresult.ConsumerID = ((OdePrim)p1).m_localID;
collisionresult.Pos = new Vector3(contacts[i].pos.X, contacts[i].pos.Y, contacts[i].pos.Z);
collisionresult.Depth = contacts[i].depth;
collisionresult.Normal = new Vector3(contacts[i].normal.X, contacts[i].normal.Y,
contacts[i].normal.Z);
lock (m_contactResults)
m_contactResults.Add(collisionresult);
}
}
if (p2 != null)
{
if (p2 is OdePrim)
{
ContactResult collisionresult = new ContactResult();
collisionresult.ConsumerID = ((OdePrim)p2).m_localID;
collisionresult.Pos = new Vector3(contacts[i].pos.X, contacts[i].pos.Y, contacts[i].pos.Z);
collisionresult.Depth = contacts[i].depth;
collisionresult.Normal = new Vector3(contacts[i].normal.X, contacts[i].normal.Y,
contacts[i].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 ODERayCastRequest
{
public Vector3 Origin;
public Vector3 Normal;
public float length;
public RaycastCallback callbackMethod;
}
public struct ContactResult
{
public Vector3 Pos;
public float Depth;
public uint ConsumerID;
public Vector3 Normal;
}
}

View File

@ -0,0 +1,48 @@
/*
* 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 Ode.NET;
using OpenSim.Framework;
using OpenSim.Region.Physics.Manager;
using OpenSim.Region.Physics.OdePlugin;
namespace OpenSim.Region.Physics.OdePlugin
{
class OdePhysicsJoint : PhysicsJoint
{
public override bool IsInPhysicsEngine
{
get
{
return (jointID != IntPtr.Zero);
}
}
public IntPtr jointID;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,122 @@
/*
* 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 Nini.Config;
using NUnit.Framework;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Region.Physics.Manager;
using log4net;
using System.Reflection;
namespace OpenSim.Region.Physics.OdePlugin
{
[TestFixture]
public class ODETestClass
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private OdePlugin cbt;
private PhysicsScene ps;
private IMeshingPlugin imp;
[SetUp]
public void Initialize()
{
// Loading ODEPlugin
cbt = new OdePlugin();
// Loading Zero Mesher
imp = new ZeroMesherPlugin();
// Getting Physics Scene
ps = cbt.GetScene("test");
// Initializing Physics Scene.
ps.Initialise(imp.GetMesher(),null);
float[] _heightmap = new float[(int)Constants.RegionSize * (int)Constants.RegionSize];
for (int i = 0; i < ((int)Constants.RegionSize * (int)Constants.RegionSize); i++)
{
_heightmap[i] = 21f;
}
ps.SetTerrain(_heightmap);
}
[TearDown]
public void Terminate()
{
ps.DeleteTerrain();
ps.Dispose();
}
[Test]
public void CreateAndDropPhysicalCube()
{
PrimitiveBaseShape newcube = PrimitiveBaseShape.CreateBox();
Vector3 position = new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f), 128f);
Vector3 size = new Vector3(0.5f, 0.5f, 0.5f);
Quaternion rot = Quaternion.Identity;
PhysicsActor prim = ps.AddPrimShape("CoolShape", newcube, position, size, rot, true);
OdePrim oprim = (OdePrim)prim;
OdeScene pscene = (OdeScene) ps;
Assert.That(oprim.m_taintadd);
prim.LocalID = 5;
for (int i = 0; i < 58; i++)
{
ps.Simulate(0.133f);
Assert.That(oprim.prim_geom != (IntPtr)0);
Assert.That(oprim.m_targetSpace != (IntPtr)0);
//Assert.That(oprim.m_targetSpace == pscene.space);
m_log.Info("TargetSpace: " + oprim.m_targetSpace + " - SceneMainSpace: " + pscene.space);
Assert.That(!oprim.m_taintadd);
m_log.Info("Prim Position (" + oprim.m_localID + "): " + prim.Position.ToString());
// Make sure we're above the ground
//Assert.That(prim.Position.Z > 20f);
//m_log.Info("PrimCollisionScore (" + oprim.m_localID + "): " + oprim.m_collisionscore);
// Make sure we've got a Body
Assert.That(oprim.Body != (IntPtr)0);
//m_log.Info(
}
// Make sure we're not somewhere above the ground
Assert.That(prim.Position.Z < 21.5f);
ps.RemovePrim(prim);
Assert.That(oprim.m_taintremove);
ps.Simulate(0.133f);
Assert.That(oprim.Body == (IntPtr)0);
}
}
}

View File

@ -0,0 +1,98 @@
/*
* Copyright ODE
* Ode.NET - .NET bindings for ODE
* Jason Perkins (starkos@industriousone.com)
* Licensed under the New BSD
* Part of the OpenDynamicsEngine
Open Dynamics Engine
Copyright (c) 2001-2007, Russell L. Smith.
All rights reserved.
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 names of ODE's copyright owner 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
"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 COPYRIGHT
OWNER OR 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.Runtime.InteropServices;
using Ode.NET;
namespace Drawstuff.NET
{
#if dDOUBLE
using dReal = System.Double;
#else
using dReal = System.Single;
#endif
public static class ds
{
public const int VERSION = 2;
public enum Texture
{
None,
Wood
}
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void CallbackFunction(int arg);
[StructLayout(LayoutKind.Sequential)]
public struct Functions
{
public int version;
public CallbackFunction start;
public CallbackFunction step;
public CallbackFunction command;
public CallbackFunction stop;
public string path_to_textures;
}
[DllImport("drawstuff", EntryPoint = "dsDrawBox")]
public static extern void DrawBox(ref d.Vector3 pos, ref d.Matrix3 R, ref d.Vector3 sides);
[DllImport("drawstuff", EntryPoint = "dsDrawCapsule")]
public static extern void DrawCapsule(ref d.Vector3 pos, ref d.Matrix3 R, dReal length, dReal radius);
[DllImport("drawstuff", EntryPoint = "dsDrawConvex")]
public static extern void DrawConvex(ref d.Vector3 pos, ref d.Matrix3 R, dReal[] planes, int planeCount, dReal[] points, int pointCount, int[] polygons);
[DllImport("drawstuff", EntryPoint = "dsSetColor")]
public static extern void SetColor(float red, float green, float blue);
[DllImport("drawstuff", EntryPoint = "dsSetTexture")]
public static extern void SetTexture(Texture texture);
[DllImport("drawstuff", EntryPoint = "dsSetViewpoint")]
public static extern void SetViewpoint(ref d.Vector3 xyz, ref d.Vector3 hpr);
[DllImport("drawstuff", EntryPoint = "dsSimulationLoop")]
public static extern void SimulationLoop(int argc, string[] argv, int window_width, int window_height, ref Functions fn);
}
}

View File

@ -487,7 +487,6 @@ namespace OpenSim.Region.Physics.Manager
public override float APIDStrength { set { return; } }
public override float APIDDamping { set { return; } }
public override void SetMomentum(Vector3 momentum)
{
}

View File

@ -1197,27 +1197,13 @@ namespace OpenSim.Region.Physics.OdePlugin
public override PIDHoverType PIDHoverType { set { return; } }
public override float PIDHoverTau { set { return; } }
public override Quaternion APIDTarget
{
set { return; }
}
public override Quaternion APIDTarget{ set { return; } }
public override bool APIDActive
{
set { return; }
}
public override float APIDStrength
{
set { return; }
}
public override float APIDDamping
{
set { return; }
}
public override bool APIDActive{ set { return; } }
public override float APIDStrength{ set { return; } }
public override float APIDDamping{ set { return; } }
public override void SubscribeEvents(int ms)
{

View File

@ -23,19 +23,6 @@
* 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.
*
*/
/* Revised Aug, Sept 2009 by Kitto Flora. ODEDynamics.cs replaces
@ -133,7 +120,7 @@ namespace OpenSim.Region.Physics.OdePlugin
// private float m_VhoverEfficiency = 0f;
private float m_VhoverTimescale = 0f;
private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height
private float m_VehicleBuoyancy = 0f; // Set by VEHICLE_BUOYANCY, for a vehicle.
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.
@ -574,7 +561,6 @@ namespace OpenSim.Region.Physics.OdePlugin
private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate
private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body
*/
//if(frcount == 0) Console.WriteLine("MoveAngular ");
// Get what the body is doing, this includes 'external' influences
d.Vector3 angularVelocity = d.BodyGetAngularVel(Body);
@ -650,7 +636,7 @@ namespace OpenSim.Region.Physics.OdePlugin
// Deflection section tba
// Sum velocities
m_lastAngularVelocity = m_angularMotorVelocity + vertattr; // tba: + bank + deflection
m_lastAngularVelocity = m_angularMotorVelocity + vertattr; // + bank + deflection
if (!m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f))
{

View File

@ -21,18 +21,6 @@
* 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 August 26 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.
*/
/*
@ -93,12 +81,7 @@ namespace OpenSim.Region.Physics.OdePlugin
private float m_PIDTau;
private float PID_D = 35f;
private float PID_G = 25f;
private bool m_usePID = false;
private Quaternion m_APIDTarget = new Quaternion();
private float m_APIDStrength = 0.5f;
private float m_APIDDamping = 0.5f;
private bool m_useAPID = false;
private bool m_usePID;
// KF: These next 7 params apply to llSetHoverHeight(float height, integer water, float tau),
// and are for non-VEHICLES only.
@ -200,9 +183,6 @@ namespace OpenSim.Region.Physics.OdePlugin
internal int m_material = (int)Material.Wood;
private int frcount = 0; // Used to limit dynamics debug output to
public OdePrim(String primName, OdeScene parent_scene, Vector3 pos, Vector3 size,
Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool pisPhysical, CollisionLocker dode)
{
@ -1581,14 +1561,9 @@ Console.WriteLine(" JointCreateFixed");
float fy = 0;
float fz = 0;
frcount++; // used to limit debug comment output
if (frcount > 100)
frcount = 0;
if (IsPhysical && (Body != IntPtr.Zero) && !m_isSelected && !childPrim) // KF: Only move root prims.
{
//if(frcount == 0) Console.WriteLine("Move " + m_primName + " VTyp " + m_vehicle.Type +
// " usePID=" + m_usePID + " seHover=" + m_useHoverPID + " useAPID=" + m_useAPID);
if (m_vehicle.Type != Vehicle.TYPE_NONE)
{
// 'VEHICLES' are dealt with in ODEDynamics.cs
@ -1596,6 +1571,7 @@ Console.WriteLine(" JointCreateFixed");
}
else
{
//Console.WriteLine("Move " + m_primName);
if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body); // KF add 161009
// NON-'VEHICLES' are dealt with here
if (d.BodyIsEnabled(Body) && !m_angularlock.ApproxEquals(Vector3.Zero, 0.003f))
@ -1617,18 +1593,21 @@ Console.WriteLine(" JointCreateFixed");
//m_log.Info(m_collisionFlags.ToString());
//KF: m_buoyancy is set by llSetBuoyancy() and is for non-vehicle.
//KF: m_buoyancy should be set by llSetBuoyancy() for non-vehicle.
// would come from SceneObjectPart.cs, public void SetBuoyancy(float fvalue) , PhysActor.Buoyancy = fvalue; ??
// m_buoyancy: (unlimited value) <0=Falls fast; 0=1g; 1=0g; >1 = floats up
// NB Prims in ODE are no subject to global gravity
fz = _parent_scene.gravityz * (1.0f - m_buoyancy) * m_mass; // force = acceleration * mass
// gravityz multiplier = 1 - m_buoyancy
fz = _parent_scene.gravityz * (1.0f - m_buoyancy) * m_mass;
if (m_usePID)
{
//if(frcount == 0) Console.WriteLine("PID " + m_primName);
// KF - this is for object MoveToTarget.
//Console.WriteLine("PID " + m_primName);
// KF - this is for object move? eg. llSetPos() ?
//if (!d.BodyIsEnabled(Body))
//d.BodySetForce(Body, 0f, 0f, 0f);
// If we're using the PID controller, then we have no gravity
//fz = (-1 * _parent_scene.gravityz) * m_mass; //KF: ?? Prims have no global gravity,so simply...
fz = 0f;
// no lock; for now it's only called from within Simulate()
@ -1763,7 +1742,7 @@ Console.WriteLine(" JointCreateFixed");
d.BodySetPosition(Body, pos.X, pos.Y, m_targetHoverHeight);
d.BodySetLinearVel(Body, vel.X, vel.Y, 0);
d.BodyAddForce(Body, 0, 0, fz);
//KF this prevents furthur motions return;
return;
}
else
{
@ -1772,45 +1751,7 @@ Console.WriteLine(" JointCreateFixed");
// We're flying and colliding with something
fz = fz + ((_target_velocity.Z - vel.Z) * (PID_D) * m_mass);
}
} // end m_useHoverPID && !m_usePID
if (m_useAPID)
{
// RotLookAt, apparently overrides all other rotation sources. Inputs:
// Quaternion m_APIDTarget
// float m_APIDStrength // From SL experiments, this is the time to get there
// float m_APIDDamping // From SL experiments, this is damping, 1.0 = damped, 0.1 = wobbly
// Also in SL the mass of the object has no effect on time to get there.
// Factors:
//if(frcount == 0) Console.WriteLine("APID ");
// get present body rotation
float limit = 1.0f;
float scaler = 50f; // adjusts damping time
float RLAservo = 0f;
d.Quaternion rot = d.BodyGetQuaternion(Body);
Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W);
Quaternion rot_diff = Quaternion.Inverse(rotq) * m_APIDTarget;
float diff_angle;
Vector3 diff_axis;
rot_diff.GetAxisAngle(out diff_axis, out diff_angle);
diff_axis.Normalize();
if(diff_angle > 0.01f) // diff_angle is always +ve
{
// PhysicsVector rotforce = new PhysicsVector(diff_axis.X, diff_axis.Y, diff_axis.Z);
Vector3 rotforce = new Vector3(diff_axis.X, diff_axis.Y, diff_axis.Z);
rotforce = rotforce * rotq;
if(diff_angle > limit) diff_angle = limit; // cap the rotate rate
// RLAservo = timestep / m_APIDStrength * m_mass * scaler;
// rotforce = rotforce * RLAservo * diff_angle ;
// d.BodyAddRelTorque(Body, rotforce.X, rotforce.Y, rotforce.Z);
RLAservo = timestep / m_APIDStrength * scaler;
rotforce = rotforce * RLAservo * diff_angle ;
d.BodySetAngularVel (Body, rotforce.X, rotforce.Y, rotforce.Z);
//Console.WriteLine("axis= " + diff_axis + " angle= " + diff_angle + "servo= " + RLAservo);
}
//if(frcount == 0) Console.WriteLine("mass= " + m_mass + " servo= " + RLAservo + " angle= " + diff_angle);
} // end m_useAPID
fx *= m_mass;
fy *= m_mass;
@ -2682,10 +2623,6 @@ Console.WriteLine(" JointCreateFixed");
l_orientation.Z = ori.Z;
l_orientation.W = ori.W;
// if(l_position.Y != m_lastposition.Y){
// Console.WriteLine("UP&V {0} {1}", m_primName, l_position);
// }
if (l_position.X > ((int)_parent_scene.WorldExtents.X - 0.05f) || l_position.X < 0f || l_position.Y > ((int)_parent_scene.WorldExtents.Y - 0.05f) || l_position.Y < 0f)
{
//base.RaiseOutOfBounds(l_position);
@ -2886,17 +2823,20 @@ Console.WriteLine(" JointCreateFixed");
public override bool PIDActive { set { m_usePID = value; } }
public override float PIDTau { set { m_PIDTau = value; } }
// For RotLookAt
public override Quaternion APIDTarget { set { m_APIDTarget = value; } }
public override bool APIDActive { set { m_useAPID = value; } }
public override float APIDStrength { set { m_APIDStrength = value; } }
public override float APIDDamping { set { m_APIDDamping = value; } }
public override float PIDHoverHeight { set { m_PIDHoverHeight = value; ; } }
public override bool PIDHoverActive { set { m_useHoverPID = value; } }
public override PIDHoverType PIDHoverType { set { m_PIDHoverType = value; } }
public override float PIDHoverTau { set { m_PIDHoverTau = value; } }
public override Quaternion APIDTarget{ set { return; } }
public override bool APIDActive{ set { return; } }
public override float APIDStrength{ set { return; } }
public override float APIDDamping{ set { return; } }
private void createAMotor(Vector3 axis)
{
if (Body == IntPtr.Zero)

View File

@ -299,6 +299,7 @@ namespace OpenSim.Region.Physics.POSPlugin
{
set { return; }
}
public override Quaternion APIDTarget
{
set { return; }

View File

@ -2781,7 +2781,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
public void llStopLookAt()
{
m_host.AddScriptLPS(1);
@ -7523,9 +7522,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
break;
case (int)ScriptBaseClass.PRIM_POSITION:
res.Add(new LSL_Vector(part.AbsolutePosition.X,
LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X,
part.AbsolutePosition.Y,
part.AbsolutePosition.Z));
part.AbsolutePosition.Z);
// For some reason, the part.AbsolutePosition.* values do not change if the
// linkset is rotated; they always reflect the child prim's world position
// as though the linkset is unrotated. This is incompatible behavior with SL's
// implementation, so will break scripts imported from there (not to mention it
// makes it more difficult to determine a child prim's actual inworld position).
if (part.ParentID != 0)
v = ((v - llGetRootPosition()) * llGetRootRotation()) + llGetRootPosition();
res.Add( v );
break;
case (int)ScriptBaseClass.PRIM_SIZE:
@ -7543,6 +7550,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
PrimitiveBaseShape Shape = part.Shape;
int primType = getScriptPrimType(part.Shape);
res.Add(new LSL_Integer(primType));
double topshearx = (double)(sbyte)Shape.PathShearX / 100.0; // Fix negative values for PathShearX
double topsheary = (double)(sbyte)Shape.PathShearY / 100.0; // and PathShearY.
switch (primType)
{
case ScriptBaseClass.PRIM_TYPE_BOX:
@ -7553,7 +7562,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0));
res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0));
res.Add(new LSL_Vector(1 - (Shape.PathScaleX / 100.0 - 1), 1 - (Shape.PathScaleY / 100.0 - 1), 0));
res.Add(new LSL_Vector(Shape.PathShearX / 100.0, Shape.PathShearY / 100.0, 0));
res.Add(new LSL_Vector(topshearx, topsheary, 0));
break;
case ScriptBaseClass.PRIM_TYPE_SPHERE:
@ -7588,7 +7597,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
res.Add(new LSL_Vector(1 - (Shape.PathScaleX / 100.0 - 1), 1 - (Shape.PathScaleY / 100.0 - 1), 0));
// vector topshear
res.Add(new LSL_Vector(Shape.PathShearX / 100.0, Shape.PathShearY / 100.0, 0));
res.Add(new LSL_Vector(topshearx, topsheary, 0));
// vector profilecut
res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0));
@ -7597,7 +7606,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
res.Add(new LSL_Vector(Shape.PathTaperX / 100.0, Shape.PathTaperY / 100.0, 0));
// float revolutions
res.Add(new LSL_Float(Shape.PathRevolutions / 50.0)); // needs fixing :(
res.Add(new LSL_Float((Shape.PathRevolutions * 0.015) + 1.0)); // Slightly inaccurate, because an unsigned
// byte is being used to represent the entire
// range of floating-point values from 1.0
// through 4.0 (which is how SL does it).
// float radiusoffset
res.Add(new LSL_Float(Shape.PathRadiusOffset / 100.0));

View File

@ -111,7 +111,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
if (emessage.StartsWith(slinfo+": "))
emessage = emessage.Substring(slinfo.Length+2);
message = String.Format("Line ({0},{1}) {2}",
message = String.Format("({0},{1}) {2}",
e.slInfo.lineNumber - 2,
e.slInfo.charPosition - 1, emessage);

View File

@ -623,7 +623,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
// The Second Life viewer's script editor begins
// countingn lines and columns at 0, so we subtract 1.
errtext += String.Format("Line ({0},{1}): {4} {2}: {3}\n",
errtext += String.Format("({0},{1}): {4} {2}: {3}\n",
lslPos.Key - 1, lslPos.Value - 1,
CompErr.ErrorNumber, text, severity);
hadErrors = true;

View File

@ -1673,7 +1673,7 @@ default
{
// The syntax error is on line 6, char 5 (expected ';', found
// '}').
Assert.AreEqual("Line (4,4) syntax error", e.Message);
Assert.AreEqual("(4,4) syntax error", e.Message);
throw;
}
}
@ -1698,7 +1698,7 @@ default
catch (System.Exception e)
{
// The syntax error is on line 5, char 14 (Syntax error)
Assert.AreEqual("Line (3,13) syntax error", e.Message);
Assert.AreEqual("(3,13) syntax error", e.Message);
throw;
}

View File

@ -974,7 +974,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
if (col == 0)
col++;
message = string.Format("Runtime error:\n" +
"Line ({0}): {1}", scriptLine - 1,
"({0}): {1}", scriptLine - 1,
e.InnerException.Message);
System.Console.WriteLine(e.ToString()+"\n");

View File

@ -78,6 +78,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
private string m_ScriptErrorMessage;
private Dictionary<string, string> m_uniqueScripts = new Dictionary<string, string>();
private bool m_AppDomainLoading;
private Dictionary<UUID,ArrayList> m_ScriptErrors =
new Dictionary<UUID,ArrayList>();
// disable warning: need to keep a reference to XEngine.EventManager
// alive to avoid it being garbage collected
@ -657,6 +659,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> linemap;
lock(m_ScriptErrors)
{
try
{
lock (m_AddingAssemblies)
@ -675,70 +679,78 @@ namespace OpenSim.Region.ScriptEngine.XEngine
{
foreach (string warning in warnings)
{
try
{
// DISPLAY WARNING INWORLD
string text = "Warning:\n" + warning;
if (text.Length > 1000)
text = text.Substring(0, 1000);
if (!ShowScriptSaveResponse(item.OwnerID,
assetID, text, true))
{
if (presence != null && (!postOnRez))
presence.ControllingClient.SendAgentAlertMessage("Script saved with warnings, check debug window!", false);
if (!m_ScriptErrors.ContainsKey(itemID))
m_ScriptErrors[itemID] = new ArrayList();
World.SimChat(Utils.StringToBytes(text),
ChatTypeEnum.DebugChannel, 2147483647,
part.AbsolutePosition,
part.Name, part.UUID, false);
}
}
catch (Exception e2) // LEGIT: User Scripting
{
m_log.Error("[XEngine]: " +
"Error displaying warning in-world: " +
e2.ToString());
m_log.Error("[XEngine]: " +
"Warning:\r\n" +
warning);
}
m_ScriptErrors[itemID].Add(warning);
// try
// {
// // DISPLAY WARNING INWORLD
// string text = "Warning:\n" + warning;
// if (text.Length > 1000)
// text = text.Substring(0, 1000);
// if (!ShowScriptSaveResponse(item.OwnerID,
// assetID, text, true))
// {
// if (presence != null && (!postOnRez))
// presence.ControllingClient.SendAgentAlertMessage("Script saved with warnings, check debug window!", false);
//
// World.SimChat(Utils.StringToBytes(text),
// ChatTypeEnum.DebugChannel, 2147483647,
// part.AbsolutePosition,
// part.Name, part.UUID, false);
// }
// }
// catch (Exception e2) // LEGIT: User Scripting
// {
// m_log.Error("[XEngine]: " +
// "Error displaying warning in-world: " +
// e2.ToString());
// m_log.Error("[XEngine]: " +
// "Warning:\r\n" +
// warning);
// }
}
}
}
catch (Exception e)
{
try
{
// try
// {
if (!m_ScriptErrors.ContainsKey(itemID))
m_ScriptErrors[itemID] = new ArrayList();
// DISPLAY ERROR INWORLD
m_ScriptErrorMessage += "Failed to compile script in object: '" + part.ParentGroup.RootPart.Name + "' Script name: '" + item.Name + "' Error message: " + e.Message.ToString();
// m_ScriptErrorMessage += "Failed to compile script in object: '" + part.ParentGroup.RootPart.Name + "' Script name: '" + item.Name + "' Error message: " + e.Message.ToString();
//
m_ScriptFailCount++;
string text = "Error compiling script '" + item.Name + "':\n" + e.Message.ToString();
if (text.Length > 1000)
text = text.Substring(0, 1000);
if (!ShowScriptSaveResponse(item.OwnerID,
assetID, text, false))
{
if (presence != null && (!postOnRez))
presence.ControllingClient.SendAgentAlertMessage("Script saved with errors, check debug window!", false);
World.SimChat(Utils.StringToBytes(text),
ChatTypeEnum.DebugChannel, 2147483647,
part.AbsolutePosition,
part.Name, part.UUID, false);
}
}
catch (Exception e2) // LEGIT: User Scripting
{
m_log.Error("[XEngine]: "+
"Error displaying error in-world: " +
e2.ToString());
m_log.Error("[XEngine]: " +
"Errormessage: Error compiling script:\r\n" +
e.Message.ToString());
}
m_ScriptErrors[itemID].Add(e.Message.ToString());
// string text = "Error compiling script '" + item.Name + "':\n" + e.Message.ToString();
// if (text.Length > 1000)
// text = text.Substring(0, 1000);
// if (!ShowScriptSaveResponse(item.OwnerID,
// assetID, text, false))
// {
// if (presence != null && (!postOnRez))
// presence.ControllingClient.SendAgentAlertMessage("Script saved with errors, check debug window!", false);
// World.SimChat(Utils.StringToBytes(text),
// ChatTypeEnum.DebugChannel, 2147483647,
// part.AbsolutePosition,
// part.Name, part.UUID, false);
// }
// }
// catch (Exception e2) // LEGIT: User Scripting
// {
// m_log.Error("[XEngine]: "+
// "Error displaying error in-world: " +
// e2.ToString());
// m_log.Error("[XEngine]: " +
// "Errormessage: Error compiling script:\r\n" +
// e.Message.ToString());
// }
return false;
}
}
@ -1252,7 +1264,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine
return UUID.Zero;
}
[DebuggerNonUserCode]
public void SetState(UUID itemID, string newState)
{
IScriptInstance instance = GetInstance(itemID);
@ -1260,13 +1271,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine
return;
instance.SetState(newState);
}
public string GetState(UUID itemID)
{
IScriptInstance instance = GetInstance(itemID);
if (instance == null)
return "default";
return instance.State;
}
public int GetStartParameter(UUID itemID)
{
@ -1552,5 +1556,21 @@ namespace OpenSim.Region.ScriptEngine.XEngine
return true;
}
public ArrayList GetScriptErrors(UUID itemID)
{
System.Threading.Thread.Sleep(1000);
lock (m_ScriptErrors)
{
if (m_ScriptErrors.ContainsKey(itemID))
{
ArrayList ret = m_ScriptErrors[itemID];
m_ScriptErrors.Remove(itemID);
return ret;
}
return new ArrayList();
}
}
}
}

View File

@ -151,6 +151,9 @@ namespace OpenSim.Services.Connectors.Grid
m_AssetService.Store(ass);
// finally
info.TerrainImage = ass.FullID;
}
catch // LEGIT: Catching problems caused by OpenJPEG p/invoke
{

View File

@ -543,6 +543,36 @@
</Files>
</Project>
<Project frameworkVersion="v3_5" name="OpenSim.Region.Physics.ChOdePlugin" path="OpenSim/Region/Physics/ChOdePlugin" 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.dll"/>
<Reference name="Nini.dll" />
<Reference name="OpenSim.Framework"/>
<Reference name="OpenSim.Framework.Console"/>
<Reference name="OpenSim.Region.Physics.Manager"/>
<Reference name="Ode.NET.dll" />
<Reference name="log4net.dll"/>
<Files>
<Match pattern="*.cs" recurse="true">
<Exclude name="Tests" pattern="Tests"/>
</Match>
</Files>
</Project>
<Project frameworkVersion="v3_5" name="OpenSim.Region.Physics.BulletXPlugin" path="OpenSim/Region/Physics/BulletXPlugin" type="Library">
<Configuration name="Debug">
<Options>