Merge branch 'master' of /home/opensim/var/repo/opensim

0.7.5-pf-bulletsim
BlueWall 2012-12-12 23:34:20 -05:00
commit 7a87c35f94
12 changed files with 228 additions and 93 deletions

View File

@ -97,7 +97,7 @@ namespace OpenSim.Framework.Console
if (!UUID.TryParse(rawUuid, out uuid)) if (!UUID.TryParse(rawUuid, out uuid))
{ {
if (console != null) if (console != null)
console.OutputFormat("{0} is not a valid uuid", rawUuid); console.OutputFormat("ERROR: {0} is not a valid uuid", rawUuid);
return false; return false;
} }
@ -110,7 +110,7 @@ namespace OpenSim.Framework.Console
if (!uint.TryParse(rawLocalId, out localId)) if (!uint.TryParse(rawLocalId, out localId))
{ {
if (console != null) if (console != null)
console.OutputFormat("{0} is not a valid local id", localId); console.OutputFormat("ERROR: {0} is not a valid local id", localId);
return false; return false;
} }
@ -118,7 +118,7 @@ namespace OpenSim.Framework.Console
if (localId == 0) if (localId == 0)
{ {
if (console != null) if (console != null)
console.OutputFormat("{0} is not a valid local id - it must be greater than 0", localId); console.OutputFormat("ERROR: {0} is not a valid local id - it must be greater than 0", localId);
return false; return false;
} }
@ -150,10 +150,30 @@ namespace OpenSim.Framework.Console
} }
if (console != null) if (console != null)
console.OutputFormat("{0} is not a valid UUID or local id", rawId); console.OutputFormat("ERROR: {0} is not a valid UUID or local id", rawId);
return false; return false;
} }
/// <summary>
/// Convert a minimum vector input from the console to an OpenMetaverse.Vector3
/// </summary>
/// <param name='console'>Can be null if no console is available.</param>
/// <param name='rawConsoleVector'>/param>
/// <param name='vector'></param>
/// <returns></returns>
public static bool TryParseConsoleInt(ICommandConsole console, string rawConsoleInt, out int i)
{
if (!int.TryParse(rawConsoleInt, out i))
{
if (console != null)
console.OutputFormat("ERROR: {0} is not a valid integer", rawConsoleInt);
return false;
}
return true;
}
/// <summary> /// <summary>
/// Convert a minimum vector input from the console to an OpenMetaverse.Vector3 /// Convert a minimum vector input from the console to an OpenMetaverse.Vector3

View File

@ -76,7 +76,7 @@ namespace OpenSim.Region.CoreModules.World.Sound
public void RemoveRegion(Scene scene) public void RemoveRegion(Scene scene)
{ {
m_scene.EventManager.OnClientLogin -= OnNewClient; m_scene.EventManager.OnNewClient -= OnNewClient;
} }
public void RegionLoaded(Scene scene) public void RegionLoaded(Scene scene)
@ -85,7 +85,7 @@ namespace OpenSim.Region.CoreModules.World.Sound
return; return;
m_scene = scene; m_scene = scene;
m_scene.EventManager.OnClientLogin += OnNewClient; m_scene.EventManager.OnNewClient += OnNewClient;
m_scene.RegisterModuleInterface<ISoundModule>(this); m_scene.RegisterModuleInterface<ISoundModule>(this);
} }

View File

@ -105,12 +105,12 @@ public sealed class BSCharacter : BSPhysObject
DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}", DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}",
LocalID, _size, Scale, _avatarDensity, _avatarVolume, RawMass); LocalID, _size, Scale, _avatarDensity, _avatarVolume, RawMass);
// do actual create at taint time // do actual creation in taint time
PhysicsScene.TaintedObject("BSCharacter.create", delegate() PhysicsScene.TaintedObject("BSCharacter.create", delegate()
{ {
DetailLog("{0},BSCharacter.create,taint", LocalID); DetailLog("{0},BSCharacter.create,taint", LocalID);
// New body and shape into PhysBody and PhysShape // New body and shape into PhysBody and PhysShape
PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this, null, null); PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this);
SetPhysicalProperties(); SetPhysicalProperties();
}); });
@ -189,6 +189,11 @@ public sealed class BSCharacter : BSPhysObject
set { set {
// When an avatar's size is set, only the height is changed. // When an avatar's size is set, only the height is changed.
_size = value; _size = value;
// Old versions of ScenePresence passed only the height. If width and/or depth are zero,
// replace with the default values.
if (_size.X == 0f) _size.X = PhysicsScene.Params.avatarCapsuleDepth;
if (_size.Y == 0f) _size.Y = PhysicsScene.Params.avatarCapsuleWidth;
ComputeAvatarScale(_size); ComputeAvatarScale(_size);
ComputeAvatarVolumeAndMass(); ComputeAvatarVolumeAndMass();
DetailLog("{0},BSCharacter.setSize,call,size={1},scale={2},density={3},volume={4},mass={5}", DetailLog("{0},BSCharacter.setSize,call,size={1},scale={2},density={3},volume={4},mass={5}",
@ -196,18 +201,18 @@ public sealed class BSCharacter : BSPhysObject
PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() PhysicsScene.TaintedObject("BSCharacter.setSize", delegate()
{ {
if (PhysShape.HasPhysicalShape) if (PhysBody.HasPhysicalBody && PhysShape.HasPhysicalShape)
{ {
BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale); BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale);
UpdatePhysicalMassProperties(RawMass); UpdatePhysicalMassProperties(RawMass);
// Make sure this change appears as a property update event
BulletSimAPI.PushUpdate2(PhysBody.ptr);
} }
}); });
} }
} }
public override OMV.Vector3 Scale { get; set; }
public override PrimitiveBaseShape Shape public override PrimitiveBaseShape Shape
{ {
set { BaseShape = value; } set { BaseShape = value; }
@ -638,9 +643,6 @@ public sealed class BSCharacter : BSPhysObject
private void ComputeAvatarScale(OMV.Vector3 size) private void ComputeAvatarScale(OMV.Vector3 size)
{ {
// The 'size' given by the simulator is the mid-point of the avatar
// and X and Y are unspecified.
OMV.Vector3 newScale = size; OMV.Vector3 newScale = size;
// newScale.X = PhysicsScene.Params.avatarCapsuleWidth; // newScale.X = PhysicsScene.Params.avatarCapsuleWidth;
// newScale.Y = PhysicsScene.Params.avatarCapsuleDepth; // newScale.Y = PhysicsScene.Params.avatarCapsuleDepth;

View File

@ -50,10 +50,11 @@ public struct MaterialAttributes
Avatar, Avatar,
NumberOfTypes // the count of types in the enum. NumberOfTypes // the count of types in the enum.
} }
// Names must be in the order of the above enum. // Names must be in the order of the above enum.
public static string[] MaterialNames = { "Stone", "Metal", "Glass", "Wood", // These names must coorespond to the lower case field names in the MaterialAttributes
"Flesh", "Plastic", "Rubber", "Light", "Avatar" }; // structure as reflection is used to select the field to put the value in.
public static string[] MaterialAttribs = { "Density", "Friction", "Restitution"}; public static readonly string[] MaterialAttribs = { "Density", "Friction", "Restitution"};
public MaterialAttributes(string t, float d, float f, float r) public MaterialAttributes(string t, float d, float f, float r)
{ {
@ -70,60 +71,74 @@ public struct MaterialAttributes
public static class BSMaterials public static class BSMaterials
{ {
public static MaterialAttributes[] Attributes; // Attributes for each material type
private static readonly MaterialAttributes[] Attributes;
// Map of material name to material type code
public static readonly Dictionary<string, MaterialAttributes.Material> MaterialMap;
static BSMaterials() static BSMaterials()
{ {
// Attribute sets for both the non-physical and physical instances of materials. // Attribute sets for both the non-physical and physical instances of materials.
Attributes = new MaterialAttributes[(int)MaterialAttributes.Material.NumberOfTypes * 2]; Attributes = new MaterialAttributes[(int)MaterialAttributes.Material.NumberOfTypes * 2];
// Map of name to type code.
MaterialMap = new Dictionary<string, MaterialAttributes.Material>();
MaterialMap.Add("Stone", MaterialAttributes.Material.Stone);
MaterialMap.Add("Metal", MaterialAttributes.Material.Metal);
MaterialMap.Add("Glass", MaterialAttributes.Material.Glass);
MaterialMap.Add("Wood", MaterialAttributes.Material.Wood);
MaterialMap.Add("Flesh", MaterialAttributes.Material.Flesh);
MaterialMap.Add("Plastic", MaterialAttributes.Material.Plastic);
MaterialMap.Add("Rubber", MaterialAttributes.Material.Rubber);
MaterialMap.Add("Light", MaterialAttributes.Material.Light);
MaterialMap.Add("Avatar", MaterialAttributes.Material.Avatar);
} }
// This is where all the default material attributes are defined. // This is where all the default material attributes are defined.
public static void InitializeFromDefaults(ConfigurationParameters parms) public static void InitializeFromDefaults(ConfigurationParameters parms)
{ {
// Values from http://wiki.secondlife.com/wiki/PRIM_MATERIAL // Values from http://wiki.secondlife.com/wiki/PRIM_MATERIAL
// public static string[] MaterialNames = { "Stone", "Metal", "Glass", "Wood", float dDensity = parms.defaultDensity;
// "Flesh", "Plastic", "Rubber", "Light", "Avatar" };
float dFriction = parms.defaultFriction; float dFriction = parms.defaultFriction;
float dRestitution = parms.defaultRestitution; float dRestitution = parms.defaultRestitution;
float dDensity = parms.defaultDensity;
Attributes[(int)MaterialAttributes.Material.Stone] = Attributes[(int)MaterialAttributes.Material.Stone] =
new MaterialAttributes("stone",dDensity, 0.8f, 0.4f); new MaterialAttributes("stone",dDensity, 0.8f, 0.4f);
Attributes[(int)MaterialAttributes.Material.Metal] = Attributes[(int)MaterialAttributes.Material.Metal] =
new MaterialAttributes("metal",dDensity, 0.3f, 0.4f); new MaterialAttributes("metal",dDensity, 0.3f, 0.4f);
Attributes[(int)MaterialAttributes.Material.Glass] = Attributes[(int)MaterialAttributes.Material.Glass] =
new MaterialAttributes("glass",dDensity, 0.2f, 0.7f); new MaterialAttributes("glass",dDensity, 0.2f, 0.7f);
Attributes[(int)MaterialAttributes.Material.Wood] = Attributes[(int)MaterialAttributes.Material.Wood] =
new MaterialAttributes("wood",dDensity, 0.6f, 0.5f); new MaterialAttributes("wood",dDensity, 0.6f, 0.5f);
Attributes[(int)MaterialAttributes.Material.Flesh] = Attributes[(int)MaterialAttributes.Material.Flesh] =
new MaterialAttributes("flesh",dDensity, 0.9f, 0.3f); new MaterialAttributes("flesh",dDensity, 0.9f, 0.3f);
Attributes[(int)MaterialAttributes.Material.Plastic] = Attributes[(int)MaterialAttributes.Material.Plastic] =
new MaterialAttributes("plastic",dDensity, 0.4f, 0.7f); new MaterialAttributes("plastic",dDensity, 0.4f, 0.7f);
Attributes[(int)MaterialAttributes.Material.Rubber] = Attributes[(int)MaterialAttributes.Material.Rubber] =
new MaterialAttributes("rubber",dDensity, 0.9f, 0.9f); new MaterialAttributes("rubber",dDensity, 0.9f, 0.9f);
Attributes[(int)MaterialAttributes.Material.Light] = Attributes[(int)MaterialAttributes.Material.Light] =
new MaterialAttributes("light",dDensity, dFriction, dRestitution); new MaterialAttributes("light",dDensity, dFriction, dRestitution);
Attributes[(int)MaterialAttributes.Material.Avatar] = Attributes[(int)MaterialAttributes.Material.Avatar] =
new MaterialAttributes("avatar",60f, 0.2f, 0f); new MaterialAttributes("avatar",60f, 0.2f, 0f);
Attributes[(int)MaterialAttributes.Material.Stone + (int)MaterialAttributes.Material.NumberOfTypes] = Attributes[(int)MaterialAttributes.Material.Stone + (int)MaterialAttributes.Material.NumberOfTypes] =
new MaterialAttributes("stonePhysical",dDensity, 0.8f, 0.4f); new MaterialAttributes("stonePhysical",dDensity, 0.8f, 0.4f);
Attributes[(int)MaterialAttributes.Material.Metal + (int)MaterialAttributes.Material.NumberOfTypes] = Attributes[(int)MaterialAttributes.Material.Metal + (int)MaterialAttributes.Material.NumberOfTypes] =
new MaterialAttributes("metalPhysical",dDensity, 0.8f, 0.4f); new MaterialAttributes("metalPhysical",dDensity, 0.8f, 0.4f);
Attributes[(int)MaterialAttributes.Material.Glass + (int)MaterialAttributes.Material.NumberOfTypes] = Attributes[(int)MaterialAttributes.Material.Glass + (int)MaterialAttributes.Material.NumberOfTypes] =
new MaterialAttributes("glassPhysical",dDensity, 0.8f, 0.7f); new MaterialAttributes("glassPhysical",dDensity, 0.8f, 0.7f);
Attributes[(int)MaterialAttributes.Material.Wood + (int)MaterialAttributes.Material.NumberOfTypes] = Attributes[(int)MaterialAttributes.Material.Wood + (int)MaterialAttributes.Material.NumberOfTypes] =
new MaterialAttributes("woodPhysical",dDensity, 0.8f, 0.5f); new MaterialAttributes("woodPhysical",dDensity, 0.8f, 0.5f);
Attributes[(int)MaterialAttributes.Material.Flesh + (int)MaterialAttributes.Material.NumberOfTypes] = Attributes[(int)MaterialAttributes.Material.Flesh + (int)MaterialAttributes.Material.NumberOfTypes] =
new MaterialAttributes("fleshPhysical",dDensity, 0.8f, 0.3f); new MaterialAttributes("fleshPhysical",dDensity, 0.8f, 0.3f);
Attributes[(int)MaterialAttributes.Material.Plastic + (int)MaterialAttributes.Material.NumberOfTypes] = Attributes[(int)MaterialAttributes.Material.Plastic + (int)MaterialAttributes.Material.NumberOfTypes] =
new MaterialAttributes("plasticPhysical",dDensity, 0.8f, 0.7f); new MaterialAttributes("plasticPhysical",dDensity, 0.8f, 0.7f);
Attributes[(int)MaterialAttributes.Material.Rubber + (int)MaterialAttributes.Material.NumberOfTypes] = Attributes[(int)MaterialAttributes.Material.Rubber + (int)MaterialAttributes.Material.NumberOfTypes] =
new MaterialAttributes("rubberPhysical",dDensity, 0.8f, 0.9f); new MaterialAttributes("rubberPhysical",dDensity, 0.8f, 0.9f);
Attributes[(int)MaterialAttributes.Material.Light + (int)MaterialAttributes.Material.NumberOfTypes] = Attributes[(int)MaterialAttributes.Material.Light + (int)MaterialAttributes.Material.NumberOfTypes] =
new MaterialAttributes("lightPhysical",dDensity, dFriction, dRestitution); new MaterialAttributes("lightPhysical",dDensity, dFriction, dRestitution);
Attributes[(int)MaterialAttributes.Material.Avatar + (int)MaterialAttributes.Material.NumberOfTypes] = Attributes[(int)MaterialAttributes.Material.Avatar + (int)MaterialAttributes.Material.NumberOfTypes] =
new MaterialAttributes("avatarPhysical",60f, 0.2f, 0f); new MaterialAttributes("avatarPhysical",60f, 0.2f, 0f);
} }
// Under the [BulletSim] section, one can change the individual material // Under the [BulletSim] section, one can change the individual material
@ -139,34 +154,34 @@ public static class BSMaterials
// the physical value. // the physical value.
public static void InitializefromParameters(IConfig pConfig) public static void InitializefromParameters(IConfig pConfig)
{ {
int matType = 0; foreach (KeyValuePair<string, MaterialAttributes.Material> kvp in MaterialMap)
foreach (string matName in MaterialAttributes.MaterialNames)
{ {
string matName = kvp.Key;
foreach (string attribName in MaterialAttributes.MaterialAttribs) foreach (string attribName in MaterialAttributes.MaterialAttribs)
{ {
string paramName = matName + attribName; string paramName = matName + attribName;
if (pConfig.Contains(paramName)) if (pConfig.Contains(paramName))
{ {
float paramValue = pConfig.GetFloat(paramName); float paramValue = pConfig.GetFloat(paramName);
SetAttributeValue(matType, attribName, paramValue); SetAttributeValue((int)kvp.Value, attribName, paramValue);
// set the physical value also // set the physical value also
SetAttributeValue(matType + (int)MaterialAttributes.Material.NumberOfTypes, attribName, paramValue); SetAttributeValue((int)kvp.Value + (int)MaterialAttributes.Material.NumberOfTypes, attribName, paramValue);
} }
paramName += "Physical"; paramName += "Physical";
if (pConfig.Contains(paramName)) if (pConfig.Contains(paramName))
{ {
float paramValue = pConfig.GetFloat(paramName); float paramValue = pConfig.GetFloat(paramName);
SetAttributeValue(matType + (int)MaterialAttributes.Material.NumberOfTypes, attribName, paramValue); SetAttributeValue((int)kvp.Value + (int)MaterialAttributes.Material.NumberOfTypes, attribName, paramValue);
} }
} }
matType++;
} }
} }
// Use reflection to set the value in the attribute structure.
private static void SetAttributeValue(int matType, string attribName, float val) private static void SetAttributeValue(int matType, string attribName, float val)
{ {
MaterialAttributes thisAttrib = Attributes[matType]; MaterialAttributes thisAttrib = Attributes[matType];
FieldInfo fieldInfo = thisAttrib.GetType().GetField(attribName); FieldInfo fieldInfo = thisAttrib.GetType().GetField(attribName.ToLower());
if (fieldInfo != null) if (fieldInfo != null)
{ {
fieldInfo.SetValue(thisAttrib, val); fieldInfo.SetValue(thisAttrib, val);
@ -174,12 +189,12 @@ public static class BSMaterials
} }
} }
// Given a material type, return a structure of attributes.
public static MaterialAttributes GetAttributes(MaterialAttributes.Material type, bool isPhysical) public static MaterialAttributes GetAttributes(MaterialAttributes.Material type, bool isPhysical)
{ {
int ind = (int)type; int ind = (int)type;
if (isPhysical) ind += (int)MaterialAttributes.Material.NumberOfTypes; if (isPhysical) ind += (int)MaterialAttributes.Material.NumberOfTypes;
return Attributes[ind]; return Attributes[ind];
} }
} }
} }

View File

@ -109,7 +109,7 @@ public abstract class BSPhysObject : PhysicsActor
public EntityProperties CurrentEntityProperties { get; set; } public EntityProperties CurrentEntityProperties { get; set; }
public EntityProperties LastEntityProperties { get; set; } public EntityProperties LastEntityProperties { get; set; }
public abstract OMV.Vector3 Scale { get; set; } public virtual OMV.Vector3 Scale { get; set; }
public abstract bool IsSolid { get; } public abstract bool IsSolid { get; }
public abstract bool IsStatic { get; } public abstract bool IsStatic { get; }

View File

@ -45,7 +45,6 @@ public sealed class BSPrim : BSPhysObject
private static readonly string LogHeader = "[BULLETS PRIM]"; private static readonly string LogHeader = "[BULLETS PRIM]";
// _size is what the user passed. Scale is what we pass to the physics engine with the mesh. // _size is what the user passed. Scale is what we pass to the physics engine with the mesh.
// Often Scale is unity because the meshmerizer will apply _size when creating the mesh.
private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user
private bool _grabbed; private bool _grabbed;
@ -93,7 +92,7 @@ public sealed class BSPrim : BSPhysObject
_physicsActorType = (int)ActorTypes.Prim; _physicsActorType = (int)ActorTypes.Prim;
_position = pos; _position = pos;
_size = size; _size = size;
Scale = size; // the scale will be set by CreateGeom depending on object type Scale = size; // prims are the size the user wants them to be (different for BSCharactes).
_orientation = rotation; _orientation = rotation;
_buoyancy = 1f; _buoyancy = 1f;
_velocity = OMV.Vector3.Zero; _velocity = OMV.Vector3.Zero;
@ -159,12 +158,10 @@ public sealed class BSPrim : BSPhysObject
// We presume the scale and size are the same. If scale must be changed for // We presume the scale and size are the same. If scale must be changed for
// the physical shape, that is done when the geometry is built. // the physical shape, that is done when the geometry is built.
_size = value; _size = value;
Scale = _size;
ForceBodyShapeRebuild(false); ForceBodyShapeRebuild(false);
} }
} }
// Scale is what we set in the physics engine. It is different than 'size' in that
// 'size' can be encorporated into the mesh. In that case, the scale is <1,1,1>.
public override OMV.Vector3 Scale { get; set; }
public override PrimitiveBaseShape Shape { public override PrimitiveBaseShape Shape {
set { set {
@ -1369,7 +1366,6 @@ public sealed class BSPrim : BSPhysObject
// Create the correct physical representation for this type of object. // Create the correct physical representation for this type of object.
// Updates PhysBody and PhysShape with the new information. // Updates PhysBody and PhysShape with the new information.
// Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary. // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary.
// Returns 'true' if either the body or the shape was changed.
PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, null, delegate(BulletBody dBody) PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, null, delegate(BulletBody dBody)
{ {
// Called if the current prim body is about to be destroyed. // Called if the current prim body is about to be destroyed.

View File

@ -309,6 +309,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
BSMaterials.InitializeFromDefaults(Params); BSMaterials.InitializeFromDefaults(Params);
if (pConfig != null) if (pConfig != null)
{ {
// Let the user add new and interesting material property values.
BSMaterials.InitializefromParameters(pConfig); BSMaterials.InitializefromParameters(pConfig);
} }
} }

View File

@ -126,6 +126,11 @@ public sealed class BSShapeCollection : IDisposable
return ret; return ret;
} }
public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPhysObject prim)
{
return GetBodyAndShape(forceRebuild, sim, prim, null, null);
}
// Track another user of a body. // Track another user of a body.
// We presume the caller has allocated the body. // We presume the caller has allocated the body.
// Bodies only have one user so the body is just put into the world if not already there. // Bodies only have one user so the body is just put into the world if not already there.
@ -460,6 +465,11 @@ public sealed class BSShapeCollection : IDisposable
&& pbs.PathScaleX == 100 && pbs.PathScaleY == 100 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
&& pbs.PathShearX == 0 && pbs.PathShearY == 0) ) ) && pbs.PathShearX == 0 && pbs.PathShearY == 0) ) )
{ {
// Get the scale of any existing shape so we can see if the new shape is same native type and same size.
OMV.Vector3 scaleOfExistingShape = OMV.Vector3.Zero;
if (prim.PhysShape.HasPhysicalShape)
scaleOfExistingShape = BulletSimAPI.GetLocalScaling2(prim.PhysShape.ptr);
if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,maybeNative,force={1},primScale={2},primSize={3},primShape={4}", if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,maybeNative,force={1},primScale={2},primSize={3},primShape={4}",
prim.LocalID, forceRebuild, prim.Scale, prim.Size, prim.PhysShape.type); prim.LocalID, forceRebuild, prim.Scale, prim.Size, prim.PhysShape.type);
@ -469,7 +479,7 @@ public sealed class BSShapeCollection : IDisposable
{ {
haveShape = true; haveShape = true;
if (forceRebuild if (forceRebuild
|| prim.Scale != prim.Size || prim.Scale != scaleOfExistingShape
|| prim.PhysShape.type != BSPhysicsShapeType.SHAPE_SPHERE || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_SPHERE
) )
{ {
@ -483,7 +493,7 @@ public sealed class BSShapeCollection : IDisposable
{ {
haveShape = true; haveShape = true;
if (forceRebuild if (forceRebuild
|| prim.Scale != prim.Size || prim.Scale != scaleOfExistingShape
|| prim.PhysShape.type != BSPhysicsShapeType.SHAPE_BOX || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_BOX
) )
{ {
@ -542,7 +552,6 @@ public sealed class BSShapeCollection : IDisposable
prim.LocalID, newShape, prim.Scale); prim.LocalID, newShape, prim.Scale);
// native shapes are scaled by Bullet // native shapes are scaled by Bullet
prim.Scale = prim.Size;
prim.PhysShape = newShape; prim.PhysShape = newShape;
return true; return true;
} }
@ -555,8 +564,8 @@ public sealed class BSShapeCollection : IDisposable
ShapeData nativeShapeData = new ShapeData(); ShapeData nativeShapeData = new ShapeData();
nativeShapeData.Type = shapeType; nativeShapeData.Type = shapeType;
nativeShapeData.ID = prim.LocalID; nativeShapeData.ID = prim.LocalID;
nativeShapeData.Scale = prim.Size; nativeShapeData.Scale = prim.Scale;
nativeShapeData.Size = prim.Size; // unneeded, I think. nativeShapeData.Size = prim.Scale; // unneeded, I think.
nativeShapeData.MeshKey = (ulong)shapeKey; nativeShapeData.MeshKey = (ulong)shapeKey;
nativeShapeData.HullKey = (ulong)shapeKey; nativeShapeData.HullKey = (ulong)shapeKey;
@ -611,8 +620,6 @@ public sealed class BSShapeCollection : IDisposable
ReferenceShape(newShape); ReferenceShape(newShape);
// meshes are already scaled by the meshmerizer
prim.Scale = new OMV.Vector3(1f, 1f, 1f);
prim.PhysShape = newShape; prim.PhysShape = newShape;
return true; // 'true' means a new shape has been added to this prim return true; // 'true' means a new shape has been added to this prim
@ -683,8 +690,6 @@ public sealed class BSShapeCollection : IDisposable
ReferenceShape(newShape); ReferenceShape(newShape);
// hulls are already scaled by the meshmerizer
prim.Scale = new OMV.Vector3(1f, 1f, 1f);
prim.PhysShape = newShape; prim.PhysShape = newShape;
return true; // 'true' means a new shape has been added to this prim return true; // 'true' means a new shape has been added to this prim
} }

View File

@ -20,6 +20,10 @@ Neb car jiggling left and right
Happens on terrain and any other mesh object. Flat cubes are much smoother. Happens on terrain and any other mesh object. Flat cubes are much smoother.
This has been reduced but not eliminated. This has been reduced but not eliminated.
For limitMotorUp, use raycast down to find if vehicle is in the air. For limitMotorUp, use raycast down to find if vehicle is in the air.
Angular motion around Z moves the vehicle in world Z and not vehicle Z in ODE.
Verify that angular motion specified around Z moves in the vehicle coordinates.
Verify llGetVel() is returning a smooth and good value for vehicle movement.
llGetVel() should return the root's velocity if requested in a child prim.
Implement function efficiency for lineaar and angular motion. Implement function efficiency for lineaar and angular motion.
Should vehicle angular/linear movement friction happen after all the components Should vehicle angular/linear movement friction happen after all the components
or does it only apply to the basic movement? or does it only apply to the basic movement?
@ -32,19 +36,14 @@ Border crossing with linked vehicle causes crash
BULLETSIM TODO LIST: BULLETSIM TODO LIST:
================================================= =================================================
Avatar height off after unsitting (float off ground) Avatar height off after unsitting (floats off ground)
Editting appearance then moving restores. Editting appearance then moving restores.
Must not be initializing height when recreating capsule after unsit. Must not be initializing height when recreating capsule after unsit.
Duplicating a physical prim causes old prim to jump away Duplicating a physical prim causes old prim to jump away
Dup a phys prim and the original become unselected and thus interacts w/ selected prim. Dup a phys prim and the original become unselected and thus interacts w/ selected prim.
Disable activity of passive linkset children.
Since the linkset is a compound object, the old prims are left lying
around and need to be phantomized so they don't collide, ...
Scenes with hundred of thousands of static objects take a lot of physics CPU time. Scenes with hundred of thousands of static objects take a lot of physics CPU time.
BSPrim.Force should set a continious force on the prim. The force should be BSPrim.Force should set a continious force on the prim. The force should be
applied each tick. Some limits? applied each tick. Some limits?
Linksets should allow collisions to individual children
Add LocalID to children shapes in LinksetCompound and create events for individuals
Gun sending shooter flying. Gun sending shooter flying.
Collision margin (gap between physical objects lying on each other) Collision margin (gap between physical objects lying on each other)
Boundry checking (crashes related to crossing boundry) Boundry checking (crashes related to crossing boundry)
@ -57,14 +56,34 @@ Small physical objects do not interact correctly
The chain will fall apart and pairs will dance around on ground The chain will fall apart and pairs will dance around on ground
Chains of 1x1x.2 will stay connected but will dance. Chains of 1x1x.2 will stay connected but will dance.
Chains above 2x2x.4 are move stable and get stablier as torui get larger. Chains above 2x2x.4 are move stable and get stablier as torui get larger.
Add material type linkage and input all the material property definitions.
Skeleton classes and table are in the sources but are not filled or used.
Add PID motor for avatar movement (slow to stop, ...) Add PID motor for avatar movement (slow to stop, ...)
setForce should set a constant force. Different than AddImpulse. setForce should set a constant force. Different than AddImpulse.
Implement raycast. Implement raycast.
Implement ShapeCollection.Dispose() Implement ShapeCollection.Dispose()
Implement water as a plain so raycasting and collisions can happen with same. Implement water as a plain so raycasting and collisions can happen with same.
Add osGetPhysicsEngineName() so scripters can tell whether BulletSim or ODE
Also osGetPhysicsEngineVerion() maybe.
LINKSETS
======================================================
Linksets should allow collisions to individual children
Add LocalID to children shapes in LinksetCompound and create events for individuals
Verify/think through scripts in children of linksets. What do they reference
and return when getting position, velocity, ...
Confirm constraint linksets still work after making all the changes for compound linksets.
Add 'changed' flag or similar to reduce the number of times a linkset is rebuilt.
For compound linksets, add ability to remove or reposition individual child shapes.
Disable activity of passive linkset children.
Since the linkset is a compound object, the old prims are left lying
around and need to be phantomized so they don't collide, ...
Speed up creation of large physical linksets
For instance, sitting in Neb's car (130 prims) takes several seconds to become physical
Eliminate collisions between objects in a linkset. (LinksetConstraint)
Have UserPointer point to struct with localID and linksetID?
Objects in original linkset still collide with each other?
MORE
======================================================
Find/remove avatar collision with ID=0. Find/remove avatar collision with ID=0.
Test avatar walking up stairs. How does compare with SL. Test avatar walking up stairs. How does compare with SL.
Radius of the capsule affects ability to climb edges. Radius of the capsule affects ability to climb edges.
@ -73,8 +92,6 @@ Debounce avatar contact so legs don't keep folding up when standing.
Implement LSL physics controls. Like STATUS_ROTATE_X. Implement LSL physics controls. Like STATUS_ROTATE_X.
Add border extensions to terrain to help region crossings and objects leaving region. Add border extensions to terrain to help region crossings and objects leaving region.
Speed up creation of large physical linksets
For instance, sitting in Neb's car (130 prims) takes several seconds to become physical
Performance test with lots of avatars. Can BulletSim support a thousand? Performance test with lots of avatars. Can BulletSim support a thousand?
Optimize collisions in C++: only send up to the object subscribed to collisions. Optimize collisions in C++: only send up to the object subscribed to collisions.
Use collision subscription and remove the collsion(A,B) and collision(B,A) Use collision subscription and remove the collsion(A,B) and collision(B,A)
@ -85,10 +102,6 @@ Avatar jump
Performance measurement and changes to make quicker. Performance measurement and changes to make quicker.
Implement detailed physics stats (GetStats()). Implement detailed physics stats (GetStats()).
Eliminate collisions between objects in a linkset. (LinksetConstraint)
Have UserPointer point to struct with localID and linksetID?
Objects in original linkset still collide with each other?
Measure performance improvement from hulls Measure performance improvement from hulls
Test not using ghost objects for volume detect implementation. Test not using ghost objects for volume detect implementation.
Performance of closures and delegates for taint processing Performance of closures and delegates for taint processing
@ -101,6 +114,9 @@ Physics Arena central pyramid: why is one side permiable?
INTERNAL IMPROVEMENT/CLEANUP INTERNAL IMPROVEMENT/CLEANUP
================================================= =================================================
Consider moving prim/character body and shape destruction in destroy()
to postTimeTime rather than protecting all the potential sets that
might have been queued up.
Remove unused fields from ShapeData (not used in API2) Remove unused fields from ShapeData (not used in API2)
Breakout code for mesh/hull/compound/native into separate BSShape* classes Breakout code for mesh/hull/compound/native into separate BSShape* classes
Standardize access to building and reference code. Standardize access to building and reference code.
@ -154,3 +170,6 @@ Package Bullet source mods for Bullet internal stats output
(Resolution: move code into WorldData.h rather than relying on patches) (Resolution: move code into WorldData.h rather than relying on patches)
Single prim vehicles don't seem to properly vehiclize. Single prim vehicles don't seem to properly vehiclize.
(Resolution: mass was not getting set properly for single prim linksets) (Resolution: mass was not getting set properly for single prim linksets)
Add material type linkage and input all the material property definitions.
Skeleton classes and table are in the sources but are not filled or used.
(Resolution:

View File

@ -58,6 +58,18 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
/// </summary> /// </summary>
public interface IScriptInstance public interface IScriptInstance
{ {
/// <summary>
/// Debug level for this script instance.
/// </summary>
/// <remarks>
/// Level == 0, no extra data is logged.
/// Level >= 1, state changes are logged.
/// Level >= 2, event firing is logged.
/// <value>
/// The debug level.
/// </value>
int DebugLevel { get; set; }
/// <summary> /// <summary>
/// Is the script currently running? /// Is the script currently running?
/// </summary> /// </summary>

View File

@ -93,6 +93,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
private UUID m_CurrentStateHash; private UUID m_CurrentStateHash;
private UUID m_RegionID; private UUID m_RegionID;
public int DebugLevel { get; set; }
public Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> LineMap { get; set; } public Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> LineMap { get; set; }
private Dictionary<string,IScriptApi> m_Apis = new Dictionary<string,IScriptApi>(); private Dictionary<string,IScriptApi> m_Apis = new Dictionary<string,IScriptApi>();
@ -548,9 +550,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
// forcibly abort the work item (this aborts the underlying thread). // forcibly abort the work item (this aborts the underlying thread).
if (!m_InSelfDelete) if (!m_InSelfDelete)
{ {
// m_log.ErrorFormat( m_log.DebugFormat(
// "[SCRIPT INSTANCE]: Aborting script {0} {1} in prim {2} {3} {4} {5}", "[SCRIPT INSTANCE]: Aborting unstopped script {0} {1} in prim {2}, localID {3}, timeout was {4} ms",
// ScriptName, ItemID, PrimName, ObjectID, m_InSelfDelete, DateTime.Now.Ticks); ScriptName, ItemID, PrimName, LocalID, timeout);
workItem.Abort(); workItem.Abort();
} }
@ -703,21 +705,42 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
if (data.EventName == "collision") if (data.EventName == "collision")
m_CollisionInQueue = false; m_CollisionInQueue = false;
} }
// m_log.DebugFormat("[XEngine]: Processing event {0} for {1}", data.EventName, this); SceneObjectPart part = Engine.World.GetSceneObjectPart(LocalID);
if (DebugLevel >= 2)
m_log.DebugFormat(
"[SCRIPT INSTANCE]: Processing event {0} for {1}/{2}({3})/{4}({5}) @ {6}/{7}",
data.EventName,
ScriptName,
part.Name,
part.LocalId,
part.ParentGroup.Name,
part.ParentGroup.UUID,
part.AbsolutePosition,
part.ParentGroup.Scene.Name);
m_DetectParams = data.DetectParams; m_DetectParams = data.DetectParams;
if (data.EventName == "state") // Hardcoded state change if (data.EventName == "state") // Hardcoded state change
{ {
// m_log.DebugFormat("[Script] Script {0}.{1} state set to {2}",
// PrimName, ScriptName, data.Params[0].ToString());
State = data.Params[0].ToString(); State = data.Params[0].ToString();
if (DebugLevel >= 1)
m_log.DebugFormat(
"[SCRIPT INSTANCE]: Changing state to {0} for {1}/{2}({3})/{4}({5}) @ {6}/{7}",
State,
ScriptName,
part.Name,
part.LocalId,
part.ParentGroup.Name,
part.ParentGroup.UUID,
part.AbsolutePosition,
part.ParentGroup.Scene.Name);
AsyncCommandManager.RemoveScript(Engine, AsyncCommandManager.RemoveScript(Engine,
LocalID, ItemID); LocalID, ItemID);
SceneObjectPart part = Engine.World.GetSceneObjectPart(
LocalID);
if (part != null) if (part != null)
{ {
part.SetScriptEvents(ItemID, part.SetScriptEvents(ItemID,
@ -729,8 +752,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
if (Engine.World.PipeEventsForScript(LocalID) || if (Engine.World.PipeEventsForScript(LocalID) ||
data.EventName == "control") // Don't freeze avies! data.EventName == "control") // Don't freeze avies!
{ {
SceneObjectPart part = Engine.World.GetSceneObjectPart(
LocalID);
// m_log.DebugFormat("[Script] Delivered event {2} in state {3} to {0}.{1}", // m_log.DebugFormat("[Script] Delivered event {2} in state {3} to {0}.{1}",
// PrimName, ScriptName, data.EventName, State); // PrimName, ScriptName, data.EventName, State);

View File

@ -304,7 +304,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
MainConsole.Instance.Commands.AddCommand( MainConsole.Instance.Commands.AddCommand(
"Scripts", false, "scripts show", "scripts show [<script-item-uuid>]", "Show script information", "Scripts", false, "scripts show", "scripts show [<script-item-uuid>]", "Show script information",
"Show information on all scripts known to the script engine." "Show information on all scripts known to the script engine.\n"
+ "If a <script-item-uuid> is given then only information on that script will be shown.", + "If a <script-item-uuid> is given then only information on that script will be shown.",
HandleShowScripts); HandleShowScripts);
@ -323,22 +323,30 @@ namespace OpenSim.Region.ScriptEngine.XEngine
MainConsole.Instance.Commands.AddCommand( MainConsole.Instance.Commands.AddCommand(
"Scripts", false, "scripts resume", "scripts resume [<script-item-uuid>]", "Resumes all suspended scripts", "Scripts", false, "scripts resume", "scripts resume [<script-item-uuid>]", "Resumes all suspended scripts",
"Resumes all currently suspended scripts.\n" "Resumes all currently suspended scripts.\n"
+ "Resumed scripts will process all events accumulated whilst suspended." + "Resumed scripts will process all events accumulated whilst suspended.\n"
+ "If a <script-item-uuid> is given then only that script will be resumed. Otherwise, all suitable scripts are resumed.", + "If a <script-item-uuid> is given then only that script will be resumed. Otherwise, all suitable scripts are resumed.",
(module, cmdparams) => HandleScriptsAction(cmdparams, HandleResumeScript)); (module, cmdparams) => HandleScriptsAction(cmdparams, HandleResumeScript));
MainConsole.Instance.Commands.AddCommand( MainConsole.Instance.Commands.AddCommand(
"Scripts", false, "scripts stop", "scripts stop [<script-item-uuid>]", "Stops all running scripts", "Scripts", false, "scripts stop", "scripts stop [<script-item-uuid>]", "Stops all running scripts",
"Stops all running scripts." "Stops all running scripts.\n"
+ "If a <script-item-uuid> is given then only that script will be stopped. Otherwise, all suitable scripts are stopped.", + "If a <script-item-uuid> is given then only that script will be stopped. Otherwise, all suitable scripts are stopped.",
(module, cmdparams) => HandleScriptsAction(cmdparams, HandleStopScript)); (module, cmdparams) => HandleScriptsAction(cmdparams, HandleStopScript));
MainConsole.Instance.Commands.AddCommand( MainConsole.Instance.Commands.AddCommand(
"Scripts", false, "scripts start", "scripts start [<script-item-uuid>]", "Starts all stopped scripts", "Scripts", false, "scripts start", "scripts start [<script-item-uuid>]", "Starts all stopped scripts",
"Starts all stopped scripts." "Starts all stopped scripts.\n"
+ "If a <script-item-uuid> is given then only that script will be started. Otherwise, all suitable scripts are started.", + "If a <script-item-uuid> is given then only that script will be started. Otherwise, all suitable scripts are started.",
(module, cmdparams) => HandleScriptsAction(cmdparams, HandleStartScript)); (module, cmdparams) => HandleScriptsAction(cmdparams, HandleStartScript));
MainConsole.Instance.Commands.AddCommand(
"Scripts", false, "debug script log", "debug scripts log <item-id> <log-level>", "Extra debug logging for a script",
"Activates or deactivates extra debug logging for the given script.\n"
+ "Level == 0, deactivate extra debug logging.\n"
+ "Level >= 1, log state changes.\n"
+ "Level >= 2, log event invocations.\n",
HandleDebugScriptLogCommand);
// MainConsole.Instance.Commands.AddCommand( // MainConsole.Instance.Commands.AddCommand(
// "Debug", false, "debug xengine", "debug xengine [<level>]", // "Debug", false, "debug xengine", "debug xengine [<level>]",
// "Turn on detailed xengine debugging.", // "Turn on detailed xengine debugging.",
@ -347,6 +355,41 @@ namespace OpenSim.Region.ScriptEngine.XEngine
// HandleDebugLevelCommand); // HandleDebugLevelCommand);
} }
private void HandleDebugScriptLogCommand(string module, string[] args)
{
if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene))
return;
if (args.Length != 5)
{
MainConsole.Instance.Output("Usage: debug script log <item-id> <log-level>");
return;
}
UUID itemId;
if (!ConsoleUtil.TryParseConsoleUuid(MainConsole.Instance, args[3], out itemId))
return;
int newLevel;
if (!ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, args[4], out newLevel))
return;
IScriptInstance si;
lock (m_Scripts)
{
// XXX: We can't give the user feedback on a bad item id because this may apply to a different script
// engine
if (!m_Scripts.TryGetValue(itemId, out si))
return;
}
si.DebugLevel = newLevel;
MainConsole.Instance.OutputFormat("Set debug level of {0} {1} to {2}", si.ScriptName, si.ItemID, newLevel);
}
/// <summary> /// <summary>
/// Change debug level /// Change debug level
/// </summary> /// </summary>
@ -418,7 +461,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
if (!UUID.TryParse(rawItemId, out itemId)) if (!UUID.TryParse(rawItemId, out itemId))
{ {
MainConsole.Instance.OutputFormat("Error - {0} is not a valid UUID", rawItemId); MainConsole.Instance.OutputFormat("ERROR: {0} is not a valid UUID", rawItemId);
return; return;
} }
@ -542,6 +585,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
sb.AppendFormat("Queued events : {0}\n", instance.EventsQueued); sb.AppendFormat("Queued events : {0}\n", instance.EventsQueued);
sb.AppendFormat("Processed events : {0}\n", instance.EventsProcessed); sb.AppendFormat("Processed events : {0}\n", instance.EventsProcessed);
sb.AppendFormat("Item UUID : {0}\n", instance.ItemID); sb.AppendFormat("Item UUID : {0}\n", instance.ItemID);
sb.AppendFormat("Asset UUID : {0}\n", instance.AssetID);
sb.AppendFormat("Containing part name: {0}\n", instance.PrimName); sb.AppendFormat("Containing part name: {0}\n", instance.PrimName);
sb.AppendFormat("Containing part UUID: {0}\n", instance.ObjectID); sb.AppendFormat("Containing part UUID: {0}\n", instance.ObjectID);
sb.AppendFormat("Position : {0}\n", sop.AbsolutePosition); sb.AppendFormat("Position : {0}\n", sop.AbsolutePosition);