* Fixed a typo in OpenMetaverse.ObjectManager
* Improved BuildFullUpdate in Simian * Added ObjectManager in Simian, prim creation is working (no editing yet) git-svn-id: http://libopenmetaverse.googlecode.com/svn/trunk@2162 52acb1d6-8a22-11de-b505-999d5b087335
This commit is contained in:
287
Programs/Simian/Extensions/ObjectManager.cs
Normal file
287
Programs/Simian/Extensions/ObjectManager.cs
Normal file
@@ -0,0 +1,287 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.Rendering;
|
||||
using OpenMetaverse.Packets;
|
||||
|
||||
namespace Simian.Extensions
|
||||
{
|
||||
public class ObjectManager : ISimianExtension
|
||||
{
|
||||
Simian Server;
|
||||
InternalDictionary<uint, SimulationObject> SceneObjects = new InternalDictionary<uint, SimulationObject>();
|
||||
InternalDictionary<UUID, SimulationObject> SceneObjectsByID = new InternalDictionary<UUID,SimulationObject>();
|
||||
int CurrentLocalID = 0;
|
||||
|
||||
public ObjectManager(Simian server)
|
||||
{
|
||||
Server = server;
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
Server.UDPServer.RegisterPacketCallback(PacketType.ObjectAdd, new UDPServer.PacketCallback(ObjectAddHandler));
|
||||
Server.UDPServer.RegisterPacketCallback(PacketType.ObjectSelect, new UDPServer.PacketCallback(ObjectSelectHandler));
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
}
|
||||
|
||||
void ObjectAddHandler(Packet packet, Agent agent)
|
||||
{
|
||||
ObjectAddPacket add = (ObjectAddPacket)packet;
|
||||
|
||||
Vector3 position = Vector3.Zero;
|
||||
Vector3 scale = add.ObjectData.Scale;
|
||||
PCode pcode = (PCode)add.ObjectData.PCode;
|
||||
PrimFlags flags = (PrimFlags)add.ObjectData.AddFlags;
|
||||
bool bypassRaycast = (add.ObjectData.BypassRaycast == 1);
|
||||
bool rayEndIsIntersection = (add.ObjectData.RayEndIsIntersection == 1);
|
||||
|
||||
#region Position Calculation
|
||||
|
||||
if (rayEndIsIntersection)
|
||||
{
|
||||
// HACK: Blindly trust where the client tells us to place
|
||||
position = add.ObjectData.RayEnd;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (add.ObjectData.RayTargetID != UUID.Zero)
|
||||
{
|
||||
SimulationObject obj;
|
||||
if (SceneObjectsByID.TryGetValue(add.ObjectData.RayTargetID, out obj))
|
||||
{
|
||||
// Test for a collision with the specified object
|
||||
position = ObjectCollisionTest(add.ObjectData.RayStart, add.ObjectData.RayEnd, obj);
|
||||
}
|
||||
}
|
||||
|
||||
if (position == Vector3.Zero)
|
||||
{
|
||||
// Test for a collision with the entire scene
|
||||
position = FullSceneCollisionTest(add.ObjectData.RayStart, add.ObjectData.RayEnd);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Position Calculation
|
||||
|
||||
#region Foliage Handling
|
||||
|
||||
// Set all foliage to phantom
|
||||
if (pcode == PCode.Grass || pcode == PCode.Tree || pcode == PCode.NewTree)
|
||||
{
|
||||
flags |= PrimFlags.Phantom;
|
||||
|
||||
if (pcode != PCode.Grass)
|
||||
{
|
||||
// Resize based on the foliage type
|
||||
Tree tree = (Tree)add.ObjectData.State;
|
||||
|
||||
switch (tree)
|
||||
{
|
||||
case Tree.Cypress1:
|
||||
case Tree.Cypress2:
|
||||
scale = new Vector3(4f, 4f, 10f);
|
||||
break;
|
||||
default:
|
||||
scale = new Vector3(4f, 4f, 4f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Foliage Handling
|
||||
|
||||
// Create an object
|
||||
Primitive prim = new Primitive();
|
||||
prim.Flags =
|
||||
PrimFlags.ObjectModify |
|
||||
PrimFlags.ObjectCopy |
|
||||
PrimFlags.ObjectAnyOwner |
|
||||
PrimFlags.ObjectMove |
|
||||
PrimFlags.ObjectTransfer |
|
||||
PrimFlags.ObjectOwnerModify;
|
||||
// TODO: Security check
|
||||
prim.GroupID = add.AgentData.GroupID;
|
||||
prim.ID = UUID.Random();
|
||||
prim.LocalID = (uint)Interlocked.Increment(ref CurrentLocalID);
|
||||
prim.MediaURL = String.Empty;
|
||||
prim.OwnerID = agent.AgentID;
|
||||
prim.Position = position;
|
||||
|
||||
prim.PrimData.Material = (Material)add.ObjectData.Material;
|
||||
prim.PrimData.PathCurve = (PathCurve)add.ObjectData.PathCurve;
|
||||
prim.PrimData.ProfileCurve = (ProfileCurve)add.ObjectData.ProfileCurve;
|
||||
prim.PrimData.PathBegin = Primitive.UnpackBeginCut(add.ObjectData.PathBegin);
|
||||
prim.PrimData.PathEnd = Primitive.UnpackEndCut(add.ObjectData.PathEnd);
|
||||
prim.PrimData.PathScaleX = Primitive.UnpackPathScale(add.ObjectData.PathScaleX);
|
||||
prim.PrimData.PathScaleY = Primitive.UnpackPathScale(add.ObjectData.PathScaleY);
|
||||
prim.PrimData.PathShearX = Primitive.UnpackPathShear((sbyte)add.ObjectData.PathShearX);
|
||||
prim.PrimData.PathShearY = Primitive.UnpackPathShear((sbyte)add.ObjectData.PathShearY);
|
||||
prim.PrimData.PathTwist = Primitive.UnpackPathTwist(add.ObjectData.PathTwist);
|
||||
prim.PrimData.PathTwistBegin = Primitive.UnpackPathTwist(add.ObjectData.PathTwistBegin);
|
||||
prim.PrimData.PathRadiusOffset = Primitive.UnpackPathTwist(add.ObjectData.PathRadiusOffset);
|
||||
prim.PrimData.PathTaperX = Primitive.UnpackPathTaper(add.ObjectData.PathTaperX);
|
||||
prim.PrimData.PathTaperY = Primitive.UnpackPathTaper(add.ObjectData.PathTaperY);
|
||||
prim.PrimData.PathRevolutions = Primitive.UnpackPathRevolutions(add.ObjectData.PathRevolutions);
|
||||
prim.PrimData.PathSkew = Primitive.UnpackPathTwist(add.ObjectData.PathSkew);
|
||||
prim.PrimData.ProfileBegin = Primitive.UnpackBeginCut(add.ObjectData.ProfileBegin);
|
||||
prim.PrimData.ProfileEnd = Primitive.UnpackEndCut(add.ObjectData.ProfileEnd);
|
||||
prim.PrimData.ProfileHollow = Primitive.UnpackProfileHollow(add.ObjectData.ProfileHollow);
|
||||
prim.PrimData.PCode = pcode;
|
||||
|
||||
prim.Properties.CreationDate = DateTime.Now;
|
||||
prim.Properties.CreatorID = agent.AgentID;
|
||||
prim.Properties.Description = String.Empty;
|
||||
prim.Properties.GroupID = add.AgentData.GroupID;
|
||||
prim.Properties.LastOwnerID = agent.AgentID;
|
||||
prim.Properties.Name = "New Object";
|
||||
prim.Properties.ObjectID = prim.ID;
|
||||
prim.Properties.OwnerID = prim.OwnerID;
|
||||
prim.Properties.Permissions = Permissions.FullPermissions;
|
||||
prim.Properties.SalePrice = 10;
|
||||
|
||||
prim.RegionHandle = Server.RegionHandle;
|
||||
prim.Rotation = add.ObjectData.Rotation;
|
||||
prim.Scale = scale;
|
||||
prim.Textures = new Primitive.TextureEntry(Primitive.TextureEntry.WHITE_TEXTURE);
|
||||
prim.TextColor = Color4.Black;
|
||||
|
||||
// Add this prim to the object database
|
||||
SimulationObject simObj = new SimulationObject(prim, Server);
|
||||
|
||||
lock (SceneObjects.Dictionary)
|
||||
SceneObjects.Dictionary[prim.LocalID] = simObj;
|
||||
lock (SceneObjectsByID.Dictionary)
|
||||
SceneObjectsByID.Dictionary[prim.ID] = simObj;
|
||||
|
||||
// Send an update out to the creator
|
||||
ObjectUpdatePacket updateToOwner = Movement.BuildFullUpdate(prim, String.Empty, prim.RegionHandle, 0,
|
||||
prim.Flags | PrimFlags.CreateSelected | PrimFlags.ObjectYouOwner);
|
||||
agent.SendPacket(updateToOwner);
|
||||
|
||||
// Send an update out to everyone else
|
||||
ObjectUpdatePacket updateToOthers = Movement.BuildFullUpdate(prim, String.Empty, prim.RegionHandle, 0,
|
||||
prim.Flags);
|
||||
lock (Server.Agents)
|
||||
{
|
||||
foreach (Agent recipient in Server.Agents.Values)
|
||||
{
|
||||
if (recipient != agent)
|
||||
recipient.SendPacket(updateToOthers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectSelectHandler(Packet packet, Agent agent)
|
||||
{
|
||||
ObjectSelectPacket select = (ObjectSelectPacket)packet;
|
||||
|
||||
ObjectPropertiesPacket properties = new ObjectPropertiesPacket();
|
||||
properties.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[select.ObjectData.Length];
|
||||
|
||||
for (int i = 0; i < select.ObjectData.Length; i++)
|
||||
{
|
||||
properties.ObjectData[i] = new ObjectPropertiesPacket.ObjectDataBlock();
|
||||
|
||||
SimulationObject obj;
|
||||
if (SceneObjects.TryGetValue(select.ObjectData[i].ObjectLocalID, out obj))
|
||||
{
|
||||
properties.ObjectData[i].BaseMask = (uint)obj.Params.Properties.Permissions.BaseMask;
|
||||
properties.ObjectData[i].CreationDate = Utils.DateTimeToUnixTime(obj.Params.Properties.CreationDate);
|
||||
properties.ObjectData[i].CreatorID = obj.Params.Properties.CreatorID;
|
||||
properties.ObjectData[i].Description = Utils.StringToBytes(obj.Params.Properties.Description);
|
||||
properties.ObjectData[i].EveryoneMask = (uint)obj.Params.Properties.Permissions.EveryoneMask;
|
||||
properties.ObjectData[i].GroupID = obj.Params.Properties.GroupID;
|
||||
properties.ObjectData[i].GroupMask = (uint)obj.Params.Properties.Permissions.GroupMask;
|
||||
properties.ObjectData[i].LastOwnerID = obj.Params.Properties.LastOwnerID;
|
||||
properties.ObjectData[i].Name = Utils.StringToBytes(obj.Params.Properties.Name);
|
||||
properties.ObjectData[i].NextOwnerMask = (uint)obj.Params.Properties.Permissions.NextOwnerMask;
|
||||
properties.ObjectData[i].ObjectID = obj.Params.ID;
|
||||
properties.ObjectData[i].OwnerID = obj.Params.Properties.OwnerID;
|
||||
properties.ObjectData[i].OwnerMask = (uint)obj.Params.Properties.Permissions.OwnerMask;
|
||||
properties.ObjectData[i].OwnershipCost = obj.Params.Properties.OwnershipCost;
|
||||
properties.ObjectData[i].SalePrice = obj.Params.Properties.SalePrice;
|
||||
properties.ObjectData[i].SaleType = (byte)obj.Params.Properties.SaleType;
|
||||
properties.ObjectData[i].SitName = new byte[0];
|
||||
properties.ObjectData[i].TextureID = new byte[0];
|
||||
properties.ObjectData[i].TouchName = new byte[0];
|
||||
}
|
||||
}
|
||||
|
||||
agent.SendPacket(properties);
|
||||
}
|
||||
|
||||
Vector3 FullSceneCollisionTest(Vector3 rayStart, Vector3 rayEnd)
|
||||
{
|
||||
// HACK: For now
|
||||
Logger.DebugLog("Full scene collision test was requested, ignoring");
|
||||
return rayEnd;
|
||||
}
|
||||
|
||||
Vector3 ObjectCollisionTest(Vector3 rayStart, Vector3 rayEnd, SimulationObject obj)
|
||||
{
|
||||
const float OO_THREE = 1f / 3f;
|
||||
|
||||
Vector3 closestPoint = rayEnd;
|
||||
|
||||
if (rayStart == rayEnd)
|
||||
{
|
||||
Logger.DebugLog("RayStart is equal to RayEnd, rezzing from given location");
|
||||
return closestPoint;
|
||||
}
|
||||
|
||||
Vector3 direction = Vector3.Normalize(rayEnd - rayStart);
|
||||
Ray ray = new Ray(rayStart, direction);
|
||||
|
||||
// Get the mesh that has been transformed into world-space
|
||||
SimpleMesh mesh = null;
|
||||
if (obj.Params.LocalID != 0)
|
||||
{
|
||||
SimulationObject parent;
|
||||
if (SceneObjects.TryGetValue(obj.Params.LocalID, out parent))
|
||||
mesh = obj.GetWorldMesh(DetailLevel.Low, parent);
|
||||
}
|
||||
else
|
||||
{
|
||||
mesh = obj.GetWorldMesh(DetailLevel.Low, null);
|
||||
}
|
||||
|
||||
|
||||
if (mesh != null)
|
||||
{
|
||||
// Iterate through all of the triangles in the mesh, doing a ray-triangle intersection
|
||||
|
||||
float closestDistance = Single.MaxValue;
|
||||
for (int i = 0; i < mesh.Indices.Count; i += 3)
|
||||
{
|
||||
if (RayTriangleIntersection(rayStart, direction, mesh.Vertices[i].Position,
|
||||
mesh.Vertices[i + 1].Position, mesh.Vertices[i + 2].Position))
|
||||
{
|
||||
// Find the barycenter of this triangle
|
||||
Vector3 center =
|
||||
(mesh.Vertices[i].Position + mesh.Vertices[i + 1].Position + mesh.Vertices[i + 2].Position) * OO_THREE;
|
||||
|
||||
Logger.DebugLog("Collision hit with triangle at " + center);
|
||||
|
||||
if ((center - rayStart).Length() < closestDistance)
|
||||
closestPoint = center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return closestPoint;
|
||||
}
|
||||
|
||||
bool RayTriangleIntersection(Vector3 origin, Vector3 direction, Vector3 vert0, Vector3 vert1, Vector3 vert2)
|
||||
{
|
||||
// TODO:
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user