Merge branch 'master' of ssh://opensimulator.org/var/git/opensim
commit
590a8b0315
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using OpenMetaverse;
|
using OpenMetaverse;
|
||||||
using OpenMetaverse.StructuredData;
|
using OpenMetaverse.StructuredData;
|
||||||
|
@ -39,8 +40,6 @@ namespace OpenSim.Framework.Monitoring
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class SimExtraStatsCollector : BaseStatsCollector
|
public class SimExtraStatsCollector : BaseStatsCollector
|
||||||
{
|
{
|
||||||
private long abnormalClientThreadTerminations;
|
|
||||||
|
|
||||||
// private long assetsInCache;
|
// private long assetsInCache;
|
||||||
// private long texturesInCache;
|
// private long texturesInCache;
|
||||||
// private long assetCacheMemoryUsage;
|
// private long assetCacheMemoryUsage;
|
||||||
|
@ -73,11 +72,6 @@ namespace OpenSim.Framework.Monitoring
|
||||||
private volatile float activeScripts;
|
private volatile float activeScripts;
|
||||||
private volatile float scriptLinesPerSecond;
|
private volatile float scriptLinesPerSecond;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Number of times that a client thread terminated because of an exception
|
|
||||||
/// </summary>
|
|
||||||
public long AbnormalClientThreadTerminations { get { return abnormalClientThreadTerminations; } }
|
|
||||||
|
|
||||||
// /// <summary>
|
// /// <summary>
|
||||||
// /// These statistics are being collected by push rather than pull. Pull would be simpler, but I had the
|
// /// These statistics are being collected by push rather than pull. Pull would be simpler, but I had the
|
||||||
// /// notion of providing some flow statistics (which pull wouldn't give us). Though admittedly these
|
// /// notion of providing some flow statistics (which pull wouldn't give us). Though admittedly these
|
||||||
|
@ -166,11 +160,6 @@ namespace OpenSim.Framework.Monitoring
|
||||||
private IDictionary<UUID, PacketQueueStatsCollector> packetQueueStatsCollectors
|
private IDictionary<UUID, PacketQueueStatsCollector> packetQueueStatsCollectors
|
||||||
= new Dictionary<UUID, PacketQueueStatsCollector>();
|
= new Dictionary<UUID, PacketQueueStatsCollector>();
|
||||||
|
|
||||||
public void AddAbnormalClientThreadTermination()
|
|
||||||
{
|
|
||||||
abnormalClientThreadTerminations++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// public void AddAsset(AssetBase asset)
|
// public void AddAsset(AssetBase asset)
|
||||||
// {
|
// {
|
||||||
// assetsInCache++;
|
// assetsInCache++;
|
||||||
|
@ -324,10 +313,12 @@ Asset service request failures: {3}" + Environment.NewLine,
|
||||||
sb.Append(Environment.NewLine);
|
sb.Append(Environment.NewLine);
|
||||||
sb.Append("CONNECTION STATISTICS");
|
sb.Append("CONNECTION STATISTICS");
|
||||||
sb.Append(Environment.NewLine);
|
sb.Append(Environment.NewLine);
|
||||||
sb.Append(
|
|
||||||
string.Format(
|
List<Stat> stats = StatsManager.GetStatsFromEachContainer("clientstack", "ClientLogoutsDueToNoReceives");
|
||||||
"Abnormal client thread terminations: {0}" + Environment.NewLine,
|
|
||||||
abnormalClientThreadTerminations));
|
sb.AppendFormat(
|
||||||
|
"Client logouts due to no data receive timeout: {0}\n\n",
|
||||||
|
stats != null ? stats.Sum(s => s.Value).ToString() : "unknown");
|
||||||
|
|
||||||
// sb.Append(Environment.NewLine);
|
// sb.Append(Environment.NewLine);
|
||||||
// sb.Append("INVENTORY STATISTICS");
|
// sb.Append("INVENTORY STATISTICS");
|
||||||
|
@ -338,7 +329,7 @@ Asset service request failures: {3}" + Environment.NewLine,
|
||||||
// InventoryServiceRetrievalFailures));
|
// InventoryServiceRetrievalFailures));
|
||||||
|
|
||||||
sb.Append(Environment.NewLine);
|
sb.Append(Environment.NewLine);
|
||||||
sb.Append("FRAME STATISTICS");
|
sb.Append("SAMPLE FRAME STATISTICS");
|
||||||
sb.Append(Environment.NewLine);
|
sb.Append(Environment.NewLine);
|
||||||
sb.Append("Dilatn SimFPS PhyFPS AgntUp RootAg ChldAg Prims AtvPrm AtvScr ScrLPS");
|
sb.Append("Dilatn SimFPS PhyFPS AgntUp RootAg ChldAg Prims AtvPrm AtvScr ScrLPS");
|
||||||
sb.Append(Environment.NewLine);
|
sb.Append(Environment.NewLine);
|
||||||
|
|
|
@ -271,7 +271,7 @@ namespace OpenSim.Framework.Monitoring
|
||||||
// Stat name is not unique across category/container/shortname key.
|
// Stat name is not unique across category/container/shortname key.
|
||||||
// XXX: For now just return false. This is to avoid problems in regression tests where all tests
|
// XXX: For now just return false. This is to avoid problems in regression tests where all tests
|
||||||
// in a class are run in the same instance of the VM.
|
// in a class are run in the same instance of the VM.
|
||||||
if (TryGetStat(stat, out category, out container))
|
if (TryGetStatParents(stat, out category, out container))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// We take a copy-on-write approach here of replacing dictionaries when keys are added or removed.
|
// We take a copy-on-write approach here of replacing dictionaries when keys are added or removed.
|
||||||
|
@ -307,7 +307,7 @@ namespace OpenSim.Framework.Monitoring
|
||||||
|
|
||||||
lock (RegisteredStats)
|
lock (RegisteredStats)
|
||||||
{
|
{
|
||||||
if (!TryGetStat(stat, out category, out container))
|
if (!TryGetStatParents(stat, out category, out container))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
newContainer = new SortedDictionary<string, Stat>(container);
|
newContainer = new SortedDictionary<string, Stat>(container);
|
||||||
|
@ -323,12 +323,67 @@ namespace OpenSim.Framework.Monitoring
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool TryGetStats(string category, out SortedDictionary<string, SortedDictionary<string, Stat>> stats)
|
public static bool TryGetStat(string category, string container, string statShortName, out Stat stat)
|
||||||
{
|
{
|
||||||
|
stat = null;
|
||||||
|
SortedDictionary<string, SortedDictionary<string, Stat>> categoryStats;
|
||||||
|
|
||||||
|
lock (RegisteredStats)
|
||||||
|
{
|
||||||
|
if (!TryGetStatsForCategory(category, out categoryStats))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
SortedDictionary<string, Stat> containerStats;
|
||||||
|
|
||||||
|
if (!categoryStats.TryGetValue(container, out containerStats))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return containerStats.TryGetValue(statShortName, out stat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool TryGetStatsForCategory(
|
||||||
|
string category, out SortedDictionary<string, SortedDictionary<string, Stat>> stats)
|
||||||
|
{
|
||||||
|
lock (RegisteredStats)
|
||||||
return RegisteredStats.TryGetValue(category, out stats);
|
return RegisteredStats.TryGetValue(category, out stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool TryGetStat(
|
/// <summary>
|
||||||
|
/// Get the same stat for each container in a given category.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// The stats if there were any to fetch. Otherwise null.
|
||||||
|
/// </returns>
|
||||||
|
/// <param name='category'></param>
|
||||||
|
/// <param name='statShortName'></param>
|
||||||
|
public static List<Stat> GetStatsFromEachContainer(string category, string statShortName)
|
||||||
|
{
|
||||||
|
SortedDictionary<string, SortedDictionary<string, Stat>> categoryStats;
|
||||||
|
|
||||||
|
lock (RegisteredStats)
|
||||||
|
{
|
||||||
|
if (!RegisteredStats.TryGetValue(category, out categoryStats))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
List<Stat> stats = null;
|
||||||
|
|
||||||
|
foreach (SortedDictionary<string, Stat> containerStats in categoryStats.Values)
|
||||||
|
{
|
||||||
|
if (containerStats.ContainsKey(statShortName))
|
||||||
|
{
|
||||||
|
if (stats == null)
|
||||||
|
stats = new List<Stat>();
|
||||||
|
|
||||||
|
stats.Add(containerStats[statShortName]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return stats;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool TryGetStatParents(
|
||||||
Stat stat,
|
Stat stat,
|
||||||
out SortedDictionary<string, SortedDictionary<string, Stat>> category,
|
out SortedDictionary<string, SortedDictionary<string, Stat>> category,
|
||||||
out SortedDictionary<string, Stat> container)
|
out SortedDictionary<string, Stat> container)
|
||||||
|
|
|
@ -67,11 +67,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
{
|
{
|
||||||
m_udpServer.AddScene(scene);
|
m_udpServer.AddScene(scene);
|
||||||
|
|
||||||
|
StatsManager.RegisterStat(
|
||||||
|
new Stat(
|
||||||
|
"ClientLogoutsDueToNoReceives",
|
||||||
|
"Number of times a client has been logged out because no packets were received before the timeout.",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"clientstack",
|
||||||
|
scene.Name,
|
||||||
|
StatType.Pull,
|
||||||
|
MeasuresOfInterest.None,
|
||||||
|
stat => stat.Value = m_udpServer.ClientLogoutsDueToNoReceives,
|
||||||
|
StatVerbosity.Debug));
|
||||||
|
|
||||||
StatsManager.RegisterStat(
|
StatsManager.RegisterStat(
|
||||||
new Stat(
|
new Stat(
|
||||||
"IncomingUDPReceivesCount",
|
"IncomingUDPReceivesCount",
|
||||||
"Number of UDP receives performed",
|
"Number of UDP receives performed",
|
||||||
"Number of UDP receives performed",
|
"",
|
||||||
"",
|
"",
|
||||||
"clientstack",
|
"clientstack",
|
||||||
scene.Name,
|
scene.Name,
|
||||||
|
@ -84,7 +97,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
new Stat(
|
new Stat(
|
||||||
"IncomingPacketsProcessedCount",
|
"IncomingPacketsProcessedCount",
|
||||||
"Number of inbound LL protocol packets processed",
|
"Number of inbound LL protocol packets processed",
|
||||||
"Number of inbound LL protocol packets processed",
|
"",
|
||||||
"",
|
"",
|
||||||
"clientstack",
|
"clientstack",
|
||||||
scene.Name,
|
scene.Name,
|
||||||
|
@ -97,7 +110,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
new Stat(
|
new Stat(
|
||||||
"OutgoingUDPSendsCount",
|
"OutgoingUDPSendsCount",
|
||||||
"Number of UDP sends performed",
|
"Number of UDP sends performed",
|
||||||
"Number of UDP sends performed",
|
"",
|
||||||
"",
|
"",
|
||||||
"clientstack",
|
"clientstack",
|
||||||
scene.Name,
|
scene.Name,
|
||||||
|
@ -149,6 +162,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
/// <summary>Maximum transmission unit, or UDP packet size, for the LLUDP protocol</summary>
|
/// <summary>Maximum transmission unit, or UDP packet size, for the LLUDP protocol</summary>
|
||||||
public const int MTU = 1400;
|
public const int MTU = 1400;
|
||||||
|
|
||||||
|
/// <summary>Number of forced client logouts due to no receipt of packets before timeout.</summary>
|
||||||
|
public int ClientLogoutsDueToNoReceives { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Default packet debug level given to new clients
|
/// Default packet debug level given to new clients
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1046,7 +1062,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
// Fire this out on a different thread so that we don't hold up outgoing packet processing for
|
// Fire this out on a different thread so that we don't hold up outgoing packet processing for
|
||||||
// everybody else if this is being called due to an ack timeout.
|
// everybody else if this is being called due to an ack timeout.
|
||||||
// This is the same as processing as the async process of a logout request.
|
// This is the same as processing as the async process of a logout request.
|
||||||
Util.FireAndForget(o => DeactivateClientDueToTimeout(client));
|
Util.FireAndForget(o => DeactivateClientDueToTimeout(client, timeoutTicks));
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1770,18 +1786,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
/// regular client pings.
|
/// regular client pings.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
/// <param name='client'></param>
|
/// <param name='client'></param>
|
||||||
private void DeactivateClientDueToTimeout(LLClientView client)
|
/// <param name='timeoutTicks'></param>
|
||||||
|
private void DeactivateClientDueToTimeout(LLClientView client, int timeoutTicks)
|
||||||
{
|
{
|
||||||
lock (client.CloseSyncLock)
|
lock (client.CloseSyncLock)
|
||||||
{
|
{
|
||||||
m_log.WarnFormat(
|
ClientLogoutsDueToNoReceives++;
|
||||||
"[LLUDPSERVER]: Ack timeout, disconnecting {0} agent for {1} in {2}",
|
|
||||||
client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, m_scene.RegionInfo.RegionName);
|
|
||||||
|
|
||||||
StatsManager.SimExtraStats.AddAbnormalClientThreadTermination();
|
m_log.WarnFormat(
|
||||||
|
"[LLUDPSERVER]: No packets received from {0} agent of {1} for {2}ms in {3}. Disconnecting.",
|
||||||
|
client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, timeoutTicks, m_scene.Name);
|
||||||
|
|
||||||
if (!client.SceneAgent.IsChildAgent)
|
if (!client.SceneAgent.IsChildAgent)
|
||||||
client.Kick("Simulator logged you out due to connection timeout");
|
client.Kick("Simulator logged you out due to connection timeout.");
|
||||||
|
|
||||||
client.CloseWithoutChecks();
|
client.CloseWithoutChecks();
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,10 +31,10 @@ using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.CoreModules;
|
||||||
using OpenSim.Region.Framework;
|
using OpenSim.Region.Framework;
|
||||||
using OpenSim.Region.Framework.Interfaces;
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
using OpenSim.Region.Framework.Scenes;
|
using OpenSim.Region.Framework.Scenes;
|
||||||
using OpenSim.Region.CoreModules;
|
|
||||||
|
|
||||||
using Mono.Addins;
|
using Mono.Addins;
|
||||||
using Nini.Config;
|
using Nini.Config;
|
||||||
|
@ -49,6 +49,10 @@ public class ExtendedPhysics : INonSharedRegionModule
|
||||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
private static string LogHeader = "[EXTENDED PHYSICS]";
|
private static string LogHeader = "[EXTENDED PHYSICS]";
|
||||||
|
|
||||||
|
// Since BulletSim is a plugin, this these values aren't defined easily in one place.
|
||||||
|
// This table must coorespond to an identical table in BSScene.
|
||||||
|
public const string PhysFunctSetLinksetType = "BulletSim.SetLinksetType";
|
||||||
|
|
||||||
private IConfig Configuration { get; set; }
|
private IConfig Configuration { get; set; }
|
||||||
private bool Enabled { get; set; }
|
private bool Enabled { get; set; }
|
||||||
private Scene BaseScene { get; set; }
|
private Scene BaseScene { get; set; }
|
||||||
|
@ -143,13 +147,6 @@ public class ExtendedPhysics : INonSharedRegionModule
|
||||||
[ScriptConstant]
|
[ScriptConstant]
|
||||||
public static int PHYS_CENTER_OF_MASS = 1 << 0;
|
public static int PHYS_CENTER_OF_MASS = 1 << 0;
|
||||||
|
|
||||||
[ScriptConstant]
|
|
||||||
public static int PHYS_LINKSET_TYPE_CONSTRAINT = 1;
|
|
||||||
[ScriptConstant]
|
|
||||||
public static int PHYS_LINKSET_TYPE_COMPOUND = 2;
|
|
||||||
[ScriptConstant]
|
|
||||||
public static int PHYS_LINKSET_TYPE_MANUAL = 3;
|
|
||||||
|
|
||||||
[ScriptInvocation]
|
[ScriptInvocation]
|
||||||
public string physGetEngineType(UUID hostID, UUID scriptID)
|
public string physGetEngineType(UUID hostID, UUID scriptID)
|
||||||
{
|
{
|
||||||
|
@ -163,9 +160,50 @@ public class ExtendedPhysics : INonSharedRegionModule
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[ScriptConstant]
|
||||||
|
public static int PHYS_LINKSET_TYPE_CONSTRAINT = 0;
|
||||||
|
[ScriptConstant]
|
||||||
|
public static int PHYS_LINKSET_TYPE_COMPOUND = 1;
|
||||||
|
[ScriptConstant]
|
||||||
|
public static int PHYS_LINKSET_TYPE_MANUAL = 2;
|
||||||
|
|
||||||
[ScriptInvocation]
|
[ScriptInvocation]
|
||||||
public void physSetLinksetType(UUID hostID, UUID scriptID, int linksetType)
|
public void physSetLinksetType(UUID hostID, UUID scriptID, int linksetType)
|
||||||
{
|
{
|
||||||
|
if (!Enabled) return;
|
||||||
|
|
||||||
|
// The part that is requesting the change.
|
||||||
|
SceneObjectPart requestingPart = BaseScene.GetSceneObjectPart(hostID);
|
||||||
|
|
||||||
|
if (requestingPart != null)
|
||||||
|
{
|
||||||
|
// The change is always made to the root of a linkset.
|
||||||
|
SceneObjectGroup containingGroup = requestingPart.ParentGroup;
|
||||||
|
SceneObjectPart rootPart = containingGroup.RootPart;
|
||||||
|
|
||||||
|
if (rootPart != null)
|
||||||
|
{
|
||||||
|
Physics.Manager.PhysicsActor rootPhysActor = rootPart.PhysActor;
|
||||||
|
if (rootPhysActor != null)
|
||||||
|
{
|
||||||
|
rootPhysActor.Extension(PhysFunctSetLinksetType, linksetType);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0} physSetLinksetType: root part does not have a physics actor. rootName={1}, hostID={2}",
|
||||||
|
LogHeader, rootPart.Name, hostID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0} physSetLinksetType: root part does not exist. RequestingPartName={1}, hostID={2}",
|
||||||
|
LogHeader, requestingPart.Name, hostID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0} physSetLinsetType: cannot find script object in scene. hostID={1}", LogHeader, hostID);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,7 +75,7 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
RawVelocity = OMV.Vector3.Zero;
|
RawVelocity = OMV.Vector3.Zero;
|
||||||
_buoyancy = ComputeBuoyancyFromFlying(isFlying);
|
_buoyancy = ComputeBuoyancyFromFlying(isFlying);
|
||||||
Friction = BSParam.AvatarStandingFriction;
|
Friction = BSParam.AvatarStandingFriction;
|
||||||
Density = BSParam.AvatarDensity / BSParam.DensityScaleFactor;
|
Density = BSParam.AvatarDensity;
|
||||||
|
|
||||||
// Old versions of ScenePresence passed only the height. If width and/or depth are zero,
|
// Old versions of ScenePresence passed only the height. If width and/or depth are zero,
|
||||||
// replace with the default values.
|
// replace with the default values.
|
||||||
|
|
|
@ -589,10 +589,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
m_vehicleMass = ControllingPrim.TotalMass;
|
m_vehicleMass = ControllingPrim.TotalMass;
|
||||||
|
|
||||||
// Friction affects are handled by this vehicle code
|
// Friction affects are handled by this vehicle code
|
||||||
m_physicsScene.PE.SetFriction(ControllingPrim.PhysBody, BSParam.VehicleFriction);
|
// m_physicsScene.PE.SetFriction(ControllingPrim.PhysBody, BSParam.VehicleFriction);
|
||||||
m_physicsScene.PE.SetRestitution(ControllingPrim.PhysBody, BSParam.VehicleRestitution);
|
// m_physicsScene.PE.SetRestitution(ControllingPrim.PhysBody, BSParam.VehicleRestitution);
|
||||||
// ControllingPrim.Linkset.SetPhysicalFriction(BSParam.VehicleFriction);
|
ControllingPrim.Linkset.SetPhysicalFriction(BSParam.VehicleFriction);
|
||||||
// ControllingPrim.Linkset.SetPhysicalRestitution(BSParam.VehicleRestitution);
|
ControllingPrim.Linkset.SetPhysicalRestitution(BSParam.VehicleRestitution);
|
||||||
|
|
||||||
// Moderate angular movement introduced by Bullet.
|
// Moderate angular movement introduced by Bullet.
|
||||||
// TODO: possibly set AngularFactor and LinearFactor for the type of vehicle.
|
// TODO: possibly set AngularFactor and LinearFactor for the type of vehicle.
|
||||||
|
@ -602,21 +602,21 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
m_physicsScene.PE.SetAngularFactorV(ControllingPrim.PhysBody, BSParam.VehicleAngularFactor);
|
m_physicsScene.PE.SetAngularFactorV(ControllingPrim.PhysBody, BSParam.VehicleAngularFactor);
|
||||||
|
|
||||||
// Vehicles report collision events so we know when it's on the ground
|
// Vehicles report collision events so we know when it's on the ground
|
||||||
m_physicsScene.PE.AddToCollisionFlags(ControllingPrim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS);
|
// m_physicsScene.PE.AddToCollisionFlags(ControllingPrim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS);
|
||||||
// ControllingPrim.Linkset.SetPhysicalCollisionFlags(CollisionFlags.BS_VEHICLE_COLLISIONS);
|
ControllingPrim.Linkset.AddToPhysicalCollisionFlags(CollisionFlags.BS_VEHICLE_COLLISIONS);
|
||||||
|
|
||||||
Vector3 inertia = m_physicsScene.PE.CalculateLocalInertia(ControllingPrim.PhysShape.physShapeInfo, m_vehicleMass);
|
// Vector3 inertia = m_physicsScene.PE.CalculateLocalInertia(ControllingPrim.PhysShape.physShapeInfo, m_vehicleMass);
|
||||||
ControllingPrim.Inertia = inertia * BSParam.VehicleInertiaFactor;
|
// ControllingPrim.Inertia = inertia * BSParam.VehicleInertiaFactor;
|
||||||
m_physicsScene.PE.SetMassProps(ControllingPrim.PhysBody, m_vehicleMass, ControllingPrim.Inertia);
|
// m_physicsScene.PE.SetMassProps(ControllingPrim.PhysBody, m_vehicleMass, ControllingPrim.Inertia);
|
||||||
m_physicsScene.PE.UpdateInertiaTensor(ControllingPrim.PhysBody);
|
// m_physicsScene.PE.UpdateInertiaTensor(ControllingPrim.PhysBody);
|
||||||
// ControllingPrim.Linkset.ComputeLocalInertia(BSParam.VehicleInertiaFactor);
|
ControllingPrim.Linkset.ComputeAndSetLocalInertia(BSParam.VehicleInertiaFactor, m_vehicleMass);
|
||||||
|
|
||||||
// Set the gravity for the vehicle depending on the buoyancy
|
// Set the gravity for the vehicle depending on the buoyancy
|
||||||
// TODO: what should be done if prim and vehicle buoyancy differ?
|
// TODO: what should be done if prim and vehicle buoyancy differ?
|
||||||
m_VehicleGravity = ControllingPrim.ComputeGravity(m_VehicleBuoyancy);
|
m_VehicleGravity = ControllingPrim.ComputeGravity(m_VehicleBuoyancy);
|
||||||
// The actual vehicle gravity is set to zero in Bullet so we can do all the application of same.
|
// The actual vehicle gravity is set to zero in Bullet so we can do all the application of same.
|
||||||
m_physicsScene.PE.SetGravity(ControllingPrim.PhysBody, Vector3.Zero);
|
// m_physicsScene.PE.SetGravity(ControllingPrim.PhysBody, Vector3.Zero);
|
||||||
// ControllingPrim.Linkset.SetPhysicalGravity(Vector3.Zero);
|
ControllingPrim.Linkset.SetPhysicalGravity(Vector3.Zero);
|
||||||
|
|
||||||
VDetailLog("{0},BSDynamics.SetPhysicalParameters,mass={1},inert={2},vehGrav={3},aDamp={4},frict={5},rest={6},lFact={7},aFact={8}",
|
VDetailLog("{0},BSDynamics.SetPhysicalParameters,mass={1},inert={2},vehGrav={3},aDamp={4},frict={5},rest={6},lFact={7},aFact={8}",
|
||||||
ControllingPrim.LocalID, m_vehicleMass, ControllingPrim.Inertia, m_VehicleGravity,
|
ControllingPrim.LocalID, m_vehicleMass, ControllingPrim.Inertia, m_VehicleGravity,
|
||||||
|
@ -1121,7 +1121,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
{
|
{
|
||||||
m_VhoverTargetHeight = m_VhoverHeight;
|
m_VhoverTargetHeight = m_VhoverHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0)
|
if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0)
|
||||||
{
|
{
|
||||||
// If body is already heigher, use its height as target height
|
// If body is already heigher, use its height as target height
|
||||||
|
@ -1170,7 +1169,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
m_VhoverTimescale, m_VhoverHeight, m_VhoverTargetHeight,
|
m_VhoverTimescale, m_VhoverHeight, m_VhoverTargetHeight,
|
||||||
verticalError, verticalCorrection);
|
verticalError, verticalCorrection);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1357,6 +1355,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
private void ComputeAngularTurning(float pTimestep)
|
private void ComputeAngularTurning(float pTimestep)
|
||||||
{
|
{
|
||||||
// The user wants this many radians per second angular change?
|
// The user wants this many radians per second angular change?
|
||||||
|
Vector3 origVehicleRotationalVelocity = VehicleRotationalVelocity; // DEBUG DEBUG
|
||||||
Vector3 currentAngularV = VehicleRotationalVelocity * Quaternion.Inverse(VehicleOrientation);
|
Vector3 currentAngularV = VehicleRotationalVelocity * Quaternion.Inverse(VehicleOrientation);
|
||||||
Vector3 angularMotorContributionV = m_angularMotor.Step(pTimestep, currentAngularV);
|
Vector3 angularMotorContributionV = m_angularMotor.Step(pTimestep, currentAngularV);
|
||||||
|
|
||||||
|
@ -1378,11 +1377,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
Vector3 frictionFactorW = ComputeFrictionFactor(m_angularFrictionTimescale, pTimestep);
|
Vector3 frictionFactorW = ComputeFrictionFactor(m_angularFrictionTimescale, pTimestep);
|
||||||
angularMotorContributionV -= (currentAngularV * frictionFactorW);
|
angularMotorContributionV -= (currentAngularV * frictionFactorW);
|
||||||
|
|
||||||
VehicleRotationalVelocity += angularMotorContributionV * VehicleOrientation;
|
Vector3 angularMotorContributionW = angularMotorContributionV * VehicleOrientation;
|
||||||
|
VehicleRotationalVelocity += angularMotorContributionW;
|
||||||
|
|
||||||
|
VDetailLog("{0}, MoveAngular,angularTurning,curAngVelV={1},origVehRotVel={2},vehRotVel={3},frictFact={4}, angContribV={5},angContribW={6}",
|
||||||
|
ControllingPrim.LocalID, currentAngularV, origVehicleRotationalVelocity, VehicleRotationalVelocity, frictionFactorW, angularMotorContributionV, angularMotorContributionW);
|
||||||
VDetailLog("{0}, MoveAngular,angularTurning,angContribV={1}", ControllingPrim.LocalID, angularMotorContributionV);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial:
|
// From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial:
|
||||||
|
@ -1409,7 +1408,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
|
|
||||||
// Flipping what was originally a timescale into a speed variable and then multiplying it by 2
|
// Flipping what was originally a timescale into a speed variable and then multiplying it by 2
|
||||||
// since only computing half the distance between the angles.
|
// since only computing half the distance between the angles.
|
||||||
float VerticalAttractionSpeed = (1 / m_verticalAttractionTimescale) * 2.0f;
|
float verticalAttractionSpeed = (1 / m_verticalAttractionTimescale) * 2.0f;
|
||||||
|
|
||||||
// Make a prediction of where the up axis will be when this is applied rather then where it is now as
|
// Make a prediction of where the up axis will be when this is applied rather then where it is now as
|
||||||
// this makes for a smoother adjustment and less fighting between the various forces.
|
// this makes for a smoother adjustment and less fighting between the various forces.
|
||||||
|
@ -1419,12 +1418,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
Vector3 torqueVector = Vector3.Cross(predictedUp, Vector3.UnitZ);
|
Vector3 torqueVector = Vector3.Cross(predictedUp, Vector3.UnitZ);
|
||||||
|
|
||||||
// Scale vector by our timescale since it is an acceleration it is r/s^2 or radians a timescale squared
|
// Scale vector by our timescale since it is an acceleration it is r/s^2 or radians a timescale squared
|
||||||
Vector3 vertContributionV = torqueVector * VerticalAttractionSpeed * VerticalAttractionSpeed;
|
Vector3 vertContributionV = torqueVector * verticalAttractionSpeed * verticalAttractionSpeed;
|
||||||
|
|
||||||
VehicleRotationalVelocity += vertContributionV;
|
VehicleRotationalVelocity += vertContributionV;
|
||||||
|
|
||||||
VDetailLog("{0}, MoveAngular,verticalAttraction,upAxis={1},PredictedUp={2},torqueVector={3},contrib={4}",
|
VDetailLog("{0}, MoveAngular,verticalAttraction,vertAttrSpeed={1},upAxis={2},PredictedUp={3},torqueVector={4},contrib={5}",
|
||||||
ControllingPrim.LocalID,
|
ControllingPrim.LocalID,
|
||||||
|
verticalAttractionSpeed,
|
||||||
vehicleUpAxis,
|
vehicleUpAxis,
|
||||||
predictedUp,
|
predictedUp,
|
||||||
torqueVector,
|
torqueVector,
|
||||||
|
@ -1437,37 +1437,38 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
// http://stackoverflow.com/questions/14939657/computing-vector-from-quaternion-works-computing-quaternion-from-vector-does-no
|
// http://stackoverflow.com/questions/14939657/computing-vector-from-quaternion-works-computing-quaternion-from-vector-does-no
|
||||||
|
|
||||||
// Create a rotation that is only the vehicle's rotation around Z
|
// Create a rotation that is only the vehicle's rotation around Z
|
||||||
Vector3 currentEuler = Vector3.Zero;
|
Vector3 currentEulerW = Vector3.Zero;
|
||||||
VehicleOrientation.GetEulerAngles(out currentEuler.X, out currentEuler.Y, out currentEuler.Z);
|
VehicleOrientation.GetEulerAngles(out currentEulerW.X, out currentEulerW.Y, out currentEulerW.Z);
|
||||||
Quaternion justZOrientation = Quaternion.CreateFromAxisAngle(Vector3.UnitZ, currentEuler.Z);
|
Quaternion justZOrientation = Quaternion.CreateFromAxisAngle(Vector3.UnitZ, currentEulerW.Z);
|
||||||
|
|
||||||
// Create the axis that is perpendicular to the up vector and the rotated up vector.
|
// Create the axis that is perpendicular to the up vector and the rotated up vector.
|
||||||
Vector3 differenceAxis = Vector3.Cross(Vector3.UnitZ * justZOrientation, Vector3.UnitZ * VehicleOrientation);
|
Vector3 differenceAxisW = Vector3.Cross(Vector3.UnitZ * justZOrientation, Vector3.UnitZ * VehicleOrientation);
|
||||||
// Compute the angle between those to vectors.
|
// Compute the angle between those to vectors.
|
||||||
double differenceAngle = Math.Acos((double)Vector3.Dot(Vector3.UnitZ, Vector3.Normalize(Vector3.UnitZ * VehicleOrientation)));
|
double differenceAngle = Math.Acos((double)Vector3.Dot(Vector3.UnitZ, Vector3.Normalize(Vector3.UnitZ * VehicleOrientation)));
|
||||||
// 'differenceAngle' is the angle to rotate and 'differenceAxis' is the plane to rotate in to get the vehicle vertical
|
// 'differenceAngle' is the angle to rotate and 'differenceAxis' is the plane to rotate in to get the vehicle vertical
|
||||||
|
|
||||||
// Reduce the change by the time period it is to change in. Timestep is handled when velocity is applied.
|
// Reduce the change by the time period it is to change in. Timestep is handled when velocity is applied.
|
||||||
// TODO: add 'efficiency'.
|
// TODO: add 'efficiency'.
|
||||||
differenceAngle /= m_verticalAttractionTimescale;
|
// differenceAngle /= m_verticalAttractionTimescale;
|
||||||
|
|
||||||
// Create the quaterian representing the correction angle
|
// Create the quaterian representing the correction angle
|
||||||
Quaternion correctionRotation = Quaternion.CreateFromAxisAngle(differenceAxis, (float)differenceAngle);
|
Quaternion correctionRotationW = Quaternion.CreateFromAxisAngle(differenceAxisW, (float)differenceAngle);
|
||||||
|
|
||||||
// Turn that quaternion into Euler values to make it into velocities to apply.
|
// Turn that quaternion into Euler values to make it into velocities to apply.
|
||||||
Vector3 vertContributionV = Vector3.Zero;
|
Vector3 vertContributionW = Vector3.Zero;
|
||||||
correctionRotation.GetEulerAngles(out vertContributionV.X, out vertContributionV.Y, out vertContributionV.Z);
|
correctionRotationW.GetEulerAngles(out vertContributionW.X, out vertContributionW.Y, out vertContributionW.Z);
|
||||||
vertContributionV *= -1f;
|
vertContributionW *= -1f;
|
||||||
|
vertContributionW /= m_verticalAttractionTimescale;
|
||||||
|
|
||||||
VehicleRotationalVelocity += vertContributionV;
|
VehicleRotationalVelocity += vertContributionW;
|
||||||
|
|
||||||
VDetailLog("{0}, MoveAngular,verticalAttraction,upAxis={1},diffAxis={2},diffAng={3},corrRot={4},contrib={5}",
|
VDetailLog("{0}, MoveAngular,verticalAttraction,upAxis={1},diffAxis={2},diffAng={3},corrRot={4},contrib={5}",
|
||||||
ControllingPrim.LocalID,
|
ControllingPrim.LocalID,
|
||||||
vehicleUpAxis,
|
vehicleUpAxis,
|
||||||
differenceAxis,
|
differenceAxisW,
|
||||||
differenceAngle,
|
differenceAngle,
|
||||||
correctionRotation,
|
correctionRotationW,
|
||||||
vertContributionV);
|
vertContributionW);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 2:
|
case 2:
|
||||||
|
|
|
@ -309,16 +309,18 @@ public abstract class BSLinkset
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
public virtual void ComputeLocalInertia(OMV.Vector3 inertiaFactor)
|
public virtual void ComputeAndSetLocalInertia(OMV.Vector3 inertiaFactor, float linksetMass)
|
||||||
{
|
{
|
||||||
ForEachMember((member) =>
|
ForEachMember((member) =>
|
||||||
{
|
{
|
||||||
if (member.PhysBody.HasPhysicalBody)
|
if (member.PhysBody.HasPhysicalBody)
|
||||||
{
|
{
|
||||||
OMV.Vector3 inertia = m_physicsScene.PE.CalculateLocalInertia(member.PhysShape.physShapeInfo, member.Mass);
|
OMV.Vector3 inertia = m_physicsScene.PE.CalculateLocalInertia(member.PhysShape.physShapeInfo, linksetMass);
|
||||||
member.Inertia = inertia * inertiaFactor;
|
member.Inertia = inertia * inertiaFactor;
|
||||||
m_physicsScene.PE.SetMassProps(member.PhysBody, member.Mass, member.Inertia);
|
m_physicsScene.PE.SetMassProps(member.PhysBody, linksetMass, member.Inertia);
|
||||||
m_physicsScene.PE.UpdateInertiaTensor(member.PhysBody);
|
m_physicsScene.PE.UpdateInertiaTensor(member.PhysBody);
|
||||||
|
DetailLog("{0},BSLinkset.ComputeAndSetLocalInertia,m.mass={1}, inertia={2}", member.LocalID, linksetMass, member.Inertia);
|
||||||
|
|
||||||
}
|
}
|
||||||
return false; // 'false' says to continue looping
|
return false; // 'false' says to continue looping
|
||||||
}
|
}
|
||||||
|
@ -334,6 +336,16 @@ public abstract class BSLinkset
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
public virtual void AddToPhysicalCollisionFlags(CollisionFlags collFlags)
|
||||||
|
{
|
||||||
|
ForEachMember((member) =>
|
||||||
|
{
|
||||||
|
if (member.PhysBody.HasPhysicalBody)
|
||||||
|
m_physicsScene.PE.AddToCollisionFlags(member.PhysBody, collFlags);
|
||||||
|
return false; // 'false' says to continue looping
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
public virtual void RemoveFromPhysicalCollisionFlags(CollisionFlags collFlags)
|
public virtual void RemoveFromPhysicalCollisionFlags(CollisionFlags collFlags)
|
||||||
{
|
{
|
||||||
ForEachMember((member) =>
|
ForEachMember((member) =>
|
||||||
|
|
|
@ -61,11 +61,11 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||||
if (LinksetRoot.PhysBody.HasPhysicalBody)
|
if (LinksetRoot.PhysBody.HasPhysicalBody)
|
||||||
m_physicsScene.PE.SetGravity(LinksetRoot.PhysBody, gravity);
|
m_physicsScene.PE.SetGravity(LinksetRoot.PhysBody, gravity);
|
||||||
}
|
}
|
||||||
public override void ComputeLocalInertia(OMV.Vector3 inertiaFactor)
|
public override void ComputeAndSetLocalInertia(OMV.Vector3 inertiaFactor, float linksetMass)
|
||||||
{
|
{
|
||||||
OMV.Vector3 inertia = m_physicsScene.PE.CalculateLocalInertia(LinksetRoot.PhysShape.physShapeInfo, LinksetRoot.Mass);
|
OMV.Vector3 inertia = m_physicsScene.PE.CalculateLocalInertia(LinksetRoot.PhysShape.physShapeInfo, linksetMass);
|
||||||
LinksetRoot.Inertia = inertia * inertiaFactor;
|
LinksetRoot.Inertia = inertia * inertiaFactor;
|
||||||
m_physicsScene.PE.SetMassProps(LinksetRoot.PhysBody, LinksetRoot.Mass, LinksetRoot.Inertia);
|
m_physicsScene.PE.SetMassProps(LinksetRoot.PhysBody, linksetMass, LinksetRoot.Inertia);
|
||||||
m_physicsScene.PE.UpdateInertiaTensor(LinksetRoot.PhysBody);
|
m_physicsScene.PE.UpdateInertiaTensor(LinksetRoot.PhysBody);
|
||||||
}
|
}
|
||||||
public override void SetPhysicalCollisionFlags(CollisionFlags collFlags)
|
public override void SetPhysicalCollisionFlags(CollisionFlags collFlags)
|
||||||
|
@ -73,6 +73,11 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||||
if (LinksetRoot.PhysBody.HasPhysicalBody)
|
if (LinksetRoot.PhysBody.HasPhysicalBody)
|
||||||
m_physicsScene.PE.SetCollisionFlags(LinksetRoot.PhysBody, collFlags);
|
m_physicsScene.PE.SetCollisionFlags(LinksetRoot.PhysBody, collFlags);
|
||||||
}
|
}
|
||||||
|
public override void AddToPhysicalCollisionFlags(CollisionFlags collFlags)
|
||||||
|
{
|
||||||
|
if (LinksetRoot.PhysBody.HasPhysicalBody)
|
||||||
|
m_physicsScene.PE.AddToCollisionFlags(LinksetRoot.PhysBody, collFlags);
|
||||||
|
}
|
||||||
public override void RemoveFromPhysicalCollisionFlags(CollisionFlags collFlags)
|
public override void RemoveFromPhysicalCollisionFlags(CollisionFlags collFlags)
|
||||||
{
|
{
|
||||||
if (LinksetRoot.PhysBody.HasPhysicalBody)
|
if (LinksetRoot.PhysBody.HasPhysicalBody)
|
||||||
|
|
|
@ -463,7 +463,7 @@ public static class BSParam
|
||||||
// Density is passed around as 100kg/m3. This scales that to 1kg/m3.
|
// Density is passed around as 100kg/m3. This scales that to 1kg/m3.
|
||||||
// Reduce by power of 100 because Bullet doesn't seem to handle objects with large mass very well
|
// Reduce by power of 100 because Bullet doesn't seem to handle objects with large mass very well
|
||||||
new ParameterDefn<float>("DensityScaleFactor", "Conversion for simulator/viewer density (100kg/m3) to physical density (1kg/m3)",
|
new ParameterDefn<float>("DensityScaleFactor", "Conversion for simulator/viewer density (100kg/m3) to physical density (1kg/m3)",
|
||||||
0.0001f ),
|
0.01f ),
|
||||||
|
|
||||||
new ParameterDefn<float>("PID_D", "Derivitive factor for motion smoothing",
|
new ParameterDefn<float>("PID_D", "Derivitive factor for motion smoothing",
|
||||||
2200f ),
|
2200f ),
|
||||||
|
@ -474,8 +474,9 @@ public static class BSParam
|
||||||
0.2f,
|
0.2f,
|
||||||
(s) => { return DefaultFriction; },
|
(s) => { return DefaultFriction; },
|
||||||
(s,v) => { DefaultFriction = v; s.UnmanagedParams[0].defaultFriction = v; } ),
|
(s,v) => { DefaultFriction = v; s.UnmanagedParams[0].defaultFriction = v; } ),
|
||||||
|
// For historical reasons, the viewer and simulator multiply the density by 100
|
||||||
new ParameterDefn<float>("DefaultDensity", "Density for new objects" ,
|
new ParameterDefn<float>("DefaultDensity", "Density for new objects" ,
|
||||||
10.000006836f, // Aluminum g/cm3
|
1000.0006836f, // Aluminum g/cm3 * 100
|
||||||
(s) => { return DefaultDensity; },
|
(s) => { return DefaultDensity; },
|
||||||
(s,v) => { DefaultDensity = v; s.UnmanagedParams[0].defaultDensity = v; } ),
|
(s,v) => { DefaultDensity = v; s.UnmanagedParams[0].defaultDensity = v; } ),
|
||||||
new ParameterDefn<float>("DefaultRestitution", "Bouncyness of an object" ,
|
new ParameterDefn<float>("DefaultRestitution", "Bouncyness of an object" ,
|
||||||
|
@ -555,8 +556,9 @@ public static class BSParam
|
||||||
0.95f ),
|
0.95f ),
|
||||||
new ParameterDefn<float>("AvatarAlwaysRunFactor", "Speed multiplier if avatar is set to always run",
|
new ParameterDefn<float>("AvatarAlwaysRunFactor", "Speed multiplier if avatar is set to always run",
|
||||||
1.3f ),
|
1.3f ),
|
||||||
new ParameterDefn<float>("AvatarDensity", "Density of an avatar. Changed on avatar recreation.",
|
// For historical reasons, density is reported * 100
|
||||||
3.5f) ,
|
new ParameterDefn<float>("AvatarDensity", "Density of an avatar. Changed on avatar recreation. Scaled times 100.",
|
||||||
|
3500f) , // 3.5 * 100
|
||||||
new ParameterDefn<float>("AvatarRestitution", "Bouncyness. Changed on avatar recreation.",
|
new ParameterDefn<float>("AvatarRestitution", "Bouncyness. Changed on avatar recreation.",
|
||||||
0f ),
|
0f ),
|
||||||
new ParameterDefn<float>("AvatarCapsuleWidth", "The distance between the sides of the avatar capsule",
|
new ParameterDefn<float>("AvatarCapsuleWidth", "The distance between the sides of the avatar capsule",
|
||||||
|
@ -608,9 +610,8 @@ public static class BSParam
|
||||||
0.0f ),
|
0.0f ),
|
||||||
new ParameterDefn<float>("VehicleRestitution", "Bouncyness factor for vehicles (0.0 - 1.0)",
|
new ParameterDefn<float>("VehicleRestitution", "Bouncyness factor for vehicles (0.0 - 1.0)",
|
||||||
0.0f ),
|
0.0f ),
|
||||||
// Turn off fudge with DensityScaleFactor = 0.0001. Value used to be 0.2f;
|
|
||||||
new ParameterDefn<float>("VehicleGroundGravityFudge", "Factor to multiply gravity if a ground vehicle is probably on the ground (0.0 - 1.0)",
|
new ParameterDefn<float>("VehicleGroundGravityFudge", "Factor to multiply gravity if a ground vehicle is probably on the ground (0.0 - 1.0)",
|
||||||
1.0f ),
|
0.2f ),
|
||||||
new ParameterDefn<float>("VehicleAngularBankingTimescaleFudge", "Factor to multiple angular banking timescale. Tune to increase realism.",
|
new ParameterDefn<float>("VehicleAngularBankingTimescaleFudge", "Factor to multiple angular banking timescale. Tune to increase realism.",
|
||||||
60.0f ),
|
60.0f ),
|
||||||
new ParameterDefn<bool>("VehicleEnableLinearDeflection", "Turn on/off vehicle linear deflection effect",
|
new ParameterDefn<bool>("VehicleEnableLinearDeflection", "Turn on/off vehicle linear deflection effect",
|
||||||
|
|
|
@ -187,10 +187,23 @@ public abstract class BSPhysObject : PhysicsActor
|
||||||
MaterialAttributes matAttrib = BSMaterials.GetAttributes(Material, false);
|
MaterialAttributes matAttrib = BSMaterials.GetAttributes(Material, false);
|
||||||
Friction = matAttrib.friction;
|
Friction = matAttrib.friction;
|
||||||
Restitution = matAttrib.restitution;
|
Restitution = matAttrib.restitution;
|
||||||
Density = matAttrib.density / BSParam.DensityScaleFactor;
|
Density = matAttrib.density;
|
||||||
// DetailLog("{0},{1}.SetMaterial,Mat={2},frict={3},rest={4},den={5}", LocalID, TypeName, Material, Friction, Restitution, Density);
|
// DetailLog("{0},{1}.SetMaterial,Mat={2},frict={3},rest={4},den={5}", LocalID, TypeName, Material, Friction, Restitution, Density);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override float Density
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return base.Density;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
DetailLog("{0},BSPhysObject.Density,set,den={1}", LocalID, value);
|
||||||
|
base.Density = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Stop all physical motion.
|
// Stop all physical motion.
|
||||||
public abstract void ZeroMotion(bool inTaintTime);
|
public abstract void ZeroMotion(bool inTaintTime);
|
||||||
public abstract void ZeroAngularMotion(bool inTaintTime);
|
public abstract void ZeroAngularMotion(bool inTaintTime);
|
||||||
|
|
Loading…
Reference in New Issue