Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5eb2526e88 | ||
|
|
641b08aa78 | ||
|
|
15d5f3d09d | ||
|
|
07dbe46ba3 | ||
|
|
ff867b59cf | ||
|
|
d4b8a13a1d | ||
|
|
a858c5daee | ||
|
|
8d431c6359 | ||
|
|
663bfbb372 | ||
|
|
d297eb39e5 | ||
|
|
29218cdb31 | ||
|
|
359f9efc76 | ||
|
|
fb211c64fd | ||
|
|
a3d140b57c | ||
|
|
f7b88d1c40 | ||
|
|
32b534f324 | ||
|
|
ffdc798720 | ||
|
|
ae852bb873 |
@@ -92,6 +92,7 @@ what it is today.
|
||||
* Flyte Xevious
|
||||
* Garmin Kawaguichi
|
||||
* Gryc Ueusp
|
||||
* Hiro Lecker
|
||||
* Imaze Rhiano
|
||||
* Intimidated
|
||||
* Jeremy Bongio (IBM)
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace OpenSim
|
||||
{
|
||||
public class VersionInfo
|
||||
{
|
||||
private const string VERSION_NUMBER = "0.7.4";
|
||||
private const string VERSION_NUMBER = "0.7.5";
|
||||
private const Flavour VERSION_FLAVOUR = Flavour.Dev;
|
||||
|
||||
public enum Flavour
|
||||
|
||||
@@ -208,6 +208,9 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
|
||||
bitmap = ImageUtils.ResizeImage(origBitmap, viewport.Width, viewport.Height);
|
||||
}
|
||||
|
||||
GC.Collect();
|
||||
m_log.Debug("[WARP 3D IMAGE MODULE]: GC.Collect()");
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
@@ -673,4 +676,4 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3418,13 +3418,16 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
public List<SceneObjectGroup> GetAttachments(uint attachmentPoint)
|
||||
{
|
||||
List<SceneObjectGroup> attachments = new List<SceneObjectGroup>();
|
||||
|
||||
lock (m_attachments)
|
||||
|
||||
if (attachmentPoint >= 0)
|
||||
{
|
||||
foreach (SceneObjectGroup so in m_attachments)
|
||||
lock (m_attachments)
|
||||
{
|
||||
if (attachmentPoint == so.AttachmentPoint)
|
||||
attachments.Add(so);
|
||||
foreach (SceneObjectGroup so in m_attachments)
|
||||
{
|
||||
if (attachmentPoint == so.AttachmentPoint)
|
||||
attachments.Add(so);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,8 +39,7 @@ public class BSCharacter : BSPhysObject
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
private static readonly string LogHeader = "[BULLETS CHAR]";
|
||||
|
||||
private BSScene _scene;
|
||||
public BSScene Scene { get { return _scene; } }
|
||||
public BSScene Scene { get; private set; }
|
||||
private String _avName;
|
||||
// private bool _stopped;
|
||||
private Vector3 _size;
|
||||
@@ -92,7 +91,7 @@ public class BSCharacter : BSPhysObject
|
||||
{
|
||||
_localID = localID;
|
||||
_avName = avName;
|
||||
_scene = parent_scene;
|
||||
Scene = parent_scene;
|
||||
_position = pos;
|
||||
_size = size;
|
||||
_flying = isFlying;
|
||||
@@ -101,11 +100,11 @@ public class BSCharacter : BSPhysObject
|
||||
_buoyancy = ComputeBuoyancyFromFlying(isFlying);
|
||||
// The dimensions of the avatar capsule are kept in the scale.
|
||||
// Physics creates a unit capsule which is scaled by the physics engine.
|
||||
_scale = new Vector3(_scene.Params.avatarCapsuleRadius, _scene.Params.avatarCapsuleRadius, size.Z);
|
||||
_density = _scene.Params.avatarDensity;
|
||||
_scale = new Vector3(Scene.Params.avatarCapsuleRadius, Scene.Params.avatarCapsuleRadius, size.Z);
|
||||
_density = Scene.Params.avatarDensity;
|
||||
ComputeAvatarVolumeAndMass(); // set _avatarVolume and _mass based on capsule size, _density and _scale
|
||||
|
||||
Linkset = new BSLinkset(_scene, this);
|
||||
Linkset = new BSLinkset(Scene, this);
|
||||
|
||||
ShapeData shapeData = new ShapeData();
|
||||
shapeData.ID = _localID;
|
||||
@@ -117,19 +116,19 @@ public class BSCharacter : BSPhysObject
|
||||
shapeData.Mass = _mass;
|
||||
shapeData.Buoyancy = _buoyancy;
|
||||
shapeData.Static = ShapeData.numericFalse;
|
||||
shapeData.Friction = _scene.Params.avatarFriction;
|
||||
shapeData.Restitution = _scene.Params.avatarRestitution;
|
||||
shapeData.Friction = Scene.Params.avatarFriction;
|
||||
shapeData.Restitution = Scene.Params.avatarRestitution;
|
||||
|
||||
// do actual create at taint time
|
||||
_scene.TaintedObject("BSCharacter.create", delegate()
|
||||
Scene.TaintedObject("BSCharacter.create", delegate()
|
||||
{
|
||||
DetailLog("{0},BSCharacter.create", _localID);
|
||||
BulletSimAPI.CreateObject(parent_scene.WorldID, shapeData);
|
||||
BulletSimAPI.CreateObject(Scene.WorldID, shapeData);
|
||||
|
||||
// Set the buoyancy for flying. This will be refactored when all the settings happen in C#
|
||||
BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, LocalID, _buoyancy);
|
||||
BulletSimAPI.SetObjectBuoyancy(Scene.WorldID, LocalID, _buoyancy);
|
||||
|
||||
Body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
|
||||
Body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(Scene.World.Ptr, LocalID));
|
||||
// avatars get all collisions no matter what (makes walking on ground and such work)
|
||||
BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
|
||||
});
|
||||
@@ -141,9 +140,9 @@ public class BSCharacter : BSPhysObject
|
||||
public override void Destroy()
|
||||
{
|
||||
DetailLog("{0},BSCharacter.Destroy", LocalID);
|
||||
_scene.TaintedObject("BSCharacter.destroy", delegate()
|
||||
Scene.TaintedObject("BSCharacter.destroy", delegate()
|
||||
{
|
||||
BulletSimAPI.DestroyObject(_scene.WorldID, _localID);
|
||||
BulletSimAPI.DestroyObject(Scene.WorldID, _localID);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -172,9 +171,9 @@ public class BSCharacter : BSPhysObject
|
||||
|
||||
ComputeAvatarVolumeAndMass();
|
||||
|
||||
_scene.TaintedObject("BSCharacter.setSize", delegate()
|
||||
Scene.TaintedObject("BSCharacter.setSize", delegate()
|
||||
{
|
||||
BulletSimAPI.SetObjectScaleMass(_scene.WorldID, LocalID, _scale, _mass, true);
|
||||
BulletSimAPI.SetObjectScaleMass(Scene.WorldID, LocalID, _scale, _mass, true);
|
||||
});
|
||||
|
||||
}
|
||||
@@ -203,17 +202,17 @@ public class BSCharacter : BSPhysObject
|
||||
|
||||
public override Vector3 Position {
|
||||
get {
|
||||
// _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
|
||||
// _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID);
|
||||
return _position;
|
||||
}
|
||||
set {
|
||||
_position = value;
|
||||
PositionSanityCheck();
|
||||
|
||||
_scene.TaintedObject("BSCharacter.setPosition", delegate()
|
||||
Scene.TaintedObject("BSCharacter.setPosition", delegate()
|
||||
{
|
||||
DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
|
||||
BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
|
||||
BulletSimAPI.SetObjectTranslation(Scene.WorldID, _localID, _position, _orientation);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -230,9 +229,7 @@ public class BSCharacter : BSPhysObject
|
||||
if (Position.Z < terrainHeight)
|
||||
{
|
||||
DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight);
|
||||
Vector3 newPos = _position;
|
||||
newPos.Z = terrainHeight + 2.0f;
|
||||
_position = newPos;
|
||||
_position.Z = terrainHeight + 2.0f;
|
||||
ret = true;
|
||||
}
|
||||
|
||||
@@ -250,10 +247,10 @@ public class BSCharacter : BSPhysObject
|
||||
{
|
||||
// The new position value must be pushed into the physics engine but we can't
|
||||
// just assign to "Position" because of potential call loops.
|
||||
_scene.TaintedObject("BSCharacter.PositionSanityCheck", delegate()
|
||||
Scene.TaintedObject("BSCharacter.PositionSanityCheck", delegate()
|
||||
{
|
||||
DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
|
||||
BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
|
||||
BulletSimAPI.SetObjectTranslation(Scene.WorldID, _localID, _position, _orientation);
|
||||
});
|
||||
ret = true;
|
||||
}
|
||||
@@ -301,10 +298,10 @@ public class BSCharacter : BSPhysObject
|
||||
set {
|
||||
_velocity = value;
|
||||
// m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity);
|
||||
_scene.TaintedObject("BSCharacter.setVelocity", delegate()
|
||||
Scene.TaintedObject("BSCharacter.setVelocity", delegate()
|
||||
{
|
||||
DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity);
|
||||
BulletSimAPI.SetObjectVelocity(_scene.WorldID, _localID, _velocity);
|
||||
BulletSimAPI.SetObjectVelocity(Scene.WorldID, _localID, _velocity);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -327,10 +324,10 @@ public class BSCharacter : BSPhysObject
|
||||
set {
|
||||
_orientation = value;
|
||||
// m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation);
|
||||
_scene.TaintedObject("BSCharacter.setOrientation", delegate()
|
||||
Scene.TaintedObject("BSCharacter.setOrientation", delegate()
|
||||
{
|
||||
// _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
|
||||
BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
|
||||
// _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID);
|
||||
BulletSimAPI.SetObjectTranslation(Scene.WorldID, _localID, _position, _orientation);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -367,11 +364,11 @@ public class BSCharacter : BSPhysObject
|
||||
set { _throttleUpdates = value; }
|
||||
}
|
||||
public override bool IsColliding {
|
||||
get { return (_collidingStep == _scene.SimulationStep); }
|
||||
get { return (_collidingStep == Scene.SimulationStep); }
|
||||
set { _isColliding = value; }
|
||||
}
|
||||
public override bool CollidingGround {
|
||||
get { return (_collidingGroundStep == _scene.SimulationStep); }
|
||||
get { return (_collidingGroundStep == Scene.SimulationStep); }
|
||||
set { _collidingGround = value; }
|
||||
}
|
||||
public override bool CollidingObj {
|
||||
@@ -393,10 +390,10 @@ public class BSCharacter : BSPhysObject
|
||||
public override float Buoyancy {
|
||||
get { return _buoyancy; }
|
||||
set { _buoyancy = value;
|
||||
_scene.TaintedObject("BSCharacter.setBuoyancy", delegate()
|
||||
Scene.TaintedObject("BSCharacter.setBuoyancy", delegate()
|
||||
{
|
||||
DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
|
||||
BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, LocalID, _buoyancy);
|
||||
BulletSimAPI.SetObjectBuoyancy(Scene.WorldID, LocalID, _buoyancy);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -440,7 +437,7 @@ public class BSCharacter : BSPhysObject
|
||||
_force.Y += force.Y;
|
||||
_force.Z += force.Z;
|
||||
// m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force);
|
||||
_scene.TaintedObject("BSCharacter.AddForce", delegate()
|
||||
Scene.TaintedObject("BSCharacter.AddForce", delegate()
|
||||
{
|
||||
DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force);
|
||||
BulletSimAPI.AddObjectForce2(Body.Ptr, _force);
|
||||
@@ -524,10 +521,9 @@ public class BSCharacter : BSPhysObject
|
||||
// Do some sanity checking for the avatar. Make sure it's above ground and inbounds.
|
||||
PositionSanityCheck2();
|
||||
|
||||
float heightHere = Scene.TerrainManager.GetTerrainHeightAtXYZ(_position); // just for debug
|
||||
float heightHere = Scene.TerrainManager.GetTerrainHeightAtXYZ(_position); // only for debug
|
||||
DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5},terrain={6}",
|
||||
LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
|
||||
entprop.Acceleration, entprop.RotationalVelocity, heightHere);
|
||||
LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity, heightHere);
|
||||
}
|
||||
|
||||
// Called by the scene when a collision with this object is reported
|
||||
@@ -539,16 +535,16 @@ public class BSCharacter : BSPhysObject
|
||||
// m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith);
|
||||
|
||||
// The following makes IsColliding() and IsCollidingGround() work
|
||||
_collidingStep = _scene.SimulationStep;
|
||||
_collidingStep = Scene.SimulationStep;
|
||||
if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID)
|
||||
{
|
||||
_collidingGroundStep = _scene.SimulationStep;
|
||||
_collidingGroundStep = Scene.SimulationStep;
|
||||
}
|
||||
// DetailLog("{0},BSCharacter.Collison,call,with={1}", LocalID, collidingWith);
|
||||
|
||||
// throttle collisions to the rate specified in the subscription
|
||||
if (_subscribedEventsMs != 0) {
|
||||
int nowTime = _scene.SimulationNowTime;
|
||||
int nowTime = Scene.SimulationNowTime;
|
||||
if (nowTime >= _nextCollisionOkTime) {
|
||||
_nextCollisionOkTime = nowTime + _subscribedEventsMs;
|
||||
|
||||
|
||||
@@ -232,15 +232,15 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
}
|
||||
|
||||
// If Debug logging level, enable logging from the unmanaged code
|
||||
m_DebugLogCallbackHandle = null;
|
||||
if (m_log.IsDebugEnabled || PhysicsLogging.Enabled)
|
||||
{
|
||||
m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader);
|
||||
if (PhysicsLogging.Enabled)
|
||||
// The handle is saved in a variable to make sure it doesn't get freed after this call
|
||||
m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLoggerPhysLog);
|
||||
else
|
||||
m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger);
|
||||
// The handle is saved in a variable to make sure it doesn't get freed after this call
|
||||
BulletSimAPI.SetDebugLogCallback(m_DebugLogCallbackHandle);
|
||||
}
|
||||
|
||||
// Get the version of the DLL
|
||||
@@ -257,7 +257,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
// m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader);
|
||||
WorldID = BulletSimAPI.Initialize(worldExtent, m_paramsHandle.AddrOfPinnedObject(),
|
||||
m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(),
|
||||
m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject());
|
||||
m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject(),
|
||||
m_DebugLogCallbackHandle);
|
||||
|
||||
// Initialization to support the transition to a new API which puts most of the logic
|
||||
// into the C# code so it is easier to modify and add to.
|
||||
@@ -265,8 +266,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
|
||||
Constraints = new BSConstraintCollection(World);
|
||||
|
||||
// Note: choose one of the two following lines
|
||||
// BulletSimAPI.CreateInitialGroundPlaneAndTerrain(WorldID);
|
||||
TerrainManager = new BSTerrainManager(this);
|
||||
TerrainManager.CreateInitialGroundPlaneAndTerrain();
|
||||
|
||||
@@ -378,7 +377,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
BSCharacter actor = new BSCharacter(localID, avName, this, position, size, isFlying);
|
||||
lock (PhysObjects) PhysObjects.Add(localID, actor);
|
||||
|
||||
// Remove kludge someday
|
||||
// TODO: Remove kludge someday.
|
||||
// We must generate a collision for avatars whether they collide or not.
|
||||
// This is required by OpenSim to update avatar animations, etc.
|
||||
lock (m_avatarsWithCollisions) m_avatarsWithCollisions.Add(actor);
|
||||
|
||||
return actor;
|
||||
@@ -1069,7 +1070,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
(s) => { return s.m_params[0].terrainRestitution; },
|
||||
(s,p,l,v) => { s.m_params[0].terrainRestitution = v; s.TaintedUpdateParameter(p,l,v); } ),
|
||||
new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.",
|
||||
0.5f,
|
||||
0.2f,
|
||||
(s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); },
|
||||
(s) => { return s.m_params[0].avatarFriction; },
|
||||
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarFriction, p, l, v); } ),
|
||||
|
||||
@@ -44,15 +44,35 @@ public class BSTerrainManager
|
||||
{
|
||||
static string LogHeader = "[BULLETSIM TERRAIN MANAGER]";
|
||||
|
||||
BSScene m_physicsScene;
|
||||
// These height values are fractional so the odd values will be
|
||||
// noticable when debugging.
|
||||
public const float HEIGHT_INITIALIZATION = 24.987f;
|
||||
public const float HEIGHT_INITIAL_LASTHEIGHT = 24.876f;
|
||||
public const float HEIGHT_GETHEIGHT_RET = 24.765f;
|
||||
|
||||
// If the min and max height are equal, we reduce the min by this
|
||||
// amount to make sure that a bounding box is built for the terrain.
|
||||
public const float HEIGHT_EQUAL_FUDGE = 0.2f;
|
||||
|
||||
public const float TERRAIN_COLLISION_MARGIN = 0.0f;
|
||||
|
||||
// Until the whole simulator is changed to pass us the region size, we rely on constants.
|
||||
public Vector3 DefaultRegionSize = new Vector3(Constants.RegionSize, Constants.RegionSize, 0f);
|
||||
|
||||
// The scene that I am part of
|
||||
private BSScene m_physicsScene;
|
||||
|
||||
// The ground plane created to keep thing from falling to infinity.
|
||||
private BulletBody m_groundPlane;
|
||||
|
||||
// If doing mega-regions, if we're region zero we will be managing multiple
|
||||
// region terrains since region zero does the physics for the whole mega-region.
|
||||
private Dictionary<Vector2, BulletBody> m_terrains;
|
||||
private Dictionary<Vector2, BulletHeightMapInfo> m_heightMaps;
|
||||
|
||||
// True of the terrain has been modified.
|
||||
// Used to force recalculation of terrain height after terrain has been modified
|
||||
private bool m_terrainModified;
|
||||
|
||||
// If we are doing mega-regions, terrains are added from TERRAIN_ID to m_terrainCount.
|
||||
// This is incremented before assigning to new region so it is the last ID allocated.
|
||||
private uint m_terrainCount = BSScene.CHILDTERRAIN_ID - 1;
|
||||
@@ -60,15 +80,22 @@ public class BSTerrainManager
|
||||
|
||||
// If doing mega-regions, this holds our offset from region zero of
|
||||
// the mega-regions. "parentScene" points to the PhysicsScene of region zero.
|
||||
private Vector3 m_worldOffset = Vector3.Zero;
|
||||
public Vector2 WorldExtents = new Vector2((int)Constants.RegionSize, (int)Constants.RegionSize);
|
||||
private PhysicsScene m_parentScene = null;
|
||||
private Vector3 m_worldOffset;
|
||||
// If the parent region (region 0), this is the extent of the combined regions
|
||||
// relative to the origin of region zero
|
||||
private Vector3 m_worldMax;
|
||||
private PhysicsScene m_parentScene;
|
||||
|
||||
public BSTerrainManager(BSScene physicsScene)
|
||||
{
|
||||
m_physicsScene = physicsScene;
|
||||
m_terrains = new Dictionary<Vector2,BulletBody>();
|
||||
m_heightMaps = new Dictionary<Vector2,BulletHeightMapInfo>();
|
||||
m_terrainModified = false;
|
||||
|
||||
// Assume one region of default size
|
||||
m_worldOffset = Vector3.Zero;
|
||||
m_worldMax = new Vector3(DefaultRegionSize.X, DefaultRegionSize.Y, 4096f);
|
||||
m_parentScene = null;
|
||||
}
|
||||
|
||||
// Create the initial instance of terrain and the underlying ground plane.
|
||||
@@ -76,173 +103,274 @@ public class BSTerrainManager
|
||||
// by the managed code.
|
||||
// The terrains and the groundPlane are not added to the list of PhysObjects.
|
||||
// This is called from the initialization routine so we presume it is
|
||||
// safe to call Bullet in real time. We hope no one is moving around prim yet.
|
||||
// safe to call Bullet in real time. We hope no one is moving prims around yet.
|
||||
public void CreateInitialGroundPlaneAndTerrain()
|
||||
{
|
||||
// The ground plane is here to catch things that are trying to drop to negative infinity
|
||||
BulletShape groundPlaneShape = new BulletShape(BulletSimAPI.CreateGroundPlaneShape2(BSScene.GROUNDPLANE_ID, 1f, TERRAIN_COLLISION_MARGIN));
|
||||
m_groundPlane = new BulletBody(BSScene.GROUNDPLANE_ID,
|
||||
BulletSimAPI.CreateGroundPlaneBody2(BSScene.GROUNDPLANE_ID, 1f, 0.4f));
|
||||
BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.Ptr, Vector3.Zero, Quaternion.Identity));
|
||||
BulletSimAPI.AddObjectToWorld2(m_physicsScene.World.Ptr, m_groundPlane.Ptr);
|
||||
|
||||
Vector3 minTerrainCoords = new Vector3(0f, 0f, 24f);
|
||||
Vector3 maxTerrainCoords = new Vector3(Constants.RegionSize, Constants.RegionSize, 25f);
|
||||
Vector3 minTerrainCoords = new Vector3(0f, 0f, HEIGHT_INITIALIZATION - HEIGHT_EQUAL_FUDGE);
|
||||
Vector3 maxTerrainCoords = new Vector3(DefaultRegionSize.X, DefaultRegionSize.Y, HEIGHT_INITIALIZATION);
|
||||
int totalHeights = (int)maxTerrainCoords.X * (int)maxTerrainCoords.Y;
|
||||
float[] initialMap = new float[totalHeights];
|
||||
for (int ii = 0; ii < totalHeights; ii++)
|
||||
{
|
||||
initialMap[ii] = 25f;
|
||||
initialMap[ii] = HEIGHT_INITIALIZATION;
|
||||
}
|
||||
CreateNewTerrainSegment(BSScene.TERRAIN_ID, initialMap, minTerrainCoords, maxTerrainCoords);
|
||||
UpdateOrCreateTerrain(BSScene.TERRAIN_ID, initialMap, minTerrainCoords, maxTerrainCoords, true);
|
||||
}
|
||||
|
||||
// Release all the terrain structures we might have allocated
|
||||
public void ReleaseGroundPlaneAndTerrain()
|
||||
{
|
||||
if (BulletSimAPI.RemoveObjectFromWorld2(m_physicsScene.World.Ptr, m_groundPlane.Ptr))
|
||||
if (m_groundPlane.Ptr != IntPtr.Zero)
|
||||
{
|
||||
BulletSimAPI.DestroyObject2(m_physicsScene.World.Ptr, m_groundPlane.Ptr);
|
||||
}
|
||||
m_groundPlane.Ptr = IntPtr.Zero;
|
||||
|
||||
foreach (KeyValuePair<Vector2, BulletBody> kvp in m_terrains)
|
||||
{
|
||||
if (BulletSimAPI.RemoveObjectFromWorld2(m_physicsScene.World.Ptr, kvp.Value.Ptr))
|
||||
if (BulletSimAPI.RemoveObjectFromWorld2(m_physicsScene.World.Ptr, m_groundPlane.Ptr))
|
||||
{
|
||||
BulletSimAPI.DestroyObject2(m_physicsScene.World.Ptr, kvp.Value.Ptr);
|
||||
BulletSimAPI.ReleaseHeightmapInfo2(m_heightMaps[kvp.Key].Ptr);
|
||||
BulletSimAPI.DestroyObject2(m_physicsScene.World.Ptr, m_groundPlane.Ptr);
|
||||
}
|
||||
m_groundPlane.Ptr = IntPtr.Zero;
|
||||
}
|
||||
|
||||
ReleaseTerrain();
|
||||
}
|
||||
|
||||
// Release all the terrain we have allocated
|
||||
public void ReleaseTerrain()
|
||||
{
|
||||
foreach (KeyValuePair<Vector2, BulletHeightMapInfo> kvp in m_heightMaps)
|
||||
{
|
||||
if (BulletSimAPI.RemoveObjectFromWorld2(m_physicsScene.World.Ptr, kvp.Value.terrainBody.Ptr))
|
||||
{
|
||||
BulletSimAPI.DestroyObject2(m_physicsScene.World.Ptr, kvp.Value.terrainBody.Ptr);
|
||||
BulletSimAPI.ReleaseHeightMapInfo2(kvp.Value.Ptr);
|
||||
}
|
||||
}
|
||||
m_terrains.Clear();
|
||||
m_heightMaps.Clear();
|
||||
}
|
||||
|
||||
// Create a new terrain description. This is used for mega-regions where
|
||||
// the children of region zero give region zero all of the terrain
|
||||
// segments since region zero does all the physics for the mega-region.
|
||||
// Call at taint time!!
|
||||
public void CreateNewTerrainSegment(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords)
|
||||
{
|
||||
// The Z coordinates are recalculated to be the min and max height of the terrain
|
||||
// itself. The caller may have passed us the real region extent.
|
||||
float minZ = float.MaxValue;
|
||||
float maxZ = float.MinValue;
|
||||
int hSize = heightMap.Length;
|
||||
for (int ii = 0; ii < hSize; ii++)
|
||||
{
|
||||
minZ = heightMap[ii] < minZ ? heightMap[ii] : minZ;
|
||||
maxZ = heightMap[ii] > maxZ ? heightMap[ii] : maxZ;
|
||||
}
|
||||
minCoords.Z = minZ;
|
||||
maxCoords.Z = maxZ;
|
||||
// If the terrain is flat, make a difference so we get a good bounding box
|
||||
if (minZ == maxZ)
|
||||
minZ -= 0.2f;
|
||||
Vector2 terrainRegionBase = new Vector2(minCoords.X, minCoords.Y);
|
||||
|
||||
// Create the heightmap data structure in the unmanaged space
|
||||
BulletHeightMapInfo mapInfo = new BulletHeightMapInfo(
|
||||
BulletSimAPI.CreateHeightmap2(minCoords, maxCoords, heightMap), heightMap);
|
||||
mapInfo.terrainRegionBase = terrainRegionBase;
|
||||
mapInfo.maxRegionExtent = maxCoords;
|
||||
mapInfo.minZ = minZ;
|
||||
mapInfo.maxZ = maxZ;
|
||||
mapInfo.sizeX = maxCoords.X - minCoords.X;
|
||||
mapInfo.sizeY = maxCoords.Y - minCoords.Y;
|
||||
|
||||
DetailLog("{0},BSScene.CreateNewTerrainSegment,call,minZ={1},maxZ={2},hMapPtr={3},minC={4},maxC={5}",
|
||||
BSScene.DetailLogZero, minZ, maxZ, mapInfo.Ptr, minCoords, maxCoords);
|
||||
// Create the terrain body from that heightmap
|
||||
BulletBody terrainBody = new BulletBody(id, BulletSimAPI.CreateTerrainBody2(id, mapInfo.Ptr, 0.01f));
|
||||
|
||||
BulletSimAPI.SetFriction2(terrainBody.Ptr, m_physicsScene.Params.terrainFriction);
|
||||
BulletSimAPI.SetHitFraction2(terrainBody.Ptr, m_physicsScene.Params.terrainHitFraction);
|
||||
BulletSimAPI.SetRestitution2(terrainBody.Ptr, m_physicsScene.Params.terrainRestitution);
|
||||
BulletSimAPI.SetCollisionFlags2(terrainBody.Ptr, CollisionFlags.CF_STATIC_OBJECT);
|
||||
BulletSimAPI.Activate2(terrainBody.Ptr, true);
|
||||
|
||||
// Add the new terrain to the dynamics world
|
||||
BulletSimAPI.AddObjectToWorld2(m_physicsScene.World.Ptr, terrainBody.Ptr);
|
||||
BulletSimAPI.UpdateSingleAabb2(m_physicsScene.World.Ptr, terrainBody.Ptr);
|
||||
|
||||
|
||||
// Add the created terrain to the management set. If we are doing mega-regions,
|
||||
// the terrains of our children will be added.
|
||||
m_terrains.Add(terrainRegionBase, terrainBody);
|
||||
m_heightMaps.Add(terrainRegionBase, mapInfo);
|
||||
}
|
||||
|
||||
// The simulator wants to set a new heightmap for the terrain.
|
||||
public void SetTerrain(float[] heightMap) {
|
||||
if (m_worldOffset != Vector3.Zero && m_parentScene != null)
|
||||
{
|
||||
// If a child of a mega-region, we shouldn't have any terrain allocated for us
|
||||
ReleaseGroundPlaneAndTerrain();
|
||||
// If doing the mega-prim stuff and we are the child of the zero region,
|
||||
// the terrain is really added to our parent
|
||||
// the terrain is added to our parent
|
||||
if (m_parentScene is BSScene)
|
||||
{
|
||||
((BSScene)m_parentScene).TerrainManager.SetTerrain(heightMap, m_worldOffset);
|
||||
DetailLog("{0},SetTerrain.ToParent,offset={1},worldMax={2}",
|
||||
BSScene.DetailLogZero, m_worldOffset, m_worldMax);
|
||||
((BSScene)m_parentScene).TerrainManager.UpdateOrCreateTerrain(BSScene.CHILDTERRAIN_ID,
|
||||
heightMap, m_worldOffset, m_worldOffset+DefaultRegionSize, false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// if not doing the mega-prim thing, just change the terrain
|
||||
SetTerrain(heightMap, m_worldOffset);
|
||||
// If not doing the mega-prim thing, just change the terrain
|
||||
DetailLog("{0},SetTerrain.Existing", BSScene.DetailLogZero);
|
||||
|
||||
UpdateOrCreateTerrain(BSScene.TERRAIN_ID, heightMap, m_worldOffset, m_worldOffset+DefaultRegionSize, false);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetTerrain(float[] heightMap, Vector3 tOffset)
|
||||
// If called with no mapInfo for the terrain, this will create a new mapInfo and terrain
|
||||
// based on the passed information. The 'id' should be either the terrain id or
|
||||
// BSScene.CHILDTERRAIN_ID. If the latter, a new child terrain ID will be allocated and used.
|
||||
// The latter feature is for creating child terrains for mega-regions.
|
||||
// If called with a mapInfo in m_heightMaps but the terrain has no body yet (mapInfo.terrainBody.Ptr == 0)
|
||||
// then a new body and shape is created and the mapInfo is filled.
|
||||
// This call is used for doing the initial terrain creation.
|
||||
// If called with a mapInfo in m_heightMaps and there is an existing terrain body, a new
|
||||
// terrain shape is created and added to the body.
|
||||
// This call is most often used to update the heightMap and parameters of the terrain.
|
||||
// The 'doNow' boolean says whether to do all the unmanaged activities right now (like when
|
||||
// calling this routine from initialization or taint-time routines) or whether to delay
|
||||
// all the unmanaged activities to taint-time.
|
||||
private void UpdateOrCreateTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords, bool doNow)
|
||||
{
|
||||
DetailLog("{0},BSTerrainManager.UpdateOrCreateTerrain,call,minC={1},maxC={2},doNow={3}",
|
||||
BSScene.DetailLogZero, minCoords, maxCoords, doNow);
|
||||
|
||||
float minZ = float.MaxValue;
|
||||
float maxZ = float.MinValue;
|
||||
Vector2 terrainRegionBase = new Vector2(minCoords.X, minCoords.Y);
|
||||
|
||||
// Copy heightMap local and compute some statistics.
|
||||
// Not really sure if we need to do this deep copy but, given
|
||||
// the magic that happens to make the closure for taint
|
||||
// below, I don't want there to be any problem with sharing
|
||||
// locations of there are multiple calls to this routine
|
||||
// within one tick.
|
||||
int heightMapSize = heightMap.Length;
|
||||
float[] localHeightMap = new float[heightMapSize];
|
||||
for (int ii = 0; ii < heightMapSize; ii++)
|
||||
{
|
||||
float height = heightMap[ii];
|
||||
if (height < minZ) minZ = height;
|
||||
if (height > maxZ) maxZ = height;
|
||||
localHeightMap[ii] = height;
|
||||
}
|
||||
|
||||
Vector2 terrainRegionBase = new Vector2(tOffset.X, tOffset.Y);
|
||||
// The shape of the terrain is from its base to its extents.
|
||||
minCoords.Z = minZ;
|
||||
maxCoords.Z = maxZ;
|
||||
|
||||
BulletHeightMapInfo mapInfo;
|
||||
if (m_heightMaps.TryGetValue(terrainRegionBase, out mapInfo))
|
||||
{
|
||||
// If this is terrain we know about, it's easy to update
|
||||
mapInfo.heightMap = localHeightMap;
|
||||
m_physicsScene.TaintedObject("BSScene.SetTerrain:UpdateExisting", delegate()
|
||||
|
||||
mapInfo.heightMap = heightMap;
|
||||
mapInfo.minCoords = minCoords;
|
||||
mapInfo.maxCoords = maxCoords;
|
||||
mapInfo.minZ = minZ;
|
||||
mapInfo.maxZ = maxZ;
|
||||
mapInfo.sizeX = maxCoords.X - minCoords.X;
|
||||
mapInfo.sizeY = maxCoords.Y - minCoords.Y;
|
||||
DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,call,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}",
|
||||
BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY);
|
||||
|
||||
BSScene.TaintCallback rebuildOperation = delegate()
|
||||
{
|
||||
DetailLog("{0},SetTerrain:UpdateExisting,baseX={1},baseY={2},minZ={3},maxZ={4}",
|
||||
BSScene.DetailLogZero, tOffset.X, tOffset.Y, minZ, maxZ);
|
||||
BulletSimAPI.UpdateHeightMap2(m_physicsScene.World.Ptr, mapInfo.Ptr, mapInfo.heightMap);
|
||||
});
|
||||
if (m_parentScene != null)
|
||||
{
|
||||
// It's possible that Combine() was called after this code was queued.
|
||||
// If we are a child of combined regions, we don't create any terrain for us.
|
||||
DetailLog("{0},UpdateOrCreateTerrain:AmACombineChild,taint", BSScene.DetailLogZero);
|
||||
|
||||
// Get rid of any terrain that may have been allocated for us.
|
||||
ReleaseGroundPlaneAndTerrain();
|
||||
|
||||
// I hate doing this, but just bail
|
||||
return;
|
||||
}
|
||||
|
||||
if (mapInfo.terrainBody.Ptr != IntPtr.Zero)
|
||||
{
|
||||
// Updating an existing terrain.
|
||||
DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,taint,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}",
|
||||
BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY);
|
||||
|
||||
// Remove from the dynamics world because we're going to mangle this object
|
||||
BulletSimAPI.RemoveObjectFromWorld2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr);
|
||||
|
||||
// Get rid of the old terrain
|
||||
BulletSimAPI.DestroyObject2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr);
|
||||
BulletSimAPI.ReleaseHeightMapInfo2(mapInfo.Ptr);
|
||||
mapInfo.Ptr = IntPtr.Zero;
|
||||
|
||||
/*
|
||||
// NOTE: This routine is half here because I can't get the terrain shape replacement
|
||||
// to work. In the short term, the above three lines completely delete the old
|
||||
// terrain and the code below recreates one from scratch.
|
||||
// Hopefully the Bullet community will help me out on this one.
|
||||
|
||||
// First, release the old collision shape (there is only one terrain)
|
||||
BulletSimAPI.DeleteCollisionShape2(m_physicsScene.World.Ptr, mapInfo.terrainShape.Ptr);
|
||||
|
||||
// Fill the existing height map info with the new location and size information
|
||||
BulletSimAPI.FillHeightMapInfo2(m_physicsScene.World.Ptr, mapInfo.Ptr, mapInfo.ID,
|
||||
mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN);
|
||||
|
||||
// Create a terrain shape based on the new info
|
||||
mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr));
|
||||
|
||||
// Stuff the shape into the existing terrain body
|
||||
BulletSimAPI.SetBodyShape2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr, mapInfo.terrainShape.Ptr);
|
||||
*/
|
||||
}
|
||||
// else
|
||||
{
|
||||
// Creating a new terrain.
|
||||
DetailLog("{0},UpdateOrCreateTerrain:CreateNewTerrain,taint,baseX={1},baseY={2},minZ={3},maxZ={4}",
|
||||
BSScene.DetailLogZero, mapInfo.minCoords.X, mapInfo.minCoords.Y, minZ, maxZ);
|
||||
|
||||
mapInfo.ID = id;
|
||||
mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(m_physicsScene.World.Ptr, mapInfo.ID,
|
||||
mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN);
|
||||
|
||||
// The terrain object initial position is at the center of the object
|
||||
Vector3 centerPos;
|
||||
centerPos.X = minCoords.X + (mapInfo.sizeX / 2f);
|
||||
centerPos.Y = minCoords.Y + (mapInfo.sizeY / 2f);
|
||||
centerPos.Z = minZ + ((maxZ - minZ) / 2f);
|
||||
|
||||
// Create the terrain shape from the mapInfo
|
||||
mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr));
|
||||
|
||||
mapInfo.terrainBody = new BulletBody(mapInfo.ID,
|
||||
BulletSimAPI.CreateBodyWithDefaultMotionState2(mapInfo.terrainShape.Ptr,
|
||||
centerPos, Quaternion.Identity));
|
||||
}
|
||||
|
||||
// Make sure the entry is in the heightmap table
|
||||
m_heightMaps[terrainRegionBase] = mapInfo;
|
||||
|
||||
// Set current terrain attributes
|
||||
BulletSimAPI.SetFriction2(mapInfo.terrainBody.Ptr, m_physicsScene.Params.terrainFriction);
|
||||
BulletSimAPI.SetHitFraction2(mapInfo.terrainBody.Ptr, m_physicsScene.Params.terrainHitFraction);
|
||||
BulletSimAPI.SetRestitution2(mapInfo.terrainBody.Ptr, m_physicsScene.Params.terrainRestitution);
|
||||
BulletSimAPI.SetCollisionFlags2(mapInfo.terrainBody.Ptr, CollisionFlags.CF_STATIC_OBJECT);
|
||||
|
||||
BulletSimAPI.SetMassProps2(mapInfo.terrainBody.Ptr, 0f, Vector3.Zero);
|
||||
BulletSimAPI.UpdateInertiaTensor2(mapInfo.terrainBody.Ptr);
|
||||
|
||||
// Return the new terrain to the world of physical objects
|
||||
BulletSimAPI.AddObjectToWorld2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr);
|
||||
|
||||
// redo its bounding box now that it is in the world
|
||||
BulletSimAPI.UpdateSingleAabb2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr);
|
||||
|
||||
// Make sure the new shape is processed.
|
||||
BulletSimAPI.Activate2(mapInfo.terrainBody.Ptr, true);
|
||||
};
|
||||
|
||||
// There is the option to do the changes now (we're already in 'taint time'), or
|
||||
// to do the Bullet operations later.
|
||||
if (doNow)
|
||||
rebuildOperation();
|
||||
else
|
||||
m_physicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:UpdateExisting", rebuildOperation);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Our mega-prim child is giving us a new terrain to add to the phys world
|
||||
uint newTerrainID = ++m_terrainCount;
|
||||
// We don't know about this terrain so either we are creating a new terrain or
|
||||
// our mega-prim child is giving us a new terrain to add to the phys world
|
||||
|
||||
Vector3 minCoords = tOffset;
|
||||
minCoords.Z = minZ;
|
||||
Vector3 maxCoords = new Vector3(tOffset.X + Constants.RegionSize,
|
||||
tOffset.Y + Constants.RegionSize,
|
||||
maxZ);
|
||||
m_physicsScene.TaintedObject("BSScene.SetTerrain:NewTerrain", delegate()
|
||||
// if this is a child terrain, calculate a unique terrain id
|
||||
uint newTerrainID = id;
|
||||
if (newTerrainID >= BSScene.CHILDTERRAIN_ID)
|
||||
newTerrainID = ++m_terrainCount;
|
||||
|
||||
float[] heightMapX = heightMap;
|
||||
Vector3 minCoordsX = minCoords;
|
||||
Vector3 maxCoordsX = maxCoords;
|
||||
|
||||
DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,call,id={1}, minC={2}, maxC={3}",
|
||||
BSScene.DetailLogZero, newTerrainID, minCoords, minCoords);
|
||||
|
||||
// Code that must happen at taint-time
|
||||
BSScene.TaintCallback createOperation = delegate()
|
||||
{
|
||||
DetailLog("{0},SetTerrain:NewTerrain,baseX={1},baseY={2}", BSScene.DetailLogZero, tOffset.X, tOffset.Y);
|
||||
CreateNewTerrainSegment(newTerrainID, heightMap, minCoords, maxCoords);
|
||||
});
|
||||
DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,taint,baseX={1},baseY={2}", BSScene.DetailLogZero, minCoords.X, minCoords.Y);
|
||||
// Create a new mapInfo that will be filled with the new info
|
||||
mapInfo = new BulletHeightMapInfo(id, heightMapX,
|
||||
BulletSimAPI.CreateHeightMapInfo2(m_physicsScene.World.Ptr, newTerrainID,
|
||||
minCoordsX, maxCoordsX, heightMapX, TERRAIN_COLLISION_MARGIN));
|
||||
// Put the unfilled heightmap info into the collection of same
|
||||
m_heightMaps.Add(terrainRegionBase, mapInfo);
|
||||
// Build the terrain
|
||||
UpdateOrCreateTerrain(newTerrainID, heightMap, minCoords, maxCoords, true);
|
||||
};
|
||||
|
||||
// If already in taint-time, just call Bullet. Otherwise queue the operations for the safe time.
|
||||
if (doNow)
|
||||
createOperation();
|
||||
else
|
||||
m_physicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:NewTerrain", createOperation);
|
||||
}
|
||||
}
|
||||
|
||||
// Someday we will have complex terrain with caves and tunnels
|
||||
// For the moment, it's flat and convex
|
||||
public float GetTerrainHeightAtXYZ(Vector3 loc)
|
||||
{
|
||||
// For the moment, it's flat and convex
|
||||
return GetTerrainHeightAtXY(loc.X, loc.Y);
|
||||
}
|
||||
|
||||
@@ -252,12 +380,22 @@ public class BSTerrainManager
|
||||
// the same size and that is the default.
|
||||
// Once the heightMapInfo is found, we have all the information to
|
||||
// compute the offset into the array.
|
||||
private float lastHeightTX = 999999f;
|
||||
private float lastHeightTY = 999999f;
|
||||
private float lastHeight = HEIGHT_INITIAL_LASTHEIGHT;
|
||||
public float GetTerrainHeightAtXY(float tX, float tY)
|
||||
{
|
||||
float ret = 30f;
|
||||
// You'd be surprized at the number of times this routine is called
|
||||
// with the same parameters as last time.
|
||||
if (!m_terrainModified && lastHeightTX == tX && lastHeightTY == tY)
|
||||
return lastHeight;
|
||||
|
||||
int offsetX = ((int)(tX / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
|
||||
int offsetY = ((int)(tY / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
|
||||
lastHeightTX = tX;
|
||||
lastHeightTY = tY;
|
||||
float ret = HEIGHT_GETHEIGHT_RET;
|
||||
|
||||
int offsetX = ((int)(tX / (int)DefaultRegionSize.X)) * (int)DefaultRegionSize.X;
|
||||
int offsetY = ((int)(tY / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y;
|
||||
Vector2 terrainBaseXY = new Vector2(offsetX, offsetY);
|
||||
|
||||
BulletHeightMapInfo mapInfo;
|
||||
@@ -265,15 +403,20 @@ public class BSTerrainManager
|
||||
{
|
||||
float regionX = tX - offsetX;
|
||||
float regionY = tY - offsetY;
|
||||
regionX = regionX > mapInfo.sizeX ? 0 : regionX;
|
||||
regionY = regionY > mapInfo.sizeY ? 0 : regionY;
|
||||
ret = mapInfo.heightMap[(int)(regionX * mapInfo.sizeX + regionY)];
|
||||
if (regionX > mapInfo.sizeX) regionX = 0;
|
||||
if (regionY > mapInfo.sizeY) regionY = 0;
|
||||
int mapIndex = (int)regionY * (int)mapInfo.sizeY + (int)regionX;
|
||||
ret = mapInfo.heightMap[mapIndex];
|
||||
m_terrainModified = false;
|
||||
DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXY,bX={1},baseY={2},szX={3},szY={4},regX={5},regY={6},index={7},ht={8}",
|
||||
BSScene.DetailLogZero, offsetX, offsetY, mapInfo.sizeX, mapInfo.sizeY, regionX, regionY, mapIndex, ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_physicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: x={1}, y={2}",
|
||||
LogHeader, tX, tY);
|
||||
m_physicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}",
|
||||
LogHeader, m_physicsScene.RegionName, tX, tY);
|
||||
}
|
||||
lastHeight = ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -282,20 +425,34 @@ public class BSTerrainManager
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// This call says I am a child to region zero in a mega-region. 'pScene' is that
|
||||
// of region zero, 'offset' is my offset from regions zero's origin, and
|
||||
// 'extents' is the largest XY that is handled in my region.
|
||||
|
||||
// This routine is called two ways:
|
||||
// One with 'offset' and 'pScene' zero and null but 'extents' giving the maximum
|
||||
// extent of the combined regions. This is to inform the parent of the size
|
||||
// of the combined regions.
|
||||
// and one with 'offset' as the offset of the child region to the base region,
|
||||
// 'pScene' pointing to the parent and 'extents' of zero. This informs the
|
||||
// child of its relative base and new parent.
|
||||
public void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents)
|
||||
{
|
||||
m_worldOffset = offset;
|
||||
WorldExtents = new Vector2(extents.X, extents.Y);
|
||||
m_worldMax = extents;
|
||||
m_parentScene = pScene;
|
||||
if (pScene != null)
|
||||
{
|
||||
// We are a child.
|
||||
// We want m_worldMax to be the highest coordinate of our piece of terrain.
|
||||
m_worldMax = offset + DefaultRegionSize;
|
||||
}
|
||||
DetailLog("{0},BSTerrainManager.Combine,offset={1},extents={2},wOffset={3},wMax={4}",
|
||||
BSScene.DetailLogZero, offset, extents, m_worldOffset, m_worldMax);
|
||||
}
|
||||
|
||||
// Unhook all the combining that I know about.
|
||||
public void UnCombine(PhysicsScene pScene)
|
||||
{
|
||||
// Just like ODE, for the moment a NOP
|
||||
DetailLog("{0},BSTerrainManager.UnCombine", BSScene.DetailLogZero);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -38,13 +38,19 @@ namespace OpenSim.Region.Physics.BulletSPlugin {
|
||||
// The physics engine controller class created at initialization
|
||||
public struct BulletSim
|
||||
{
|
||||
public BulletSim(uint id, BSScene bss, IntPtr xx) { ID = id; scene = bss; Ptr = xx; }
|
||||
public uint ID;
|
||||
public BulletSim(uint worldId, BSScene bss, IntPtr xx) { worldID = worldId; scene = bss; Ptr = xx; }
|
||||
public uint worldID;
|
||||
// The scene is only in here so very low level routines have a handle to print debug/error messages
|
||||
public BSScene scene;
|
||||
public IntPtr Ptr;
|
||||
}
|
||||
|
||||
public struct BulletShape
|
||||
{
|
||||
public BulletShape(IntPtr xx) { Ptr = xx; }
|
||||
public IntPtr Ptr;
|
||||
}
|
||||
|
||||
// An allocated Bullet btRigidBody
|
||||
public struct BulletBody
|
||||
{
|
||||
@@ -66,20 +72,26 @@ public struct BulletConstraint
|
||||
// than making copies.
|
||||
public class BulletHeightMapInfo
|
||||
{
|
||||
public BulletHeightMapInfo(IntPtr xx, float[] hm) {
|
||||
public BulletHeightMapInfo(uint id, float[] hm, IntPtr xx) {
|
||||
ID = id;
|
||||
Ptr = xx;
|
||||
heightMap = hm;
|
||||
terrainRegionBase = new Vector2(0f, 0f);
|
||||
maxRegionExtent = new Vector3(100f, 100f, 25f);
|
||||
minCoords = new Vector3(100f, 100f, 25f);
|
||||
maxCoords = new Vector3(101f, 101f, 26f);
|
||||
minZ = maxZ = 0f;
|
||||
sizeX = sizeY = 256f;
|
||||
}
|
||||
public uint ID;
|
||||
public IntPtr Ptr;
|
||||
public float[] heightMap;
|
||||
public Vector2 terrainRegionBase;
|
||||
public Vector3 maxRegionExtent;
|
||||
public Vector3 minCoords;
|
||||
public Vector3 maxCoords;
|
||||
public float sizeX, sizeY;
|
||||
public float minZ, maxZ;
|
||||
public BulletShape terrainShape;
|
||||
public BulletBody terrainBody;
|
||||
}
|
||||
|
||||
// ===============================================================================
|
||||
@@ -248,6 +260,10 @@ public enum ConstraintParamAxis : int
|
||||
// ===============================================================================
|
||||
static class BulletSimAPI {
|
||||
|
||||
// Link back to the managed code for outputting log messages
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
[return: MarshalAs(UnmanagedType.LPStr)]
|
||||
public static extern string GetVersion();
|
||||
@@ -255,7 +271,8 @@ public static extern string GetVersion();
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern uint Initialize(Vector3 maxPosition, IntPtr parms,
|
||||
int maxCollisions, IntPtr collisionArray,
|
||||
int maxUpdates, IntPtr updateArray);
|
||||
int maxUpdates, IntPtr updateArray,
|
||||
DebugLogCallback logRoutine);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void CreateInitialGroundPlaneAndTerrain(uint worldID);
|
||||
@@ -372,8 +389,6 @@ public static extern Vector3 RecoverFromPenetration(uint worldID, uint id);
|
||||
public static extern void DumpBulletStatistics();
|
||||
|
||||
// Log a debug message
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg);
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void SetDebugLogCallback(DebugLogCallback callback);
|
||||
|
||||
@@ -407,7 +422,7 @@ public static extern IntPtr Initialize2(Vector3 maxPosition, IntPtr parms,
|
||||
public static extern bool UpdateParameter2(IntPtr world, uint localID, String parm, float value);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void SetHeightmap2(IntPtr world, float[] heightmap);
|
||||
public static extern void SetHeightMap2(IntPtr world, float[] heightmap);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void Shutdown2(IntPtr sim);
|
||||
@@ -442,25 +457,31 @@ public static extern IntPtr BuildNativeShape2(IntPtr world,
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool DeleteCollisionShape2(IntPtr world, IntPtr shape);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr CreateBodyFromShape2(IntPtr sim, IntPtr shape, Vector3 pos, Quaternion rot);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr CreateBodyWithDefaultMotionState2(IntPtr shape, Vector3 pos, Quaternion rot);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool SetBodyShape2(IntPtr sim, IntPtr obj, IntPtr shape);
|
||||
// =====================================================================================
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr CreateGroundPlaneBody2(uint id, float height, float collisionMargin);
|
||||
public static extern IntPtr CreateHeightMapInfo2(IntPtr sim, uint id, Vector3 minCoords, Vector3 maxCoords,
|
||||
[MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr CreateTerrainBody2(uint id,
|
||||
IntPtr heightMapInfo,
|
||||
float collisionMargin);
|
||||
public static extern IntPtr FillHeightMapInfo2(IntPtr sim, IntPtr mapInfo, uint id, Vector3 minCoords, Vector3 maxCoords,
|
||||
[MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr CreateHeightmap2(Vector3 minCoords, Vector3 maxCoords,
|
||||
[MarshalAs(UnmanagedType.LPArray)] float[] heightMap);
|
||||
public static extern bool ReleaseHeightMapInfo2(IntPtr heightMapInfo);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool ReleaseHeightmapInfo2(IntPtr heightMapInfo);
|
||||
public static extern IntPtr CreateGroundPlaneShape2(uint id, float height, float collisionMargin);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void UpdateHeightMap2(IntPtr world, IntPtr heightMapInfo,
|
||||
[MarshalAs(UnmanagedType.LPArray)] float[] heightMap);
|
||||
public static extern IntPtr CreateTerrainShape2(IntPtr mapInfo);
|
||||
|
||||
// =====================================================================================
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
|
||||
@@ -310,7 +310,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
// ---------- Integer ----------
|
||||
else if (lslparm is LSL_Integer)
|
||||
{
|
||||
if (type == typeof(int))
|
||||
if (type == typeof(int) || type == typeof(float))
|
||||
return (int)(LSL_Integer)lslparm;
|
||||
}
|
||||
|
||||
|
||||
@@ -1673,6 +1673,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
return;
|
||||
}
|
||||
|
||||
MessageObject(objUUID, message);
|
||||
}
|
||||
|
||||
private void MessageObject(UUID objUUID, string message)
|
||||
{
|
||||
object[] resobj = new object[] { new LSL_Types.LSLString(m_host.UUID.ToString()), new LSL_Types.LSLString(message) };
|
||||
|
||||
SceneObjectPart sceneOP = World.GetSceneObjectPart(objUUID);
|
||||
@@ -3224,6 +3229,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
}
|
||||
}
|
||||
|
||||
#region Attachment commands
|
||||
|
||||
public void osForceAttachToAvatar(int attachmentPoint)
|
||||
{
|
||||
CheckThreatLevel(ThreatLevel.High, "osForceAttachToAvatar");
|
||||
@@ -3313,6 +3320,175 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
((LSL_Api)m_LSL_Api).DetachFromAvatar();
|
||||
}
|
||||
|
||||
public LSL_List osGetNumberOfAttachments(LSL_Key avatar, LSL_List attachmentPoints)
|
||||
{
|
||||
CheckThreatLevel(ThreatLevel.Moderate, "osGetNumberOfAttachments");
|
||||
|
||||
m_host.AddScriptLPS(1);
|
||||
|
||||
UUID targetUUID;
|
||||
ScenePresence target;
|
||||
LSL_List resp = new LSL_List();
|
||||
|
||||
if (attachmentPoints.Length >= 1 && UUID.TryParse(avatar.ToString(), out targetUUID) && World.TryGetScenePresence(targetUUID, out target))
|
||||
{
|
||||
foreach (object point in attachmentPoints.Data)
|
||||
{
|
||||
LSL_Integer ipoint = new LSL_Integer(
|
||||
(point is LSL_Integer || point is int || point is uint) ?
|
||||
(int)point :
|
||||
0
|
||||
);
|
||||
resp.Add(ipoint);
|
||||
if (ipoint == 0)
|
||||
{
|
||||
// indicates zero attachments
|
||||
resp.Add(new LSL_Integer(0));
|
||||
}
|
||||
else
|
||||
{
|
||||
// gets the number of attachments on the attachment point
|
||||
resp.Add(new LSL_Integer(target.GetAttachments((uint)ipoint).Count));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return resp;
|
||||
}
|
||||
|
||||
public void osMessageAttachments(LSL_Key avatar, string message, LSL_List attachmentPoints, int options)
|
||||
{
|
||||
CheckThreatLevel(ThreatLevel.Moderate, "osMessageAttachments");
|
||||
m_host.AddScriptLPS(1);
|
||||
|
||||
UUID targetUUID;
|
||||
ScenePresence target;
|
||||
|
||||
if (attachmentPoints.Length >= 1 && UUID.TryParse(avatar.ToString(), out targetUUID) && World.TryGetScenePresence(targetUUID, out target))
|
||||
{
|
||||
List<int> aps = new List<int>();
|
||||
foreach (object point in attachmentPoints.Data)
|
||||
{
|
||||
int ipoint;
|
||||
if (int.TryParse(point.ToString(), out ipoint))
|
||||
{
|
||||
aps.Add(ipoint);
|
||||
}
|
||||
}
|
||||
|
||||
List<SceneObjectGroup> attachments = new List<SceneObjectGroup>();
|
||||
|
||||
bool msgAll = aps.Contains(ScriptBaseClass.OS_ATTACH_MSG_ALL);
|
||||
bool invertPoints = (options & ScriptBaseClass.OS_ATTACH_MSG_INVERT_POINTS) != 0;
|
||||
|
||||
if (msgAll && invertPoints)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (msgAll || invertPoints)
|
||||
{
|
||||
attachments = target.GetAttachments();
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (int point in aps)
|
||||
{
|
||||
if (point > 0)
|
||||
{
|
||||
attachments.AddRange(target.GetAttachments((uint)point));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if we have no attachments at this point, exit now
|
||||
if (attachments.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
List<SceneObjectGroup> ignoreThese = new List<SceneObjectGroup>();
|
||||
|
||||
if (invertPoints)
|
||||
{
|
||||
foreach (SceneObjectGroup attachment in attachments)
|
||||
{
|
||||
if (aps.Contains((int)attachment.AttachmentPoint))
|
||||
{
|
||||
ignoreThese.Add(attachment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (SceneObjectGroup attachment in ignoreThese)
|
||||
{
|
||||
attachments.Remove(attachment);
|
||||
}
|
||||
ignoreThese.Clear();
|
||||
|
||||
// if inverting removed all attachments to check, exit now
|
||||
if (attachments.Count < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ((options & ScriptBaseClass.OS_ATTACH_MSG_OBJECT_CREATOR) != 0)
|
||||
{
|
||||
foreach (SceneObjectGroup attachment in attachments)
|
||||
{
|
||||
if (attachment.RootPart.CreatorID != m_host.CreatorID)
|
||||
{
|
||||
ignoreThese.Add(attachment);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (SceneObjectGroup attachment in ignoreThese)
|
||||
{
|
||||
attachments.Remove(attachment);
|
||||
}
|
||||
ignoreThese.Clear();
|
||||
|
||||
// if filtering by same object creator removed all
|
||||
// attachments to check, exit now
|
||||
if (attachments.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ((options & ScriptBaseClass.OS_ATTACH_MSG_SCRIPT_CREATOR) != 0)
|
||||
{
|
||||
foreach (SceneObjectGroup attachment in attachments)
|
||||
{
|
||||
if (attachment.RootPart.CreatorID != m_item.CreatorID)
|
||||
{
|
||||
ignoreThese.Add(attachment);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (SceneObjectGroup attachment in ignoreThese)
|
||||
{
|
||||
attachments.Remove(attachment);
|
||||
}
|
||||
ignoreThese.Clear();
|
||||
|
||||
// if filtering by object creator must match originating
|
||||
// script creator removed all attachments to check,
|
||||
// exit now
|
||||
if (attachments.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (SceneObjectGroup attachment in attachments)
|
||||
{
|
||||
MessageObject(attachment.RootPart.UUID, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Checks if thing is a UUID.
|
||||
/// </summary>
|
||||
|
||||
@@ -157,7 +157,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
|
||||
void osAvatarPlayAnimation(string avatar, string animation);
|
||||
void osAvatarStopAnimation(string avatar, string animation);
|
||||
|
||||
// Attachment commands
|
||||
#region Attachment commands
|
||||
|
||||
/// <summary>
|
||||
/// Attach the object containing this script to the avatar that owns it without asking for PERMISSION_ATTACH
|
||||
@@ -192,6 +192,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
|
||||
/// <remarks>Nothing happens if the object is not attached.</remarks>
|
||||
void osForceDetachFromAvatar();
|
||||
|
||||
/// <summary>
|
||||
/// Returns a strided list of the specified attachment points and the number of attachments on those points.
|
||||
/// </summary>
|
||||
/// <param name="avatar">avatar UUID</param>
|
||||
/// <param name="attachmentPoints">list of ATTACH_* constants</param>
|
||||
/// <returns></returns>
|
||||
LSL_List osGetNumberOfAttachments(LSL_Key avatar, LSL_List attachmentPoints);
|
||||
|
||||
/// <summary>
|
||||
/// Sends a specified message to the specified avatar's attachments on
|
||||
/// the specified attachment points.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Behaves as osMessageObject(), without the sending script needing to know the attachment keys in advance.
|
||||
/// </remarks>
|
||||
/// <param name="avatar">avatar UUID</param>
|
||||
/// <param name="message">message string</param>
|
||||
/// <param name="attachmentPoints">list of ATTACH_* constants, or -1 for all attachments. If -1 is specified and OS_ATTACH_MSG_INVERT_POINTS is present in flags, no action is taken.</param>
|
||||
/// <param name="flags">flags further constraining the attachments to deliver the message to.</param>
|
||||
void osMessageAttachments(LSL_Key avatar, string message, LSL_List attachmentPoints, int flags);
|
||||
|
||||
#endregion
|
||||
|
||||
//texture draw functions
|
||||
string osMovePen(string drawList, int x, int y);
|
||||
string osDrawLine(string drawList, int startX, int startY, int endX, int endY);
|
||||
|
||||
@@ -237,6 +237,58 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
|
||||
public const int ATTACH_HUD_BOTTOM = 37;
|
||||
public const int ATTACH_HUD_BOTTOM_RIGHT = 38;
|
||||
|
||||
#region osMessageAttachments constants
|
||||
|
||||
/// <summary>
|
||||
/// Instructs osMessageAttachements to send the message to attachments
|
||||
/// on every point.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// One might expect this to be named OS_ATTACH_ALL, but then one might
|
||||
/// also expect functions designed to attach or detach or get
|
||||
/// attachments to work with it too. Attaching a no-copy item to
|
||||
/// many attachments could be dangerous.
|
||||
/// when combined with OS_ATTACH_MSG_INVERT_POINTS, will prevent the
|
||||
/// message from being sent.
|
||||
/// if combined with OS_ATTACH_MSG_OBJECT_CREATOR or
|
||||
/// OS_ATTACH_MSG_SCRIPT_CREATOR, could result in no message being
|
||||
/// sent- this is expected behaviour.
|
||||
/// </remarks>
|
||||
public const int OS_ATTACH_MSG_ALL = -65535;
|
||||
|
||||
/// <summary>
|
||||
/// Instructs osMessageAttachements to invert how the attachment points
|
||||
/// list should be treated (e.g. go from inclusive operation to
|
||||
/// exclusive operation).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This might be used if you want to deliver a message to one set of
|
||||
/// attachments and a different message to everything else. With
|
||||
/// this flag, you only need to build one explicit list for both calls.
|
||||
/// </remarks>
|
||||
public const int OS_ATTACH_MSG_INVERT_POINTS = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Instructs osMessageAttachments to only send the message to
|
||||
/// attachments with a CreatorID that matches the host object CreatorID
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This would be used if distributed in an object vendor/updater server.
|
||||
/// </remarks>
|
||||
public const int OS_ATTACH_MSG_OBJECT_CREATOR = 2;
|
||||
|
||||
/// <summary>
|
||||
/// Instructs osMessageAttachments to only send the message to
|
||||
/// attachments with a CreatorID that matches the sending script CreatorID
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This might be used if the script is distributed independently of a
|
||||
/// containing object.
|
||||
/// </remarks>
|
||||
public const int OS_ATTACH_MSG_SCRIPT_CREATOR = 4;
|
||||
|
||||
#endregion
|
||||
|
||||
public const int LAND_LEVEL = 0;
|
||||
public const int LAND_RAISE = 1;
|
||||
public const int LAND_LOWER = 2;
|
||||
|
||||
@@ -289,7 +289,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
|
||||
m_OSSL_Functions.osAvatarStopAnimation(avatar, animation);
|
||||
}
|
||||
|
||||
// Avatar functions
|
||||
#region Attachment commands
|
||||
|
||||
public void osForceAttachToAvatar(int attachmentPoint)
|
||||
{
|
||||
@@ -311,6 +311,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
|
||||
m_OSSL_Functions.osForceDetachFromAvatar();
|
||||
}
|
||||
|
||||
public LSL_List osGetNumberOfAttachments(LSL_Key avatar, LSL_List attachmentPoints)
|
||||
{
|
||||
return m_OSSL_Functions.osGetNumberOfAttachments(avatar, attachmentPoints);
|
||||
}
|
||||
|
||||
public void osMessageAttachments(LSL_Key avatar, string message, LSL_List attachmentPoints, int flags)
|
||||
{
|
||||
m_OSSL_Functions.osMessageAttachments(avatar, message, attachmentPoints, flags);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// Texture Draw functions
|
||||
|
||||
public string osMovePen(string drawList, int x, int y)
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user