diff --git a/OpenSim/Framework/PrimitiveBaseShape.cs b/OpenSim/Framework/PrimitiveBaseShape.cs
index 6a38278ff2..9c2a4f9ac1 100644
--- a/OpenSim/Framework/PrimitiveBaseShape.cs
+++ b/OpenSim/Framework/PrimitiveBaseShape.cs
@@ -227,8 +227,12 @@ namespace OpenSim.Framework
{
get
{
- //m_log.DebugFormat("[PRIMITIVE BASE SHAPE]: get m_textureEntry length {0}", m_textureEntry.Length);
- return new Primitive.TextureEntry(m_textureEntry, 0, m_textureEntry.Length);
+ //m_log.DebugFormat("[SHAPE]: get m_textureEntry length {0}", m_textureEntry.Length);
+ try { return new Primitive.TextureEntry(m_textureEntry, 0, m_textureEntry.Length); }
+ catch { }
+
+ m_log.Warn("[SHAPE]: Failed to decode texture, length=" + ((m_textureEntry != null) ? m_textureEntry.Length : 0));
+ return new Primitive.TextureEntry(null);
}
set { m_textureEntry = value.GetBytes(); }
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
index 9a6ef77437..350c041f7d 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
@@ -42,6 +42,7 @@ using Nwc.XmlRpc;
using OpenMetaverse.StructuredData;
using CoolHTTPListener = HttpServer.HttpListener;
using HttpListener=System.Net.HttpListener;
+using LogPrio=HttpServer.LogPrio;
namespace OpenSim.Framework.Servers.HttpServer
{
@@ -294,7 +295,7 @@ namespace OpenSim.Framework.Servers.HttpServer
headervals[headername] = req.Headers[headername];
}
- keysvals.Add("headers",headervals);
+ keysvals.Add("headers", headervals);
keysvals.Add("querystringkeys", querystringkeys);
psEvArgs.Request(psreq.RequestID, keysvals);
@@ -341,7 +342,7 @@ namespace OpenSim.Framework.Servers.HttpServer
// the request can be passed through to the other handlers. This is a low
// probability event; if a request is matched it is normally expected to be
// handled
- //m_log.Debug("[BASE HTTP SERVER]: Handling Request" + request.RawUrl);
+// m_log.Debug("[BASE HTTP SERVER]: Handling request to " + request.RawUrl);
IHttpAgentHandler agentHandler;
@@ -496,7 +497,8 @@ namespace OpenSim.Framework.Servers.HttpServer
{
case null:
case "text/html":
- //m_log.Info("[Debug BASE HTTP SERVER]: found a text/html content type");
+// m_log.DebugFormat(
+// "[BASE HTTP SERVER]: Found a text/html content type for request {0}", request.RawUrl);
HandleHTTPRequest(request, response);
return;
@@ -524,10 +526,11 @@ namespace OpenSim.Framework.Servers.HttpServer
HandleLLSDRequests(request, response);
return;
}
- //m_log.Info("[Debug BASE HTTP SERVER]: Checking for HTTP Handler");
+
+// m_log.DebugFormat("[BASE HTTP SERVER]: Checking for HTTP Handler for request {0}", request.RawUrl);
if (DoWeHaveAHTTPHandler(request.RawUrl))
{
- //m_log.Info("[Debug BASE HTTP SERVER]: found HTTP Handler");
+// m_log.DebugFormat("[BASE HTTP SERVER]: Found HTTP Handler for request {0}", request.RawUrl);
HandleHTTPRequest(request, response);
return;
}
@@ -623,7 +626,7 @@ namespace OpenSim.Framework.Servers.HttpServer
private bool TryGetHTTPHandler(string handlerKey, out GenericHTTPMethod HTTPHandler)
{
- //m_log.DebugFormat("[BASE HTTP HANDLER]: Looking for HTTP handler for {0}", handlerKey);
+// m_log.DebugFormat("[BASE HTTP HANDLER]: Looking for HTTP handler for {0}", handlerKey);
string bestMatch = null;
@@ -943,7 +946,7 @@ namespace OpenSim.Framework.Servers.HttpServer
}
catch (IOException e)
{
- m_log.DebugFormat("[BASE HTTP SERVER]: LLSD IOException {0}.", e);
+ m_log.WarnFormat("[BASE HTTP SERVER]: LLSD IOException {0}.", e);
}
catch (SocketException e)
{
@@ -1218,7 +1221,11 @@ namespace OpenSim.Framework.Servers.HttpServer
}
public void HandleHTTPRequest(OSHttpRequest request, OSHttpResponse response)
- {
+ {
+// m_log.DebugFormat(
+// "[BASE HTTP SERVER]: HandleHTTPRequest for request to {0}, method {1}",
+// request.RawUrl, request.HttpMethod);
+
switch (request.HttpMethod)
{
case "OPTIONS":
@@ -1233,6 +1240,8 @@ namespace OpenSim.Framework.Servers.HttpServer
private void HandleContentVerbs(OSHttpRequest request, OSHttpResponse response)
{
+// m_log.DebugFormat("[BASE HTTP SERVER]: HandleContentVerbs for request to {0}", request.RawUrl);
+
// This is a test. There's a workable alternative.. as this way sucks.
// We'd like to put this into a text file parhaps that's easily editable.
//
@@ -1273,13 +1282,15 @@ namespace OpenSim.Framework.Servers.HttpServer
foreach (string queryname in querystringkeys)
{
+// m_log.DebugFormat(
+// "[BASE HTTP SERVER]: Got query paremeter {0}={1}", queryname, request.QueryString[queryname]);
keysvals.Add(queryname, request.QueryString[queryname]);
requestVars.Add(queryname, keysvals[queryname]);
}
foreach (string headername in rHeaders)
{
- //m_log.Warn("[HEADER]: " + headername + "=" + request.Headers[headername]);
+// m_log.Debug("[BASE HTTP SERVER]: " + headername + "=" + request.Headers[headername]);
headervals[headername] = request.Headers[headername];
}
@@ -1288,15 +1299,16 @@ namespace OpenSim.Framework.Servers.HttpServer
host = (string)headervals["Host"];
}
- keysvals.Add("headers",headervals);
+ keysvals.Add("headers", headervals);
keysvals.Add("querystringkeys", querystringkeys);
keysvals.Add("requestvars", requestVars);
+// keysvals.Add("form", request.Form);
if (keysvals.Contains("method"))
{
- //m_log.Warn("[HTTP]: Contains Method");
+// m_log.Debug("[BASE HTTP SERVER]: Contains Method");
string method = (string) keysvals["method"];
- //m_log.Warn("[HTTP]: " + requestBody);
+// m_log.Debug("[BASE HTTP SERVER]: " + requestBody);
GenericHTTPMethod requestprocessor;
bool foundHandler = TryGetHTTPHandler(method, out requestprocessor);
if (foundHandler)
@@ -1308,13 +1320,12 @@ namespace OpenSim.Framework.Servers.HttpServer
}
else
{
- //m_log.Warn("[HTTP]: Handler Not Found");
+// m_log.Warn("[BASE HTTP SERVER]: Handler Not Found");
SendHTML404(response, host);
}
}
else
{
-
GenericHTTPMethod requestprocessor;
bool foundHandler = TryGetHTTPHandlerPathBased(request.RawUrl, out requestprocessor);
if (foundHandler)
@@ -1326,7 +1337,7 @@ namespace OpenSim.Framework.Servers.HttpServer
}
else
{
- //m_log.Warn("[HTTP]: Handler Not Found");
+// m_log.Warn("[BASE HTTP SERVER]: Handler Not Found2");
SendHTML404(response, host);
}
}
@@ -1374,8 +1385,7 @@ namespace OpenSim.Framework.Servers.HttpServer
{
if (String.IsNullOrEmpty(bestMatch) || searchquery.Length > bestMatch.Length)
{
- // You have to specifically register for '/' and to get it, you must specificaly request it
- //
+ // You have to specifically register for '/' and to get it, you must specifically request it
if (pattern == "/" && searchquery == "/" || pattern != "/")
bestMatch = pattern;
}
@@ -1814,30 +1824,36 @@ namespace OpenSim.Framework.Servers.HttpServer
///
/// Relays HttpServer log messages to our own logging mechanism.
///
- /// There is also a UseTraceLogs line in this file that can be uncommented for more detailed log information
+ /// To use this you must uncomment the switch section
+ ///
+ /// You may also be able to get additional trace information from HttpServer if you uncomment the UseTraceLogs
+ /// property in StartHttp() for the HttpListener
public class HttpServerLogWriter : ILogWriter
{
- //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+ private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public void Write(object source, LogPrio priority, string message)
{
/*
switch (priority)
{
- case HttpServer.LogPrio.Debug:
- m_log.DebugFormat("[{0}]: {1}", source.ToString(), message);
+ case LogPrio.Trace:
+ m_log.DebugFormat("[{0}]: {1}", source, message);
+ break;
+ case LogPrio.Debug:
+ m_log.DebugFormat("[{0}]: {1}", source, message);
break;
- case HttpServer.LogPrio.Error:
- m_log.ErrorFormat("[{0}]: {1}", source.ToString(), message);
+ case LogPrio.Error:
+ m_log.ErrorFormat("[{0}]: {1}", source, message);
break;
- case HttpServer.LogPrio.Info:
- m_log.InfoFormat("[{0}]: {1}", source.ToString(), message);
+ case LogPrio.Info:
+ m_log.InfoFormat("[{0}]: {1}", source, message);
break;
- case HttpServer.LogPrio.Warning:
- m_log.WarnFormat("[{0}]: {1}", source.ToString(), message);
+ case LogPrio.Warning:
+ m_log.WarnFormat("[{0}]: {1}", source, message);
break;
- case HttpServer.LogPrio.Fatal:
- m_log.ErrorFormat("[{0}]: FATAL! - {1}", source.ToString(), message);
+ case LogPrio.Fatal:
+ m_log.ErrorFormat("[{0}]: FATAL! - {1}", source, message);
break;
default:
break;
@@ -1847,4 +1863,4 @@ namespace OpenSim.Framework.Servers.HttpServer
return;
}
}
-}
+}
\ No newline at end of file
diff --git a/OpenSim/Framework/Servers/HttpServer/OSHttpRequest.cs b/OpenSim/Framework/Servers/HttpServer/OSHttpRequest.cs
index bcfb0a4025..e354dfbd1a 100644
--- a/OpenSim/Framework/Servers/HttpServer/OSHttpRequest.cs
+++ b/OpenSim/Framework/Servers/HttpServer/OSHttpRequest.cs
@@ -127,6 +127,11 @@ namespace OpenSim.Framework.Servers.HttpServer
}
private Hashtable _query;
+ ///
+ /// POST request values, if applicable
+ ///
+// public Hashtable Form { get; private set; }
+
public string RawUrl
{
get { return _request.Uri.AbsolutePath; }
@@ -228,6 +233,13 @@ namespace OpenSim.Framework.Servers.HttpServer
{
_log.ErrorFormat("[OSHttpRequest]: Error parsing querystring");
}
+
+// Form = new Hashtable();
+// foreach (HttpInputItem item in req.Form)
+// {
+// _log.DebugFormat("[OSHttpRequest]: Got form item {0}={1}", item.Name, item.Value);
+// Form.Add(item.Name, item.Value);
+// }
}
public override string ToString()
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs
index 7e816502a1..38b20843e0 100755
--- a/OpenSim/Region/Application/OpenSim.cs
+++ b/OpenSim/Region/Application/OpenSim.cs
@@ -897,7 +897,7 @@ namespace OpenSim
{
connections.AppendFormat("{0}: {1} ({2}) from {3} on circuit {4}\n",
scene.RegionInfo.RegionName, client.Name, client.AgentId, client.RemoteEndPoint, client.CircuitCode);
- }, false
+ }
);
}
);
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
index 36d24e8200..850474d834 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
@@ -1020,7 +1020,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// Handle outgoing packets, resends, acknowledgements, and pings for each
// client. m_packetSent will be set to true if a packet is sent
- m_scene.ForEachClient(clientPacketHandler, false);
+ m_scene.ForEachClient(clientPacketHandler);
// If nothing was sent, sleep for the minimum amount of time before a
// token bucket could get more tokens
diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
index 967c0a1f09..37cdaae2bd 100644
--- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
@@ -642,7 +642,7 @@ namespace Flotsam.RegionModules.AssetCache
{
UuidGatherer gatherer = new UuidGatherer(m_AssetService);
- Dictionary assets = new Dictionary();
+ Dictionary assets = new Dictionary();
foreach (Scene s in m_Scenes)
{
StampRegionStatusFile(s.RegionInfo.RegionID);
diff --git a/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs b/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs
index 3614915c5e..9df60743ae 100644
--- a/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs
@@ -89,60 +89,57 @@ namespace OpenSim.Region.CoreModules.Avatar.Combat.CombatModule
get { return true; }
}
- private void KillAvatar(uint killerObjectLocalID, ScenePresence DeadAvatar)
+ private void KillAvatar(uint killerObjectLocalID, ScenePresence deadAvatar)
{
+ string deadAvatarMessage;
+ ScenePresence killingAvatar = null;
+ string killingAvatarMessage;
+
if (killerObjectLocalID == 0)
- DeadAvatar.ControllingClient.SendAgentAlertMessage("You committed suicide!", true);
+ deadAvatarMessage = "You committed suicide!";
else
{
- bool foundResult = false;
- string resultstring = String.Empty;
- ScenePresence[] allav = DeadAvatar.Scene.GetScenePresences();
- try
+ // Try to get the avatar responsible for the killing
+ killingAvatar = deadAvatar.Scene.GetScenePresence(killerObjectLocalID);
+ if (killingAvatar == null)
{
- for (int i = 0; i < allav.Length; i++)
+ // Try to get the object which was responsible for the killing
+ SceneObjectPart part = deadAvatar.Scene.GetSceneObjectPart(killerObjectLocalID);
+ if (part == null)
{
- ScenePresence av = allav[i];
-
- if (av.LocalId == killerObjectLocalID)
- {
- av.ControllingClient.SendAlertMessage("You fragged " + DeadAvatar.Firstname + " " + DeadAvatar.Lastname);
- resultstring = av.Firstname + " " + av.Lastname;
- foundResult = true;
- }
- }
- } catch (InvalidOperationException)
- {
-
- }
-
- if (!foundResult)
- {
- SceneObjectPart part = DeadAvatar.Scene.GetSceneObjectPart(killerObjectLocalID);
- if (part != null)
- {
- ScenePresence av = DeadAvatar.Scene.GetScenePresence(part.OwnerID);
- if (av != null)
- {
- av.ControllingClient.SendAlertMessage("You fragged " + DeadAvatar.Firstname + " " + DeadAvatar.Lastname);
- resultstring = av.Firstname + " " + av.Lastname;
- DeadAvatar.ControllingClient.SendAgentAlertMessage("You got killed by " + resultstring + "!", true);
- }
- else
- {
- string killer = DeadAvatar.Scene.GetUserName(part.OwnerID);
- DeadAvatar.ControllingClient.SendAgentAlertMessage("You impaled yourself on " + part.Name + " owned by " + killer +"!", true);
- }
- //DeadAvatar.Scene. part.ObjectOwner
+ // Cause of death: Unknown
+ deadAvatarMessage = "You died!";
}
else
{
- DeadAvatar.ControllingClient.SendAgentAlertMessage("You died!", true);
+ // Try to find the avatar wielding the killing object
+ killingAvatar = deadAvatar.Scene.GetScenePresence(part.OwnerID);
+ if (killingAvatar == null)
+ deadAvatarMessage = String.Format("You impaled yourself on {0} owned by {1}!", part.Name, deadAvatar.Scene.GetUserName(part.OwnerID));
+ else
+ {
+ killingAvatarMessage = String.Format("You fragged {0}!", deadAvatar.Name);
+ deadAvatarMessage = String.Format("You got killed by {0}!", killingAvatar.Name);
+ }
}
}
+ else
+ {
+ killingAvatarMessage = String.Format("You fragged {0}!", deadAvatar.Name);
+ deadAvatarMessage = String.Format("You got killed by {0}!", killingAvatar.Name);
+ }
}
- DeadAvatar.Health = 100;
- DeadAvatar.Scene.TeleportClientHome(DeadAvatar.UUID, DeadAvatar.ControllingClient);
+ try
+ {
+ deadAvatar.ControllingClient.SendAgentAlertMessage(deadAvatarMessage, true);
+ if(killingAvatar != null)
+ killingAvatar.ControllingClient.SendAlertMessage("You fragged " + deadAvatar.Firstname + " " + deadAvatar.Lastname);
+ }
+ catch (InvalidOperationException)
+ { }
+
+ deadAvatar.Health = 100;
+ deadAvatar.Scene.TeleportClientHome(deadAvatar.UUID, deadAvatar.ControllingClient);
}
private void AvatarEnteringParcel(ScenePresence avatar, int localLandID, UUID regionID)
diff --git a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs
index b8e013c672..c31266c0e1 100644
--- a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs
@@ -87,31 +87,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog
public void SendAlertToUser(string firstName, string lastName, string message, bool modal)
{
- ScenePresence[] presenceList = m_scene.GetScenePresences();
-
- for (int i = 0; i < presenceList.Length; i++)
- {
- ScenePresence presence = presenceList[i];
-
- if (presence.Firstname == firstName && presence.Lastname == lastName)
- {
- presence.ControllingClient.SendAgentAlertMessage(message, modal);
- break;
- }
- }
+ ScenePresence presence = m_scene.GetScenePresence(firstName, lastName);
+ if(presence != null)
+ presence.ControllingClient.SendAgentAlertMessage(message, modal);
}
public void SendGeneralAlert(string message)
{
- ScenePresence[] presenceList = m_scene.GetScenePresences();
-
- for (int i = 0; i < presenceList.Length; i++)
+ m_scene.ForEachScenePresence(delegate(ScenePresence presence)
{
- ScenePresence presence = presenceList[i];
-
if (!presence.IsChildAgent)
presence.ControllingClient.SendAlertMessage(message);
- }
+ });
}
public void SendDialogToUser(
@@ -179,14 +166,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog
public void SendNotificationToUsersInRegion(
UUID fromAvatarID, string fromAvatarName, string message)
{
- ScenePresence[] presences = m_scene.GetScenePresences();
-
- for (int i = 0; i < presences.Length; i++)
+ m_scene.ForEachScenePresence(delegate(ScenePresence presence)
{
- ScenePresence presence = presences[i];
if (!presence.IsChildAgent)
presence.ControllingClient.SendBlueBoxMessage(fromAvatarID, fromAvatarName, message);
- }
+ });
}
///
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
index ef10104f33..cfe3caa849 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
@@ -73,7 +73,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
///
/// Used to collect the uuids of the assets that we need to save into the archive
///
- protected Dictionary m_assetUuids = new Dictionary();
+ protected Dictionary m_assetUuids = new Dictionary();
///
/// Used to collect the uuids of the users that we need to save into the archive
@@ -305,7 +305,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
}
new AssetsRequest(
- new AssetsArchiver(m_archiveWriter), m_assetUuids.Keys,
+ new AssetsArchiver(m_archiveWriter), m_assetUuids,
m_scene.AssetService, ReceivedAllAssets).Execute();
}
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs
index 664f38d21b..58ce550773 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs
@@ -150,7 +150,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
if (asset != null)
{
// OK, now fetch the inside.
- Dictionary ids = new Dictionary();
+ Dictionary ids = new Dictionary();
HGUuidGatherer uuidGatherer = new HGUuidGatherer(this, m_scene.AssetService, userAssetURL);
uuidGatherer.GatherAssetUuids(asset.FullID, (AssetType)asset.Type, ids);
foreach (UUID uuid in ids.Keys)
@@ -173,7 +173,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
AssetBase asset = m_scene.AssetService.Get(assetID.ToString());
if (asset != null)
{
- Dictionary ids = new Dictionary();
+ Dictionary ids = new Dictionary();
HGUuidGatherer uuidGatherer = new HGUuidGatherer(this, m_scene.AssetService, string.Empty);
uuidGatherer.GatherAssetUuids(asset.FullID, (AssetType)asset.Type, ids);
foreach (UUID uuid in ids.Keys)
diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
index 643764fa12..678e7723ff 100644
--- a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
@@ -285,24 +285,22 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
return;
}
- byte[] assetData;
+ byte[] assetData = null;
AssetBase oldAsset = null;
if (BlendWithOldTexture)
{
- UUID lastTextureID = part.Shape.Textures.DefaultTexture.TextureID;
- oldAsset = scene.AssetService.Get(lastTextureID.ToString());
- if (oldAsset != null)
+ Primitive.TextureEntryFace defaultFace = part.Shape.Textures.DefaultTexture;
+ if (defaultFace != null)
{
- assetData = BlendTextures(data, oldAsset.Data, SetNewFrontAlpha, FrontAlpha);
- }
- else
- {
- assetData = new byte[data.Length];
- Array.Copy(data, assetData, data.Length);
+ oldAsset = scene.AssetService.Get(defaultFace.TextureID.ToString());
+
+ if (oldAsset != null)
+ assetData = BlendTextures(data, oldAsset.Data, SetNewFrontAlpha, FrontAlpha);
}
}
- else
+
+ if (assetData == null)
{
assetData = new byte[data.Length];
Array.Copy(data, assetData, data.Length);
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
index 783d606f64..e32dbb3bfd 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
@@ -166,6 +166,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
return m_sceneList[0];
}
+ public ISimulationService GetInnerService()
+ {
+ return this;
+ }
+
/**
* Agent-related communications
*/
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
index 4d82a05cee..9e8454f72f 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
@@ -156,6 +156,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
return m_localBackend.GetScene(handle);
}
+ public ISimulationService GetInnerService()
+ {
+ return m_localBackend;
+ }
+
/**
* Agent-related communications
*/
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs
index b61b341d2a..b25636ffcb 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs
@@ -100,7 +100,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
/// if there was an io problem with creating the file
public void ArchiveRegion()
{
- Dictionary assetUuids = new Dictionary();
+ Dictionary assetUuids = new Dictionary();
List entities = m_scene.GetEntities();
List sceneObjects = new List();
@@ -142,18 +142,18 @@ namespace OpenSim.Region.CoreModules.World.Archiver
// Make sure that we also request terrain texture assets
RegionSettings regionSettings = m_scene.RegionInfo.RegionSettings;
-
+
if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1)
- assetUuids[regionSettings.TerrainTexture1] = 1;
+ assetUuids[regionSettings.TerrainTexture1] = AssetType.Texture;
if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2)
- assetUuids[regionSettings.TerrainTexture2] = 1;
+ assetUuids[regionSettings.TerrainTexture2] = AssetType.Texture;
if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3)
- assetUuids[regionSettings.TerrainTexture3] = 1;
+ assetUuids[regionSettings.TerrainTexture3] = AssetType.Texture;
if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4)
- assetUuids[regionSettings.TerrainTexture4] = 1;
+ assetUuids[regionSettings.TerrainTexture4] = AssetType.Texture;
TarArchiveWriter archiveWriter = new TarArchiveWriter(m_saveStream);
@@ -168,7 +168,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
m_requestId);
new AssetsRequest(
- new AssetsArchiver(archiveWriter), assetUuids.Keys,
+ new AssetsArchiver(archiveWriter), assetUuids,
m_scene.AssetService, awre.ReceivedAllAssets).Execute();
}
}
diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
index c9fce91060..4215f97343 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
@@ -74,7 +74,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
///
/// uuids to request
///
- protected ICollection m_uuids;
+ protected IDictionary m_uuids;
///
/// Callback used when all the assets requested have been received.
@@ -104,7 +104,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
protected AssetsArchiver m_assetsArchiver;
protected internal AssetsRequest(
- AssetsArchiver assetsArchiver, ICollection uuids,
+ AssetsArchiver assetsArchiver, IDictionary uuids,
IAssetService assetService, AssetsRequestCallback assetsRequestCallback)
{
m_assetsArchiver = assetsArchiver;
@@ -132,9 +132,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver
return;
}
- foreach (UUID uuid in m_uuids)
+ foreach (KeyValuePair kvp in m_uuids)
{
- m_assetService.Get(uuid.ToString(), this, AssetRequestCallback);
+ m_assetService.Get(kvp.Key.ToString(), kvp.Value, PreAssetRequestCallback);
}
m_requestCallbackTimer.Enabled = true;
@@ -157,7 +157,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
// Calculate which uuids were not found. This is an expensive way of doing it, but this is a failure
// case anyway.
List uuids = new List();
- foreach (UUID uuid in m_uuids)
+ foreach (UUID uuid in m_uuids.Keys)
{
uuids.Add(uuid);
}
@@ -200,6 +200,19 @@ namespace OpenSim.Region.CoreModules.World.Archiver
}
}
+ protected void PreAssetRequestCallback(string fetchedAssetID, object assetType, AssetBase fetchedAsset)
+ {
+ // Check for broken asset types and fix them with the AssetType gleaned by UuidGatherer
+ if (fetchedAsset != null && fetchedAsset.Type == (sbyte)AssetType.Unknown)
+ {
+ AssetType type = (AssetType)assetType;
+ m_log.InfoFormat("[ARCHIVER]: Rewriting broken asset type for {0} to {1}", fetchedAsset.ID, type);
+ fetchedAsset.Type = (sbyte)type;
+ }
+
+ AssetRequestCallback(fetchedAssetID, this, fetchedAsset);
+ }
+
///
/// Called back by the asset cache when it has the asset
///
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
index e3bab2d2e7..464d922f38 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
@@ -469,12 +469,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
private void handleEstateTeleportAllUsersHomeRequest(IClientAPI remover_client, UUID invoice, UUID senderID)
{
// Get a fresh list that will not change as people get teleported away
- ScenePresence[] presences = m_scene.GetScenePresences();
+ List presences = m_scene.GetScenePresences();
- for (int i = 0; i < presences.Length; i++)
+ foreach(ScenePresence p in presences)
{
- ScenePresence p = presences[i];
-
if (p.UUID != senderID)
{
// make sure they are still there, we could be working down a long list
diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
index e85136ae17..331f183e1d 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
@@ -892,7 +892,7 @@ namespace OpenSim.Region.CoreModules.World.Land
foreach (List ol in returns.Values)
{
- if (m_scene.Permissions.CanUseObjectReturn(this, type, remote_client, ol))
+ if (m_scene.Permissions.CanReturnObjects(this, remote_client.AgentId, ol))
m_scene.returnObjects(ol.ToArray(), remote_client.AgentId);
}
}
diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
index 5c7f3b7225..4dbdb015d0 100644
--- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
@@ -217,7 +217,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
m_scene.Permissions.OnIssueEstateCommand += CanIssueEstateCommand; //FULLY IMPLEMENTED
m_scene.Permissions.OnMoveObject += CanMoveObject; //MAYBE FULLY IMPLEMENTED
m_scene.Permissions.OnObjectEntry += CanObjectEntry;
- m_scene.Permissions.OnReturnObject += CanReturnObject; //NOT YET IMPLEMENTED
+ m_scene.Permissions.OnReturnObjects += CanReturnObjects; //NOT YET IMPLEMENTED
m_scene.Permissions.OnRezObject += CanRezObject; //MAYBE FULLY IMPLEMENTED
m_scene.Permissions.OnRunConsoleCommand += CanRunConsoleCommand;
m_scene.Permissions.OnRunScript += CanRunScript; //NOT YET IMPLEMENTED
@@ -247,7 +247,6 @@ namespace OpenSim.Region.CoreModules.World.Permissions
m_scene.Permissions.OnDeleteUserInventory += CanDeleteUserInventory; //NOT YET IMPLEMENTED
m_scene.Permissions.OnTeleport += CanTeleport; //NOT YET IMPLEMENTED
- m_scene.Permissions.OnUseObjectReturn += CanUseObjectReturn; //NOT YET IMPLEMENTED
m_scene.AddCommand(this, "bypass permissions",
"bypass permissions ",
@@ -1275,12 +1274,106 @@ namespace OpenSim.Region.CoreModules.World.Permissions
return false;
}
- private bool CanReturnObject(UUID objectID, UUID returnerID, Scene scene)
+ private bool CanReturnObjects(ILandObject land, UUID user, List objects, Scene scene)
{
DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
if (m_bypassPermissions) return m_bypassPermissionsValue;
- return GenericObjectPermission(returnerID, objectID, false);
+ GroupPowers powers;
+ ILandObject l;
+
+ ScenePresence sp = scene.GetScenePresence(user);
+ if (sp == null)
+ return false;
+
+ IClientAPI client = sp.ControllingClient;
+
+ foreach (SceneObjectGroup g in new List(objects))
+ {
+ // Any user can return their own objects at any time
+ //
+ if (GenericObjectPermission(user, g.UUID, false))
+ continue;
+
+ // This is a short cut for efficiency. If land is non-null,
+ // then all objects are on that parcel and we can save
+ // ourselves the checking for each prim. Much faster.
+ //
+ if (land != null)
+ {
+ l = land;
+ }
+ else
+ {
+ Vector3 pos = g.AbsolutePosition;
+
+ l = scene.LandChannel.GetLandObject(pos.X, pos.Y);
+ }
+
+ // If it's not over any land, then we can't do a thing
+ if (l == null)
+ {
+ objects.Remove(g);
+ continue;
+ }
+
+ // If we own the land outright, then allow
+ //
+ if (l.LandData.OwnerID == user)
+ continue;
+
+ // Group voodoo
+ //
+ if (land.LandData.IsGroupOwned)
+ {
+ powers = (GroupPowers)client.GetGroupPowers(land.LandData.GroupID);
+ // Not a group member, or no rights at all
+ //
+ if (powers == (GroupPowers)0)
+ {
+ objects.Remove(g);
+ continue;
+ }
+
+ // Group deeded object?
+ //
+ if (g.OwnerID == l.LandData.GroupID &&
+ (powers & GroupPowers.ReturnGroupOwned) == (GroupPowers)0)
+ {
+ objects.Remove(g);
+ continue;
+ }
+
+ // Group set object?
+ //
+ if (g.GroupID == l.LandData.GroupID &&
+ (powers & GroupPowers.ReturnGroupSet) == (GroupPowers)0)
+ {
+ objects.Remove(g);
+ continue;
+ }
+
+ if ((powers & GroupPowers.ReturnNonGroup) == (GroupPowers)0)
+ {
+ objects.Remove(g);
+ continue;
+ }
+
+ // So we can remove all objects from this group land.
+ // Fine.
+ //
+ continue;
+ }
+
+ // By default, we can't remove
+ //
+ objects.Remove(g);
+ }
+
+ if (objects.Count == 0)
+ return false;
+
+ return true;
}
private bool CanRezObject(int objectCount, UUID owner, Vector3 objectPosition, Scene scene)
@@ -1747,67 +1840,6 @@ namespace OpenSim.Region.CoreModules.World.Permissions
return GenericObjectPermission(agentID, prim, false);
}
- private bool CanUseObjectReturn(ILandObject parcel, uint type, IClientAPI client, List retlist, Scene scene)
- {
- DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
- if (m_bypassPermissions) return m_bypassPermissionsValue;
-
- long powers = 0;
- if (parcel.LandData.GroupID != UUID.Zero)
- client.GetGroupPowers(parcel.LandData.GroupID);
-
- switch (type)
- {
- case (uint)ObjectReturnType.Owner:
- // Don't let group members return owner's objects, ever
- //
- if (parcel.LandData.IsGroupOwned)
- {
- if ((powers & (long)GroupPowers.ReturnGroupOwned) != 0)
- return true;
- }
- else
- {
- if (parcel.LandData.OwnerID != client.AgentId)
- return false;
- }
- return GenericParcelOwnerPermission(client.AgentId, parcel, (ulong)GroupPowers.ReturnGroupOwned);
- case (uint)ObjectReturnType.Group:
- if (parcel.LandData.OwnerID != client.AgentId)
- {
- // If permissionis granted through a group...
- //
- if ((powers & (long)GroupPowers.ReturnGroupSet) != 0)
- {
- foreach (SceneObjectGroup g in new List(retlist))
- {
- // check for and remove group owned objects unless
- // the user also has permissions to return those
- //
- if (g.OwnerID == g.GroupID &&
- ((powers & (long)GroupPowers.ReturnGroupOwned) == 0))
- {
- retlist.Remove(g);
- }
- }
- // And allow the operation
- //
- return true;
- }
- }
- return GenericParcelOwnerPermission(client.AgentId, parcel, (ulong)GroupPowers.ReturnGroupSet);
- case (uint)ObjectReturnType.Other:
- if ((powers & (long)GroupPowers.ReturnNonGroup) != 0)
- return true;
- return GenericParcelOwnerPermission(client.AgentId, parcel, (ulong)GroupPowers.ReturnNonGroup);
- case (uint)ObjectReturnType.List:
- break;
- }
-
- return GenericParcelOwnerPermission(client.AgentId, parcel, 0);
- // Is it correct to be less restrictive for lists of objects to be returned?
- }
-
private bool CanCompileScript(UUID ownerUUID, int scriptType, Scene scene) {
//m_log.DebugFormat("check if {0} is allowed to compile {1}", ownerUUID, scriptType);
switch (scriptType) {
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/MapImageModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/MapImageModule.cs
index 285d36a3d6..b71b5f61a5 100644
--- a/OpenSim/Region/CoreModules/World/WorldMap/MapImageModule.cs
+++ b/OpenSim/Region/CoreModules/World/WorldMap/MapImageModule.cs
@@ -251,13 +251,12 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
// if you want tree blocks on the map comment the above line and uncomment the below line
//mapdotspot = Color.PaleGreen;
- if (part.Shape.Textures == null)
+ Primitive.TextureEntry textureEntry = part.Shape.Textures;
+
+ if (textureEntry == null || textureEntry.DefaultTexture == null)
continue;
- if (part.Shape.Textures.DefaultTexture == null)
- continue;
-
- Color4 texcolor = part.Shape.Textures.DefaultTexture.RGBA;
+ Color4 texcolor = textureEntry.DefaultTexture.RGBA;
// Not sure why some of these are null, oh well.
diff --git a/OpenSim/Region/DataSnapshot/ObjectSnapshot.cs b/OpenSim/Region/DataSnapshot/ObjectSnapshot.cs
index 76dac6107e..f441aa9a84 100644
--- a/OpenSim/Region/DataSnapshot/ObjectSnapshot.cs
+++ b/OpenSim/Region/DataSnapshot/ObjectSnapshot.cs
@@ -203,44 +203,54 @@ namespace OpenSim.Region.DataSnapshot.Providers
{
string bestguess = string.Empty;
Dictionary counts = new Dictionary();
- if (sog.RootPart.Shape != null && sog.RootPart.Shape.ProfileShape == ProfileShape.Square &&
- sog.RootPart.Shape.Textures != null && sog.RootPart.Shape.Textures.FaceTextures != null)
- {
- if (sog.RootPart.Shape.Textures.DefaultTexture.TextureID != UUID.Zero &&
- sog.RootPart.Shape.Textures.DefaultTexture.TextureID != m_DefaultImage &&
- sog.RootPart.Shape.Textures.DefaultTexture.TextureID != m_BlankImage &&
- sog.RootPart.Shape.Textures.DefaultTexture.RGBA.A < 50)
- {
- counts[sog.RootPart.Shape.Textures.DefaultTexture.TextureID] = 8;
- }
- foreach (Primitive.TextureEntryFace tentry in sog.RootPart.Shape.Textures.FaceTextures)
+ PrimitiveBaseShape shape = sog.RootPart.Shape;
+ if (shape != null && shape.ProfileShape == ProfileShape.Square)
+ {
+ Primitive.TextureEntry textures = shape.Textures;
+ if (textures != null)
{
- if (tentry != null)
+ if (textures.DefaultTexture != null &&
+ textures.DefaultTexture.TextureID != UUID.Zero &&
+ textures.DefaultTexture.TextureID != m_DefaultImage &&
+ textures.DefaultTexture.TextureID != m_BlankImage &&
+ textures.DefaultTexture.RGBA.A < 50f)
{
- if (tentry.TextureID != UUID.Zero && tentry.TextureID != m_DefaultImage && tentry.TextureID != m_BlankImage && tentry.RGBA.A < 50)
+ counts[textures.DefaultTexture.TextureID] = 8;
+ }
+
+ if (textures.FaceTextures != null)
+ {
+ foreach (Primitive.TextureEntryFace tentry in textures.FaceTextures)
{
- int c = 0;
- counts.TryGetValue(tentry.TextureID, out c);
- counts[tentry.TextureID] = c + 1;
- // decrease the default texture count
- if (counts.ContainsKey(sog.RootPart.Shape.Textures.DefaultTexture.TextureID))
- counts[sog.RootPart.Shape.Textures.DefaultTexture.TextureID] = counts[sog.RootPart.Shape.Textures.DefaultTexture.TextureID] - 1;
+ if (tentry != null)
+ {
+ if (tentry.TextureID != UUID.Zero && tentry.TextureID != m_DefaultImage && tentry.TextureID != m_BlankImage && tentry.RGBA.A < 50)
+ {
+ int c = 0;
+ counts.TryGetValue(tentry.TextureID, out c);
+ counts[tentry.TextureID] = c + 1;
+ // decrease the default texture count
+ if (counts.ContainsKey(textures.DefaultTexture.TextureID))
+ counts[textures.DefaultTexture.TextureID] = counts[textures.DefaultTexture.TextureID] - 1;
+ }
+ }
+ }
+ }
+
+ // Let's pick the most unique texture
+ int min = 9999;
+ foreach (KeyValuePair kv in counts)
+ {
+ if (kv.Value < min && kv.Value >= 1)
+ {
+ bestguess = kv.Key.ToString();
+ min = kv.Value;
}
}
}
-
- // Let's pick the most unique texture
- int min = 9999;
- foreach (KeyValuePair kv in counts)
- {
- if (kv.Value < min && kv.Value >= 1)
- {
- bestguess = kv.Key.ToString();
- min = kv.Value;
- }
- }
}
+
return bestguess;
}
}
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 6ebd04811d..cadb85810b 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -1522,9 +1522,10 @@ namespace OpenSim.Region.Framework.Scenes
if (remoteClient != null)
{
permissionToTake =
- Permissions.CanReturnObject(
- grp.UUID,
- remoteClient.AgentId);
+ Permissions.CanReturnObjects(
+ null,
+ remoteClient.AgentId,
+ new List() {grp});
permissionToDelete = permissionToTake;
if (permissionToDelete)
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
index d1d6b6a377..7dab04fbd2 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
@@ -48,7 +48,7 @@ namespace OpenSim.Region.Framework.Scenes
public delegate bool EditObjectInventoryHandler(UUID objectID, UUID editorID, Scene scene);
public delegate bool MoveObjectHandler(UUID objectID, UUID moverID, Scene scene);
public delegate bool ObjectEntryHandler(UUID objectID, bool enteringRegion, Vector3 newPoint, Scene scene);
- public delegate bool ReturnObjectHandler(UUID objectID, UUID returnerID, Scene scene);
+ public delegate bool ReturnObjectsHandler(ILandObject land, UUID user, List objects, Scene scene);
public delegate bool InstantMessageHandler(UUID user, UUID target, Scene startScene);
public delegate bool InventoryTransferHandler(UUID user, UUID target, Scene startScene);
public delegate bool ViewScriptHandler(UUID script, UUID objectID, UUID user, Scene scene);
@@ -81,7 +81,6 @@ namespace OpenSim.Region.Framework.Scenes
public delegate bool CopyUserInventoryHandler(UUID itemID, UUID userID);
public delegate bool DeleteUserInventoryHandler(UUID itemID, UUID userID);
public delegate bool TeleportHandler(UUID userID, Scene scene);
- public delegate bool UseObjectReturnHandler(ILandObject landData, uint type, IClientAPI client, List retlist, Scene scene);
#endregion
public class ScenePermissions
@@ -107,7 +106,7 @@ namespace OpenSim.Region.Framework.Scenes
public event EditObjectInventoryHandler OnEditObjectInventory;
public event MoveObjectHandler OnMoveObject;
public event ObjectEntryHandler OnObjectEntry;
- public event ReturnObjectHandler OnReturnObject;
+ public event ReturnObjectsHandler OnReturnObjects;
public event InstantMessageHandler OnInstantMessage;
public event InventoryTransferHandler OnInventoryTransfer;
public event ViewScriptHandler OnViewScript;
@@ -140,7 +139,6 @@ namespace OpenSim.Region.Framework.Scenes
public event CopyUserInventoryHandler OnCopyUserInventory;
public event DeleteUserInventoryHandler OnDeleteUserInventory;
public event TeleportHandler OnTeleport;
- public event UseObjectReturnHandler OnUseObjectReturn;
#endregion
#region Object Permission Checks
@@ -377,15 +375,15 @@ namespace OpenSim.Region.Framework.Scenes
#endregion
#region RETURN OBJECT
- public bool CanReturnObject(UUID objectID, UUID returnerID)
+ public bool CanReturnObjects(ILandObject land, UUID user, List objects)
{
- ReturnObjectHandler handler = OnReturnObject;
+ ReturnObjectsHandler handler = OnReturnObjects;
if (handler != null)
{
Delegate[] list = handler.GetInvocationList();
- foreach (ReturnObjectHandler h in list)
+ foreach (ReturnObjectsHandler h in list)
{
- if (h(objectID, returnerID, m_scene) == false)
+ if (h(land, user, objects, m_scene) == false)
return false;
}
}
@@ -949,20 +947,5 @@ namespace OpenSim.Region.Framework.Scenes
}
return true;
}
-
- public bool CanUseObjectReturn(ILandObject landData, uint type , IClientAPI client, List retlist)
- {
- UseObjectReturnHandler handler = OnUseObjectReturn;
- if (handler != null)
- {
- Delegate[] list = handler.GetInvocationList();
- foreach (UseObjectReturnHandler h in list)
- {
- if (h(landData, type, client, retlist, m_scene) == false)
- return false;
- }
- }
- return true;
- }
}
}
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 03f1ee2d87..b2c8dfdcab 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -131,7 +131,6 @@ namespace OpenSim.Region.Framework.Scenes
private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing
private int m_incrementsof15seconds;
private volatile bool m_backingup;
- private bool m_useAsyncWhenPossible;
private Dictionary m_returns = new Dictionary();
private Dictionary m_groupsWithTargets = new Dictionary();
@@ -656,9 +655,6 @@ namespace OpenSim.Region.Framework.Scenes
//
IConfig startupConfig = m_config.Configs["Startup"];
- // Should we try to run loops synchronously or asynchronously?
- m_useAsyncWhenPossible = startupConfig.GetBoolean("use_async_when_possible", false);
-
//Animation states
m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
// TODO: Change default to true once the feature is supported
@@ -3636,9 +3632,7 @@ namespace OpenSim.Region.Framework.Scenes
public virtual void AgentCrossing(UUID agentID, Vector3 position, bool isFlying)
{
ScenePresence presence;
- m_sceneGraph.TryGetAvatar(agentID, out presence);
-
- if (presence != null)
+ if(m_sceneGraph.TryGetAvatar(agentID, out presence))
{
try
{
@@ -3813,9 +3807,7 @@ namespace OpenSim.Region.Framework.Scenes
Vector3 lookAt, uint teleportFlags)
{
ScenePresence sp;
- m_sceneGraph.TryGetAvatar(remoteClient.AgentId, out sp);
-
- if (sp != null)
+ if(m_sceneGraph.TryGetAvatar(remoteClient.AgentId, out sp))
{
uint regionX = m_regInfo.RegionLocX;
uint regionY = m_regInfo.RegionLocY;
@@ -4171,6 +4163,11 @@ namespace OpenSim.Region.Framework.Scenes
//The idea is to have a group of method that return a list of avatars meeting some requirement
// ie it could be all m_scenePresences within a certain range of the calling prim/avatar.
+ //
+ // GetAvatars returns a new list of all root agent presences in the scene
+ // GetScenePresences returns a new list of all presences in the scene or a filter may be passed.
+ // GetScenePresence returns the presence with matching UUID or first/last name.
+ // ForEachScenePresence requests the Scene to run a delegate function against all presences.
///
/// Return a list of all avatars in this region.
@@ -4187,7 +4184,7 @@ namespace OpenSim.Region.Framework.Scenes
/// This list is a new object, so it can be iterated over without locking.
///
///
- public ScenePresence[] GetScenePresences()
+ public List GetScenePresences()
{
return m_sceneGraph.GetScenePresences();
}
@@ -4213,6 +4210,28 @@ namespace OpenSim.Region.Framework.Scenes
return m_sceneGraph.GetScenePresence(avatarID);
}
+ ///
+ /// Request the ScenePresence in this region by first/last name.
+ /// Should normally only be a single match, but first is always returned
+ ///
+ ///
+ ///
+ ///
+ public ScenePresence GetScenePresence(string firstName, string lastName)
+ {
+ return m_sceneGraph.GetScenePresence(firstName, lastName);
+ }
+
+ ///
+ /// Request the ScenePresence in this region by localID.
+ ///
+ ///
+ ///
+ public ScenePresence GetScenePresence(uint localID)
+ {
+ return m_sceneGraph.GetScenePresence(localID);
+ }
+
public override bool PresenceChildStatus(UUID avatarID)
{
ScenePresence cp = GetScenePresence(avatarID);
@@ -4228,25 +4247,14 @@ namespace OpenSim.Region.Framework.Scenes
}
///
- ///
+ /// Performs action on all scene presences.
///
///
public void ForEachScenePresence(Action action)
{
- // We don't want to try to send messages if there are no avatars.
if (m_sceneGraph != null)
{
- try
- {
- ScenePresence[] presences = GetScenePresences();
- for (int i = 0; i < presences.Length; i++)
- action(presences[i]);
- }
- catch (Exception e)
- {
- m_log.Info("[BUG] in " + RegionInfo.RegionName + ": " + e.ToString());
- m_log.Info("[BUG] Stack Trace: " + e.StackTrace);
- }
+ m_sceneGraph.ForEachScenePresence(action);
}
}
@@ -4322,20 +4330,7 @@ namespace OpenSim.Region.Framework.Scenes
public void ForEachClient(Action action)
{
- ForEachClient(action, m_useAsyncWhenPossible);
- }
-
- public void ForEachClient(Action action, bool doAsynchronous)
- {
- // FIXME: Asynchronous iteration is disabled until we have a threading model that
- // can support calling this function from an async packet handler without
- // potentially deadlocking
m_clientManager.ForEachSync(action);
-
- //if (doAsynchronous)
- // m_clientManager.ForEach(action);
- //else
- // m_clientManager.ForEachSync(action);
}
public bool TryGetClient(UUID avatarID, out IClientAPI client)
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index db70d6ac05..19298d2274 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -165,9 +165,10 @@ namespace OpenSim.Region.Framework.Scenes
protected internal void UpdatePresences()
{
- ScenePresence[] updateScenePresences = GetScenePresences();
- for (int i = 0; i < updateScenePresences.Length; i++)
- updateScenePresences[i].Update();
+ ForEachScenePresence(delegate(ScenePresence presence)
+ {
+ presence.Update();
+ });
}
protected internal float UpdatePhysics(double elapsed)
@@ -196,9 +197,10 @@ namespace OpenSim.Region.Framework.Scenes
protected internal void UpdateScenePresenceMovement()
{
- ScenePresence[] moveEntities = GetScenePresences();
- for (int i = 0; i < moveEntities.Length; i++)
- moveEntities[i].UpdateMovement();
+ ForEachScenePresence(delegate(ScenePresence presence)
+ {
+ presence.UpdateMovement();
+ });
}
#endregion
@@ -640,18 +642,16 @@ namespace OpenSim.Region.Framework.Scenes
public void RecalculateStats()
{
- ScenePresence[] presences = GetScenePresences();
int rootcount = 0;
int childcount = 0;
- for (int i = 0; i < presences.Length; i++)
+ ForEachScenePresence(delegate(ScenePresence presence)
{
- ScenePresence user = presences[i];
- if (user.IsChildAgent)
+ if (presence.IsChildAgent)
++childcount;
else
++rootcount;
- }
+ });
m_numRootAgents = rootcount;
m_numChildAgents = childcount;
@@ -698,25 +698,6 @@ namespace OpenSim.Region.Framework.Scenes
#endregion
#region Get Methods
-
- ///
- /// Request a List of all scene presences in this scene. This is a new list, so no
- /// locking is required to iterate over it.
- ///
- ///
- protected internal ScenePresence[] GetScenePresences()
- {
- return m_scenePresenceArray;
- }
-
- protected internal List GetAvatars()
- {
- List result =
- GetScenePresences(delegate(ScenePresence scenePresence) { return !scenePresence.IsChildAgent; });
-
- return result;
- }
-
///
/// Get the controlling client for the given avatar, if there is one.
///
@@ -742,44 +723,118 @@ namespace OpenSim.Region.Framework.Scenes
return null;
}
+ // The idea is to have a group of method that return a list of avatars meeting some requirement
+ // ie it could be all m_scenePresences within a certain range of the calling prim/avatar.
+ //
+ // GetAvatars returns a new list of all root agent presences in the scene
+ // GetScenePresences returns a new list of all presences in the scene or a filter may be passed.
+ // GetScenePresence returns the presence with matching UUID or the first presence matching the passed filter.
+ // ForEachScenePresence requests the Scene to run a delegate function against all presences.
+
+ ///
+ /// Request a list of all avatars in this region (no child agents)
+ /// This list is a new object, so it can be iterated over without locking.
+ ///
+ ///
+ public List GetAvatars()
+ {
+ return GetScenePresences(delegate(ScenePresence scenePresence)
+ {
+ return !scenePresence.IsChildAgent;
+ });
+ }
+
+ ///
+ /// Request a list of m_scenePresences in this World
+ /// Returns a copy so it can be iterated without a lock.
+ /// There is no guarantee that presences will remain in the scene after the list is returned.
+ ///
+ ///
+ protected internal List GetScenePresences()
+ {
+ List result;
+ lock (m_scenePresences)
+ {
+ result = new List(m_scenePresenceArray.Length);
+ result.AddRange(m_scenePresenceArray);
+ }
+ return result;
+ }
+
///
/// Request a filtered list of m_scenePresences in this World
+ /// Returns a copy so it can be iterated without a lock.
+ /// There is no guarantee that presences will remain in the scene after the list is returned.
///
///
protected internal List GetScenePresences(FilterAvatarList filter)
{
- // No locking of scene presences here since we're passing back a list...
-
List result = new List();
- ScenePresence[] scenePresences = GetScenePresences();
-
- for (int i = 0; i < scenePresences.Length; i++)
+ // Check each ScenePresence against the filter
+ ForEachScenePresence(delegate(ScenePresence presence)
{
- ScenePresence avatar = scenePresences[i];
- if (filter(avatar))
- result.Add(avatar);
- }
-
+ if (filter(presence))
+ result.Add(presence);
+ });
return result;
}
+ ///
+ /// Request the ScenePresence in this region matching filter.
+ /// Only the first match is returned.
+ ///
+ ///
+ ///
+ ///
+ protected internal ScenePresence GetScenePresence(FilterAvatarList filter)
+ {
+ ScenePresence result = null;
+ // Get all of the ScenePresences
+ List presences = GetScenePresences();
+ foreach (ScenePresence presence in presences)
+ {
+ if (filter(presence))
+ {
+ result = presence;
+ break;
+ }
+ }
+ return result;
+ }
+
+ protected internal ScenePresence GetScenePresence(string firstName, string lastName)
+ {
+ return GetScenePresence(delegate(ScenePresence presence)
+ {
+ return(presence.Firstname == firstName && presence.Lastname == lastName);
+ });
+ }
+
///
/// Request a scene presence by UUID
///
- ///
+ ///
/// null if the agent was not found
protected internal ScenePresence GetScenePresence(UUID agentID)
{
ScenePresence sp;
-
- lock (m_scenePresences)
- {
- m_scenePresences.TryGetValue(agentID, out sp);
- }
-
+ TryGetAvatar(agentID, out sp);
return sp;
}
+ ///
+ /// Request the ScenePresence in this region by localID.
+ ///
+ ///
+ ///
+ protected internal ScenePresence GetScenePresence(uint localID)
+ {
+ return GetScenePresence(delegate(ScenePresence presence)
+ {
+ return (presence.LocalId == localID);
+ });
+ }
+
///
/// Get a scene object group that contains the prim with the given local id
///
@@ -934,29 +989,19 @@ namespace OpenSim.Region.Framework.Scenes
protected internal bool TryGetAvatar(UUID avatarId, out ScenePresence avatar)
{
lock (m_scenePresences)
- return m_scenePresences.TryGetValue(avatarId, out avatar);
+ {
+ m_scenePresences.TryGetValue(avatarId, out avatar);
+ }
+ return (avatar != null);
}
protected internal bool TryGetAvatarByName(string avatarName, out ScenePresence avatar)
{
- ScenePresence[] presences = GetScenePresences();
-
- for (int i = 0; i < presences.Length; i++)
+ avatar = GetScenePresence(delegate(ScenePresence presence)
{
- ScenePresence presence = presences[i];
-
- if (!presence.IsChildAgent)
- {
- if (String.Compare(avatarName, presence.ControllingClient.Name, true) == 0)
- {
- avatar = presence;
- return true;
- }
- }
- }
-
- avatar = null;
- return false;
+ return (String.Compare(avatarName, presence.ControllingClient.Name, true) == 0);
+ });
+ return (avatar != null);
}
///
@@ -1037,6 +1082,28 @@ namespace OpenSim.Region.Framework.Scenes
}
}
}
+
+
+ ///
+ /// Performs action on all scene presences.
+ ///
+ ///
+ public void ForEachScenePresence(Action action)
+ {
+ List presences = GetScenePresences();
+ try
+ {
+ foreach(ScenePresence presence in presences)
+ {
+ action(presence);
+ }
+ }
+ catch (Exception e)
+ {
+ m_log.Info("[BUG] in " + m_parentScene.RegionInfo.RegionName + ": " + e.ToString());
+ m_log.Info("[BUG] Stack Trace: " + e.StackTrace);
+ }
+ }
#endregion
diff --git a/OpenSim/Region/Framework/Scenes/SceneManager.cs b/OpenSim/Region/Framework/Scenes/SceneManager.cs
index 680c39a622..a9555322e3 100644
--- a/OpenSim/Region/Framework/Scenes/SceneManager.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneManager.cs
@@ -414,12 +414,8 @@ namespace OpenSim.Region.Framework.Scenes
ForEachCurrentScene(
delegate(Scene scene)
{
- ScenePresence[] scenePresences = scene.GetScenePresences();
-
- for (int i = 0; i < scenePresences.Length; i++)
+ scene.ForEachScenePresence(delegate(ScenePresence scenePresence)
{
- ScenePresence scenePresence = scenePresences[i];
-
if (!scenePresence.IsChildAgent)
{
m_log.DebugFormat("Packet debug for {0} {1} set to {2}",
@@ -429,7 +425,7 @@ namespace OpenSim.Region.Framework.Scenes
scenePresence.ControllingClient.SetDebugPacketLevel(newDebug);
}
- }
+ });
}
);
}
@@ -441,14 +437,11 @@ namespace OpenSim.Region.Framework.Scenes
ForEachCurrentScene(
delegate(Scene scene)
{
- ScenePresence[] scenePresences = scene.GetScenePresences();
-
- for (int i = 0; i < scenePresences.Length; i++)
+ scene.ForEachScenePresence(delegate(ScenePresence scenePresence)
{
- ScenePresence scenePresence = scenePresences[i];
if (!scenePresence.IsChildAgent)
avatars.Add(scenePresence);
- }
+ });
}
);
@@ -461,7 +454,7 @@ namespace OpenSim.Region.Framework.Scenes
ForEachCurrentScene(delegate(Scene scene)
{
- ScenePresence[] scenePresences = scene.GetScenePresences();
+ List scenePresences = scene.GetScenePresences();
presences.AddRange(scenePresences);
});
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index d083119d09..3895d93457 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -1370,8 +1370,8 @@ namespace OpenSim.Region.Framework.Scenes
{
// part.Inventory.RemoveScriptInstances();
- ScenePresence[] avatars = Scene.GetScenePresences();
- for (int i = 0; i < avatars.Length; i++)
+ List avatars = Scene.GetScenePresences();
+ for (int i = 0; i < avatars.Count; i++)
{
if (avatars[i].ParentID == LocalId)
{
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 48e34ee4f3..539f2b1cb9 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -1208,15 +1208,14 @@ namespace OpenSim.Region.Framework.Scenes
private void SendObjectPropertiesToClient(UUID AgentID)
{
- ScenePresence[] avatars = m_parentGroup.Scene.GetScenePresences();
- for (int i = 0; i < avatars.Length; i++)
+ m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
{
// Ugly reference :(
- if (avatars[i].UUID == AgentID)
+ if (avatar.UUID == AgentID)
{
- m_parentGroup.GetProperties(avatars[i].ControllingClient);
+ m_parentGroup.GetProperties(avatar.ControllingClient);
}
- }
+ });
}
// TODO: unused:
@@ -1271,11 +1270,10 @@ namespace OpenSim.Region.Framework.Scenes
///
public void AddFullUpdateToAllAvatars()
{
- ScenePresence[] avatars = m_parentGroup.Scene.GetScenePresences();
- for (int i = 0; i < avatars.Length; i++)
+ m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
{
- avatars[i].SceneViewer.QueuePartForUpdate(this);
- }
+ avatar.SceneViewer.QueuePartForUpdate(this);
+ });
}
public void AddFullUpdateToAvatar(ScenePresence presence)
@@ -1296,11 +1294,10 @@ namespace OpenSim.Region.Framework.Scenes
/// Terse updates
public void AddTerseUpdateToAllAvatars()
{
- ScenePresence[] avatars = m_parentGroup.Scene.GetScenePresences();
- for (int i = 0; i < avatars.Length; i++)
+ m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
{
- avatars[i].SceneViewer.QueuePartForUpdate(this);
- }
+ avatar.SceneViewer.QueuePartForUpdate(this);
+ });
}
public void AddTerseUpdateToAvatar(ScenePresence presence)
@@ -2137,17 +2134,13 @@ namespace OpenSim.Region.Framework.Scenes
}
else
{
- ScenePresence[] avlist = m_parentGroup.Scene.GetScenePresences();
-
- for (int i = 0; i < avlist.Length; i++)
+ m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence av)
{
- ScenePresence av = avlist[i];
-
if (av.LocalId == localId)
{
if (m_parentGroup.RootPart.CollisionFilter.ContainsValue(av.UUID.ToString()) || m_parentGroup.RootPart.CollisionFilter.ContainsValue(av.Name))
{
- bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1,out data);
+ bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data);
//If it is 1, it is to accept ONLY collisions from this avatar
if (found)
{
@@ -2169,7 +2162,7 @@ namespace OpenSim.Region.Framework.Scenes
}
else
{
- bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1,out data);
+ bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data);
//If it is 1, it is to accept ONLY collisions from this avatar, so this other avatar will not work
if (!found)
{
@@ -2187,7 +2180,7 @@ namespace OpenSim.Region.Framework.Scenes
}
}
- }
+ });
}
}
if (colliding.Count > 0)
@@ -2273,17 +2266,13 @@ namespace OpenSim.Region.Framework.Scenes
}
else
{
- ScenePresence[] avlist = m_parentGroup.Scene.GetScenePresences();
-
- for (int i = 0; i < avlist.Length; i++)
+ m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence av)
{
- ScenePresence av = avlist[i];
-
if (av.LocalId == localId)
{
if (m_parentGroup.RootPart.CollisionFilter.ContainsValue(av.UUID.ToString()) || m_parentGroup.RootPart.CollisionFilter.ContainsValue(av.Name))
{
- bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1,out data);
+ bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data);
//If it is 1, it is to accept ONLY collisions from this avatar
if (found)
{
@@ -2305,7 +2294,7 @@ namespace OpenSim.Region.Framework.Scenes
}
else
{
- bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1,out data);
+ bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data);
//If it is 1, it is to accept ONLY collisions from this avatar, so this other avatar will not work
if (!found)
{
@@ -2323,7 +2312,7 @@ namespace OpenSim.Region.Framework.Scenes
}
}
- }
+ });
}
}
if (colliding.Count > 0)
@@ -2404,17 +2393,13 @@ namespace OpenSim.Region.Framework.Scenes
}
else
{
- ScenePresence[] avlist = m_parentGroup.Scene.GetScenePresences();
-
- for (int i = 0; i < avlist.Length; i++)
+ m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence av)
{
- ScenePresence av = avlist[i];
-
if (av.LocalId == localId)
{
if (m_parentGroup.RootPart.CollisionFilter.ContainsValue(av.UUID.ToString()) || m_parentGroup.RootPart.CollisionFilter.ContainsValue(av.Name))
{
- bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1,out data);
+ bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data);
//If it is 1, it is to accept ONLY collisions from this avatar
if (found)
{
@@ -2436,7 +2421,7 @@ namespace OpenSim.Region.Framework.Scenes
}
else
{
- bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1,out data);
+ bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data);
//If it is 1, it is to accept ONLY collisions from this avatar, so this other avatar will not work
if (!found)
{
@@ -2454,7 +2439,7 @@ namespace OpenSim.Region.Framework.Scenes
}
}
- }
+ });
}
}
@@ -2863,11 +2848,10 @@ namespace OpenSim.Region.Framework.Scenes
///
public void SendFullUpdateToAllClients()
{
- ScenePresence[] avatars = m_parentGroup.Scene.GetScenePresences();
- for (int i = 0; i < avatars.Length; i++)
+ m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
{
- SendFullUpdate(avatars[i].ControllingClient, avatars[i].GenerateClientFlags(UUID));
- }
+ SendFullUpdate(avatar.ControllingClient, avatar.GenerateClientFlags(UUID));
+ });
}
///
@@ -2876,13 +2860,12 @@ namespace OpenSim.Region.Framework.Scenes
///
public void SendFullUpdateToAllClientsExcept(UUID agentID)
{
- ScenePresence[] avatars = m_parentGroup.Scene.GetScenePresences();
- for (int i = 0; i < avatars.Length; i++)
+ m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
{
// Ugly reference :(
- if (avatars[i].UUID != agentID)
- SendFullUpdate(avatars[i].ControllingClient, avatars[i].GenerateClientFlags(UUID));
- }
+ if (avatar.UUID != agentID)
+ SendFullUpdate(avatar.ControllingClient, avatar.GenerateClientFlags(UUID));
+ });
}
///
@@ -3083,11 +3066,10 @@ namespace OpenSim.Region.Framework.Scenes
///
public void SendTerseUpdateToAllClients()
{
- ScenePresence[] avatars = m_parentGroup.Scene.GetScenePresences();
- for (int i = 0; i < avatars.Length; i++)
+ m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
{
- SendTerseUpdateToClient(avatars[i].ControllingClient);
- }
+ SendTerseUpdateToClient(avatar.ControllingClient);
+ });
}
public void SetAttachmentPoint(uint AttachmentPoint)
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 608e84c657..1e530e1c2f 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -881,7 +881,7 @@ namespace OpenSim.Region.Framework.Scenes
if (land != null)
{
//Don't restrict gods, estate managers, or land owners to the TP point. This behaviour mimics agni.
- if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero && m_godLevel < 200 && !m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid) && land.LandData.OwnerID != m_uuid)
+ if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero && m_userLevel < 200 && !m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid) && land.LandData.OwnerID != m_uuid)
{
pos = land.LandData.UserLocation;
}
@@ -959,14 +959,11 @@ namespace OpenSim.Region.Framework.Scenes
m_isChildAgent = false;
- ScenePresence[] animAgents = m_scene.GetScenePresences();
- for (int i = 0; i < animAgents.Length; i++)
+ m_scene.ForEachScenePresence(delegate(ScenePresence presence)
{
- ScenePresence presence = animAgents[i];
-
if (presence != this)
presence.Animator.SendAnimPackToClient(ControllingClient);
- }
+ });
m_scene.EventManager.TriggerOnMakeRootAgent(this);
}
@@ -2671,13 +2668,10 @@ Console.WriteLine("Scripted Sit ofset {0}", m_pos);
public void SendInitialFullUpdateToAllClients()
{
m_perfMonMS = Util.EnvironmentTickCount();
-
- ScenePresence[] avatars = m_scene.GetScenePresences();
-
- for (int i = 0; i < avatars.Length; i++)
+ int avUpdates = 0;
+ m_scene.ForEachScenePresence(delegate(ScenePresence avatar)
{
- ScenePresence avatar = avatars[i];
-
+ ++avUpdates;
// only send if this is the root (children are only "listening posts" in a foreign region)
if (!IsChildAgent)
{
@@ -2693,9 +2687,9 @@ Console.WriteLine("Scripted Sit ofset {0}", m_pos);
avatar.Animator.SendAnimPackToClient(ControllingClient);
}
}
- }
+ });
- m_scene.StatsReporter.AddAgentUpdates(avatars.Length);
+ m_scene.StatsReporter.AddAgentUpdates(avUpdates);
m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
//Animator.SendAnimPack();
diff --git a/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
index 6686264ec1..8b80ebe3dc 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
@@ -61,7 +61,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
AssetBase corruptAsset = AssetHelpers.CreateAsset(corruptAssetUuid, "CORRUPT ASSET", UUID.Zero);
m_assetService.Store(corruptAsset);
- IDictionary foundAssetUuids = new Dictionary();
+ IDictionary foundAssetUuids = new Dictionary();
m_uuidGatherer.GatherAssetUuids(corruptAssetUuid, AssetType.Object, foundAssetUuids);
// We count the uuid as gathered even if the asset itself is corrupt.
@@ -77,7 +77,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
TestHelper.InMethod();
UUID missingAssetUuid = UUID.Parse("00000000-0000-0000-0000-000000000666");
- IDictionary foundAssetUuids = new Dictionary();
+ IDictionary foundAssetUuids = new Dictionary();
m_uuidGatherer.GatherAssetUuids(missingAssetUuid, AssetType.Object, foundAssetUuids);
diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
index 3edb6775cf..0ec3cc3c73 100644
--- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
+++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
@@ -84,9 +84,9 @@ namespace OpenSim.Region.Framework.Scenes
/// The uuid of the asset for which to gather referenced assets
/// The type of the asset for the uuid given
/// The assets gathered
- public void GatherAssetUuids(UUID assetUuid, AssetType assetType, IDictionary assetUuids)
+ public void GatherAssetUuids(UUID assetUuid, AssetType assetType, IDictionary assetUuids)
{
- assetUuids[assetUuid] = 1;
+ assetUuids[assetUuid] = assetType;
if (AssetType.Bodypart == assetType || AssetType.Clothing == assetType)
{
@@ -116,7 +116,7 @@ namespace OpenSim.Region.Framework.Scenes
///
/// The scene object for which to gather assets
/// The assets gathered
- public void GatherAssetUuids(SceneObjectGroup sceneObject, IDictionary assetUuids)
+ public void GatherAssetUuids(SceneObjectGroup sceneObject, IDictionary assetUuids)
{
// m_log.DebugFormat(
// "[ASSET GATHERER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID);
@@ -129,25 +129,26 @@ namespace OpenSim.Region.Framework.Scenes
try
{
Primitive.TextureEntry textureEntry = part.Shape.Textures;
-
- // Get the prim's default texture. This will be used for faces which don't have their own texture
- assetUuids[textureEntry.DefaultTexture.TextureID] = 1;
-
- // XXX: Not a great way to iterate through face textures, but there's no
- // other method available to tell how many faces there actually are
- //int i = 0;
- foreach (Primitive.TextureEntryFace texture in textureEntry.FaceTextures)
+ if (textureEntry != null)
{
- if (texture != null)
+ // Get the prim's default texture. This will be used for faces which don't have their own texture
+ if (textureEntry.DefaultTexture != null)
+ assetUuids[textureEntry.DefaultTexture.TextureID] = AssetType.Texture;
+
+ if (textureEntry.FaceTextures != null)
{
- //m_log.DebugFormat("[ARCHIVER]: Got face {0}", i++);
- assetUuids[texture.TextureID] = 1;
+ // Loop through the rest of the texture faces (a non-null face means the face is different from DefaultTexture)
+ foreach (Primitive.TextureEntryFace texture in textureEntry.FaceTextures)
+ {
+ if (texture != null)
+ assetUuids[texture.TextureID] = AssetType.Texture;
+ }
}
}
// If the prim is a sculpt then preserve this information too
if (part.Shape.SculptTexture != UUID.Zero)
- assetUuids[part.Shape.SculptTexture] = 1;
+ assetUuids[part.Shape.SculptTexture] = AssetType.Texture;
TaskInventoryDictionary taskDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone();
@@ -217,7 +218,7 @@ namespace OpenSim.Region.Framework.Scenes
///
///
/// Dictionary in which to record the references
- protected void GetScriptAssetUuids(UUID scriptUuid, IDictionary assetUuids)
+ protected void GetScriptAssetUuids(UUID scriptUuid, IDictionary assetUuids)
{
AssetBase scriptAsset = GetAsset(scriptUuid);
@@ -232,7 +233,9 @@ namespace OpenSim.Region.Framework.Scenes
{
UUID uuid = new UUID(uuidMatch.Value);
//m_log.DebugFormat("[ARCHIVER]: Recording {0} in script", uuid);
- assetUuids[uuid] = 1;
+
+ // Assume AssetIDs embedded in scripts are textures
+ assetUuids[uuid] = AssetType.Texture;
}
}
}
@@ -242,7 +245,7 @@ namespace OpenSim.Region.Framework.Scenes
///
///
/// Dictionary in which to record the references
- protected void GetWearableAssetUuids(UUID wearableAssetUuid, IDictionary assetUuids)
+ protected void GetWearableAssetUuids(UUID wearableAssetUuid, IDictionary assetUuids)
{
AssetBase assetBase = GetAsset(wearableAssetUuid);
@@ -257,8 +260,7 @@ namespace OpenSim.Region.Framework.Scenes
foreach (UUID uuid in wearableAsset.Textures.Values)
{
- //m_log.DebugFormat("[ARCHIVER]: Got bodypart uuid {0}", uuid);
- assetUuids[uuid] = 1;
+ assetUuids[uuid] = AssetType.Texture;
}
}
}
@@ -270,7 +272,7 @@ namespace OpenSim.Region.Framework.Scenes
///
///
///
- protected void GetSceneObjectAssetUuids(UUID sceneObjectUuid, IDictionary assetUuids)
+ protected void GetSceneObjectAssetUuids(UUID sceneObjectUuid, IDictionary assetUuids)
{
AssetBase objectAsset = GetAsset(sceneObjectUuid);
@@ -284,7 +286,7 @@ namespace OpenSim.Region.Framework.Scenes
}
}
- protected void GetGestureAssetUuids(UUID gestureUuid, IDictionary assetUuids)
+ protected void GetGestureAssetUuids(UUID gestureUuid, IDictionary assetUuids)
{
AssetBase assetBase = GetAsset(gestureUuid);
@@ -316,7 +318,7 @@ namespace OpenSim.Region.Framework.Scenes
// If it can be parsed as a UUID, it is an asset ID
UUID uuid;
if (UUID.TryParse(id, out uuid))
- assetUuids[uuid] = 1;
+ assetUuids[uuid] = AssetType.Animation;
}
}
}
diff --git a/OpenSim/Region/Physics/Meshing/PrimMesher.cs b/OpenSim/Region/Physics/Meshing/PrimMesher.cs
index 6e9654bb38..932943c081 100644
--- a/OpenSim/Region/Physics/Meshing/PrimMesher.cs
+++ b/OpenSim/Region/Physics/Meshing/PrimMesher.cs
@@ -1,2201 +1,2201 @@
-/*
- * Copyright (c) Contributors
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the OpenSimulator Project nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.IO;
-
-namespace PrimMesher
-{
- public struct Quat
- {
- /// X value
- public float X;
- /// Y value
- public float Y;
- /// Z value
- public float Z;
- /// W value
- public float W;
-
- public Quat(float x, float y, float z, float w)
- {
- X = x;
- Y = y;
- Z = z;
- W = w;
- }
-
- public Quat(Coord axis, float angle)
- {
- axis = axis.Normalize();
-
- angle *= 0.5f;
- float c = (float)Math.Cos(angle);
- float s = (float)Math.Sin(angle);
-
- X = axis.X * s;
- Y = axis.Y * s;
- Z = axis.Z * s;
- W = c;
-
- Normalize();
- }
-
- public float Length()
- {
- return (float)Math.Sqrt(X * X + Y * Y + Z * Z + W * W);
- }
-
- public Quat Normalize()
- {
- const float MAG_THRESHOLD = 0.0000001f;
- float mag = Length();
-
- // Catch very small rounding errors when normalizing
- if (mag > MAG_THRESHOLD)
- {
- float oomag = 1f / mag;
- X *= oomag;
- Y *= oomag;
- Z *= oomag;
- W *= oomag;
- }
- else
- {
- X = 0f;
- Y = 0f;
- Z = 0f;
- W = 1f;
- }
-
- return this;
- }
-
- public static Quat operator *(Quat q1, Quat q2)
- {
- float x = q1.W * q2.X + q1.X * q2.W + q1.Y * q2.Z - q1.Z * q2.Y;
- float y = q1.W * q2.Y - q1.X * q2.Z + q1.Y * q2.W + q1.Z * q2.X;
- float z = q1.W * q2.Z + q1.X * q2.Y - q1.Y * q2.X + q1.Z * q2.W;
- float w = q1.W * q2.W - q1.X * q2.X - q1.Y * q2.Y - q1.Z * q2.Z;
- return new Quat(x, y, z, w);
- }
-
- public override string ToString()
- {
- return "< X: " + this.X.ToString() + ", Y: " + this.Y.ToString() + ", Z: " + this.Z.ToString() + ", W: " + this.W.ToString() + ">";
- }
- }
-
- public struct Coord
- {
- public float X;
- public float Y;
- public float Z;
-
- public Coord(float x, float y, float z)
- {
- this.X = x;
- this.Y = y;
- this.Z = z;
- }
-
- public float Length()
- {
- return (float)Math.Sqrt(this.X * this.X + this.Y * this.Y + this.Z * this.Z);
- }
-
- public Coord Invert()
- {
- this.X = -this.X;
- this.Y = -this.Y;
- this.Z = -this.Z;
-
- return this;
- }
-
- public Coord Normalize()
- {
- const float MAG_THRESHOLD = 0.0000001f;
- float mag = Length();
-
- // Catch very small rounding errors when normalizing
- if (mag > MAG_THRESHOLD)
- {
- float oomag = 1.0f / mag;
- this.X *= oomag;
- this.Y *= oomag;
- this.Z *= oomag;
- }
- else
- {
- this.X = 0.0f;
- this.Y = 0.0f;
- this.Z = 0.0f;
- }
-
- return this;
- }
-
- public override string ToString()
- {
- return this.X.ToString() + " " + this.Y.ToString() + " " + this.Z.ToString();
- }
-
- public static Coord Cross(Coord c1, Coord c2)
- {
- return new Coord(
- c1.Y * c2.Z - c2.Y * c1.Z,
- c1.Z * c2.X - c2.Z * c1.X,
- c1.X * c2.Y - c2.X * c1.Y
- );
- }
-
- public static Coord operator +(Coord v, Coord a)
- {
- return new Coord(v.X + a.X, v.Y + a.Y, v.Z + a.Z);
- }
-
- public static Coord operator *(Coord v, Coord m)
- {
- return new Coord(v.X * m.X, v.Y * m.Y, v.Z * m.Z);
- }
-
- public static Coord operator *(Coord v, Quat q)
- {
- // From http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/transforms/
-
- Coord c2 = new Coord(0.0f, 0.0f, 0.0f);
-
- c2.X = q.W * q.W * v.X +
- 2f * q.Y * q.W * v.Z -
- 2f * q.Z * q.W * v.Y +
- q.X * q.X * v.X +
- 2f * q.Y * q.X * v.Y +
- 2f * q.Z * q.X * v.Z -
- q.Z * q.Z * v.X -
- q.Y * q.Y * v.X;
-
- c2.Y =
- 2f * q.X * q.Y * v.X +
- q.Y * q.Y * v.Y +
- 2f * q.Z * q.Y * v.Z +
- 2f * q.W * q.Z * v.X -
- q.Z * q.Z * v.Y +
- q.W * q.W * v.Y -
- 2f * q.X * q.W * v.Z -
- q.X * q.X * v.Y;
-
- c2.Z =
- 2f * q.X * q.Z * v.X +
- 2f * q.Y * q.Z * v.Y +
- q.Z * q.Z * v.Z -
- 2f * q.W * q.Y * v.X -
- q.Y * q.Y * v.Z +
- 2f * q.W * q.X * v.Y -
- q.X * q.X * v.Z +
- q.W * q.W * v.Z;
-
- return c2;
- }
- }
-
- public struct UVCoord
- {
- public float U;
- public float V;
-
-
- public UVCoord(float u, float v)
- {
- this.U = u;
- this.V = v;
- }
- }
-
- public struct Face
- {
- public int primFace;
-
- // vertices
- public int v1;
- public int v2;
- public int v3;
-
- //normals
- public int n1;
- public int n2;
- public int n3;
-
- // uvs
- public int uv1;
- public int uv2;
- public int uv3;
-
-
- public Face(int v1, int v2, int v3)
- {
- primFace = 0;
-
- this.v1 = v1;
- this.v2 = v2;
- this.v3 = v3;
-
- this.n1 = 0;
- this.n2 = 0;
- this.n3 = 0;
-
- this.uv1 = 0;
- this.uv2 = 0;
- this.uv3 = 0;
-
- }
-
- public Face(int v1, int v2, int v3, int n1, int n2, int n3)
- {
- primFace = 0;
-
- this.v1 = v1;
- this.v2 = v2;
- this.v3 = v3;
-
- this.n1 = n1;
- this.n2 = n2;
- this.n3 = n3;
-
- this.uv1 = 0;
- this.uv2 = 0;
- this.uv3 = 0;
- }
-
- public Coord SurfaceNormal(List coordList)
- {
- Coord c1 = coordList[this.v1];
- Coord c2 = coordList[this.v2];
- Coord c3 = coordList[this.v3];
-
- Coord edge1 = new Coord(c2.X - c1.X, c2.Y - c1.Y, c2.Z - c1.Z);
- Coord edge2 = new Coord(c3.X - c1.X, c3.Y - c1.Y, c3.Z - c1.Z);
-
- return Coord.Cross(edge1, edge2).Normalize();
- }
- }
-
- public struct ViewerFace
- {
- public int primFaceNumber;
-
- public Coord v1;
- public Coord v2;
- public Coord v3;
-
- public int coordIndex1;
- public int coordIndex2;
- public int coordIndex3;
-
- public Coord n1;
- public Coord n2;
- public Coord n3;
-
- public UVCoord uv1;
- public UVCoord uv2;
- public UVCoord uv3;
-
- public ViewerFace(int primFaceNumber)
- {
- this.primFaceNumber = primFaceNumber;
-
- this.v1 = new Coord();
- this.v2 = new Coord();
- this.v3 = new Coord();
-
- this.coordIndex1 = this.coordIndex2 = this.coordIndex3 = -1; // -1 means not assigned yet
-
- this.n1 = new Coord();
- this.n2 = new Coord();
- this.n3 = new Coord();
-
- this.uv1 = new UVCoord();
- this.uv2 = new UVCoord();
- this.uv3 = new UVCoord();
- }
-
- public void Scale(float x, float y, float z)
- {
- this.v1.X *= x;
- this.v1.Y *= y;
- this.v1.Z *= z;
-
- this.v2.X *= x;
- this.v2.Y *= y;
- this.v2.Z *= z;
-
- this.v3.X *= x;
- this.v3.Y *= y;
- this.v3.Z *= z;
- }
-
- public void AddPos(float x, float y, float z)
- {
- this.v1.X += x;
- this.v2.X += x;
- this.v3.X += x;
-
- this.v1.Y += y;
- this.v2.Y += y;
- this.v3.Y += y;
-
- this.v1.Z += z;
- this.v2.Z += z;
- this.v3.Z += z;
- }
-
- public void AddRot(Quat q)
- {
- this.v1 *= q;
- this.v2 *= q;
- this.v3 *= q;
-
- this.n1 *= q;
- this.n2 *= q;
- this.n3 *= q;
- }
-
- public void CalcSurfaceNormal()
- {
-
- Coord edge1 = new Coord(this.v2.X - this.v1.X, this.v2.Y - this.v1.Y, this.v2.Z - this.v1.Z);
- Coord edge2 = new Coord(this.v3.X - this.v1.X, this.v3.Y - this.v1.Y, this.v3.Z - this.v1.Z);
-
- this.n1 = this.n2 = this.n3 = Coord.Cross(edge1, edge2).Normalize();
- }
- }
-
- internal struct Angle
- {
- internal float angle;
- internal float X;
- internal float Y;
-
- internal Angle(float angle, float x, float y)
- {
- this.angle = angle;
- this.X = x;
- this.Y = y;
- }
- }
-
- internal class AngleList
- {
- private float iX, iY; // intersection point
-
- private static Angle[] angles3 =
- {
- new Angle(0.0f, 1.0f, 0.0f),
- new Angle(0.33333333333333333f, -0.5f, 0.86602540378443871f),
- new Angle(0.66666666666666667f, -0.5f, -0.86602540378443837f),
- new Angle(1.0f, 1.0f, 0.0f)
- };
-
- private static Coord[] normals3 =
- {
- new Coord(0.25f, 0.4330127019f, 0.0f).Normalize(),
- new Coord(-0.5f, 0.0f, 0.0f).Normalize(),
- new Coord(0.25f, -0.4330127019f, 0.0f).Normalize(),
- new Coord(0.25f, 0.4330127019f, 0.0f).Normalize()
- };
-
- private static Angle[] angles4 =
- {
- new Angle(0.0f, 1.0f, 0.0f),
- new Angle(0.25f, 0.0f, 1.0f),
- new Angle(0.5f, -1.0f, 0.0f),
- new Angle(0.75f, 0.0f, -1.0f),
- new Angle(1.0f, 1.0f, 0.0f)
- };
-
- private static Coord[] normals4 =
- {
- new Coord(0.5f, 0.5f, 0.0f).Normalize(),
- new Coord(-0.5f, 0.5f, 0.0f).Normalize(),
- new Coord(-0.5f, -0.5f, 0.0f).Normalize(),
- new Coord(0.5f, -0.5f, 0.0f).Normalize(),
- new Coord(0.5f, 0.5f, 0.0f).Normalize()
- };
-
- private static Angle[] angles24 =
- {
- new Angle(0.0f, 1.0f, 0.0f),
- new Angle(0.041666666666666664f, 0.96592582628906831f, 0.25881904510252074f),
- new Angle(0.083333333333333329f, 0.86602540378443871f, 0.5f),
- new Angle(0.125f, 0.70710678118654757f, 0.70710678118654746f),
- new Angle(0.16666666666666667f, 0.5f, 0.8660254037844386f),
- new Angle(0.20833333333333331f, 0.25881904510252096f, 0.9659258262890682f),
- new Angle(0.25f, 0.0f, 1.0f),
- new Angle(0.29166666666666663f, -0.25881904510252063f, 0.96592582628906831f),
- new Angle(0.33333333333333333f, -0.5f, 0.86602540378443871f),
- new Angle(0.375f, -0.70710678118654746f, 0.70710678118654757f),
- new Angle(0.41666666666666663f, -0.86602540378443849f, 0.5f),
- new Angle(0.45833333333333331f, -0.9659258262890682f, 0.25881904510252102f),
- new Angle(0.5f, -1.0f, 0.0f),
- new Angle(0.54166666666666663f, -0.96592582628906842f, -0.25881904510252035f),
- new Angle(0.58333333333333326f, -0.86602540378443882f, -0.5f),
- new Angle(0.62499999999999989f, -0.70710678118654791f, -0.70710678118654713f),
- new Angle(0.66666666666666667f, -0.5f, -0.86602540378443837f),
- new Angle(0.70833333333333326f, -0.25881904510252152f, -0.96592582628906809f),
- new Angle(0.75f, 0.0f, -1.0f),
- new Angle(0.79166666666666663f, 0.2588190451025203f, -0.96592582628906842f),
- new Angle(0.83333333333333326f, 0.5f, -0.86602540378443904f),
- new Angle(0.875f, 0.70710678118654735f, -0.70710678118654768f),
- new Angle(0.91666666666666663f, 0.86602540378443837f, -0.5f),
- new Angle(0.95833333333333326f, 0.96592582628906809f, -0.25881904510252157f),
- new Angle(1.0f, 1.0f, 0.0f)
- };
-
- private Angle interpolatePoints(float newPoint, Angle p1, Angle p2)
- {
- float m = (newPoint - p1.angle) / (p2.angle - p1.angle);
- return new Angle(newPoint, p1.X + m * (p2.X - p1.X), p1.Y + m * (p2.Y - p1.Y));
- }
-
- private void intersection(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)
- { // ref: http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/
- double denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
- double uaNumerator = (x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3);
-
- if (denom != 0.0)
- {
- double ua = uaNumerator / denom;
- iX = (float)(x1 + ua * (x2 - x1));
- iY = (float)(y1 + ua * (y2 - y1));
- }
- }
-
- internal List angles;
- internal List normals;
-
- internal void makeAngles(int sides, float startAngle, float stopAngle)
- {
- angles = new List();
- normals = new List();
-
- double twoPi = System.Math.PI * 2.0;
- float twoPiInv = 1.0f / (float)twoPi;
-
- if (sides < 1)
- throw new Exception("number of sides not greater than zero");
- if (stopAngle <= startAngle)
- throw new Exception("stopAngle not greater than startAngle");
-
- if ((sides == 3 || sides == 4 || sides == 24))
- {
- startAngle *= twoPiInv;
- stopAngle *= twoPiInv;
-
- Angle[] sourceAngles;
- if (sides == 3)
- sourceAngles = angles3;
- else if (sides == 4)
- sourceAngles = angles4;
- else sourceAngles = angles24;
-
- int startAngleIndex = (int)(startAngle * sides);
- int endAngleIndex = sourceAngles.Length - 1;
- if (stopAngle < 1.0f)
- endAngleIndex = (int)(stopAngle * sides) + 1;
- if (endAngleIndex == startAngleIndex)
- endAngleIndex++;
-
- for (int angleIndex = startAngleIndex; angleIndex < endAngleIndex + 1; angleIndex++)
- {
- angles.Add(sourceAngles[angleIndex]);
- if (sides == 3)
- normals.Add(normals3[angleIndex]);
- else if (sides == 4)
- normals.Add(normals4[angleIndex]);
- }
-
- if (startAngle > 0.0f)
- angles[0] = interpolatePoints(startAngle, angles[0], angles[1]);
-
- if (stopAngle < 1.0f)
- {
- int lastAngleIndex = angles.Count - 1;
- angles[lastAngleIndex] = interpolatePoints(stopAngle, angles[lastAngleIndex - 1], angles[lastAngleIndex]);
- }
- }
- else
- {
- double stepSize = twoPi / sides;
-
- int startStep = (int)(startAngle / stepSize);
- double angle = stepSize * startStep;
- int step = startStep;
- double stopAngleTest = stopAngle;
- if (stopAngle < twoPi)
- {
- stopAngleTest = stepSize * ((int)(stopAngle / stepSize) + 1);
- if (stopAngleTest < stopAngle)
- stopAngleTest += stepSize;
- if (stopAngleTest > twoPi)
- stopAngleTest = twoPi;
- }
-
- while (angle <= stopAngleTest)
- {
- Angle newAngle;
- newAngle.angle = (float)angle;
- newAngle.X = (float)System.Math.Cos(angle);
- newAngle.Y = (float)System.Math.Sin(angle);
- angles.Add(newAngle);
- step += 1;
- angle = stepSize * step;
- }
-
- if (startAngle > angles[0].angle)
- {
- Angle newAngle;
- intersection(angles[0].X, angles[0].Y, angles[1].X, angles[1].Y, 0.0f, 0.0f, (float)Math.Cos(startAngle), (float)Math.Sin(startAngle));
- newAngle.angle = startAngle;
- newAngle.X = iX;
- newAngle.Y = iY;
- angles[0] = newAngle;
- }
-
- int index = angles.Count - 1;
- if (stopAngle < angles[index].angle)
- {
- Angle newAngle;
- intersection(angles[index - 1].X, angles[index - 1].Y, angles[index].X, angles[index].Y, 0.0f, 0.0f, (float)Math.Cos(stopAngle), (float)Math.Sin(stopAngle));
- newAngle.angle = stopAngle;
- newAngle.X = iX;
- newAngle.Y = iY;
- angles[index] = newAngle;
- }
- }
- }
- }
-
- ///
- /// generates a profile for extrusion
- ///
- internal class Profile
- {
- private const float twoPi = 2.0f * (float)Math.PI;
-
- internal string errorMessage = null;
-
- internal List coords;
- internal List faces;
- internal List vertexNormals;
- internal List us;
- internal List faceUVs;
- internal List faceNumbers;
-
- // use these for making individual meshes for each prim face
- internal List outerCoordIndices = null;
- internal List hollowCoordIndices = null;
- internal List cut1CoordIndices = null;
- internal List cut2CoordIndices = null;
-
- internal Coord faceNormal = new Coord(0.0f, 0.0f, 1.0f);
- internal Coord cutNormal1 = new Coord();
- internal Coord cutNormal2 = new Coord();
-
- internal int numOuterVerts = 0;
- internal int numHollowVerts = 0;
-
- internal bool calcVertexNormals = false;
- internal int bottomFaceNumber = 0;
- internal int numPrimFaces = 0;
-
- internal Profile()
- {
- this.coords = new List();
- this.faces = new List();
- this.vertexNormals = new List();
- this.us = new List();
- this.faceUVs = new List();
- this.faceNumbers = new List();
- }
-
- internal Profile(int sides, float profileStart, float profileEnd, float hollow, int hollowSides, bool createFaces, bool calcVertexNormals)
- {
- this.calcVertexNormals = calcVertexNormals;
- this.coords = new List();
- this.faces = new List();
- this.vertexNormals = new List();
- this.us = new List();
- this.faceUVs = new List();
- this.faceNumbers = new List();
-
- Coord center = new Coord(0.0f, 0.0f, 0.0f);
- //bool hasCenter = false;
-
- List hollowCoords = new List();
- List hollowNormals = new List();
- List hollowUs = new List();
-
- if (calcVertexNormals)
- {
- this.outerCoordIndices = new List();
- this.hollowCoordIndices = new List();
- this.cut1CoordIndices = new List();
- this.cut2CoordIndices = new List();
- }
-
- bool hasHollow = (hollow > 0.0f);
-
- bool hasProfileCut = (profileStart > 0.0f || profileEnd < 1.0f);
-
- AngleList angles = new AngleList();
- AngleList hollowAngles = new AngleList();
-
- float xScale = 0.5f;
- float yScale = 0.5f;
- if (sides == 4) // corners of a square are sqrt(2) from center
- {
- xScale = 0.707f;
- yScale = 0.707f;
- }
-
- float startAngle = profileStart * twoPi;
- float stopAngle = profileEnd * twoPi;
-
- try { angles.makeAngles(sides, startAngle, stopAngle); }
- catch (Exception ex)
- {
-
- errorMessage = "makeAngles failed: Exception: " + ex.ToString()
- + "\nsides: " + sides.ToString() + " startAngle: " + startAngle.ToString() + " stopAngle: " + stopAngle.ToString();
-
- return;
- }
-
- this.numOuterVerts = angles.angles.Count;
-
- // flag to create as few triangles as possible for 3 or 4 side profile
- bool simpleFace = (sides < 5 && !hasHollow && !hasProfileCut);
-
- if (hasHollow)
- {
- if (sides == hollowSides)
- hollowAngles = angles;
- else
- {
- try { hollowAngles.makeAngles(hollowSides, startAngle, stopAngle); }
- catch (Exception ex)
- {
- errorMessage = "makeAngles failed: Exception: " + ex.ToString()
- + "\nsides: " + sides.ToString() + " startAngle: " + startAngle.ToString() + " stopAngle: " + stopAngle.ToString();
-
- return;
- }
- }
- this.numHollowVerts = hollowAngles.angles.Count;
- }
- else if (!simpleFace)
- {
- this.coords.Add(center);
- //hasCenter = true;
- if (this.calcVertexNormals)
- this.vertexNormals.Add(new Coord(0.0f, 0.0f, 1.0f));
- this.us.Add(0.0f);
- }
-
- float z = 0.0f;
-
- Angle angle;
- Coord newVert = new Coord();
- if (hasHollow && hollowSides != sides)
- {
- int numHollowAngles = hollowAngles.angles.Count;
- for (int i = 0; i < numHollowAngles; i++)
- {
- angle = hollowAngles.angles[i];
- newVert.X = hollow * xScale * angle.X;
- newVert.Y = hollow * yScale * angle.Y;
- newVert.Z = z;
-
- hollowCoords.Add(newVert);
- if (this.calcVertexNormals)
- {
- if (hollowSides < 5)
- hollowNormals.Add(hollowAngles.normals[i].Invert());
- else
- hollowNormals.Add(new Coord(-angle.X, -angle.Y, 0.0f));
-
- hollowUs.Add(angle.angle * hollow);
- }
- }
- }
-
- int index = 0;
- int numAngles = angles.angles.Count;
-
- for (int i = 0; i < numAngles; i++)
- {
- angle = angles.angles[i];
- newVert.X = angle.X * xScale;
- newVert.Y = angle.Y * yScale;
- newVert.Z = z;
- this.coords.Add(newVert);
- if (this.calcVertexNormals)
- {
- this.outerCoordIndices.Add(this.coords.Count - 1);
-
- if (sides < 5)
- {
- this.vertexNormals.Add(angles.normals[i]);
- float u = angle.angle;
- this.us.Add(u);
- }
- else
- {
- this.vertexNormals.Add(new Coord(angle.X, angle.Y, 0.0f));
- this.us.Add(angle.angle);
- }
- }
-
- if (hasHollow)
- {
- if (hollowSides == sides)
- {
- newVert.X *= hollow;
- newVert.Y *= hollow;
- newVert.Z = z;
- hollowCoords.Add(newVert);
- if (this.calcVertexNormals)
- {
- if (sides < 5)
- {
- hollowNormals.Add(angles.normals[i].Invert());
- }
-
- else
- hollowNormals.Add(new Coord(-angle.X, -angle.Y, 0.0f));
-
- hollowUs.Add(angle.angle * hollow);
- }
- }
- }
- else if (!simpleFace && createFaces && angle.angle > 0.0001f)
- {
- Face newFace = new Face();
- newFace.v1 = 0;
- newFace.v2 = index;
- newFace.v3 = index + 1;
-
- this.faces.Add(newFace);
- }
- index += 1;
- }
-
- if (hasHollow)
- {
- hollowCoords.Reverse();
- if (this.calcVertexNormals)
- {
- hollowNormals.Reverse();
- hollowUs.Reverse();
- }
-
- if (createFaces)
- {
- //int numOuterVerts = this.coords.Count;
- //numOuterVerts = this.coords.Count;
- //int numHollowVerts = hollowCoords.Count;
- int numTotalVerts = this.numOuterVerts + this.numHollowVerts;
-
- if (this.numOuterVerts == this.numHollowVerts)
- {
- Face newFace = new Face();
-
- for (int coordIndex = 0; coordIndex < this.numOuterVerts - 1; coordIndex++)
- {
- newFace.v1 = coordIndex;
- newFace.v2 = coordIndex + 1;
- newFace.v3 = numTotalVerts - coordIndex - 1;
- this.faces.Add(newFace);
-
- newFace.v1 = coordIndex + 1;
- newFace.v2 = numTotalVerts - coordIndex - 2;
- newFace.v3 = numTotalVerts - coordIndex - 1;
- this.faces.Add(newFace);
- }
- }
- else
- {
- if (this.numOuterVerts < this.numHollowVerts)
- {
- Face newFace = new Face();
- int j = 0; // j is the index for outer vertices
- int maxJ = this.numOuterVerts - 1;
- for (int i = 0; i < this.numHollowVerts; i++) // i is the index for inner vertices
- {
- if (j < maxJ)
- if (angles.angles[j + 1].angle - hollowAngles.angles[i].angle < hollowAngles.angles[i].angle - angles.angles[j].angle + 0.000001f)
- {
- newFace.v1 = numTotalVerts - i - 1;
- newFace.v2 = j;
- newFace.v3 = j + 1;
-
- this.faces.Add(newFace);
- j += 1;
- }
-
- newFace.v1 = j;
- newFace.v2 = numTotalVerts - i - 2;
- newFace.v3 = numTotalVerts - i - 1;
-
- this.faces.Add(newFace);
- }
- }
- else // numHollowVerts < numOuterVerts
- {
- Face newFace = new Face();
- int j = 0; // j is the index for inner vertices
- int maxJ = this.numHollowVerts - 1;
- for (int i = 0; i < this.numOuterVerts; i++)
- {
- if (j < maxJ)
- if (hollowAngles.angles[j + 1].angle - angles.angles[i].angle < angles.angles[i].angle - hollowAngles.angles[j].angle + 0.000001f)
- {
- newFace.v1 = i;
- newFace.v2 = numTotalVerts - j - 2;
- newFace.v3 = numTotalVerts - j - 1;
-
- this.faces.Add(newFace);
- j += 1;
- }
-
- newFace.v1 = numTotalVerts - j - 1;
- newFace.v2 = i;
- newFace.v3 = i + 1;
-
- this.faces.Add(newFace);
- }
- }
- }
- }
-
- if (calcVertexNormals)
- {
- foreach (Coord hc in hollowCoords)
- {
- this.coords.Add(hc);
- hollowCoordIndices.Add(this.coords.Count - 1);
- }
- }
- else
- this.coords.AddRange(hollowCoords);
-
- if (this.calcVertexNormals)
- {
- this.vertexNormals.AddRange(hollowNormals);
- this.us.AddRange(hollowUs);
-
- }
- }
-
- if (simpleFace && createFaces)
- {
- if (sides == 3)
- this.faces.Add(new Face(0, 1, 2));
- else if (sides == 4)
- {
- this.faces.Add(new Face(0, 1, 2));
- this.faces.Add(new Face(0, 2, 3));
- }
- }
-
- if (calcVertexNormals && hasProfileCut)
- {
- if (hasHollow)
- {
- int lastOuterVertIndex = this.numOuterVerts - 1;
-
- this.cut1CoordIndices.Add(0);
- this.cut1CoordIndices.Add(this.coords.Count - 1);
-
- this.cut2CoordIndices.Add(lastOuterVertIndex + 1);
- this.cut2CoordIndices.Add(lastOuterVertIndex);
-
- this.cutNormal1.X = this.coords[0].Y - this.coords[this.coords.Count - 1].Y;
- this.cutNormal1.Y = -(this.coords[0].X - this.coords[this.coords.Count - 1].X);
-
- this.cutNormal2.X = this.coords[lastOuterVertIndex + 1].Y - this.coords[lastOuterVertIndex].Y;
- this.cutNormal2.Y = -(this.coords[lastOuterVertIndex + 1].X - this.coords[lastOuterVertIndex].X);
- }
-
- else
- {
- this.cutNormal1.X = this.vertexNormals[1].Y;
- this.cutNormal1.Y = -this.vertexNormals[1].X;
-
- this.cutNormal2.X = -this.vertexNormals[this.vertexNormals.Count - 2].Y;
- this.cutNormal2.Y = this.vertexNormals[this.vertexNormals.Count - 2].X;
-
- }
- this.cutNormal1.Normalize();
- this.cutNormal2.Normalize();
- }
-
- this.MakeFaceUVs();
-
- hollowCoords = null;
- hollowNormals = null;
- hollowUs = null;
-
- if (calcVertexNormals)
- { // calculate prim face numbers
-
- // face number order is top, outer, hollow, bottom, start cut, end cut
- // I know it's ugly but so is the whole concept of prim face numbers
-
- int faceNum = 1; // start with outer faces
- int startVert = hasProfileCut && !hasHollow ? 1 : 0;
- if (startVert > 0)
- this.faceNumbers.Add(-1);
- for (int i = 0; i < this.numOuterVerts - 1; i++)
- this.faceNumbers.Add(sides < 5 ? faceNum++ : faceNum);
-
- //if (!hasHollow && !hasProfileCut)
- // this.bottomFaceNumber = faceNum++;
-
- this.faceNumbers.Add(hasProfileCut ? -1 : faceNum++);
-
- if (sides > 4 && (hasHollow || hasProfileCut))
- faceNum++;
-
- if (hasHollow)
- {
- for (int i = 0; i < this.numHollowVerts; i++)
- this.faceNumbers.Add(faceNum);
-
- faceNum++;
- }
- //if (hasProfileCut || hasHollow)
- // this.bottomFaceNumber = faceNum++;
- this.bottomFaceNumber = faceNum++;
-
- if (hasHollow && hasProfileCut)
- this.faceNumbers.Add(faceNum++);
- for (int i = 0; i < this.faceNumbers.Count; i++)
- if (this.faceNumbers[i] == -1)
- this.faceNumbers[i] = faceNum++;
-
-
- this.numPrimFaces = faceNum;
- }
-
- }
-
- internal void MakeFaceUVs()
- {
- this.faceUVs = new List();
- foreach (Coord c in this.coords)
- this.faceUVs.Add(new UVCoord(0.5f + c.X, 0.5f - c.Y));
- }
-
- internal Profile Copy()
- {
- return this.Copy(true);
- }
-
- internal Profile Copy(bool needFaces)
- {
- Profile copy = new Profile();
-
- copy.coords.AddRange(this.coords);
- copy.faceUVs.AddRange(this.faceUVs);
-
- if (needFaces)
- copy.faces.AddRange(this.faces);
- if ((copy.calcVertexNormals = this.calcVertexNormals) == true)
- {
- copy.vertexNormals.AddRange(this.vertexNormals);
- copy.faceNormal = this.faceNormal;
- copy.cutNormal1 = this.cutNormal1;
- copy.cutNormal2 = this.cutNormal2;
- copy.us.AddRange(this.us);
- copy.faceNumbers.AddRange(this.faceNumbers);
-
- copy.cut1CoordIndices = new List(this.cut1CoordIndices);
- copy.cut2CoordIndices = new List(this.cut2CoordIndices);
- copy.hollowCoordIndices = new List(this.hollowCoordIndices);
- copy.outerCoordIndices = new List(this.outerCoordIndices);
- }
- copy.numOuterVerts = this.numOuterVerts;
- copy.numHollowVerts = this.numHollowVerts;
-
- return copy;
- }
-
- internal void AddPos(Coord v)
- {
- this.AddPos(v.X, v.Y, v.Z);
- }
-
- internal void AddPos(float x, float y, float z)
- {
- int i;
- int numVerts = this.coords.Count;
- Coord vert;
-
- for (i = 0; i < numVerts; i++)
- {
- vert = this.coords[i];
- vert.X += x;
- vert.Y += y;
- vert.Z += z;
- this.coords[i] = vert;
- }
- }
-
- internal void AddRot(Quat q)
- {
- int i;
- int numVerts = this.coords.Count;
-
- for (i = 0; i < numVerts; i++)
- this.coords[i] *= q;
-
- if (this.calcVertexNormals)
- {
- int numNormals = this.vertexNormals.Count;
- for (i = 0; i < numNormals; i++)
- this.vertexNormals[i] *= q;
-
- this.faceNormal *= q;
- this.cutNormal1 *= q;
- this.cutNormal2 *= q;
-
- }
- }
-
- internal void Scale(float x, float y)
- {
- int i;
- int numVerts = this.coords.Count;
- Coord vert;
-
- for (i = 0; i < numVerts; i++)
- {
- vert = this.coords[i];
- vert.X *= x;
- vert.Y *= y;
- this.coords[i] = vert;
- }
- }
-
- ///
- /// Changes order of the vertex indices and negates the center vertex normal. Does not alter vertex normals of radial vertices
- ///
- internal void FlipNormals()
- {
- int i;
- int numFaces = this.faces.Count;
- Face tmpFace;
- int tmp;
-
- for (i = 0; i < numFaces; i++)
- {
- tmpFace = this.faces[i];
- tmp = tmpFace.v3;
- tmpFace.v3 = tmpFace.v1;
- tmpFace.v1 = tmp;
- this.faces[i] = tmpFace;
- }
-
- if (this.calcVertexNormals)
- {
- int normalCount = this.vertexNormals.Count;
- if (normalCount > 0)
- {
- Coord n = this.vertexNormals[normalCount - 1];
- n.Z = -n.Z;
- this.vertexNormals[normalCount - 1] = n;
- }
- }
-
- this.faceNormal.X = -this.faceNormal.X;
- this.faceNormal.Y = -this.faceNormal.Y;
- this.faceNormal.Z = -this.faceNormal.Z;
-
- int numfaceUVs = this.faceUVs.Count;
- for (i = 0; i < numfaceUVs; i++)
- {
- UVCoord uv = this.faceUVs[i];
- uv.V = 1.0f - uv.V;
- this.faceUVs[i] = uv;
- }
- }
-
- internal void AddValue2FaceVertexIndices(int num)
- {
- int numFaces = this.faces.Count;
- Face tmpFace;
- for (int i = 0; i < numFaces; i++)
- {
- tmpFace = this.faces[i];
- tmpFace.v1 += num;
- tmpFace.v2 += num;
- tmpFace.v3 += num;
-
- this.faces[i] = tmpFace;
- }
- }
-
- internal void AddValue2FaceNormalIndices(int num)
- {
- if (this.calcVertexNormals)
- {
- int numFaces = this.faces.Count;
- Face tmpFace;
- for (int i = 0; i < numFaces; i++)
- {
- tmpFace = this.faces[i];
- tmpFace.n1 += num;
- tmpFace.n2 += num;
- tmpFace.n3 += num;
-
- this.faces[i] = tmpFace;
- }
- }
- }
-
- internal void DumpRaw(String path, String name, String title)
- {
- if (path == null)
- return;
- String fileName = name + "_" + title + ".raw";
- String completePath = System.IO.Path.Combine(path, fileName);
- StreamWriter sw = new StreamWriter(completePath);
-
- for (int i = 0; i < this.faces.Count; i++)
- {
- string s = this.coords[this.faces[i].v1].ToString();
- s += " " + this.coords[this.faces[i].v2].ToString();
- s += " " + this.coords[this.faces[i].v3].ToString();
-
- sw.WriteLine(s);
- }
-
- sw.Close();
- }
- }
-
- public struct PathNode
- {
- public Coord position;
- public Quat rotation;
- public float xScale;
- public float yScale;
- public float percentOfPath;
- }
-
- public enum PathType { Linear = 0, Circular = 1, Flexible = 2 }
-
- public class Path
- {
- public List pathNodes = new List();
-
- public float twistBegin = 0.0f;
- public float twistEnd = 0.0f;
- public float topShearX = 0.0f;
- public float topShearY = 0.0f;
- public float pathCutBegin = 0.0f;
- public float pathCutEnd = 1.0f;
- public float dimpleBegin = 0.0f;
- public float dimpleEnd = 1.0f;
- public float skew = 0.0f;
- public float holeSizeX = 1.0f; // called pathScaleX in pbs
- public float holeSizeY = 0.25f;
- public float taperX = 0.0f;
- public float taperY = 0.0f;
- public float radius = 0.0f;
- public float revolutions = 1.0f;
- public int stepsPerRevolution = 24;
-
- private const float twoPi = 2.0f * (float)Math.PI;
-
- public void Create(PathType pathType, int steps)
- {
- if (pathType == PathType.Linear || pathType == PathType.Flexible)
- {
- int step = 0;
-
- float length = this.pathCutEnd - this.pathCutBegin;
- float twistTotal = twistEnd - twistBegin;
- float twistTotalAbs = Math.Abs(twistTotal);
- if (twistTotalAbs > 0.01f)
- steps += (int)(twistTotalAbs * 3.66); // dahlia's magic number
-
- float start = -0.5f;
- float stepSize = length / (float)steps;
- float percentOfPathMultiplier = stepSize;
- float xOffset = 0.0f;
- float yOffset = 0.0f;
- float zOffset = start;
- float xOffsetStepIncrement = this.topShearX / steps;
- float yOffsetStepIncrement = this.topShearY / steps;
-
- float percentOfPath = this.pathCutBegin;
- zOffset += percentOfPath;
-
- // sanity checks
-
- bool done = false;
-
- while (!done)
- {
- PathNode newNode = new PathNode();
-
- newNode.xScale = 1.0f;
- if (this.taperX == 0.0f)
- newNode.xScale = 1.0f;
- else if (this.taperX > 0.0f)
- newNode.xScale = 1.0f - percentOfPath * this.taperX;
- else newNode.xScale = 1.0f + (1.0f - percentOfPath) * this.taperX;
-
- newNode.yScale = 1.0f;
- if (this.taperY == 0.0f)
- newNode.yScale = 1.0f;
- else if (this.taperY > 0.0f)
- newNode.yScale = 1.0f - percentOfPath * this.taperY;
- else newNode.yScale = 1.0f + (1.0f - percentOfPath) * this.taperY;
-
- float twist = twistBegin + twistTotal * percentOfPath;
-
- newNode.rotation = new Quat(new Coord(0.0f, 0.0f, 1.0f), twist);
- newNode.position = new Coord(xOffset, yOffset, zOffset);
- newNode.percentOfPath = percentOfPath;
-
- pathNodes.Add(newNode);
-
- if (step < steps)
- {
- step += 1;
- percentOfPath += percentOfPathMultiplier;
- xOffset += xOffsetStepIncrement;
- yOffset += yOffsetStepIncrement;
- zOffset += stepSize;
- if (percentOfPath > this.pathCutEnd)
- done = true;
- }
- else done = true;
- }
- } // end of linear path code
-
- else // pathType == Circular
- {
- float twistTotal = twistEnd - twistBegin;
-
- // if the profile has a lot of twist, add more layers otherwise the layers may overlap
- // and the resulting mesh may be quite inaccurate. This method is arbitrary and doesn't
- // accurately match the viewer
- float twistTotalAbs = Math.Abs(twistTotal);
- if (twistTotalAbs > 0.01f)
- {
- if (twistTotalAbs > Math.PI * 1.5f)
- steps *= 2;
- if (twistTotalAbs > Math.PI * 3.0f)
- steps *= 2;
- }
-
- float yPathScale = this.holeSizeY * 0.5f;
- float pathLength = this.pathCutEnd - this.pathCutBegin;
- float totalSkew = this.skew * 2.0f * pathLength;
- float skewStart = this.pathCutBegin * 2.0f * this.skew - this.skew;
- float xOffsetTopShearXFactor = this.topShearX * (0.25f + 0.5f * (0.5f - this.holeSizeY));
- float yShearCompensation = 1.0f + Math.Abs(this.topShearY) * 0.25f;
-
- // It's not quite clear what pushY (Y top shear) does, but subtracting it from the start and end
- // angles appears to approximate it's effects on path cut. Likewise, adding it to the angle used
- // to calculate the sine for generating the path radius appears to approximate it's effects there
- // too, but there are some subtle differences in the radius which are noticeable as the prim size
- // increases and it may affect megaprims quite a bit. The effect of the Y top shear parameter on
- // the meshes generated with this technique appear nearly identical in shape to the same prims when
- // displayed by the viewer.
-
- float startAngle = (twoPi * this.pathCutBegin * this.revolutions) - this.topShearY * 0.9f;
- float endAngle = (twoPi * this.pathCutEnd * this.revolutions) - this.topShearY * 0.9f;
- float stepSize = twoPi / this.stepsPerRevolution;
-
- int step = (int)(startAngle / stepSize);
- float angle = startAngle;
-
- bool done = false;
- while (!done) // loop through the length of the path and add the layers
- {
- PathNode newNode = new PathNode();
-
- float xProfileScale = (1.0f - Math.Abs(this.skew)) * this.holeSizeX;
- float yProfileScale = this.holeSizeY;
-
- float percentOfPath = angle / (twoPi * this.revolutions);
- float percentOfAngles = (angle - startAngle) / (endAngle - startAngle);
-
- if (this.taperX > 0.01f)
- xProfileScale *= 1.0f - percentOfPath * this.taperX;
- else if (this.taperX < -0.01f)
- xProfileScale *= 1.0f + (1.0f - percentOfPath) * this.taperX;
-
- if (this.taperY > 0.01f)
- yProfileScale *= 1.0f - percentOfPath * this.taperY;
- else if (this.taperY < -0.01f)
- yProfileScale *= 1.0f + (1.0f - percentOfPath) * this.taperY;
-
- newNode.xScale = xProfileScale;
- newNode.yScale = yProfileScale;
-
- float radiusScale = 1.0f;
- if (this.radius > 0.001f)
- radiusScale = 1.0f - this.radius * percentOfPath;
- else if (this.radius < 0.001f)
- radiusScale = 1.0f + this.radius * (1.0f - percentOfPath);
-
- float twist = twistBegin + twistTotal * percentOfPath;
-
- float xOffset = 0.5f * (skewStart + totalSkew * percentOfAngles);
- xOffset += (float)Math.Sin(angle) * xOffsetTopShearXFactor;
-
- float yOffset = yShearCompensation * (float)Math.Cos(angle) * (0.5f - yPathScale) * radiusScale;
-
- float zOffset = (float)Math.Sin(angle + this.topShearY) * (0.5f - yPathScale) * radiusScale;
-
- newNode.position = new Coord(xOffset, yOffset, zOffset);
-
- // now orient the rotation of the profile layer relative to it's position on the path
- // adding taperY to the angle used to generate the quat appears to approximate the viewer
-
- newNode.rotation = new Quat(new Coord(1.0f, 0.0f, 0.0f), angle + this.topShearY);
-
- // next apply twist rotation to the profile layer
- if (twistTotal != 0.0f || twistBegin != 0.0f)
- newNode.rotation *= new Quat(new Coord(0.0f, 0.0f, 1.0f), twist);
-
- newNode.percentOfPath = percentOfPath;
-
- pathNodes.Add(newNode);
-
- // calculate terms for next iteration
- // calculate the angle for the next iteration of the loop
-
- if (angle >= endAngle - 0.01)
- done = true;
- else
- {
- step += 1;
- angle = stepSize * step;
- if (angle > endAngle)
- angle = endAngle;
- }
- }
- }
- }
- }
-
- public class PrimMesh
- {
- public string errorMessage = "";
- private const float twoPi = 2.0f * (float)Math.PI;
-
- public List coords;
- public List normals;
- public List faces;
-
- public List viewerFaces;
-
- private int sides = 4;
- private int hollowSides = 4;
- private float profileStart = 0.0f;
- private float profileEnd = 1.0f;
- private float hollow = 0.0f;
- public int twistBegin = 0;
- public int twistEnd = 0;
- public float topShearX = 0.0f;
- public float topShearY = 0.0f;
- public float pathCutBegin = 0.0f;
- public float pathCutEnd = 1.0f;
- public float dimpleBegin = 0.0f;
- public float dimpleEnd = 1.0f;
- public float skew = 0.0f;
- public float holeSizeX = 1.0f; // called pathScaleX in pbs
- public float holeSizeY = 0.25f;
- public float taperX = 0.0f;
- public float taperY = 0.0f;
- public float radius = 0.0f;
- public float revolutions = 1.0f;
- public int stepsPerRevolution = 24;
-
- private bool hasProfileCut = false;
- private bool hasHollow = false;
- public bool calcVertexNormals = false;
- private bool normalsProcessed = false;
- public bool viewerMode = false;
-
- public int numPrimFaces = 0;
-
- ///
- /// Human readable string representation of the parameters used to create a mesh.
- ///
- ///
- public string ParamsToDisplayString()
- {
- string s = "";
- s += "sides..................: " + this.sides.ToString();
- s += "\nhollowSides..........: " + this.hollowSides.ToString();
- s += "\nprofileStart.........: " + this.profileStart.ToString();
- s += "\nprofileEnd...........: " + this.profileEnd.ToString();
- s += "\nhollow...............: " + this.hollow.ToString();
- s += "\ntwistBegin...........: " + this.twistBegin.ToString();
- s += "\ntwistEnd.............: " + this.twistEnd.ToString();
- s += "\ntopShearX............: " + this.topShearX.ToString();
- s += "\ntopShearY............: " + this.topShearY.ToString();
- s += "\npathCutBegin.........: " + this.pathCutBegin.ToString();
- s += "\npathCutEnd...........: " + this.pathCutEnd.ToString();
- s += "\ndimpleBegin..........: " + this.dimpleBegin.ToString();
- s += "\ndimpleEnd............: " + this.dimpleEnd.ToString();
- s += "\nskew.................: " + this.skew.ToString();
- s += "\nholeSizeX............: " + this.holeSizeX.ToString();
- s += "\nholeSizeY............: " + this.holeSizeY.ToString();
- s += "\ntaperX...............: " + this.taperX.ToString();
- s += "\ntaperY...............: " + this.taperY.ToString();
- s += "\nradius...............: " + this.radius.ToString();
- s += "\nrevolutions..........: " + this.revolutions.ToString();
- s += "\nstepsPerRevolution...: " + this.stepsPerRevolution.ToString();
-
- return s;
- }
-
- ///
- /// Constructs a PrimMesh object and creates the profile for extrusion.
- ///
- ///
- ///
- ///
- ///
- ///
- public PrimMesh(int sides, float profileStart, float profileEnd, float hollow, int hollowSides)
- {
- this.coords = new List();
- this.faces = new List();
-
- this.sides = sides;
- this.profileStart = profileStart;
- this.profileEnd = profileEnd;
- this.hollow = hollow;
- this.hollowSides = hollowSides;
-
- if (sides < 3)
- this.sides = 3;
- if (hollowSides < 3)
- this.hollowSides = 3;
- if (profileStart < 0.0f)
- this.profileStart = 0.0f;
- if (profileEnd > 1.0f)
- this.profileEnd = 1.0f;
- if (profileEnd < 0.02f)
- this.profileEnd = 0.02f;
- if (profileStart >= profileEnd)
- this.profileStart = profileEnd - 0.02f;
- if (hollow > 0.99f)
- this.hollow = 0.99f;
- if (hollow < 0.0f)
- this.hollow = 0.0f;
-
- this.hasProfileCut = (this.profileStart > 0.0f || this.profileEnd < 1.0f);
- this.hasHollow = (this.hollow > 0.001f);
- }
-
- ///
- /// Extrudes a profile along a path.
- ///
- public void Extrude(PathType pathType)
- {
- this.coords = new List();
- this.faces = new List();
-
- if (this.viewerMode)
- {
- this.viewerFaces = new List();
- this.calcVertexNormals = true;
- }
-
- if (this.calcVertexNormals)
- this.normals = new List();
-
- int steps = 1;
-
- float length = this.pathCutEnd - this.pathCutBegin;
- normalsProcessed = false;
-
- if (this.viewerMode && this.sides == 3)
- {
- // prisms don't taper well so add some vertical resolution
- // other prims may benefit from this but just do prisms for now
- if (Math.Abs(this.taperX) > 0.01 || Math.Abs(this.taperY) > 0.01)
- steps = (int)(steps * 4.5 * length);
- }
-
-
- float twistBegin = this.twistBegin / 360.0f * twoPi;
- float twistEnd = this.twistEnd / 360.0f * twoPi;
- float twistTotal = twistEnd - twistBegin;
- float twistTotalAbs = Math.Abs(twistTotal);
- if (twistTotalAbs > 0.01f)
- steps += (int)(twistTotalAbs * 3.66); // dahlia's magic number
-
- float hollow = this.hollow;
-
- // sanity checks
- float initialProfileRot = 0.0f;
- if (pathType == PathType.Circular)
- {
- if (this.sides == 3)
- {
- initialProfileRot = (float)Math.PI;
- if (this.hollowSides == 4)
- {
- if (hollow > 0.7f)
- hollow = 0.7f;
- hollow *= 0.707f;
- }
- else hollow *= 0.5f;
- }
- else if (this.sides == 4)
- {
- initialProfileRot = 0.25f * (float)Math.PI;
- if (this.hollowSides != 4)
- hollow *= 0.707f;
- }
- else if (this.sides > 4)
- {
- initialProfileRot = (float)Math.PI;
- if (this.hollowSides == 4)
- {
- if (hollow > 0.7f)
- hollow = 0.7f;
- hollow /= 0.7f;
- }
- }
- }
- else
- {
- if (this.sides == 3)
- {
- if (this.hollowSides == 4)
- {
- if (hollow > 0.7f)
- hollow = 0.7f;
- hollow *= 0.707f;
- }
- else hollow *= 0.5f;
- }
- else if (this.sides == 4)
- {
- initialProfileRot = 1.25f * (float)Math.PI;
- if (this.hollowSides != 4)
- hollow *= 0.707f;
- }
- else if (this.sides == 24 && this.hollowSides == 4)
- hollow *= 1.414f;
- }
-
- Profile profile = new Profile(this.sides, this.profileStart, this.profileEnd, hollow, this.hollowSides, true, calcVertexNormals);
- this.errorMessage = profile.errorMessage;
-
- this.numPrimFaces = profile.numPrimFaces;
-
- int cut1Vert = -1;
- int cut2Vert = -1;
- if (hasProfileCut)
- {
- cut1Vert = hasHollow ? profile.coords.Count - 1 : 0;
- cut2Vert = hasHollow ? profile.numOuterVerts - 1 : profile.numOuterVerts;
- }
-
- if (initialProfileRot != 0.0f)
- {
- profile.AddRot(new Quat(new Coord(0.0f, 0.0f, 1.0f), initialProfileRot));
- if (viewerMode)
- profile.MakeFaceUVs();
- }
-
- Coord lastCutNormal1 = new Coord();
- Coord lastCutNormal2 = new Coord();
- float lastV = 1.0f;
-
- Path path = new Path();
- path.twistBegin = twistBegin;
- path.twistEnd = twistEnd;
- path.topShearX = topShearX;
- path.topShearY = topShearY;
- path.pathCutBegin = pathCutBegin;
- path.pathCutEnd = pathCutEnd;
- path.dimpleBegin = dimpleBegin;
- path.dimpleEnd = dimpleEnd;
- path.skew = skew;
- path.holeSizeX = holeSizeX;
- path.holeSizeY = holeSizeY;
- path.taperX = taperX;
- path.taperY = taperY;
- path.radius = radius;
- path.revolutions = revolutions;
- path.stepsPerRevolution = stepsPerRevolution;
-
- path.Create(pathType, steps);
-
- bool needEndFaces = false;
- if (pathType == PathType.Circular)
- {
- needEndFaces = false;
- if (this.pathCutBegin != 0.0f || this.pathCutEnd != 1.0f)
- needEndFaces = true;
- else if (this.taperX != 0.0f || this.taperY != 0.0f)
- needEndFaces = true;
- else if (this.skew != 0.0f)
- needEndFaces = true;
- else if (twistTotal != 0.0f)
- needEndFaces = true;
- else if (this.radius != 0.0f)
- needEndFaces = true;
- }
- else needEndFaces = true;
-
- for (int nodeIndex = 0; nodeIndex < path.pathNodes.Count; nodeIndex++)
- {
- PathNode node = path.pathNodes[nodeIndex];
- Profile newLayer = profile.Copy();
- newLayer.Scale(node.xScale, node.yScale);
-
- newLayer.AddRot(node.rotation);
- newLayer.AddPos(node.position);
-
- if (needEndFaces && nodeIndex == 0)
- {
- newLayer.FlipNormals();
-
- // add the top faces to the viewerFaces list here
- if (this.viewerMode)
- {
- Coord faceNormal = newLayer.faceNormal;
- ViewerFace newViewerFace = new ViewerFace(profile.bottomFaceNumber);
- int numFaces = newLayer.faces.Count;
- List faces = newLayer.faces;
-
- for (int i = 0; i < numFaces; i++)
- {
- Face face = faces[i];
- newViewerFace.v1 = newLayer.coords[face.v1];
- newViewerFace.v2 = newLayer.coords[face.v2];
- newViewerFace.v3 = newLayer.coords[face.v3];
-
- newViewerFace.coordIndex1 = face.v1;
- newViewerFace.coordIndex2 = face.v2;
- newViewerFace.coordIndex3 = face.v3;
-
- newViewerFace.n1 = faceNormal;
- newViewerFace.n2 = faceNormal;
- newViewerFace.n3 = faceNormal;
-
- newViewerFace.uv1 = newLayer.faceUVs[face.v1];
- newViewerFace.uv2 = newLayer.faceUVs[face.v2];
- newViewerFace.uv3 = newLayer.faceUVs[face.v3];
-
- this.viewerFaces.Add(newViewerFace);
- }
- }
- } // if (nodeIndex == 0)
-
- // append this layer
-
- int coordsLen = this.coords.Count;
- newLayer.AddValue2FaceVertexIndices(coordsLen);
-
- this.coords.AddRange(newLayer.coords);
-
- if (this.calcVertexNormals)
- {
- newLayer.AddValue2FaceNormalIndices(this.normals.Count);
- this.normals.AddRange(newLayer.vertexNormals);
- }
-
- if (node.percentOfPath < this.pathCutBegin + 0.01f || node.percentOfPath > this.pathCutEnd - 0.01f)
- this.faces.AddRange(newLayer.faces);
-
- // fill faces between layers
-
- int numVerts = newLayer.coords.Count;
- Face newFace = new Face();
-
- if (nodeIndex > 0)
- {
- int startVert = coordsLen + 1;
- int endVert = this.coords.Count;
-
- if (sides < 5 || this.hasProfileCut || hollow > 0.0f)
- startVert--;
-
- for (int i = startVert; i < endVert; i++)
- {
- int iNext = i + 1;
- if (i == endVert - 1)
- iNext = startVert;
-
- int whichVert = i - startVert;
-
- newFace.v1 = i;
- newFace.v2 = i - numVerts;
- newFace.v3 = iNext - numVerts;
- this.faces.Add(newFace);
-
- newFace.v2 = iNext - numVerts;
- newFace.v3 = iNext;
- this.faces.Add(newFace);
-
- if (this.viewerMode)
- {
- // add the side faces to the list of viewerFaces here
-
- int primFaceNum = profile.faceNumbers[whichVert];
- if (!needEndFaces)
- primFaceNum -= 1;
-
- ViewerFace newViewerFace1 = new ViewerFace(primFaceNum);
- ViewerFace newViewerFace2 = new ViewerFace(primFaceNum);
-
- float u1 = newLayer.us[whichVert];
- float u2 = 1.0f;
- if (whichVert < newLayer.us.Count - 1)
- u2 = newLayer.us[whichVert + 1];
-
- if (whichVert == cut1Vert || whichVert == cut2Vert)
- {
- u1 = 0.0f;
- u2 = 1.0f;
- }
- else if (sides < 5)
- {
- if (whichVert < profile.numOuterVerts)
- { // boxes and prisms have one texture face per side of the prim, so the U values have to be scaled
- // to reflect the entire texture width
- u1 *= sides;
- u2 *= sides;
- u2 -= (int)u1;
- u1 -= (int)u1;
- if (u2 < 0.1f)
- u2 = 1.0f;
- }
- else if (whichVert > profile.coords.Count - profile.numHollowVerts - 1)
- {
- u1 *= 2.0f;
- u2 *= 2.0f;
- }
- }
-
- newViewerFace1.uv1.U = u1;
- newViewerFace1.uv2.U = u1;
- newViewerFace1.uv3.U = u2;
-
- newViewerFace1.uv1.V = 1.0f - node.percentOfPath;
- newViewerFace1.uv2.V = lastV;
- newViewerFace1.uv3.V = lastV;
-
- newViewerFace2.uv1.U = u1;
- newViewerFace2.uv2.U = u2;
- newViewerFace2.uv3.U = u2;
-
- newViewerFace2.uv1.V = 1.0f - node.percentOfPath;
- newViewerFace2.uv2.V = lastV;
- newViewerFace2.uv3.V = 1.0f - node.percentOfPath;
-
- newViewerFace1.v1 = this.coords[i];
- newViewerFace1.v2 = this.coords[i - numVerts];
- newViewerFace1.v3 = this.coords[iNext - numVerts];
-
- newViewerFace2.v1 = this.coords[i];
- newViewerFace2.v2 = this.coords[iNext - numVerts];
- newViewerFace2.v3 = this.coords[iNext];
-
- newViewerFace1.coordIndex1 = i;
- newViewerFace1.coordIndex2 = i - numVerts;
- newViewerFace1.coordIndex3 = iNext - numVerts;
-
- newViewerFace2.coordIndex1 = i;
- newViewerFace2.coordIndex2 = iNext - numVerts;
- newViewerFace2.coordIndex3 = iNext;
-
- // profile cut faces
- if (whichVert == cut1Vert)
- {
- newViewerFace1.n1 = newLayer.cutNormal1;
- newViewerFace1.n2 = newViewerFace1.n3 = lastCutNormal1;
-
- newViewerFace2.n1 = newViewerFace2.n3 = newLayer.cutNormal1;
- newViewerFace2.n2 = lastCutNormal1;
- }
- else if (whichVert == cut2Vert)
- {
- newViewerFace1.n1 = newLayer.cutNormal2;
- newViewerFace1.n2 = newViewerFace1.n3 = lastCutNormal2;
-
- newViewerFace2.n1 = newViewerFace2.n3 = newLayer.cutNormal2;
- newViewerFace2.n2 = lastCutNormal2;
- }
-
- else // outer and hollow faces
- {
- if ((sides < 5 && whichVert < newLayer.numOuterVerts) || (hollowSides < 5 && whichVert >= newLayer.numOuterVerts))
- { // looks terrible when path is twisted... need vertex normals here
- newViewerFace1.CalcSurfaceNormal();
- newViewerFace2.CalcSurfaceNormal();
- }
- else
- {
- newViewerFace1.n1 = this.normals[i];
- newViewerFace1.n2 = this.normals[i - numVerts];
- newViewerFace1.n3 = this.normals[iNext - numVerts];
-
- newViewerFace2.n1 = this.normals[i];
- newViewerFace2.n2 = this.normals[iNext - numVerts];
- newViewerFace2.n3 = this.normals[iNext];
- }
- }
-
- this.viewerFaces.Add(newViewerFace1);
- this.viewerFaces.Add(newViewerFace2);
-
- }
- }
- }
-
- lastCutNormal1 = newLayer.cutNormal1;
- lastCutNormal2 = newLayer.cutNormal2;
- lastV = 1.0f - node.percentOfPath;
-
- if (needEndFaces && nodeIndex == path.pathNodes.Count - 1 && viewerMode)
- {
- // add the top faces to the viewerFaces list here
- Coord faceNormal = newLayer.faceNormal;
- ViewerFace newViewerFace = new ViewerFace();
- newViewerFace.primFaceNumber = 0;
- int numFaces = newLayer.faces.Count;
- List faces = newLayer.faces;
-
- for (int i = 0; i < numFaces; i++)
- {
- Face face = faces[i];
- newViewerFace.v1 = newLayer.coords[face.v1 - coordsLen];
- newViewerFace.v2 = newLayer.coords[face.v2 - coordsLen];
- newViewerFace.v3 = newLayer.coords[face.v3 - coordsLen];
-
- newViewerFace.coordIndex1 = face.v1 - coordsLen;
- newViewerFace.coordIndex2 = face.v2 - coordsLen;
- newViewerFace.coordIndex3 = face.v3 - coordsLen;
-
- newViewerFace.n1 = faceNormal;
- newViewerFace.n2 = faceNormal;
- newViewerFace.n3 = faceNormal;
-
- newViewerFace.uv1 = newLayer.faceUVs[face.v1 - coordsLen];
- newViewerFace.uv2 = newLayer.faceUVs[face.v2 - coordsLen];
- newViewerFace.uv3 = newLayer.faceUVs[face.v3 - coordsLen];
-
- this.viewerFaces.Add(newViewerFace);
- }
- }
-
-
- } // for (int nodeIndex = 0; nodeIndex < path.pathNodes.Count; nodeIndex++)
-
- }
-
-
- ///
- /// DEPRICATED - use Extrude(PathType.Linear) instead
- /// Extrudes a profile along a straight line path. Used for prim types box, cylinder, and prism.
- ///
- ///
- public void ExtrudeLinear()
- {
- this.Extrude(PathType.Linear);
- }
-
-
- ///
- /// DEPRICATED - use Extrude(PathType.Circular) instead
- /// Extrude a profile into a circular path prim mesh. Used for prim types torus, tube, and ring.
- ///
- ///
- public void ExtrudeCircular()
- {
- this.Extrude(PathType.Circular);
- }
-
-
- private Coord SurfaceNormal(Coord c1, Coord c2, Coord c3)
- {
- Coord edge1 = new Coord(c2.X - c1.X, c2.Y - c1.Y, c2.Z - c1.Z);
- Coord edge2 = new Coord(c3.X - c1.X, c3.Y - c1.Y, c3.Z - c1.Z);
-
- Coord normal = Coord.Cross(edge1, edge2);
-
- normal.Normalize();
-
- return normal;
- }
-
- private Coord SurfaceNormal(Face face)
- {
- return SurfaceNormal(this.coords[face.v1], this.coords[face.v2], this.coords[face.v3]);
- }
-
- ///
- /// Calculate the surface normal for a face in the list of faces
- ///
- ///
- ///
- public Coord SurfaceNormal(int faceIndex)
- {
- int numFaces = this.faces.Count;
- if (faceIndex < 0 || faceIndex >= numFaces)
- throw new Exception("faceIndex out of range");
-
- return SurfaceNormal(this.faces[faceIndex]);
- }
-
- ///
- /// Duplicates a PrimMesh object. All object properties are copied by value, including lists.
- ///
- ///
- public PrimMesh Copy()
- {
- PrimMesh copy = new PrimMesh(this.sides, this.profileStart, this.profileEnd, this.hollow, this.hollowSides);
- copy.twistBegin = this.twistBegin;
- copy.twistEnd = this.twistEnd;
- copy.topShearX = this.topShearX;
- copy.topShearY = this.topShearY;
- copy.pathCutBegin = this.pathCutBegin;
- copy.pathCutEnd = this.pathCutEnd;
- copy.dimpleBegin = this.dimpleBegin;
- copy.dimpleEnd = this.dimpleEnd;
- copy.skew = this.skew;
- copy.holeSizeX = this.holeSizeX;
- copy.holeSizeY = this.holeSizeY;
- copy.taperX = this.taperX;
- copy.taperY = this.taperY;
- copy.radius = this.radius;
- copy.revolutions = this.revolutions;
- copy.stepsPerRevolution = this.stepsPerRevolution;
- copy.calcVertexNormals = this.calcVertexNormals;
- copy.normalsProcessed = this.normalsProcessed;
- copy.viewerMode = this.viewerMode;
- copy.numPrimFaces = this.numPrimFaces;
- copy.errorMessage = this.errorMessage;
-
- copy.coords = new List(this.coords);
- copy.faces = new List(this.faces);
- copy.viewerFaces = new List(this.viewerFaces);
- copy.normals = new List(this.normals);
-
- return copy;
- }
-
- ///
- /// Calculate surface normals for all of the faces in the list of faces in this mesh
- ///
- public void CalcNormals()
- {
- if (normalsProcessed)
- return;
-
- normalsProcessed = true;
-
- int numFaces = faces.Count;
-
- if (!this.calcVertexNormals)
- this.normals = new List();
-
- for (int i = 0; i < numFaces; i++)
- {
- Face face = faces[i];
-
- this.normals.Add(SurfaceNormal(i).Normalize());
-
- int normIndex = normals.Count - 1;
- face.n1 = normIndex;
- face.n2 = normIndex;
- face.n3 = normIndex;
-
- this.faces[i] = face;
- }
- }
-
- ///
- /// Adds a value to each XYZ vertex coordinate in the mesh
- ///
- ///
- ///
- ///
- public void AddPos(float x, float y, float z)
- {
- int i;
- int numVerts = this.coords.Count;
- Coord vert;
-
- for (i = 0; i < numVerts; i++)
- {
- vert = this.coords[i];
- vert.X += x;
- vert.Y += y;
- vert.Z += z;
- this.coords[i] = vert;
- }
-
- if (this.viewerFaces != null)
- {
- int numViewerFaces = this.viewerFaces.Count;
-
- for (i = 0; i < numViewerFaces; i++)
- {
- ViewerFace v = this.viewerFaces[i];
- v.AddPos(x, y, z);
- this.viewerFaces[i] = v;
- }
- }
- }
-
- ///
- /// Rotates the mesh
- ///
- ///
- public void AddRot(Quat q)
- {
- int i;
- int numVerts = this.coords.Count;
-
- for (i = 0; i < numVerts; i++)
- this.coords[i] *= q;
-
- if (this.normals != null)
- {
- int numNormals = this.normals.Count;
- for (i = 0; i < numNormals; i++)
- this.normals[i] *= q;
- }
-
- if (this.viewerFaces != null)
- {
- int numViewerFaces = this.viewerFaces.Count;
-
- for (i = 0; i < numViewerFaces; i++)
- {
- ViewerFace v = this.viewerFaces[i];
- v.v1 *= q;
- v.v2 *= q;
- v.v3 *= q;
-
- v.n1 *= q;
- v.n2 *= q;
- v.n3 *= q;
- this.viewerFaces[i] = v;
- }
- }
- }
-
-#if VERTEX_INDEXER
- public VertexIndexer GetVertexIndexer()
- {
- if (this.viewerMode && this.viewerFaces.Count > 0)
- return new VertexIndexer(this);
- return null;
- }
-#endif
-
- ///
- /// Scales the mesh
- ///
- ///
- ///
- ///
- public void Scale(float x, float y, float z)
- {
- int i;
- int numVerts = this.coords.Count;
- //Coord vert;
-
- Coord m = new Coord(x, y, z);
- for (i = 0; i < numVerts; i++)
- this.coords[i] *= m;
-
- if (this.viewerFaces != null)
- {
- int numViewerFaces = this.viewerFaces.Count;
- for (i = 0; i < numViewerFaces; i++)
- {
- ViewerFace v = this.viewerFaces[i];
- v.v1 *= m;
- v.v2 *= m;
- v.v3 *= m;
- this.viewerFaces[i] = v;
- }
-
- }
-
- }
-
- ///
- /// Dumps the mesh to a Blender compatible "Raw" format file
- ///
- ///
- ///
- ///
- public void DumpRaw(String path, String name, String title)
- {
- if (path == null)
- return;
- String fileName = name + "_" + title + ".raw";
- String completePath = System.IO.Path.Combine(path, fileName);
- StreamWriter sw = new StreamWriter(completePath);
-
- for (int i = 0; i < this.faces.Count; i++)
- {
- string s = this.coords[this.faces[i].v1].ToString();
- s += " " + this.coords[this.faces[i].v2].ToString();
- s += " " + this.coords[this.faces[i].v3].ToString();
-
- sw.WriteLine(s);
- }
-
- sw.Close();
- }
- }
-}
+/*
+ * Copyright (c) Contributors
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSimulator Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO;
+
+namespace PrimMesher
+{
+ public struct Quat
+ {
+ /// X value
+ public float X;
+ /// Y value
+ public float Y;
+ /// Z value
+ public float Z;
+ /// W value
+ public float W;
+
+ public Quat(float x, float y, float z, float w)
+ {
+ X = x;
+ Y = y;
+ Z = z;
+ W = w;
+ }
+
+ public Quat(Coord axis, float angle)
+ {
+ axis = axis.Normalize();
+
+ angle *= 0.5f;
+ float c = (float)Math.Cos(angle);
+ float s = (float)Math.Sin(angle);
+
+ X = axis.X * s;
+ Y = axis.Y * s;
+ Z = axis.Z * s;
+ W = c;
+
+ Normalize();
+ }
+
+ public float Length()
+ {
+ return (float)Math.Sqrt(X * X + Y * Y + Z * Z + W * W);
+ }
+
+ public Quat Normalize()
+ {
+ const float MAG_THRESHOLD = 0.0000001f;
+ float mag = Length();
+
+ // Catch very small rounding errors when normalizing
+ if (mag > MAG_THRESHOLD)
+ {
+ float oomag = 1f / mag;
+ X *= oomag;
+ Y *= oomag;
+ Z *= oomag;
+ W *= oomag;
+ }
+ else
+ {
+ X = 0f;
+ Y = 0f;
+ Z = 0f;
+ W = 1f;
+ }
+
+ return this;
+ }
+
+ public static Quat operator *(Quat q1, Quat q2)
+ {
+ float x = q1.W * q2.X + q1.X * q2.W + q1.Y * q2.Z - q1.Z * q2.Y;
+ float y = q1.W * q2.Y - q1.X * q2.Z + q1.Y * q2.W + q1.Z * q2.X;
+ float z = q1.W * q2.Z + q1.X * q2.Y - q1.Y * q2.X + q1.Z * q2.W;
+ float w = q1.W * q2.W - q1.X * q2.X - q1.Y * q2.Y - q1.Z * q2.Z;
+ return new Quat(x, y, z, w);
+ }
+
+ public override string ToString()
+ {
+ return "< X: " + this.X.ToString() + ", Y: " + this.Y.ToString() + ", Z: " + this.Z.ToString() + ", W: " + this.W.ToString() + ">";
+ }
+ }
+
+ public struct Coord
+ {
+ public float X;
+ public float Y;
+ public float Z;
+
+ public Coord(float x, float y, float z)
+ {
+ this.X = x;
+ this.Y = y;
+ this.Z = z;
+ }
+
+ public float Length()
+ {
+ return (float)Math.Sqrt(this.X * this.X + this.Y * this.Y + this.Z * this.Z);
+ }
+
+ public Coord Invert()
+ {
+ this.X = -this.X;
+ this.Y = -this.Y;
+ this.Z = -this.Z;
+
+ return this;
+ }
+
+ public Coord Normalize()
+ {
+ const float MAG_THRESHOLD = 0.0000001f;
+ float mag = Length();
+
+ // Catch very small rounding errors when normalizing
+ if (mag > MAG_THRESHOLD)
+ {
+ float oomag = 1.0f / mag;
+ this.X *= oomag;
+ this.Y *= oomag;
+ this.Z *= oomag;
+ }
+ else
+ {
+ this.X = 0.0f;
+ this.Y = 0.0f;
+ this.Z = 0.0f;
+ }
+
+ return this;
+ }
+
+ public override string ToString()
+ {
+ return this.X.ToString() + " " + this.Y.ToString() + " " + this.Z.ToString();
+ }
+
+ public static Coord Cross(Coord c1, Coord c2)
+ {
+ return new Coord(
+ c1.Y * c2.Z - c2.Y * c1.Z,
+ c1.Z * c2.X - c2.Z * c1.X,
+ c1.X * c2.Y - c2.X * c1.Y
+ );
+ }
+
+ public static Coord operator +(Coord v, Coord a)
+ {
+ return new Coord(v.X + a.X, v.Y + a.Y, v.Z + a.Z);
+ }
+
+ public static Coord operator *(Coord v, Coord m)
+ {
+ return new Coord(v.X * m.X, v.Y * m.Y, v.Z * m.Z);
+ }
+
+ public static Coord operator *(Coord v, Quat q)
+ {
+ // From http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/transforms/
+
+ Coord c2 = new Coord(0.0f, 0.0f, 0.0f);
+
+ c2.X = q.W * q.W * v.X +
+ 2f * q.Y * q.W * v.Z -
+ 2f * q.Z * q.W * v.Y +
+ q.X * q.X * v.X +
+ 2f * q.Y * q.X * v.Y +
+ 2f * q.Z * q.X * v.Z -
+ q.Z * q.Z * v.X -
+ q.Y * q.Y * v.X;
+
+ c2.Y =
+ 2f * q.X * q.Y * v.X +
+ q.Y * q.Y * v.Y +
+ 2f * q.Z * q.Y * v.Z +
+ 2f * q.W * q.Z * v.X -
+ q.Z * q.Z * v.Y +
+ q.W * q.W * v.Y -
+ 2f * q.X * q.W * v.Z -
+ q.X * q.X * v.Y;
+
+ c2.Z =
+ 2f * q.X * q.Z * v.X +
+ 2f * q.Y * q.Z * v.Y +
+ q.Z * q.Z * v.Z -
+ 2f * q.W * q.Y * v.X -
+ q.Y * q.Y * v.Z +
+ 2f * q.W * q.X * v.Y -
+ q.X * q.X * v.Z +
+ q.W * q.W * v.Z;
+
+ return c2;
+ }
+ }
+
+ public struct UVCoord
+ {
+ public float U;
+ public float V;
+
+
+ public UVCoord(float u, float v)
+ {
+ this.U = u;
+ this.V = v;
+ }
+ }
+
+ public struct Face
+ {
+ public int primFace;
+
+ // vertices
+ public int v1;
+ public int v2;
+ public int v3;
+
+ //normals
+ public int n1;
+ public int n2;
+ public int n3;
+
+ // uvs
+ public int uv1;
+ public int uv2;
+ public int uv3;
+
+
+ public Face(int v1, int v2, int v3)
+ {
+ primFace = 0;
+
+ this.v1 = v1;
+ this.v2 = v2;
+ this.v3 = v3;
+
+ this.n1 = 0;
+ this.n2 = 0;
+ this.n3 = 0;
+
+ this.uv1 = 0;
+ this.uv2 = 0;
+ this.uv3 = 0;
+
+ }
+
+ public Face(int v1, int v2, int v3, int n1, int n2, int n3)
+ {
+ primFace = 0;
+
+ this.v1 = v1;
+ this.v2 = v2;
+ this.v3 = v3;
+
+ this.n1 = n1;
+ this.n2 = n2;
+ this.n3 = n3;
+
+ this.uv1 = 0;
+ this.uv2 = 0;
+ this.uv3 = 0;
+ }
+
+ public Coord SurfaceNormal(List coordList)
+ {
+ Coord c1 = coordList[this.v1];
+ Coord c2 = coordList[this.v2];
+ Coord c3 = coordList[this.v3];
+
+ Coord edge1 = new Coord(c2.X - c1.X, c2.Y - c1.Y, c2.Z - c1.Z);
+ Coord edge2 = new Coord(c3.X - c1.X, c3.Y - c1.Y, c3.Z - c1.Z);
+
+ return Coord.Cross(edge1, edge2).Normalize();
+ }
+ }
+
+ public struct ViewerFace
+ {
+ public int primFaceNumber;
+
+ public Coord v1;
+ public Coord v2;
+ public Coord v3;
+
+ public int coordIndex1;
+ public int coordIndex2;
+ public int coordIndex3;
+
+ public Coord n1;
+ public Coord n2;
+ public Coord n3;
+
+ public UVCoord uv1;
+ public UVCoord uv2;
+ public UVCoord uv3;
+
+ public ViewerFace(int primFaceNumber)
+ {
+ this.primFaceNumber = primFaceNumber;
+
+ this.v1 = new Coord();
+ this.v2 = new Coord();
+ this.v3 = new Coord();
+
+ this.coordIndex1 = this.coordIndex2 = this.coordIndex3 = -1; // -1 means not assigned yet
+
+ this.n1 = new Coord();
+ this.n2 = new Coord();
+ this.n3 = new Coord();
+
+ this.uv1 = new UVCoord();
+ this.uv2 = new UVCoord();
+ this.uv3 = new UVCoord();
+ }
+
+ public void Scale(float x, float y, float z)
+ {
+ this.v1.X *= x;
+ this.v1.Y *= y;
+ this.v1.Z *= z;
+
+ this.v2.X *= x;
+ this.v2.Y *= y;
+ this.v2.Z *= z;
+
+ this.v3.X *= x;
+ this.v3.Y *= y;
+ this.v3.Z *= z;
+ }
+
+ public void AddPos(float x, float y, float z)
+ {
+ this.v1.X += x;
+ this.v2.X += x;
+ this.v3.X += x;
+
+ this.v1.Y += y;
+ this.v2.Y += y;
+ this.v3.Y += y;
+
+ this.v1.Z += z;
+ this.v2.Z += z;
+ this.v3.Z += z;
+ }
+
+ public void AddRot(Quat q)
+ {
+ this.v1 *= q;
+ this.v2 *= q;
+ this.v3 *= q;
+
+ this.n1 *= q;
+ this.n2 *= q;
+ this.n3 *= q;
+ }
+
+ public void CalcSurfaceNormal()
+ {
+
+ Coord edge1 = new Coord(this.v2.X - this.v1.X, this.v2.Y - this.v1.Y, this.v2.Z - this.v1.Z);
+ Coord edge2 = new Coord(this.v3.X - this.v1.X, this.v3.Y - this.v1.Y, this.v3.Z - this.v1.Z);
+
+ this.n1 = this.n2 = this.n3 = Coord.Cross(edge1, edge2).Normalize();
+ }
+ }
+
+ internal struct Angle
+ {
+ internal float angle;
+ internal float X;
+ internal float Y;
+
+ internal Angle(float angle, float x, float y)
+ {
+ this.angle = angle;
+ this.X = x;
+ this.Y = y;
+ }
+ }
+
+ internal class AngleList
+ {
+ private float iX, iY; // intersection point
+
+ private static Angle[] angles3 =
+ {
+ new Angle(0.0f, 1.0f, 0.0f),
+ new Angle(0.33333333333333333f, -0.5f, 0.86602540378443871f),
+ new Angle(0.66666666666666667f, -0.5f, -0.86602540378443837f),
+ new Angle(1.0f, 1.0f, 0.0f)
+ };
+
+ private static Coord[] normals3 =
+ {
+ new Coord(0.25f, 0.4330127019f, 0.0f).Normalize(),
+ new Coord(-0.5f, 0.0f, 0.0f).Normalize(),
+ new Coord(0.25f, -0.4330127019f, 0.0f).Normalize(),
+ new Coord(0.25f, 0.4330127019f, 0.0f).Normalize()
+ };
+
+ private static Angle[] angles4 =
+ {
+ new Angle(0.0f, 1.0f, 0.0f),
+ new Angle(0.25f, 0.0f, 1.0f),
+ new Angle(0.5f, -1.0f, 0.0f),
+ new Angle(0.75f, 0.0f, -1.0f),
+ new Angle(1.0f, 1.0f, 0.0f)
+ };
+
+ private static Coord[] normals4 =
+ {
+ new Coord(0.5f, 0.5f, 0.0f).Normalize(),
+ new Coord(-0.5f, 0.5f, 0.0f).Normalize(),
+ new Coord(-0.5f, -0.5f, 0.0f).Normalize(),
+ new Coord(0.5f, -0.5f, 0.0f).Normalize(),
+ new Coord(0.5f, 0.5f, 0.0f).Normalize()
+ };
+
+ private static Angle[] angles24 =
+ {
+ new Angle(0.0f, 1.0f, 0.0f),
+ new Angle(0.041666666666666664f, 0.96592582628906831f, 0.25881904510252074f),
+ new Angle(0.083333333333333329f, 0.86602540378443871f, 0.5f),
+ new Angle(0.125f, 0.70710678118654757f, 0.70710678118654746f),
+ new Angle(0.16666666666666667f, 0.5f, 0.8660254037844386f),
+ new Angle(0.20833333333333331f, 0.25881904510252096f, 0.9659258262890682f),
+ new Angle(0.25f, 0.0f, 1.0f),
+ new Angle(0.29166666666666663f, -0.25881904510252063f, 0.96592582628906831f),
+ new Angle(0.33333333333333333f, -0.5f, 0.86602540378443871f),
+ new Angle(0.375f, -0.70710678118654746f, 0.70710678118654757f),
+ new Angle(0.41666666666666663f, -0.86602540378443849f, 0.5f),
+ new Angle(0.45833333333333331f, -0.9659258262890682f, 0.25881904510252102f),
+ new Angle(0.5f, -1.0f, 0.0f),
+ new Angle(0.54166666666666663f, -0.96592582628906842f, -0.25881904510252035f),
+ new Angle(0.58333333333333326f, -0.86602540378443882f, -0.5f),
+ new Angle(0.62499999999999989f, -0.70710678118654791f, -0.70710678118654713f),
+ new Angle(0.66666666666666667f, -0.5f, -0.86602540378443837f),
+ new Angle(0.70833333333333326f, -0.25881904510252152f, -0.96592582628906809f),
+ new Angle(0.75f, 0.0f, -1.0f),
+ new Angle(0.79166666666666663f, 0.2588190451025203f, -0.96592582628906842f),
+ new Angle(0.83333333333333326f, 0.5f, -0.86602540378443904f),
+ new Angle(0.875f, 0.70710678118654735f, -0.70710678118654768f),
+ new Angle(0.91666666666666663f, 0.86602540378443837f, -0.5f),
+ new Angle(0.95833333333333326f, 0.96592582628906809f, -0.25881904510252157f),
+ new Angle(1.0f, 1.0f, 0.0f)
+ };
+
+ private Angle interpolatePoints(float newPoint, Angle p1, Angle p2)
+ {
+ float m = (newPoint - p1.angle) / (p2.angle - p1.angle);
+ return new Angle(newPoint, p1.X + m * (p2.X - p1.X), p1.Y + m * (p2.Y - p1.Y));
+ }
+
+ private void intersection(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)
+ { // ref: http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/
+ double denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
+ double uaNumerator = (x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3);
+
+ if (denom != 0.0)
+ {
+ double ua = uaNumerator / denom;
+ iX = (float)(x1 + ua * (x2 - x1));
+ iY = (float)(y1 + ua * (y2 - y1));
+ }
+ }
+
+ internal List angles;
+ internal List normals;
+
+ internal void makeAngles(int sides, float startAngle, float stopAngle)
+ {
+ angles = new List();
+ normals = new List();
+
+ double twoPi = System.Math.PI * 2.0;
+ float twoPiInv = 1.0f / (float)twoPi;
+
+ if (sides < 1)
+ throw new Exception("number of sides not greater than zero");
+ if (stopAngle <= startAngle)
+ throw new Exception("stopAngle not greater than startAngle");
+
+ if ((sides == 3 || sides == 4 || sides == 24))
+ {
+ startAngle *= twoPiInv;
+ stopAngle *= twoPiInv;
+
+ Angle[] sourceAngles;
+ if (sides == 3)
+ sourceAngles = angles3;
+ else if (sides == 4)
+ sourceAngles = angles4;
+ else sourceAngles = angles24;
+
+ int startAngleIndex = (int)(startAngle * sides);
+ int endAngleIndex = sourceAngles.Length - 1;
+ if (stopAngle < 1.0f)
+ endAngleIndex = (int)(stopAngle * sides) + 1;
+ if (endAngleIndex == startAngleIndex)
+ endAngleIndex++;
+
+ for (int angleIndex = startAngleIndex; angleIndex < endAngleIndex + 1; angleIndex++)
+ {
+ angles.Add(sourceAngles[angleIndex]);
+ if (sides == 3)
+ normals.Add(normals3[angleIndex]);
+ else if (sides == 4)
+ normals.Add(normals4[angleIndex]);
+ }
+
+ if (startAngle > 0.0f)
+ angles[0] = interpolatePoints(startAngle, angles[0], angles[1]);
+
+ if (stopAngle < 1.0f)
+ {
+ int lastAngleIndex = angles.Count - 1;
+ angles[lastAngleIndex] = interpolatePoints(stopAngle, angles[lastAngleIndex - 1], angles[lastAngleIndex]);
+ }
+ }
+ else
+ {
+ double stepSize = twoPi / sides;
+
+ int startStep = (int)(startAngle / stepSize);
+ double angle = stepSize * startStep;
+ int step = startStep;
+ double stopAngleTest = stopAngle;
+ if (stopAngle < twoPi)
+ {
+ stopAngleTest = stepSize * ((int)(stopAngle / stepSize) + 1);
+ if (stopAngleTest < stopAngle)
+ stopAngleTest += stepSize;
+ if (stopAngleTest > twoPi)
+ stopAngleTest = twoPi;
+ }
+
+ while (angle <= stopAngleTest)
+ {
+ Angle newAngle;
+ newAngle.angle = (float)angle;
+ newAngle.X = (float)System.Math.Cos(angle);
+ newAngle.Y = (float)System.Math.Sin(angle);
+ angles.Add(newAngle);
+ step += 1;
+ angle = stepSize * step;
+ }
+
+ if (startAngle > angles[0].angle)
+ {
+ Angle newAngle;
+ intersection(angles[0].X, angles[0].Y, angles[1].X, angles[1].Y, 0.0f, 0.0f, (float)Math.Cos(startAngle), (float)Math.Sin(startAngle));
+ newAngle.angle = startAngle;
+ newAngle.X = iX;
+ newAngle.Y = iY;
+ angles[0] = newAngle;
+ }
+
+ int index = angles.Count - 1;
+ if (stopAngle < angles[index].angle)
+ {
+ Angle newAngle;
+ intersection(angles[index - 1].X, angles[index - 1].Y, angles[index].X, angles[index].Y, 0.0f, 0.0f, (float)Math.Cos(stopAngle), (float)Math.Sin(stopAngle));
+ newAngle.angle = stopAngle;
+ newAngle.X = iX;
+ newAngle.Y = iY;
+ angles[index] = newAngle;
+ }
+ }
+ }
+ }
+
+ ///
+ /// generates a profile for extrusion
+ ///
+ internal class Profile
+ {
+ private const float twoPi = 2.0f * (float)Math.PI;
+
+ internal string errorMessage = null;
+
+ internal List coords;
+ internal List faces;
+ internal List vertexNormals;
+ internal List us;
+ internal List faceUVs;
+ internal List faceNumbers;
+
+ // use these for making individual meshes for each prim face
+ internal List outerCoordIndices = null;
+ internal List hollowCoordIndices = null;
+ internal List cut1CoordIndices = null;
+ internal List cut2CoordIndices = null;
+
+ internal Coord faceNormal = new Coord(0.0f, 0.0f, 1.0f);
+ internal Coord cutNormal1 = new Coord();
+ internal Coord cutNormal2 = new Coord();
+
+ internal int numOuterVerts = 0;
+ internal int numHollowVerts = 0;
+
+ internal bool calcVertexNormals = false;
+ internal int bottomFaceNumber = 0;
+ internal int numPrimFaces = 0;
+
+ internal Profile()
+ {
+ this.coords = new List();
+ this.faces = new List();
+ this.vertexNormals = new List();
+ this.us = new List();
+ this.faceUVs = new List();
+ this.faceNumbers = new List();
+ }
+
+ internal Profile(int sides, float profileStart, float profileEnd, float hollow, int hollowSides, bool createFaces, bool calcVertexNormals)
+ {
+ this.calcVertexNormals = calcVertexNormals;
+ this.coords = new List();
+ this.faces = new List();
+ this.vertexNormals = new List();
+ this.us = new List();
+ this.faceUVs = new List();
+ this.faceNumbers = new List();
+
+ Coord center = new Coord(0.0f, 0.0f, 0.0f);
+ //bool hasCenter = false;
+
+ List hollowCoords = new List();
+ List hollowNormals = new List();
+ List hollowUs = new List();
+
+ if (calcVertexNormals)
+ {
+ this.outerCoordIndices = new List();
+ this.hollowCoordIndices = new List();
+ this.cut1CoordIndices = new List();
+ this.cut2CoordIndices = new List();
+ }
+
+ bool hasHollow = (hollow > 0.0f);
+
+ bool hasProfileCut = (profileStart > 0.0f || profileEnd < 1.0f);
+
+ AngleList angles = new AngleList();
+ AngleList hollowAngles = new AngleList();
+
+ float xScale = 0.5f;
+ float yScale = 0.5f;
+ if (sides == 4) // corners of a square are sqrt(2) from center
+ {
+ xScale = 0.707f;
+ yScale = 0.707f;
+ }
+
+ float startAngle = profileStart * twoPi;
+ float stopAngle = profileEnd * twoPi;
+
+ try { angles.makeAngles(sides, startAngle, stopAngle); }
+ catch (Exception ex)
+ {
+
+ errorMessage = "makeAngles failed: Exception: " + ex.ToString()
+ + "\nsides: " + sides.ToString() + " startAngle: " + startAngle.ToString() + " stopAngle: " + stopAngle.ToString();
+
+ return;
+ }
+
+ this.numOuterVerts = angles.angles.Count;
+
+ // flag to create as few triangles as possible for 3 or 4 side profile
+ bool simpleFace = (sides < 5 && !hasHollow && !hasProfileCut);
+
+ if (hasHollow)
+ {
+ if (sides == hollowSides)
+ hollowAngles = angles;
+ else
+ {
+ try { hollowAngles.makeAngles(hollowSides, startAngle, stopAngle); }
+ catch (Exception ex)
+ {
+ errorMessage = "makeAngles failed: Exception: " + ex.ToString()
+ + "\nsides: " + sides.ToString() + " startAngle: " + startAngle.ToString() + " stopAngle: " + stopAngle.ToString();
+
+ return;
+ }
+ }
+ this.numHollowVerts = hollowAngles.angles.Count;
+ }
+ else if (!simpleFace)
+ {
+ this.coords.Add(center);
+ //hasCenter = true;
+ if (this.calcVertexNormals)
+ this.vertexNormals.Add(new Coord(0.0f, 0.0f, 1.0f));
+ this.us.Add(0.0f);
+ }
+
+ float z = 0.0f;
+
+ Angle angle;
+ Coord newVert = new Coord();
+ if (hasHollow && hollowSides != sides)
+ {
+ int numHollowAngles = hollowAngles.angles.Count;
+ for (int i = 0; i < numHollowAngles; i++)
+ {
+ angle = hollowAngles.angles[i];
+ newVert.X = hollow * xScale * angle.X;
+ newVert.Y = hollow * yScale * angle.Y;
+ newVert.Z = z;
+
+ hollowCoords.Add(newVert);
+ if (this.calcVertexNormals)
+ {
+ if (hollowSides < 5)
+ hollowNormals.Add(hollowAngles.normals[i].Invert());
+ else
+ hollowNormals.Add(new Coord(-angle.X, -angle.Y, 0.0f));
+
+ hollowUs.Add(angle.angle * hollow);
+ }
+ }
+ }
+
+ int index = 0;
+ int numAngles = angles.angles.Count;
+
+ for (int i = 0; i < numAngles; i++)
+ {
+ angle = angles.angles[i];
+ newVert.X = angle.X * xScale;
+ newVert.Y = angle.Y * yScale;
+ newVert.Z = z;
+ this.coords.Add(newVert);
+ if (this.calcVertexNormals)
+ {
+ this.outerCoordIndices.Add(this.coords.Count - 1);
+
+ if (sides < 5)
+ {
+ this.vertexNormals.Add(angles.normals[i]);
+ float u = angle.angle;
+ this.us.Add(u);
+ }
+ else
+ {
+ this.vertexNormals.Add(new Coord(angle.X, angle.Y, 0.0f));
+ this.us.Add(angle.angle);
+ }
+ }
+
+ if (hasHollow)
+ {
+ if (hollowSides == sides)
+ {
+ newVert.X *= hollow;
+ newVert.Y *= hollow;
+ newVert.Z = z;
+ hollowCoords.Add(newVert);
+ if (this.calcVertexNormals)
+ {
+ if (sides < 5)
+ {
+ hollowNormals.Add(angles.normals[i].Invert());
+ }
+
+ else
+ hollowNormals.Add(new Coord(-angle.X, -angle.Y, 0.0f));
+
+ hollowUs.Add(angle.angle * hollow);
+ }
+ }
+ }
+ else if (!simpleFace && createFaces && angle.angle > 0.0001f)
+ {
+ Face newFace = new Face();
+ newFace.v1 = 0;
+ newFace.v2 = index;
+ newFace.v3 = index + 1;
+
+ this.faces.Add(newFace);
+ }
+ index += 1;
+ }
+
+ if (hasHollow)
+ {
+ hollowCoords.Reverse();
+ if (this.calcVertexNormals)
+ {
+ hollowNormals.Reverse();
+ hollowUs.Reverse();
+ }
+
+ if (createFaces)
+ {
+ //int numOuterVerts = this.coords.Count;
+ //numOuterVerts = this.coords.Count;
+ //int numHollowVerts = hollowCoords.Count;
+ int numTotalVerts = this.numOuterVerts + this.numHollowVerts;
+
+ if (this.numOuterVerts == this.numHollowVerts)
+ {
+ Face newFace = new Face();
+
+ for (int coordIndex = 0; coordIndex < this.numOuterVerts - 1; coordIndex++)
+ {
+ newFace.v1 = coordIndex;
+ newFace.v2 = coordIndex + 1;
+ newFace.v3 = numTotalVerts - coordIndex - 1;
+ this.faces.Add(newFace);
+
+ newFace.v1 = coordIndex + 1;
+ newFace.v2 = numTotalVerts - coordIndex - 2;
+ newFace.v3 = numTotalVerts - coordIndex - 1;
+ this.faces.Add(newFace);
+ }
+ }
+ else
+ {
+ if (this.numOuterVerts < this.numHollowVerts)
+ {
+ Face newFace = new Face();
+ int j = 0; // j is the index for outer vertices
+ int maxJ = this.numOuterVerts - 1;
+ for (int i = 0; i < this.numHollowVerts; i++) // i is the index for inner vertices
+ {
+ if (j < maxJ)
+ if (angles.angles[j + 1].angle - hollowAngles.angles[i].angle < hollowAngles.angles[i].angle - angles.angles[j].angle + 0.000001f)
+ {
+ newFace.v1 = numTotalVerts - i - 1;
+ newFace.v2 = j;
+ newFace.v3 = j + 1;
+
+ this.faces.Add(newFace);
+ j += 1;
+ }
+
+ newFace.v1 = j;
+ newFace.v2 = numTotalVerts - i - 2;
+ newFace.v3 = numTotalVerts - i - 1;
+
+ this.faces.Add(newFace);
+ }
+ }
+ else // numHollowVerts < numOuterVerts
+ {
+ Face newFace = new Face();
+ int j = 0; // j is the index for inner vertices
+ int maxJ = this.numHollowVerts - 1;
+ for (int i = 0; i < this.numOuterVerts; i++)
+ {
+ if (j < maxJ)
+ if (hollowAngles.angles[j + 1].angle - angles.angles[i].angle < angles.angles[i].angle - hollowAngles.angles[j].angle + 0.000001f)
+ {
+ newFace.v1 = i;
+ newFace.v2 = numTotalVerts - j - 2;
+ newFace.v3 = numTotalVerts - j - 1;
+
+ this.faces.Add(newFace);
+ j += 1;
+ }
+
+ newFace.v1 = numTotalVerts - j - 1;
+ newFace.v2 = i;
+ newFace.v3 = i + 1;
+
+ this.faces.Add(newFace);
+ }
+ }
+ }
+ }
+
+ if (calcVertexNormals)
+ {
+ foreach (Coord hc in hollowCoords)
+ {
+ this.coords.Add(hc);
+ hollowCoordIndices.Add(this.coords.Count - 1);
+ }
+ }
+ else
+ this.coords.AddRange(hollowCoords);
+
+ if (this.calcVertexNormals)
+ {
+ this.vertexNormals.AddRange(hollowNormals);
+ this.us.AddRange(hollowUs);
+
+ }
+ }
+
+ if (simpleFace && createFaces)
+ {
+ if (sides == 3)
+ this.faces.Add(new Face(0, 1, 2));
+ else if (sides == 4)
+ {
+ this.faces.Add(new Face(0, 1, 2));
+ this.faces.Add(new Face(0, 2, 3));
+ }
+ }
+
+ if (calcVertexNormals && hasProfileCut)
+ {
+ if (hasHollow)
+ {
+ int lastOuterVertIndex = this.numOuterVerts - 1;
+
+ this.cut1CoordIndices.Add(0);
+ this.cut1CoordIndices.Add(this.coords.Count - 1);
+
+ this.cut2CoordIndices.Add(lastOuterVertIndex + 1);
+ this.cut2CoordIndices.Add(lastOuterVertIndex);
+
+ this.cutNormal1.X = this.coords[0].Y - this.coords[this.coords.Count - 1].Y;
+ this.cutNormal1.Y = -(this.coords[0].X - this.coords[this.coords.Count - 1].X);
+
+ this.cutNormal2.X = this.coords[lastOuterVertIndex + 1].Y - this.coords[lastOuterVertIndex].Y;
+ this.cutNormal2.Y = -(this.coords[lastOuterVertIndex + 1].X - this.coords[lastOuterVertIndex].X);
+ }
+
+ else
+ {
+ this.cutNormal1.X = this.vertexNormals[1].Y;
+ this.cutNormal1.Y = -this.vertexNormals[1].X;
+
+ this.cutNormal2.X = -this.vertexNormals[this.vertexNormals.Count - 2].Y;
+ this.cutNormal2.Y = this.vertexNormals[this.vertexNormals.Count - 2].X;
+
+ }
+ this.cutNormal1.Normalize();
+ this.cutNormal2.Normalize();
+ }
+
+ this.MakeFaceUVs();
+
+ hollowCoords = null;
+ hollowNormals = null;
+ hollowUs = null;
+
+ if (calcVertexNormals)
+ { // calculate prim face numbers
+
+ // face number order is top, outer, hollow, bottom, start cut, end cut
+ // I know it's ugly but so is the whole concept of prim face numbers
+
+ int faceNum = 1; // start with outer faces
+ int startVert = hasProfileCut && !hasHollow ? 1 : 0;
+ if (startVert > 0)
+ this.faceNumbers.Add(-1);
+ for (int i = 0; i < this.numOuterVerts - 1; i++)
+ this.faceNumbers.Add(sides < 5 ? faceNum++ : faceNum);
+
+ //if (!hasHollow && !hasProfileCut)
+ // this.bottomFaceNumber = faceNum++;
+
+ this.faceNumbers.Add(hasProfileCut ? -1 : faceNum++);
+
+ if (sides > 4 && (hasHollow || hasProfileCut))
+ faceNum++;
+
+ if (hasHollow)
+ {
+ for (int i = 0; i < this.numHollowVerts; i++)
+ this.faceNumbers.Add(faceNum);
+
+ faceNum++;
+ }
+ //if (hasProfileCut || hasHollow)
+ // this.bottomFaceNumber = faceNum++;
+ this.bottomFaceNumber = faceNum++;
+
+ if (hasHollow && hasProfileCut)
+ this.faceNumbers.Add(faceNum++);
+ for (int i = 0; i < this.faceNumbers.Count; i++)
+ if (this.faceNumbers[i] == -1)
+ this.faceNumbers[i] = faceNum++;
+
+
+ this.numPrimFaces = faceNum;
+ }
+
+ }
+
+ internal void MakeFaceUVs()
+ {
+ this.faceUVs = new List();
+ foreach (Coord c in this.coords)
+ this.faceUVs.Add(new UVCoord(0.5f + c.X, 0.5f - c.Y));
+ }
+
+ internal Profile Copy()
+ {
+ return this.Copy(true);
+ }
+
+ internal Profile Copy(bool needFaces)
+ {
+ Profile copy = new Profile();
+
+ copy.coords.AddRange(this.coords);
+ copy.faceUVs.AddRange(this.faceUVs);
+
+ if (needFaces)
+ copy.faces.AddRange(this.faces);
+ if ((copy.calcVertexNormals = this.calcVertexNormals) == true)
+ {
+ copy.vertexNormals.AddRange(this.vertexNormals);
+ copy.faceNormal = this.faceNormal;
+ copy.cutNormal1 = this.cutNormal1;
+ copy.cutNormal2 = this.cutNormal2;
+ copy.us.AddRange(this.us);
+ copy.faceNumbers.AddRange(this.faceNumbers);
+
+ copy.cut1CoordIndices = new List(this.cut1CoordIndices);
+ copy.cut2CoordIndices = new List(this.cut2CoordIndices);
+ copy.hollowCoordIndices = new List(this.hollowCoordIndices);
+ copy.outerCoordIndices = new List(this.outerCoordIndices);
+ }
+ copy.numOuterVerts = this.numOuterVerts;
+ copy.numHollowVerts = this.numHollowVerts;
+
+ return copy;
+ }
+
+ internal void AddPos(Coord v)
+ {
+ this.AddPos(v.X, v.Y, v.Z);
+ }
+
+ internal void AddPos(float x, float y, float z)
+ {
+ int i;
+ int numVerts = this.coords.Count;
+ Coord vert;
+
+ for (i = 0; i < numVerts; i++)
+ {
+ vert = this.coords[i];
+ vert.X += x;
+ vert.Y += y;
+ vert.Z += z;
+ this.coords[i] = vert;
+ }
+ }
+
+ internal void AddRot(Quat q)
+ {
+ int i;
+ int numVerts = this.coords.Count;
+
+ for (i = 0; i < numVerts; i++)
+ this.coords[i] *= q;
+
+ if (this.calcVertexNormals)
+ {
+ int numNormals = this.vertexNormals.Count;
+ for (i = 0; i < numNormals; i++)
+ this.vertexNormals[i] *= q;
+
+ this.faceNormal *= q;
+ this.cutNormal1 *= q;
+ this.cutNormal2 *= q;
+
+ }
+ }
+
+ internal void Scale(float x, float y)
+ {
+ int i;
+ int numVerts = this.coords.Count;
+ Coord vert;
+
+ for (i = 0; i < numVerts; i++)
+ {
+ vert = this.coords[i];
+ vert.X *= x;
+ vert.Y *= y;
+ this.coords[i] = vert;
+ }
+ }
+
+ ///
+ /// Changes order of the vertex indices and negates the center vertex normal. Does not alter vertex normals of radial vertices
+ ///
+ internal void FlipNormals()
+ {
+ int i;
+ int numFaces = this.faces.Count;
+ Face tmpFace;
+ int tmp;
+
+ for (i = 0; i < numFaces; i++)
+ {
+ tmpFace = this.faces[i];
+ tmp = tmpFace.v3;
+ tmpFace.v3 = tmpFace.v1;
+ tmpFace.v1 = tmp;
+ this.faces[i] = tmpFace;
+ }
+
+ if (this.calcVertexNormals)
+ {
+ int normalCount = this.vertexNormals.Count;
+ if (normalCount > 0)
+ {
+ Coord n = this.vertexNormals[normalCount - 1];
+ n.Z = -n.Z;
+ this.vertexNormals[normalCount - 1] = n;
+ }
+ }
+
+ this.faceNormal.X = -this.faceNormal.X;
+ this.faceNormal.Y = -this.faceNormal.Y;
+ this.faceNormal.Z = -this.faceNormal.Z;
+
+ int numfaceUVs = this.faceUVs.Count;
+ for (i = 0; i < numfaceUVs; i++)
+ {
+ UVCoord uv = this.faceUVs[i];
+ uv.V = 1.0f - uv.V;
+ this.faceUVs[i] = uv;
+ }
+ }
+
+ internal void AddValue2FaceVertexIndices(int num)
+ {
+ int numFaces = this.faces.Count;
+ Face tmpFace;
+ for (int i = 0; i < numFaces; i++)
+ {
+ tmpFace = this.faces[i];
+ tmpFace.v1 += num;
+ tmpFace.v2 += num;
+ tmpFace.v3 += num;
+
+ this.faces[i] = tmpFace;
+ }
+ }
+
+ internal void AddValue2FaceNormalIndices(int num)
+ {
+ if (this.calcVertexNormals)
+ {
+ int numFaces = this.faces.Count;
+ Face tmpFace;
+ for (int i = 0; i < numFaces; i++)
+ {
+ tmpFace = this.faces[i];
+ tmpFace.n1 += num;
+ tmpFace.n2 += num;
+ tmpFace.n3 += num;
+
+ this.faces[i] = tmpFace;
+ }
+ }
+ }
+
+ internal void DumpRaw(String path, String name, String title)
+ {
+ if (path == null)
+ return;
+ String fileName = name + "_" + title + ".raw";
+ String completePath = System.IO.Path.Combine(path, fileName);
+ StreamWriter sw = new StreamWriter(completePath);
+
+ for (int i = 0; i < this.faces.Count; i++)
+ {
+ string s = this.coords[this.faces[i].v1].ToString();
+ s += " " + this.coords[this.faces[i].v2].ToString();
+ s += " " + this.coords[this.faces[i].v3].ToString();
+
+ sw.WriteLine(s);
+ }
+
+ sw.Close();
+ }
+ }
+
+ public struct PathNode
+ {
+ public Coord position;
+ public Quat rotation;
+ public float xScale;
+ public float yScale;
+ public float percentOfPath;
+ }
+
+ public enum PathType { Linear = 0, Circular = 1, Flexible = 2 }
+
+ public class Path
+ {
+ public List pathNodes = new List();
+
+ public float twistBegin = 0.0f;
+ public float twistEnd = 0.0f;
+ public float topShearX = 0.0f;
+ public float topShearY = 0.0f;
+ public float pathCutBegin = 0.0f;
+ public float pathCutEnd = 1.0f;
+ public float dimpleBegin = 0.0f;
+ public float dimpleEnd = 1.0f;
+ public float skew = 0.0f;
+ public float holeSizeX = 1.0f; // called pathScaleX in pbs
+ public float holeSizeY = 0.25f;
+ public float taperX = 0.0f;
+ public float taperY = 0.0f;
+ public float radius = 0.0f;
+ public float revolutions = 1.0f;
+ public int stepsPerRevolution = 24;
+
+ private const float twoPi = 2.0f * (float)Math.PI;
+
+ public void Create(PathType pathType, int steps)
+ {
+ if (pathType == PathType.Linear || pathType == PathType.Flexible)
+ {
+ int step = 0;
+
+ float length = this.pathCutEnd - this.pathCutBegin;
+ float twistTotal = twistEnd - twistBegin;
+ float twistTotalAbs = Math.Abs(twistTotal);
+ if (twistTotalAbs > 0.01f)
+ steps += (int)(twistTotalAbs * 3.66); // dahlia's magic number
+
+ float start = -0.5f;
+ float stepSize = length / (float)steps;
+ float percentOfPathMultiplier = stepSize;
+ float xOffset = 0.0f;
+ float yOffset = 0.0f;
+ float zOffset = start;
+ float xOffsetStepIncrement = this.topShearX / steps;
+ float yOffsetStepIncrement = this.topShearY / steps;
+
+ float percentOfPath = this.pathCutBegin;
+ zOffset += percentOfPath;
+
+ // sanity checks
+
+ bool done = false;
+
+ while (!done)
+ {
+ PathNode newNode = new PathNode();
+
+ newNode.xScale = 1.0f;
+ if (this.taperX == 0.0f)
+ newNode.xScale = 1.0f;
+ else if (this.taperX > 0.0f)
+ newNode.xScale = 1.0f - percentOfPath * this.taperX;
+ else newNode.xScale = 1.0f + (1.0f - percentOfPath) * this.taperX;
+
+ newNode.yScale = 1.0f;
+ if (this.taperY == 0.0f)
+ newNode.yScale = 1.0f;
+ else if (this.taperY > 0.0f)
+ newNode.yScale = 1.0f - percentOfPath * this.taperY;
+ else newNode.yScale = 1.0f + (1.0f - percentOfPath) * this.taperY;
+
+ float twist = twistBegin + twistTotal * percentOfPath;
+
+ newNode.rotation = new Quat(new Coord(0.0f, 0.0f, 1.0f), twist);
+ newNode.position = new Coord(xOffset, yOffset, zOffset);
+ newNode.percentOfPath = percentOfPath;
+
+ pathNodes.Add(newNode);
+
+ if (step < steps)
+ {
+ step += 1;
+ percentOfPath += percentOfPathMultiplier;
+ xOffset += xOffsetStepIncrement;
+ yOffset += yOffsetStepIncrement;
+ zOffset += stepSize;
+ if (percentOfPath > this.pathCutEnd)
+ done = true;
+ }
+ else done = true;
+ }
+ } // end of linear path code
+
+ else // pathType == Circular
+ {
+ float twistTotal = twistEnd - twistBegin;
+
+ // if the profile has a lot of twist, add more layers otherwise the layers may overlap
+ // and the resulting mesh may be quite inaccurate. This method is arbitrary and doesn't
+ // accurately match the viewer
+ float twistTotalAbs = Math.Abs(twistTotal);
+ if (twistTotalAbs > 0.01f)
+ {
+ if (twistTotalAbs > Math.PI * 1.5f)
+ steps *= 2;
+ if (twistTotalAbs > Math.PI * 3.0f)
+ steps *= 2;
+ }
+
+ float yPathScale = this.holeSizeY * 0.5f;
+ float pathLength = this.pathCutEnd - this.pathCutBegin;
+ float totalSkew = this.skew * 2.0f * pathLength;
+ float skewStart = this.pathCutBegin * 2.0f * this.skew - this.skew;
+ float xOffsetTopShearXFactor = this.topShearX * (0.25f + 0.5f * (0.5f - this.holeSizeY));
+ float yShearCompensation = 1.0f + Math.Abs(this.topShearY) * 0.25f;
+
+ // It's not quite clear what pushY (Y top shear) does, but subtracting it from the start and end
+ // angles appears to approximate it's effects on path cut. Likewise, adding it to the angle used
+ // to calculate the sine for generating the path radius appears to approximate it's effects there
+ // too, but there are some subtle differences in the radius which are noticeable as the prim size
+ // increases and it may affect megaprims quite a bit. The effect of the Y top shear parameter on
+ // the meshes generated with this technique appear nearly identical in shape to the same prims when
+ // displayed by the viewer.
+
+ float startAngle = (twoPi * this.pathCutBegin * this.revolutions) - this.topShearY * 0.9f;
+ float endAngle = (twoPi * this.pathCutEnd * this.revolutions) - this.topShearY * 0.9f;
+ float stepSize = twoPi / this.stepsPerRevolution;
+
+ int step = (int)(startAngle / stepSize);
+ float angle = startAngle;
+
+ bool done = false;
+ while (!done) // loop through the length of the path and add the layers
+ {
+ PathNode newNode = new PathNode();
+
+ float xProfileScale = (1.0f - Math.Abs(this.skew)) * this.holeSizeX;
+ float yProfileScale = this.holeSizeY;
+
+ float percentOfPath = angle / (twoPi * this.revolutions);
+ float percentOfAngles = (angle - startAngle) / (endAngle - startAngle);
+
+ if (this.taperX > 0.01f)
+ xProfileScale *= 1.0f - percentOfPath * this.taperX;
+ else if (this.taperX < -0.01f)
+ xProfileScale *= 1.0f + (1.0f - percentOfPath) * this.taperX;
+
+ if (this.taperY > 0.01f)
+ yProfileScale *= 1.0f - percentOfPath * this.taperY;
+ else if (this.taperY < -0.01f)
+ yProfileScale *= 1.0f + (1.0f - percentOfPath) * this.taperY;
+
+ newNode.xScale = xProfileScale;
+ newNode.yScale = yProfileScale;
+
+ float radiusScale = 1.0f;
+ if (this.radius > 0.001f)
+ radiusScale = 1.0f - this.radius * percentOfPath;
+ else if (this.radius < 0.001f)
+ radiusScale = 1.0f + this.radius * (1.0f - percentOfPath);
+
+ float twist = twistBegin + twistTotal * percentOfPath;
+
+ float xOffset = 0.5f * (skewStart + totalSkew * percentOfAngles);
+ xOffset += (float)Math.Sin(angle) * xOffsetTopShearXFactor;
+
+ float yOffset = yShearCompensation * (float)Math.Cos(angle) * (0.5f - yPathScale) * radiusScale;
+
+ float zOffset = (float)Math.Sin(angle + this.topShearY) * (0.5f - yPathScale) * radiusScale;
+
+ newNode.position = new Coord(xOffset, yOffset, zOffset);
+
+ // now orient the rotation of the profile layer relative to it's position on the path
+ // adding taperY to the angle used to generate the quat appears to approximate the viewer
+
+ newNode.rotation = new Quat(new Coord(1.0f, 0.0f, 0.0f), angle + this.topShearY);
+
+ // next apply twist rotation to the profile layer
+ if (twistTotal != 0.0f || twistBegin != 0.0f)
+ newNode.rotation *= new Quat(new Coord(0.0f, 0.0f, 1.0f), twist);
+
+ newNode.percentOfPath = percentOfPath;
+
+ pathNodes.Add(newNode);
+
+ // calculate terms for next iteration
+ // calculate the angle for the next iteration of the loop
+
+ if (angle >= endAngle - 0.01)
+ done = true;
+ else
+ {
+ step += 1;
+ angle = stepSize * step;
+ if (angle > endAngle)
+ angle = endAngle;
+ }
+ }
+ }
+ }
+ }
+
+ public class PrimMesh
+ {
+ public string errorMessage = "";
+ private const float twoPi = 2.0f * (float)Math.PI;
+
+ public List coords;
+ public List normals;
+ public List faces;
+
+ public List viewerFaces;
+
+ private int sides = 4;
+ private int hollowSides = 4;
+ private float profileStart = 0.0f;
+ private float profileEnd = 1.0f;
+ private float hollow = 0.0f;
+ public int twistBegin = 0;
+ public int twistEnd = 0;
+ public float topShearX = 0.0f;
+ public float topShearY = 0.0f;
+ public float pathCutBegin = 0.0f;
+ public float pathCutEnd = 1.0f;
+ public float dimpleBegin = 0.0f;
+ public float dimpleEnd = 1.0f;
+ public float skew = 0.0f;
+ public float holeSizeX = 1.0f; // called pathScaleX in pbs
+ public float holeSizeY = 0.25f;
+ public float taperX = 0.0f;
+ public float taperY = 0.0f;
+ public float radius = 0.0f;
+ public float revolutions = 1.0f;
+ public int stepsPerRevolution = 24;
+
+ private bool hasProfileCut = false;
+ private bool hasHollow = false;
+ public bool calcVertexNormals = false;
+ private bool normalsProcessed = false;
+ public bool viewerMode = false;
+
+ public int numPrimFaces = 0;
+
+ ///
+ /// Human readable string representation of the parameters used to create a mesh.
+ ///
+ ///
+ public string ParamsToDisplayString()
+ {
+ string s = "";
+ s += "sides..................: " + this.sides.ToString();
+ s += "\nhollowSides..........: " + this.hollowSides.ToString();
+ s += "\nprofileStart.........: " + this.profileStart.ToString();
+ s += "\nprofileEnd...........: " + this.profileEnd.ToString();
+ s += "\nhollow...............: " + this.hollow.ToString();
+ s += "\ntwistBegin...........: " + this.twistBegin.ToString();
+ s += "\ntwistEnd.............: " + this.twistEnd.ToString();
+ s += "\ntopShearX............: " + this.topShearX.ToString();
+ s += "\ntopShearY............: " + this.topShearY.ToString();
+ s += "\npathCutBegin.........: " + this.pathCutBegin.ToString();
+ s += "\npathCutEnd...........: " + this.pathCutEnd.ToString();
+ s += "\ndimpleBegin..........: " + this.dimpleBegin.ToString();
+ s += "\ndimpleEnd............: " + this.dimpleEnd.ToString();
+ s += "\nskew.................: " + this.skew.ToString();
+ s += "\nholeSizeX............: " + this.holeSizeX.ToString();
+ s += "\nholeSizeY............: " + this.holeSizeY.ToString();
+ s += "\ntaperX...............: " + this.taperX.ToString();
+ s += "\ntaperY...............: " + this.taperY.ToString();
+ s += "\nradius...............: " + this.radius.ToString();
+ s += "\nrevolutions..........: " + this.revolutions.ToString();
+ s += "\nstepsPerRevolution...: " + this.stepsPerRevolution.ToString();
+
+ return s;
+ }
+
+ ///
+ /// Constructs a PrimMesh object and creates the profile for extrusion.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public PrimMesh(int sides, float profileStart, float profileEnd, float hollow, int hollowSides)
+ {
+ this.coords = new List();
+ this.faces = new List();
+
+ this.sides = sides;
+ this.profileStart = profileStart;
+ this.profileEnd = profileEnd;
+ this.hollow = hollow;
+ this.hollowSides = hollowSides;
+
+ if (sides < 3)
+ this.sides = 3;
+ if (hollowSides < 3)
+ this.hollowSides = 3;
+ if (profileStart < 0.0f)
+ this.profileStart = 0.0f;
+ if (profileEnd > 1.0f)
+ this.profileEnd = 1.0f;
+ if (profileEnd < 0.02f)
+ this.profileEnd = 0.02f;
+ if (profileStart >= profileEnd)
+ this.profileStart = profileEnd - 0.02f;
+ if (hollow > 0.99f)
+ this.hollow = 0.99f;
+ if (hollow < 0.0f)
+ this.hollow = 0.0f;
+
+ this.hasProfileCut = (this.profileStart > 0.0f || this.profileEnd < 1.0f);
+ this.hasHollow = (this.hollow > 0.001f);
+ }
+
+ ///
+ /// Extrudes a profile along a path.
+ ///
+ public void Extrude(PathType pathType)
+ {
+ this.coords = new List();
+ this.faces = new List();
+
+ if (this.viewerMode)
+ {
+ this.viewerFaces = new List();
+ this.calcVertexNormals = true;
+ }
+
+ if (this.calcVertexNormals)
+ this.normals = new List();
+
+ int steps = 1;
+
+ float length = this.pathCutEnd - this.pathCutBegin;
+ normalsProcessed = false;
+
+ if (this.viewerMode && this.sides == 3)
+ {
+ // prisms don't taper well so add some vertical resolution
+ // other prims may benefit from this but just do prisms for now
+ if (Math.Abs(this.taperX) > 0.01 || Math.Abs(this.taperY) > 0.01)
+ steps = (int)(steps * 4.5 * length);
+ }
+
+
+ float twistBegin = this.twistBegin / 360.0f * twoPi;
+ float twistEnd = this.twistEnd / 360.0f * twoPi;
+ float twistTotal = twistEnd - twistBegin;
+ float twistTotalAbs = Math.Abs(twistTotal);
+ if (twistTotalAbs > 0.01f)
+ steps += (int)(twistTotalAbs * 3.66); // dahlia's magic number
+
+ float hollow = this.hollow;
+
+ // sanity checks
+ float initialProfileRot = 0.0f;
+ if (pathType == PathType.Circular)
+ {
+ if (this.sides == 3)
+ {
+ initialProfileRot = (float)Math.PI;
+ if (this.hollowSides == 4)
+ {
+ if (hollow > 0.7f)
+ hollow = 0.7f;
+ hollow *= 0.707f;
+ }
+ else hollow *= 0.5f;
+ }
+ else if (this.sides == 4)
+ {
+ initialProfileRot = 0.25f * (float)Math.PI;
+ if (this.hollowSides != 4)
+ hollow *= 0.707f;
+ }
+ else if (this.sides > 4)
+ {
+ initialProfileRot = (float)Math.PI;
+ if (this.hollowSides == 4)
+ {
+ if (hollow > 0.7f)
+ hollow = 0.7f;
+ hollow /= 0.7f;
+ }
+ }
+ }
+ else
+ {
+ if (this.sides == 3)
+ {
+ if (this.hollowSides == 4)
+ {
+ if (hollow > 0.7f)
+ hollow = 0.7f;
+ hollow *= 0.707f;
+ }
+ else hollow *= 0.5f;
+ }
+ else if (this.sides == 4)
+ {
+ initialProfileRot = 1.25f * (float)Math.PI;
+ if (this.hollowSides != 4)
+ hollow *= 0.707f;
+ }
+ else if (this.sides == 24 && this.hollowSides == 4)
+ hollow *= 1.414f;
+ }
+
+ Profile profile = new Profile(this.sides, this.profileStart, this.profileEnd, hollow, this.hollowSides, true, calcVertexNormals);
+ this.errorMessage = profile.errorMessage;
+
+ this.numPrimFaces = profile.numPrimFaces;
+
+ int cut1Vert = -1;
+ int cut2Vert = -1;
+ if (hasProfileCut)
+ {
+ cut1Vert = hasHollow ? profile.coords.Count - 1 : 0;
+ cut2Vert = hasHollow ? profile.numOuterVerts - 1 : profile.numOuterVerts;
+ }
+
+ if (initialProfileRot != 0.0f)
+ {
+ profile.AddRot(new Quat(new Coord(0.0f, 0.0f, 1.0f), initialProfileRot));
+ if (viewerMode)
+ profile.MakeFaceUVs();
+ }
+
+ Coord lastCutNormal1 = new Coord();
+ Coord lastCutNormal2 = new Coord();
+ float lastV = 1.0f;
+
+ Path path = new Path();
+ path.twistBegin = twistBegin;
+ path.twistEnd = twistEnd;
+ path.topShearX = topShearX;
+ path.topShearY = topShearY;
+ path.pathCutBegin = pathCutBegin;
+ path.pathCutEnd = pathCutEnd;
+ path.dimpleBegin = dimpleBegin;
+ path.dimpleEnd = dimpleEnd;
+ path.skew = skew;
+ path.holeSizeX = holeSizeX;
+ path.holeSizeY = holeSizeY;
+ path.taperX = taperX;
+ path.taperY = taperY;
+ path.radius = radius;
+ path.revolutions = revolutions;
+ path.stepsPerRevolution = stepsPerRevolution;
+
+ path.Create(pathType, steps);
+
+ bool needEndFaces = false;
+ if (pathType == PathType.Circular)
+ {
+ needEndFaces = false;
+ if (this.pathCutBegin != 0.0f || this.pathCutEnd != 1.0f)
+ needEndFaces = true;
+ else if (this.taperX != 0.0f || this.taperY != 0.0f)
+ needEndFaces = true;
+ else if (this.skew != 0.0f)
+ needEndFaces = true;
+ else if (twistTotal != 0.0f)
+ needEndFaces = true;
+ else if (this.radius != 0.0f)
+ needEndFaces = true;
+ }
+ else needEndFaces = true;
+
+ for (int nodeIndex = 0; nodeIndex < path.pathNodes.Count; nodeIndex++)
+ {
+ PathNode node = path.pathNodes[nodeIndex];
+ Profile newLayer = profile.Copy();
+ newLayer.Scale(node.xScale, node.yScale);
+
+ newLayer.AddRot(node.rotation);
+ newLayer.AddPos(node.position);
+
+ if (needEndFaces && nodeIndex == 0)
+ {
+ newLayer.FlipNormals();
+
+ // add the top faces to the viewerFaces list here
+ if (this.viewerMode)
+ {
+ Coord faceNormal = newLayer.faceNormal;
+ ViewerFace newViewerFace = new ViewerFace(profile.bottomFaceNumber);
+ int numFaces = newLayer.faces.Count;
+ List faces = newLayer.faces;
+
+ for (int i = 0; i < numFaces; i++)
+ {
+ Face face = faces[i];
+ newViewerFace.v1 = newLayer.coords[face.v1];
+ newViewerFace.v2 = newLayer.coords[face.v2];
+ newViewerFace.v3 = newLayer.coords[face.v3];
+
+ newViewerFace.coordIndex1 = face.v1;
+ newViewerFace.coordIndex2 = face.v2;
+ newViewerFace.coordIndex3 = face.v3;
+
+ newViewerFace.n1 = faceNormal;
+ newViewerFace.n2 = faceNormal;
+ newViewerFace.n3 = faceNormal;
+
+ newViewerFace.uv1 = newLayer.faceUVs[face.v1];
+ newViewerFace.uv2 = newLayer.faceUVs[face.v2];
+ newViewerFace.uv3 = newLayer.faceUVs[face.v3];
+
+ this.viewerFaces.Add(newViewerFace);
+ }
+ }
+ } // if (nodeIndex == 0)
+
+ // append this layer
+
+ int coordsLen = this.coords.Count;
+ newLayer.AddValue2FaceVertexIndices(coordsLen);
+
+ this.coords.AddRange(newLayer.coords);
+
+ if (this.calcVertexNormals)
+ {
+ newLayer.AddValue2FaceNormalIndices(this.normals.Count);
+ this.normals.AddRange(newLayer.vertexNormals);
+ }
+
+ if (node.percentOfPath < this.pathCutBegin + 0.01f || node.percentOfPath > this.pathCutEnd - 0.01f)
+ this.faces.AddRange(newLayer.faces);
+
+ // fill faces between layers
+
+ int numVerts = newLayer.coords.Count;
+ Face newFace = new Face();
+
+ if (nodeIndex > 0)
+ {
+ int startVert = coordsLen + 1;
+ int endVert = this.coords.Count;
+
+ if (sides < 5 || this.hasProfileCut || hollow > 0.0f)
+ startVert--;
+
+ for (int i = startVert; i < endVert; i++)
+ {
+ int iNext = i + 1;
+ if (i == endVert - 1)
+ iNext = startVert;
+
+ int whichVert = i - startVert;
+
+ newFace.v1 = i;
+ newFace.v2 = i - numVerts;
+ newFace.v3 = iNext - numVerts;
+ this.faces.Add(newFace);
+
+ newFace.v2 = iNext - numVerts;
+ newFace.v3 = iNext;
+ this.faces.Add(newFace);
+
+ if (this.viewerMode)
+ {
+ // add the side faces to the list of viewerFaces here
+
+ int primFaceNum = profile.faceNumbers[whichVert];
+ if (!needEndFaces)
+ primFaceNum -= 1;
+
+ ViewerFace newViewerFace1 = new ViewerFace(primFaceNum);
+ ViewerFace newViewerFace2 = new ViewerFace(primFaceNum);
+
+ float u1 = newLayer.us[whichVert];
+ float u2 = 1.0f;
+ if (whichVert < newLayer.us.Count - 1)
+ u2 = newLayer.us[whichVert + 1];
+
+ if (whichVert == cut1Vert || whichVert == cut2Vert)
+ {
+ u1 = 0.0f;
+ u2 = 1.0f;
+ }
+ else if (sides < 5)
+ {
+ if (whichVert < profile.numOuterVerts)
+ { // boxes and prisms have one texture face per side of the prim, so the U values have to be scaled
+ // to reflect the entire texture width
+ u1 *= sides;
+ u2 *= sides;
+ u2 -= (int)u1;
+ u1 -= (int)u1;
+ if (u2 < 0.1f)
+ u2 = 1.0f;
+ }
+ else if (whichVert > profile.coords.Count - profile.numHollowVerts - 1)
+ {
+ u1 *= 2.0f;
+ u2 *= 2.0f;
+ }
+ }
+
+ newViewerFace1.uv1.U = u1;
+ newViewerFace1.uv2.U = u1;
+ newViewerFace1.uv3.U = u2;
+
+ newViewerFace1.uv1.V = 1.0f - node.percentOfPath;
+ newViewerFace1.uv2.V = lastV;
+ newViewerFace1.uv3.V = lastV;
+
+ newViewerFace2.uv1.U = u1;
+ newViewerFace2.uv2.U = u2;
+ newViewerFace2.uv3.U = u2;
+
+ newViewerFace2.uv1.V = 1.0f - node.percentOfPath;
+ newViewerFace2.uv2.V = lastV;
+ newViewerFace2.uv3.V = 1.0f - node.percentOfPath;
+
+ newViewerFace1.v1 = this.coords[i];
+ newViewerFace1.v2 = this.coords[i - numVerts];
+ newViewerFace1.v3 = this.coords[iNext - numVerts];
+
+ newViewerFace2.v1 = this.coords[i];
+ newViewerFace2.v2 = this.coords[iNext - numVerts];
+ newViewerFace2.v3 = this.coords[iNext];
+
+ newViewerFace1.coordIndex1 = i;
+ newViewerFace1.coordIndex2 = i - numVerts;
+ newViewerFace1.coordIndex3 = iNext - numVerts;
+
+ newViewerFace2.coordIndex1 = i;
+ newViewerFace2.coordIndex2 = iNext - numVerts;
+ newViewerFace2.coordIndex3 = iNext;
+
+ // profile cut faces
+ if (whichVert == cut1Vert)
+ {
+ newViewerFace1.n1 = newLayer.cutNormal1;
+ newViewerFace1.n2 = newViewerFace1.n3 = lastCutNormal1;
+
+ newViewerFace2.n1 = newViewerFace2.n3 = newLayer.cutNormal1;
+ newViewerFace2.n2 = lastCutNormal1;
+ }
+ else if (whichVert == cut2Vert)
+ {
+ newViewerFace1.n1 = newLayer.cutNormal2;
+ newViewerFace1.n2 = newViewerFace1.n3 = lastCutNormal2;
+
+ newViewerFace2.n1 = newViewerFace2.n3 = newLayer.cutNormal2;
+ newViewerFace2.n2 = lastCutNormal2;
+ }
+
+ else // outer and hollow faces
+ {
+ if ((sides < 5 && whichVert < newLayer.numOuterVerts) || (hollowSides < 5 && whichVert >= newLayer.numOuterVerts))
+ { // looks terrible when path is twisted... need vertex normals here
+ newViewerFace1.CalcSurfaceNormal();
+ newViewerFace2.CalcSurfaceNormal();
+ }
+ else
+ {
+ newViewerFace1.n1 = this.normals[i];
+ newViewerFace1.n2 = this.normals[i - numVerts];
+ newViewerFace1.n3 = this.normals[iNext - numVerts];
+
+ newViewerFace2.n1 = this.normals[i];
+ newViewerFace2.n2 = this.normals[iNext - numVerts];
+ newViewerFace2.n3 = this.normals[iNext];
+ }
+ }
+
+ this.viewerFaces.Add(newViewerFace1);
+ this.viewerFaces.Add(newViewerFace2);
+
+ }
+ }
+ }
+
+ lastCutNormal1 = newLayer.cutNormal1;
+ lastCutNormal2 = newLayer.cutNormal2;
+ lastV = 1.0f - node.percentOfPath;
+
+ if (needEndFaces && nodeIndex == path.pathNodes.Count - 1 && viewerMode)
+ {
+ // add the top faces to the viewerFaces list here
+ Coord faceNormal = newLayer.faceNormal;
+ ViewerFace newViewerFace = new ViewerFace();
+ newViewerFace.primFaceNumber = 0;
+ int numFaces = newLayer.faces.Count;
+ List faces = newLayer.faces;
+
+ for (int i = 0; i < numFaces; i++)
+ {
+ Face face = faces[i];
+ newViewerFace.v1 = newLayer.coords[face.v1 - coordsLen];
+ newViewerFace.v2 = newLayer.coords[face.v2 - coordsLen];
+ newViewerFace.v3 = newLayer.coords[face.v3 - coordsLen];
+
+ newViewerFace.coordIndex1 = face.v1 - coordsLen;
+ newViewerFace.coordIndex2 = face.v2 - coordsLen;
+ newViewerFace.coordIndex3 = face.v3 - coordsLen;
+
+ newViewerFace.n1 = faceNormal;
+ newViewerFace.n2 = faceNormal;
+ newViewerFace.n3 = faceNormal;
+
+ newViewerFace.uv1 = newLayer.faceUVs[face.v1 - coordsLen];
+ newViewerFace.uv2 = newLayer.faceUVs[face.v2 - coordsLen];
+ newViewerFace.uv3 = newLayer.faceUVs[face.v3 - coordsLen];
+
+ this.viewerFaces.Add(newViewerFace);
+ }
+ }
+
+
+ } // for (int nodeIndex = 0; nodeIndex < path.pathNodes.Count; nodeIndex++)
+
+ }
+
+
+ ///
+ /// DEPRICATED - use Extrude(PathType.Linear) instead
+ /// Extrudes a profile along a straight line path. Used for prim types box, cylinder, and prism.
+ ///
+ ///
+ public void ExtrudeLinear()
+ {
+ this.Extrude(PathType.Linear);
+ }
+
+
+ ///
+ /// DEPRICATED - use Extrude(PathType.Circular) instead
+ /// Extrude a profile into a circular path prim mesh. Used for prim types torus, tube, and ring.
+ ///
+ ///
+ public void ExtrudeCircular()
+ {
+ this.Extrude(PathType.Circular);
+ }
+
+
+ private Coord SurfaceNormal(Coord c1, Coord c2, Coord c3)
+ {
+ Coord edge1 = new Coord(c2.X - c1.X, c2.Y - c1.Y, c2.Z - c1.Z);
+ Coord edge2 = new Coord(c3.X - c1.X, c3.Y - c1.Y, c3.Z - c1.Z);
+
+ Coord normal = Coord.Cross(edge1, edge2);
+
+ normal.Normalize();
+
+ return normal;
+ }
+
+ private Coord SurfaceNormal(Face face)
+ {
+ return SurfaceNormal(this.coords[face.v1], this.coords[face.v2], this.coords[face.v3]);
+ }
+
+ ///
+ /// Calculate the surface normal for a face in the list of faces
+ ///
+ ///
+ ///
+ public Coord SurfaceNormal(int faceIndex)
+ {
+ int numFaces = this.faces.Count;
+ if (faceIndex < 0 || faceIndex >= numFaces)
+ throw new Exception("faceIndex out of range");
+
+ return SurfaceNormal(this.faces[faceIndex]);
+ }
+
+ ///
+ /// Duplicates a PrimMesh object. All object properties are copied by value, including lists.
+ ///
+ ///
+ public PrimMesh Copy()
+ {
+ PrimMesh copy = new PrimMesh(this.sides, this.profileStart, this.profileEnd, this.hollow, this.hollowSides);
+ copy.twistBegin = this.twistBegin;
+ copy.twistEnd = this.twistEnd;
+ copy.topShearX = this.topShearX;
+ copy.topShearY = this.topShearY;
+ copy.pathCutBegin = this.pathCutBegin;
+ copy.pathCutEnd = this.pathCutEnd;
+ copy.dimpleBegin = this.dimpleBegin;
+ copy.dimpleEnd = this.dimpleEnd;
+ copy.skew = this.skew;
+ copy.holeSizeX = this.holeSizeX;
+ copy.holeSizeY = this.holeSizeY;
+ copy.taperX = this.taperX;
+ copy.taperY = this.taperY;
+ copy.radius = this.radius;
+ copy.revolutions = this.revolutions;
+ copy.stepsPerRevolution = this.stepsPerRevolution;
+ copy.calcVertexNormals = this.calcVertexNormals;
+ copy.normalsProcessed = this.normalsProcessed;
+ copy.viewerMode = this.viewerMode;
+ copy.numPrimFaces = this.numPrimFaces;
+ copy.errorMessage = this.errorMessage;
+
+ copy.coords = new List(this.coords);
+ copy.faces = new List(this.faces);
+ copy.viewerFaces = new List(this.viewerFaces);
+ copy.normals = new List(this.normals);
+
+ return copy;
+ }
+
+ ///
+ /// Calculate surface normals for all of the faces in the list of faces in this mesh
+ ///
+ public void CalcNormals()
+ {
+ if (normalsProcessed)
+ return;
+
+ normalsProcessed = true;
+
+ int numFaces = faces.Count;
+
+ if (!this.calcVertexNormals)
+ this.normals = new List();
+
+ for (int i = 0; i < numFaces; i++)
+ {
+ Face face = faces[i];
+
+ this.normals.Add(SurfaceNormal(i).Normalize());
+
+ int normIndex = normals.Count - 1;
+ face.n1 = normIndex;
+ face.n2 = normIndex;
+ face.n3 = normIndex;
+
+ this.faces[i] = face;
+ }
+ }
+
+ ///
+ /// Adds a value to each XYZ vertex coordinate in the mesh
+ ///
+ ///
+ ///
+ ///
+ public void AddPos(float x, float y, float z)
+ {
+ int i;
+ int numVerts = this.coords.Count;
+ Coord vert;
+
+ for (i = 0; i < numVerts; i++)
+ {
+ vert = this.coords[i];
+ vert.X += x;
+ vert.Y += y;
+ vert.Z += z;
+ this.coords[i] = vert;
+ }
+
+ if (this.viewerFaces != null)
+ {
+ int numViewerFaces = this.viewerFaces.Count;
+
+ for (i = 0; i < numViewerFaces; i++)
+ {
+ ViewerFace v = this.viewerFaces[i];
+ v.AddPos(x, y, z);
+ this.viewerFaces[i] = v;
+ }
+ }
+ }
+
+ ///
+ /// Rotates the mesh
+ ///
+ ///
+ public void AddRot(Quat q)
+ {
+ int i;
+ int numVerts = this.coords.Count;
+
+ for (i = 0; i < numVerts; i++)
+ this.coords[i] *= q;
+
+ if (this.normals != null)
+ {
+ int numNormals = this.normals.Count;
+ for (i = 0; i < numNormals; i++)
+ this.normals[i] *= q;
+ }
+
+ if (this.viewerFaces != null)
+ {
+ int numViewerFaces = this.viewerFaces.Count;
+
+ for (i = 0; i < numViewerFaces; i++)
+ {
+ ViewerFace v = this.viewerFaces[i];
+ v.v1 *= q;
+ v.v2 *= q;
+ v.v3 *= q;
+
+ v.n1 *= q;
+ v.n2 *= q;
+ v.n3 *= q;
+ this.viewerFaces[i] = v;
+ }
+ }
+ }
+
+#if VERTEX_INDEXER
+ public VertexIndexer GetVertexIndexer()
+ {
+ if (this.viewerMode && this.viewerFaces.Count > 0)
+ return new VertexIndexer(this);
+ return null;
+ }
+#endif
+
+ ///
+ /// Scales the mesh
+ ///
+ ///
+ ///
+ ///
+ public void Scale(float x, float y, float z)
+ {
+ int i;
+ int numVerts = this.coords.Count;
+ //Coord vert;
+
+ Coord m = new Coord(x, y, z);
+ for (i = 0; i < numVerts; i++)
+ this.coords[i] *= m;
+
+ if (this.viewerFaces != null)
+ {
+ int numViewerFaces = this.viewerFaces.Count;
+ for (i = 0; i < numViewerFaces; i++)
+ {
+ ViewerFace v = this.viewerFaces[i];
+ v.v1 *= m;
+ v.v2 *= m;
+ v.v3 *= m;
+ this.viewerFaces[i] = v;
+ }
+
+ }
+
+ }
+
+ ///
+ /// Dumps the mesh to a Blender compatible "Raw" format file
+ ///
+ ///
+ ///
+ ///
+ public void DumpRaw(String path, String name, String title)
+ {
+ if (path == null)
+ return;
+ String fileName = name + "_" + title + ".raw";
+ String completePath = System.IO.Path.Combine(path, fileName);
+ StreamWriter sw = new StreamWriter(completePath);
+
+ for (int i = 0; i < this.faces.Count; i++)
+ {
+ string s = this.coords[this.faces[i].v1].ToString();
+ s += " " + this.coords[this.faces[i].v2].ToString();
+ s += " " + this.coords[this.faces[i].v3].ToString();
+
+ sw.WriteLine(s);
+ }
+
+ sw.Close();
+ }
+ }
+}
diff --git a/OpenSim/Region/Physics/Meshing/SculptMesh.cs b/OpenSim/Region/Physics/Meshing/SculptMesh.cs
index 11b6cd42c5..ebc5be61b1 100644
--- a/OpenSim/Region/Physics/Meshing/SculptMesh.cs
+++ b/OpenSim/Region/Physics/Meshing/SculptMesh.cs
@@ -1,645 +1,645 @@
-/*
- * Copyright (c) Contributors
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the OpenSimulator Project nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-// to build without references to System.Drawing, comment this out
-#define SYSTEM_DRAWING
-
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.IO;
-
-#if SYSTEM_DRAWING
-using System.Drawing;
-using System.Drawing.Imaging;
-#endif
-
-namespace PrimMesher
-{
-
- public class SculptMesh
- {
- public List coords;
- public List faces;
-
- public List viewerFaces;
- public List normals;
- public List uvs;
-
- public enum SculptType { sphere = 1, torus = 2, plane = 3, cylinder = 4 };
-
-#if SYSTEM_DRAWING
- private Bitmap ScaleImage(Bitmap srcImage, float scale, bool removeAlpha)
- {
- int sourceWidth = srcImage.Width;
- int sourceHeight = srcImage.Height;
- int sourceX = 0;
- int sourceY = 0;
-
- int destX = 0;
- int destY = 0;
- int destWidth = (int)(srcImage.Width * scale);
- int destHeight = (int)(srcImage.Height * scale);
-
- Bitmap scaledImage;
-
- if (removeAlpha)
- {
- if (srcImage.PixelFormat == PixelFormat.Format32bppArgb)
- for (int y = 0; y < srcImage.Height; y++)
- for (int x = 0; x < srcImage.Width; x++)
- {
- Color c = srcImage.GetPixel(x, y);
- srcImage.SetPixel(x, y, Color.FromArgb(255, c.R, c.G, c.B));
- }
-
- scaledImage = new Bitmap(destWidth, destHeight,
- PixelFormat.Format24bppRgb);
- }
- else
- scaledImage = new Bitmap(srcImage, destWidth, destHeight);
-
- scaledImage.SetResolution(96.0f, 96.0f);
-
- Graphics grPhoto = Graphics.FromImage(scaledImage);
- grPhoto.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Low;
-
- grPhoto.DrawImage(srcImage,
- new Rectangle(destX, destY, destWidth, destHeight),
- new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight),
- GraphicsUnit.Pixel);
-
- grPhoto.Dispose();
- return scaledImage;
- }
-
-
- public SculptMesh SculptMeshFromFile(string fileName, SculptType sculptType, int lod, bool viewerMode)
- {
- Bitmap bitmap = (Bitmap)Bitmap.FromFile(fileName);
- SculptMesh sculptMesh = new SculptMesh(bitmap, sculptType, lod, viewerMode);
- bitmap.Dispose();
- return sculptMesh;
- }
-
- public SculptMesh(string fileName, int sculptType, int lod, int viewerMode, int mirror, int invert)
- {
- Bitmap bitmap = (Bitmap)Bitmap.FromFile(fileName);
- _SculptMesh(bitmap, (SculptType)sculptType, lod, viewerMode != 0, mirror != 0, invert != 0);
- bitmap.Dispose();
- }
-#endif
-
- ///
- /// ** Experimental ** May disappear from future versions ** not recommeneded for use in applications
- /// Construct a sculpt mesh from a 2D array of floats
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public SculptMesh(float[,] zMap, float xBegin, float xEnd, float yBegin, float yEnd, bool viewerMode)
- {
- float xStep, yStep;
- float uStep, vStep;
-
- int numYElements = zMap.GetLength(0);
- int numXElements = zMap.GetLength(1);
-
- try
- {
- xStep = (xEnd - xBegin) / (float)(numXElements - 1);
- yStep = (yEnd - yBegin) / (float)(numYElements - 1);
-
- uStep = 1.0f / (numXElements - 1);
- vStep = 1.0f / (numYElements - 1);
- }
- catch (DivideByZeroException)
- {
- return;
- }
-
- coords = new List();
- faces = new List();
- normals = new List();
- uvs = new List();
-
- viewerFaces = new List();
-
- int p1, p2, p3, p4;
-
- int x, y;
- int xStart = 0, yStart = 0;
-
- for (y = yStart; y < numYElements; y++)
- {
- int rowOffset = y * numXElements;
-
- for (x = xStart; x < numXElements; x++)
- {
- /*
- * p1-----p2
- * | \ f2 |
- * | \ |
- * | f1 \|
- * p3-----p4
- */
-
- p4 = rowOffset + x;
- p3 = p4 - 1;
-
- p2 = p4 - numXElements;
- p1 = p3 - numXElements;
-
- Coord c = new Coord(xBegin + x * xStep, yBegin + y * yStep, zMap[y, x]);
- this.coords.Add(c);
- if (viewerMode)
- {
- this.normals.Add(new Coord());
- this.uvs.Add(new UVCoord(uStep * x, 1.0f - vStep * y));
- }
-
- if (y > 0 && x > 0)
- {
- Face f1, f2;
-
- if (viewerMode)
- {
- f1 = new Face(p1, p4, p3, p1, p4, p3);
- f1.uv1 = p1;
- f1.uv2 = p4;
- f1.uv3 = p3;
-
- f2 = new Face(p1, p2, p4, p1, p2, p4);
- f2.uv1 = p1;
- f2.uv2 = p2;
- f2.uv3 = p4;
- }
- else
- {
- f1 = new Face(p1, p4, p3);
- f2 = new Face(p1, p2, p4);
- }
-
- this.faces.Add(f1);
- this.faces.Add(f2);
- }
- }
- }
-
- if (viewerMode)
- calcVertexNormals(SculptType.plane, numXElements, numYElements);
- }
-
-#if SYSTEM_DRAWING
- public SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode)
- {
- _SculptMesh(sculptBitmap, sculptType, lod, viewerMode, false, false);
- }
-
- public SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode, bool mirror, bool invert)
- {
- _SculptMesh(sculptBitmap, sculptType, lod, viewerMode, mirror, invert);
- }
-#endif
-
- public SculptMesh(List> rows, SculptType sculptType, bool viewerMode, bool mirror, bool invert)
- {
- _SculptMesh(rows, sculptType, viewerMode, mirror, invert);
- }
-
-#if SYSTEM_DRAWING
- ///
- /// converts a bitmap to a list of lists of coords, while scaling the image.
- /// the scaling is done in floating point so as to allow for reduced vertex position
- /// quantization as the position will be averaged between pixel values. this routine will
- /// likely fail if the bitmap width and height are not powers of 2.
- ///
- ///
- ///
- ///
- ///
- private List> bitmap2Coords(Bitmap bitmap, int scale, bool mirror)
- {
- int numRows = bitmap.Height / scale;
- int numCols = bitmap.Width / scale;
- List> rows = new List>(numRows);
-
- float pixScale = 1.0f / (scale * scale);
- pixScale /= 255;
-
- int imageX, imageY = 0;
-
- int rowNdx, colNdx;
-
- for (rowNdx = 0; rowNdx < numRows; rowNdx++)
- {
- List row = new List(numCols);
- for (colNdx = 0; colNdx < numCols; colNdx++)
- {
- imageX = colNdx * scale;
- int imageYStart = rowNdx * scale;
- int imageYEnd = imageYStart + scale;
- int imageXEnd = imageX + scale;
- float rSum = 0.0f;
- float gSum = 0.0f;
- float bSum = 0.0f;
- for (; imageX < imageXEnd; imageX++)
- {
- for (imageY = imageYStart; imageY < imageYEnd; imageY++)
- {
- Color c = bitmap.GetPixel(imageX, imageY);
- if (c.A != 255)
- {
- bitmap.SetPixel(imageX, imageY, Color.FromArgb(255, c.R, c.G, c.B));
- c = bitmap.GetPixel(imageX, imageY);
- }
- rSum += c.R;
- gSum += c.G;
- bSum += c.B;
- }
- }
- if (mirror)
- row.Add(new Coord(-(rSum * pixScale - 0.5f), gSum * pixScale - 0.5f, bSum * pixScale - 0.5f));
- else
- row.Add(new Coord(rSum * pixScale - 0.5f, gSum * pixScale - 0.5f, bSum * pixScale - 0.5f));
-
- }
- rows.Add(row);
- }
- return rows;
- }
-
-
- void _SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode, bool mirror, bool invert)
- {
- coords = new List();
- faces = new List();
- normals = new List();
- uvs = new List();
-
- sculptType = (SculptType)(((int)sculptType) & 0x07);
-
- if (mirror)
- if (sculptType == SculptType.plane)
- invert = !invert;
-
- float sculptBitmapLod = (float)Math.Sqrt(sculptBitmap.Width * sculptBitmap.Height);
-
- float sourceScaleFactor = (float)(lod) / sculptBitmapLod;
-
- float fScale = 1.0f / sourceScaleFactor;
-
- int iScale = (int)fScale;
- if (iScale < 1) iScale = 1;
- if (iScale > 2 && iScale % 2 == 0)
- _SculptMesh(bitmap2Coords(ScaleImage(sculptBitmap, 64.0f / sculptBitmapLod, true), 64 / lod, mirror), sculptType, viewerMode, mirror, invert);
- else
- _SculptMesh(bitmap2Coords(sculptBitmap, iScale, mirror), sculptType, viewerMode, mirror, invert);
- }
-#endif
-
-
- void _SculptMesh(List> rows, SculptType sculptType, bool viewerMode, bool mirror, bool invert)
- {
- coords = new List();
- faces = new List();
- normals = new List();
- uvs = new List();
-
- sculptType = (SculptType)(((int)sculptType) & 0x07);
-
- if (mirror)
- if (sculptType == SculptType.plane)
- invert = !invert;
-
- viewerFaces = new List();
-
- int width = rows[0].Count;
-
- int p1, p2, p3, p4;
-
- int imageX, imageY;
-
- if (sculptType != SculptType.plane)
- {
- for (int rowNdx = 0; rowNdx < rows.Count; rowNdx++)
- rows[rowNdx].Add(rows[rowNdx][0]);
- }
-
- Coord topPole = rows[0][width / 2];
- Coord bottomPole = rows[rows.Count - 1][width / 2];
-
- if (sculptType == SculptType.sphere)
- {
- int count = rows[0].Count;
- List topPoleRow = new List(count);
- List bottomPoleRow = new List(count);
-
- for (int i = 0; i < count; i++)
- {
- topPoleRow.Add(topPole);
- bottomPoleRow.Add(bottomPole);
- }
- rows.Insert(0, topPoleRow);
- rows.Add(bottomPoleRow);
- }
- else if (sculptType == SculptType.torus)
- rows.Add(rows[0]);
-
- int coordsDown = rows.Count;
- int coordsAcross = rows[0].Count;
-
- float widthUnit = 1.0f / (coordsAcross - 1);
- float heightUnit = 1.0f / (coordsDown - 1);
-
- for (imageY = 0; imageY < coordsDown; imageY++)
- {
- int rowOffset = imageY * coordsAcross;
-
- for (imageX = 0; imageX < coordsAcross; imageX++)
- {
- /*
- * p1-----p2
- * | \ f2 |
- * | \ |
- * | f1 \|
- * p3-----p4
- */
-
- p4 = rowOffset + imageX;
- p3 = p4 - 1;
-
- p2 = p4 - coordsAcross;
- p1 = p3 - coordsAcross;
-
- this.coords.Add(rows[imageY][imageX]);
- if (viewerMode)
- {
- this.normals.Add(new Coord());
- this.uvs.Add(new UVCoord(widthUnit * imageX, heightUnit * imageY));
- }
-
- if (imageY > 0 && imageX > 0)
- {
- Face f1, f2;
-
- if (viewerMode)
- {
- if (invert)
- {
- f1 = new Face(p1, p4, p3, p1, p4, p3);
- f1.uv1 = p1;
- f1.uv2 = p4;
- f1.uv3 = p3;
-
- f2 = new Face(p1, p2, p4, p1, p2, p4);
- f2.uv1 = p1;
- f2.uv2 = p2;
- f2.uv3 = p4;
- }
- else
- {
- f1 = new Face(p1, p3, p4, p1, p3, p4);
- f1.uv1 = p1;
- f1.uv2 = p3;
- f1.uv3 = p4;
-
- f2 = new Face(p1, p4, p2, p1, p4, p2);
- f2.uv1 = p1;
- f2.uv2 = p4;
- f2.uv3 = p2;
- }
- }
- else
- {
- if (invert)
- {
- f1 = new Face(p1, p4, p3);
- f2 = new Face(p1, p2, p4);
- }
- else
- {
- f1 = new Face(p1, p3, p4);
- f2 = new Face(p1, p4, p2);
- }
- }
-
- this.faces.Add(f1);
- this.faces.Add(f2);
- }
- }
- }
-
- if (viewerMode)
- calcVertexNormals(sculptType, coordsAcross, coordsDown);
- }
-
- ///
- /// Duplicates a SculptMesh object. All object properties are copied by value, including lists.
- ///
- ///
- public SculptMesh Copy()
- {
- return new SculptMesh(this);
- }
-
- public SculptMesh(SculptMesh sm)
- {
- coords = new List(sm.coords);
- faces = new List(sm.faces);
- viewerFaces = new List(sm.viewerFaces);
- normals = new List(sm.normals);
- uvs = new List(sm.uvs);
- }
-
- private void calcVertexNormals(SculptType sculptType, int xSize, int ySize)
- { // compute vertex normals by summing all the surface normals of all the triangles sharing
- // each vertex and then normalizing
- int numFaces = this.faces.Count;
- for (int i = 0; i < numFaces; i++)
- {
- Face face = this.faces[i];
- Coord surfaceNormal = face.SurfaceNormal(this.coords);
- this.normals[face.n1] += surfaceNormal;
- this.normals[face.n2] += surfaceNormal;
- this.normals[face.n3] += surfaceNormal;
- }
-
- int numNormals = this.normals.Count;
- for (int i = 0; i < numNormals; i++)
- this.normals[i] = this.normals[i].Normalize();
-
- if (sculptType != SculptType.plane)
- { // blend the vertex normals at the cylinder seam
- for (int y = 0; y < ySize; y++)
- {
- int rowOffset = y * xSize;
-
- this.normals[rowOffset] = this.normals[rowOffset + xSize - 1] = (this.normals[rowOffset] + this.normals[rowOffset + xSize - 1]).Normalize();
- }
- }
-
- foreach (Face face in this.faces)
- {
- ViewerFace vf = new ViewerFace(0);
- vf.v1 = this.coords[face.v1];
- vf.v2 = this.coords[face.v2];
- vf.v3 = this.coords[face.v3];
-
- vf.coordIndex1 = face.v1;
- vf.coordIndex2 = face.v2;
- vf.coordIndex3 = face.v3;
-
- vf.n1 = this.normals[face.n1];
- vf.n2 = this.normals[face.n2];
- vf.n3 = this.normals[face.n3];
-
- vf.uv1 = this.uvs[face.uv1];
- vf.uv2 = this.uvs[face.uv2];
- vf.uv3 = this.uvs[face.uv3];
-
- this.viewerFaces.Add(vf);
- }
- }
-
- ///
- /// Adds a value to each XYZ vertex coordinate in the mesh
- ///
- ///
- ///
- ///
- public void AddPos(float x, float y, float z)
- {
- int i;
- int numVerts = this.coords.Count;
- Coord vert;
-
- for (i = 0; i < numVerts; i++)
- {
- vert = this.coords[i];
- vert.X += x;
- vert.Y += y;
- vert.Z += z;
- this.coords[i] = vert;
- }
-
- if (this.viewerFaces != null)
- {
- int numViewerFaces = this.viewerFaces.Count;
-
- for (i = 0; i < numViewerFaces; i++)
- {
- ViewerFace v = this.viewerFaces[i];
- v.AddPos(x, y, z);
- this.viewerFaces[i] = v;
- }
- }
- }
-
- ///
- /// Rotates the mesh
- ///
- ///
- public void AddRot(Quat q)
- {
- int i;
- int numVerts = this.coords.Count;
-
- for (i = 0; i < numVerts; i++)
- this.coords[i] *= q;
-
- int numNormals = this.normals.Count;
- for (i = 0; i < numNormals; i++)
- this.normals[i] *= q;
-
- if (this.viewerFaces != null)
- {
- int numViewerFaces = this.viewerFaces.Count;
-
- for (i = 0; i < numViewerFaces; i++)
- {
- ViewerFace v = this.viewerFaces[i];
- v.v1 *= q;
- v.v2 *= q;
- v.v3 *= q;
-
- v.n1 *= q;
- v.n2 *= q;
- v.n3 *= q;
-
- this.viewerFaces[i] = v;
- }
- }
- }
-
- public void Scale(float x, float y, float z)
- {
- int i;
- int numVerts = this.coords.Count;
-
- Coord m = new Coord(x, y, z);
- for (i = 0; i < numVerts; i++)
- this.coords[i] *= m;
-
- if (this.viewerFaces != null)
- {
- int numViewerFaces = this.viewerFaces.Count;
- for (i = 0; i < numViewerFaces; i++)
- {
- ViewerFace v = this.viewerFaces[i];
- v.v1 *= m;
- v.v2 *= m;
- v.v3 *= m;
- this.viewerFaces[i] = v;
- }
- }
- }
-
- public void DumpRaw(String path, String name, String title)
- {
- if (path == null)
- return;
- String fileName = name + "_" + title + ".raw";
- String completePath = System.IO.Path.Combine(path, fileName);
- StreamWriter sw = new StreamWriter(completePath);
-
- for (int i = 0; i < this.faces.Count; i++)
- {
- string s = this.coords[this.faces[i].v1].ToString();
- s += " " + this.coords[this.faces[i].v2].ToString();
- s += " " + this.coords[this.faces[i].v3].ToString();
-
- sw.WriteLine(s);
- }
-
- sw.Close();
- }
- }
-}
+/*
+ * Copyright (c) Contributors
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSimulator Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// to build without references to System.Drawing, comment this out
+#define SYSTEM_DRAWING
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO;
+
+#if SYSTEM_DRAWING
+using System.Drawing;
+using System.Drawing.Imaging;
+#endif
+
+namespace PrimMesher
+{
+
+ public class SculptMesh
+ {
+ public List coords;
+ public List faces;
+
+ public List viewerFaces;
+ public List normals;
+ public List uvs;
+
+ public enum SculptType { sphere = 1, torus = 2, plane = 3, cylinder = 4 };
+
+#if SYSTEM_DRAWING
+ private Bitmap ScaleImage(Bitmap srcImage, float scale, bool removeAlpha)
+ {
+ int sourceWidth = srcImage.Width;
+ int sourceHeight = srcImage.Height;
+ int sourceX = 0;
+ int sourceY = 0;
+
+ int destX = 0;
+ int destY = 0;
+ int destWidth = (int)(srcImage.Width * scale);
+ int destHeight = (int)(srcImage.Height * scale);
+
+ Bitmap scaledImage;
+
+ if (removeAlpha)
+ {
+ if (srcImage.PixelFormat == PixelFormat.Format32bppArgb)
+ for (int y = 0; y < srcImage.Height; y++)
+ for (int x = 0; x < srcImage.Width; x++)
+ {
+ Color c = srcImage.GetPixel(x, y);
+ srcImage.SetPixel(x, y, Color.FromArgb(255, c.R, c.G, c.B));
+ }
+
+ scaledImage = new Bitmap(destWidth, destHeight,
+ PixelFormat.Format24bppRgb);
+ }
+ else
+ scaledImage = new Bitmap(srcImage, destWidth, destHeight);
+
+ scaledImage.SetResolution(96.0f, 96.0f);
+
+ Graphics grPhoto = Graphics.FromImage(scaledImage);
+ grPhoto.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Low;
+
+ grPhoto.DrawImage(srcImage,
+ new Rectangle(destX, destY, destWidth, destHeight),
+ new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight),
+ GraphicsUnit.Pixel);
+
+ grPhoto.Dispose();
+ return scaledImage;
+ }
+
+
+ public SculptMesh SculptMeshFromFile(string fileName, SculptType sculptType, int lod, bool viewerMode)
+ {
+ Bitmap bitmap = (Bitmap)Bitmap.FromFile(fileName);
+ SculptMesh sculptMesh = new SculptMesh(bitmap, sculptType, lod, viewerMode);
+ bitmap.Dispose();
+ return sculptMesh;
+ }
+
+ public SculptMesh(string fileName, int sculptType, int lod, int viewerMode, int mirror, int invert)
+ {
+ Bitmap bitmap = (Bitmap)Bitmap.FromFile(fileName);
+ _SculptMesh(bitmap, (SculptType)sculptType, lod, viewerMode != 0, mirror != 0, invert != 0);
+ bitmap.Dispose();
+ }
+#endif
+
+ ///
+ /// ** Experimental ** May disappear from future versions ** not recommeneded for use in applications
+ /// Construct a sculpt mesh from a 2D array of floats
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public SculptMesh(float[,] zMap, float xBegin, float xEnd, float yBegin, float yEnd, bool viewerMode)
+ {
+ float xStep, yStep;
+ float uStep, vStep;
+
+ int numYElements = zMap.GetLength(0);
+ int numXElements = zMap.GetLength(1);
+
+ try
+ {
+ xStep = (xEnd - xBegin) / (float)(numXElements - 1);
+ yStep = (yEnd - yBegin) / (float)(numYElements - 1);
+
+ uStep = 1.0f / (numXElements - 1);
+ vStep = 1.0f / (numYElements - 1);
+ }
+ catch (DivideByZeroException)
+ {
+ return;
+ }
+
+ coords = new List();
+ faces = new List();
+ normals = new List();
+ uvs = new List();
+
+ viewerFaces = new List();
+
+ int p1, p2, p3, p4;
+
+ int x, y;
+ int xStart = 0, yStart = 0;
+
+ for (y = yStart; y < numYElements; y++)
+ {
+ int rowOffset = y * numXElements;
+
+ for (x = xStart; x < numXElements; x++)
+ {
+ /*
+ * p1-----p2
+ * | \ f2 |
+ * | \ |
+ * | f1 \|
+ * p3-----p4
+ */
+
+ p4 = rowOffset + x;
+ p3 = p4 - 1;
+
+ p2 = p4 - numXElements;
+ p1 = p3 - numXElements;
+
+ Coord c = new Coord(xBegin + x * xStep, yBegin + y * yStep, zMap[y, x]);
+ this.coords.Add(c);
+ if (viewerMode)
+ {
+ this.normals.Add(new Coord());
+ this.uvs.Add(new UVCoord(uStep * x, 1.0f - vStep * y));
+ }
+
+ if (y > 0 && x > 0)
+ {
+ Face f1, f2;
+
+ if (viewerMode)
+ {
+ f1 = new Face(p1, p4, p3, p1, p4, p3);
+ f1.uv1 = p1;
+ f1.uv2 = p4;
+ f1.uv3 = p3;
+
+ f2 = new Face(p1, p2, p4, p1, p2, p4);
+ f2.uv1 = p1;
+ f2.uv2 = p2;
+ f2.uv3 = p4;
+ }
+ else
+ {
+ f1 = new Face(p1, p4, p3);
+ f2 = new Face(p1, p2, p4);
+ }
+
+ this.faces.Add(f1);
+ this.faces.Add(f2);
+ }
+ }
+ }
+
+ if (viewerMode)
+ calcVertexNormals(SculptType.plane, numXElements, numYElements);
+ }
+
+#if SYSTEM_DRAWING
+ public SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode)
+ {
+ _SculptMesh(sculptBitmap, sculptType, lod, viewerMode, false, false);
+ }
+
+ public SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode, bool mirror, bool invert)
+ {
+ _SculptMesh(sculptBitmap, sculptType, lod, viewerMode, mirror, invert);
+ }
+#endif
+
+ public SculptMesh(List> rows, SculptType sculptType, bool viewerMode, bool mirror, bool invert)
+ {
+ _SculptMesh(rows, sculptType, viewerMode, mirror, invert);
+ }
+
+#if SYSTEM_DRAWING
+ ///
+ /// converts a bitmap to a list of lists of coords, while scaling the image.
+ /// the scaling is done in floating point so as to allow for reduced vertex position
+ /// quantization as the position will be averaged between pixel values. this routine will
+ /// likely fail if the bitmap width and height are not powers of 2.
+ ///
+ ///
+ ///
+ ///
+ ///
+ private List> bitmap2Coords(Bitmap bitmap, int scale, bool mirror)
+ {
+ int numRows = bitmap.Height / scale;
+ int numCols = bitmap.Width / scale;
+ List> rows = new List>(numRows);
+
+ float pixScale = 1.0f / (scale * scale);
+ pixScale /= 255;
+
+ int imageX, imageY = 0;
+
+ int rowNdx, colNdx;
+
+ for (rowNdx = 0; rowNdx < numRows; rowNdx++)
+ {
+ List row = new List(numCols);
+ for (colNdx = 0; colNdx < numCols; colNdx++)
+ {
+ imageX = colNdx * scale;
+ int imageYStart = rowNdx * scale;
+ int imageYEnd = imageYStart + scale;
+ int imageXEnd = imageX + scale;
+ float rSum = 0.0f;
+ float gSum = 0.0f;
+ float bSum = 0.0f;
+ for (; imageX < imageXEnd; imageX++)
+ {
+ for (imageY = imageYStart; imageY < imageYEnd; imageY++)
+ {
+ Color c = bitmap.GetPixel(imageX, imageY);
+ if (c.A != 255)
+ {
+ bitmap.SetPixel(imageX, imageY, Color.FromArgb(255, c.R, c.G, c.B));
+ c = bitmap.GetPixel(imageX, imageY);
+ }
+ rSum += c.R;
+ gSum += c.G;
+ bSum += c.B;
+ }
+ }
+ if (mirror)
+ row.Add(new Coord(-(rSum * pixScale - 0.5f), gSum * pixScale - 0.5f, bSum * pixScale - 0.5f));
+ else
+ row.Add(new Coord(rSum * pixScale - 0.5f, gSum * pixScale - 0.5f, bSum * pixScale - 0.5f));
+
+ }
+ rows.Add(row);
+ }
+ return rows;
+ }
+
+
+ void _SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode, bool mirror, bool invert)
+ {
+ coords = new List();
+ faces = new List();
+ normals = new List();
+ uvs = new List();
+
+ sculptType = (SculptType)(((int)sculptType) & 0x07);
+
+ if (mirror)
+ if (sculptType == SculptType.plane)
+ invert = !invert;
+
+ float sculptBitmapLod = (float)Math.Sqrt(sculptBitmap.Width * sculptBitmap.Height);
+
+ float sourceScaleFactor = (float)(lod) / sculptBitmapLod;
+
+ float fScale = 1.0f / sourceScaleFactor;
+
+ int iScale = (int)fScale;
+ if (iScale < 1) iScale = 1;
+ if (iScale > 2 && iScale % 2 == 0)
+ _SculptMesh(bitmap2Coords(ScaleImage(sculptBitmap, 64.0f / sculptBitmapLod, true), 64 / lod, mirror), sculptType, viewerMode, mirror, invert);
+ else
+ _SculptMesh(bitmap2Coords(sculptBitmap, iScale, mirror), sculptType, viewerMode, mirror, invert);
+ }
+#endif
+
+
+ void _SculptMesh(List> rows, SculptType sculptType, bool viewerMode, bool mirror, bool invert)
+ {
+ coords = new List();
+ faces = new List();
+ normals = new List();
+ uvs = new List();
+
+ sculptType = (SculptType)(((int)sculptType) & 0x07);
+
+ if (mirror)
+ if (sculptType == SculptType.plane)
+ invert = !invert;
+
+ viewerFaces = new List();
+
+ int width = rows[0].Count;
+
+ int p1, p2, p3, p4;
+
+ int imageX, imageY;
+
+ if (sculptType != SculptType.plane)
+ {
+ for (int rowNdx = 0; rowNdx < rows.Count; rowNdx++)
+ rows[rowNdx].Add(rows[rowNdx][0]);
+ }
+
+ Coord topPole = rows[0][width / 2];
+ Coord bottomPole = rows[rows.Count - 1][width / 2];
+
+ if (sculptType == SculptType.sphere)
+ {
+ int count = rows[0].Count;
+ List topPoleRow = new List(count);
+ List bottomPoleRow = new List(count);
+
+ for (int i = 0; i < count; i++)
+ {
+ topPoleRow.Add(topPole);
+ bottomPoleRow.Add(bottomPole);
+ }
+ rows.Insert(0, topPoleRow);
+ rows.Add(bottomPoleRow);
+ }
+ else if (sculptType == SculptType.torus)
+ rows.Add(rows[0]);
+
+ int coordsDown = rows.Count;
+ int coordsAcross = rows[0].Count;
+
+ float widthUnit = 1.0f / (coordsAcross - 1);
+ float heightUnit = 1.0f / (coordsDown - 1);
+
+ for (imageY = 0; imageY < coordsDown; imageY++)
+ {
+ int rowOffset = imageY * coordsAcross;
+
+ for (imageX = 0; imageX < coordsAcross; imageX++)
+ {
+ /*
+ * p1-----p2
+ * | \ f2 |
+ * | \ |
+ * | f1 \|
+ * p3-----p4
+ */
+
+ p4 = rowOffset + imageX;
+ p3 = p4 - 1;
+
+ p2 = p4 - coordsAcross;
+ p1 = p3 - coordsAcross;
+
+ this.coords.Add(rows[imageY][imageX]);
+ if (viewerMode)
+ {
+ this.normals.Add(new Coord());
+ this.uvs.Add(new UVCoord(widthUnit * imageX, heightUnit * imageY));
+ }
+
+ if (imageY > 0 && imageX > 0)
+ {
+ Face f1, f2;
+
+ if (viewerMode)
+ {
+ if (invert)
+ {
+ f1 = new Face(p1, p4, p3, p1, p4, p3);
+ f1.uv1 = p1;
+ f1.uv2 = p4;
+ f1.uv3 = p3;
+
+ f2 = new Face(p1, p2, p4, p1, p2, p4);
+ f2.uv1 = p1;
+ f2.uv2 = p2;
+ f2.uv3 = p4;
+ }
+ else
+ {
+ f1 = new Face(p1, p3, p4, p1, p3, p4);
+ f1.uv1 = p1;
+ f1.uv2 = p3;
+ f1.uv3 = p4;
+
+ f2 = new Face(p1, p4, p2, p1, p4, p2);
+ f2.uv1 = p1;
+ f2.uv2 = p4;
+ f2.uv3 = p2;
+ }
+ }
+ else
+ {
+ if (invert)
+ {
+ f1 = new Face(p1, p4, p3);
+ f2 = new Face(p1, p2, p4);
+ }
+ else
+ {
+ f1 = new Face(p1, p3, p4);
+ f2 = new Face(p1, p4, p2);
+ }
+ }
+
+ this.faces.Add(f1);
+ this.faces.Add(f2);
+ }
+ }
+ }
+
+ if (viewerMode)
+ calcVertexNormals(sculptType, coordsAcross, coordsDown);
+ }
+
+ ///
+ /// Duplicates a SculptMesh object. All object properties are copied by value, including lists.
+ ///
+ ///
+ public SculptMesh Copy()
+ {
+ return new SculptMesh(this);
+ }
+
+ public SculptMesh(SculptMesh sm)
+ {
+ coords = new List(sm.coords);
+ faces = new List(sm.faces);
+ viewerFaces = new List(sm.viewerFaces);
+ normals = new List(sm.normals);
+ uvs = new List(sm.uvs);
+ }
+
+ private void calcVertexNormals(SculptType sculptType, int xSize, int ySize)
+ { // compute vertex normals by summing all the surface normals of all the triangles sharing
+ // each vertex and then normalizing
+ int numFaces = this.faces.Count;
+ for (int i = 0; i < numFaces; i++)
+ {
+ Face face = this.faces[i];
+ Coord surfaceNormal = face.SurfaceNormal(this.coords);
+ this.normals[face.n1] += surfaceNormal;
+ this.normals[face.n2] += surfaceNormal;
+ this.normals[face.n3] += surfaceNormal;
+ }
+
+ int numNormals = this.normals.Count;
+ for (int i = 0; i < numNormals; i++)
+ this.normals[i] = this.normals[i].Normalize();
+
+ if (sculptType != SculptType.plane)
+ { // blend the vertex normals at the cylinder seam
+ for (int y = 0; y < ySize; y++)
+ {
+ int rowOffset = y * xSize;
+
+ this.normals[rowOffset] = this.normals[rowOffset + xSize - 1] = (this.normals[rowOffset] + this.normals[rowOffset + xSize - 1]).Normalize();
+ }
+ }
+
+ foreach (Face face in this.faces)
+ {
+ ViewerFace vf = new ViewerFace(0);
+ vf.v1 = this.coords[face.v1];
+ vf.v2 = this.coords[face.v2];
+ vf.v3 = this.coords[face.v3];
+
+ vf.coordIndex1 = face.v1;
+ vf.coordIndex2 = face.v2;
+ vf.coordIndex3 = face.v3;
+
+ vf.n1 = this.normals[face.n1];
+ vf.n2 = this.normals[face.n2];
+ vf.n3 = this.normals[face.n3];
+
+ vf.uv1 = this.uvs[face.uv1];
+ vf.uv2 = this.uvs[face.uv2];
+ vf.uv3 = this.uvs[face.uv3];
+
+ this.viewerFaces.Add(vf);
+ }
+ }
+
+ ///
+ /// Adds a value to each XYZ vertex coordinate in the mesh
+ ///
+ ///
+ ///
+ ///
+ public void AddPos(float x, float y, float z)
+ {
+ int i;
+ int numVerts = this.coords.Count;
+ Coord vert;
+
+ for (i = 0; i < numVerts; i++)
+ {
+ vert = this.coords[i];
+ vert.X += x;
+ vert.Y += y;
+ vert.Z += z;
+ this.coords[i] = vert;
+ }
+
+ if (this.viewerFaces != null)
+ {
+ int numViewerFaces = this.viewerFaces.Count;
+
+ for (i = 0; i < numViewerFaces; i++)
+ {
+ ViewerFace v = this.viewerFaces[i];
+ v.AddPos(x, y, z);
+ this.viewerFaces[i] = v;
+ }
+ }
+ }
+
+ ///
+ /// Rotates the mesh
+ ///
+ ///
+ public void AddRot(Quat q)
+ {
+ int i;
+ int numVerts = this.coords.Count;
+
+ for (i = 0; i < numVerts; i++)
+ this.coords[i] *= q;
+
+ int numNormals = this.normals.Count;
+ for (i = 0; i < numNormals; i++)
+ this.normals[i] *= q;
+
+ if (this.viewerFaces != null)
+ {
+ int numViewerFaces = this.viewerFaces.Count;
+
+ for (i = 0; i < numViewerFaces; i++)
+ {
+ ViewerFace v = this.viewerFaces[i];
+ v.v1 *= q;
+ v.v2 *= q;
+ v.v3 *= q;
+
+ v.n1 *= q;
+ v.n2 *= q;
+ v.n3 *= q;
+
+ this.viewerFaces[i] = v;
+ }
+ }
+ }
+
+ public void Scale(float x, float y, float z)
+ {
+ int i;
+ int numVerts = this.coords.Count;
+
+ Coord m = new Coord(x, y, z);
+ for (i = 0; i < numVerts; i++)
+ this.coords[i] *= m;
+
+ if (this.viewerFaces != null)
+ {
+ int numViewerFaces = this.viewerFaces.Count;
+ for (i = 0; i < numViewerFaces; i++)
+ {
+ ViewerFace v = this.viewerFaces[i];
+ v.v1 *= m;
+ v.v2 *= m;
+ v.v3 *= m;
+ this.viewerFaces[i] = v;
+ }
+ }
+ }
+
+ public void DumpRaw(String path, String name, String title)
+ {
+ if (path == null)
+ return;
+ String fileName = name + "_" + title + ".raw";
+ String completePath = System.IO.Path.Combine(path, fileName);
+ StreamWriter sw = new StreamWriter(completePath);
+
+ for (int i = 0; i < this.faces.Count; i++)
+ {
+ string s = this.coords[this.faces[i].v1].ToString();
+ s += " " + this.coords[this.faces[i].v2].ToString();
+ s += " " + this.coords[this.faces[i].v3].ToString();
+
+ sw.WriteLine(s);
+ }
+
+ sw.Close();
+ }
+ }
+}
diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
index 92f060b4cd..0b8771c3ad 100644
--- a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
+++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
@@ -922,7 +922,7 @@ namespace OpenSim.Region.RegionCombinerModule
VirtualRegion.Permissions.OnIssueEstateCommand += BigRegion.PermissionModule.CanIssueEstateCommand; //FULLY IMPLEMENTED
VirtualRegion.Permissions.OnMoveObject += BigRegion.PermissionModule.CanMoveObject; //MAYBE FULLY IMPLEMENTED
VirtualRegion.Permissions.OnObjectEntry += BigRegion.PermissionModule.CanObjectEntry;
- VirtualRegion.Permissions.OnReturnObject += BigRegion.PermissionModule.CanReturnObject; //NOT YET IMPLEMENTED
+ VirtualRegion.Permissions.OnReturnObjects += BigRegion.PermissionModule.CanReturnObjects; //NOT YET IMPLEMENTED
VirtualRegion.Permissions.OnRezObject += BigRegion.PermissionModule.CanRezObject; //MAYBE FULLY IMPLEMENTED
VirtualRegion.Permissions.OnRunConsoleCommand += BigRegion.PermissionModule.CanRunConsoleCommand;
VirtualRegion.Permissions.OnRunScript += BigRegion.PermissionModule.CanRunScript; //NOT YET IMPLEMENTED
@@ -948,7 +948,6 @@ namespace OpenSim.Region.RegionCombinerModule
VirtualRegion.Permissions.OnEditUserInventory += BigRegion.PermissionModule.CanEditUserInventory; //NOT YET IMPLEMENTED
VirtualRegion.Permissions.OnDeleteUserInventory += BigRegion.PermissionModule.CanDeleteUserInventory; //NOT YET IMPLEMENTED
VirtualRegion.Permissions.OnTeleport += BigRegion.PermissionModule.CanTeleport; //NOT YET IMPLEMENTED
- VirtualRegion.Permissions.OnUseObjectReturn += BigRegion.PermissionModule.CanUseObjectReturn; //NOT YET IMPLEMENTED
}
#region console commands
diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerPermissionModule.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerPermissionModule.cs
index 4d1af57450..393322d2d1 100644
--- a/OpenSim/Region/RegionCombinerModule/RegionCombinerPermissionModule.cs
+++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerPermissionModule.cs
@@ -135,9 +135,9 @@ namespace OpenSim.Region.RegionCombinerModule
return m_rootScene.Permissions.CanObjectEntry(objectid, enteringregion, newpoint);
}
- public bool CanReturnObject(UUID objectid, UUID returnerid, Scene scene)
+ public bool CanReturnObjects(ILandObject land, UUID user, List objects, Scene scene)
{
- return m_rootScene.Permissions.CanReturnObject(objectid, returnerid);
+ return m_rootScene.Permissions.CanReturnObjects(land, user, objects);
}
public bool CanRezObject(int objectcount, UUID owner, Vector3 objectposition, Scene scene)
@@ -265,11 +265,6 @@ namespace OpenSim.Region.RegionCombinerModule
return m_rootScene.Permissions.CanTeleport(userid);
}
- public bool CanUseObjectReturn(ILandObject landdata, uint type, IClientAPI client, List retlist, Scene scene)
- {
- return m_rootScene.Permissions.CanUseObjectReturn(landdata, type, client, retlist);
- }
-
#endregion
}
-}
\ No newline at end of file
+}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 8f82304ddb..0c373b9108 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -221,8 +221,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public List GetLinkParts(int linkType)
{
- List ret = new List();
- if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
+ List ret = new List();
+ if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
return ret;
ret.Add(m_host);
@@ -1115,6 +1115,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return detectedParams.TouchUV;
}
+ [DebuggerNonUserCode]
public virtual void llDie()
{
m_host.AddScriptLPS(1);
@@ -1190,8 +1191,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
public void llSetStatus(int status, int value)
- {
- if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
+ {
+ if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
return;
m_host.AddScriptLPS(1);
@@ -1367,7 +1368,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
protected void SetScale(SceneObjectPart part, LSL_Vector scale)
- {
+ {
// TODO: this needs to trigger a persistance save as well
if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
return;
@@ -1426,8 +1427,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
protected void SetColor(SceneObjectPart part, LSL_Vector color, int face)
- {
- if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
+ {
+ if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
return;
Primitive.TextureEntry tex = part.Shape.Textures;
@@ -1471,8 +1472,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
public void SetTexGen(SceneObjectPart part, int face,int style)
- {
- if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
+ {
+ if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
return;
Primitive.TextureEntry tex = part.Shape.Textures;
@@ -1504,8 +1505,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
public void SetGlow(SceneObjectPart part, int face, float glow)
- {
- if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
+ {
+ if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
return;
Primitive.TextureEntry tex = part.Shape.Textures;
@@ -1532,8 +1533,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump)
- {
- if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
+ {
+ if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
return;
Shininess sval = new Shininess();
@@ -1584,8 +1585,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
public void SetFullBright(SceneObjectPart part, int face, bool bright)
- {
- if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
+ {
+ if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
return;
Primitive.TextureEntry tex = part.Shape.Textures;
@@ -1654,8 +1655,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
protected void SetAlpha(SceneObjectPart part, double alpha, int face)
- {
- if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
+ {
+ if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
return;
Primitive.TextureEntry tex = part.Shape.Textures;
@@ -1702,8 +1703,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
///
protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction,
float wind, float tension, LSL_Vector Force)
- {
- if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
+ {
+ if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
return;
if (flexi)
@@ -1737,8 +1738,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
///
///
protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff)
- {
- if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
+ {
+ if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
return;
if (light)
@@ -1823,8 +1824,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
protected void SetTexture(SceneObjectPart part, string texture, int face)
- {
- if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
+ {
+ if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
return;
UUID textureID=new UUID();
@@ -1871,8 +1872,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
protected void ScaleTexture(SceneObjectPart part, double u, double v, int face)
- {
- if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
+ {
+ if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
return;
Primitive.TextureEntry tex = part.Shape.Textures;
@@ -1910,8 +1911,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
protected void OffsetTexture(SceneObjectPart part, double u, double v, int face)
- {
- if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
+ {
+ if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
return;
Primitive.TextureEntry tex = part.Shape.Textures;
@@ -1949,8 +1950,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
protected void RotateTexture(SceneObjectPart part, double rotation, int face)
- {
- if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
+ {
+ if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
return;
Primitive.TextureEntry tex = part.Shape.Textures;
@@ -2022,8 +2023,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
protected void SetPos(SceneObjectPart part, LSL_Vector targetPos)
- {
- if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
+ {
+ if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
return;
// Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos)
@@ -2119,8 +2120,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
protected void SetRot(SceneObjectPart part, Quaternion rot)
- {
- if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
+ {
+ if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
return;
part.UpdateRotation(rot);
@@ -4019,7 +4020,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
bucket);
if (m_TransferModule != null)
- m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
+ m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
//This delay should only occur when giving inventory to avatars.
ScriptSleep(3000);
@@ -4194,6 +4195,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
ScenePresence presence = World.GetScenePresence(agentId);
if (presence != null)
{
+ // agent must not be a god
+ if (presence.GodLevel >= 200) return;
+
// agent must be over the owners land
if (m_host.OwnerID == World.LandChannel.GetLandObject(
presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
@@ -6689,9 +6693,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist)
- {
- ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
- if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
+ {
+ ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
+ if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
return shapeBlock;
if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT &&
@@ -6762,8 +6766,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector taper_b, LSL_Vector topshear, byte fudge)
- {
- if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
+ {
+ if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
return;
ObjectShapePacket.ObjectDataBlock shapeBlock;
@@ -6814,8 +6818,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte fudge)
- {
- if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
+ {
+ if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
return;
ObjectShapePacket.ObjectDataBlock shapeBlock;
@@ -6859,8 +6863,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector holesize, LSL_Vector topshear, LSL_Vector profilecut, LSL_Vector taper_a, float revolutions, float radiusoffset, float skew, byte fudge)
- {
- if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
+ {
+ if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
return;
ObjectShapePacket.ObjectDataBlock shapeBlock;
@@ -6983,8 +6987,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type)
- {
- if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
+ {
+ if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
return;
ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
@@ -7020,13 +7024,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
public void llSetPrimitiveParams(LSL_List rules)
- {
+ {
m_host.AddScriptLPS(1);
SetPrimParams(m_host, rules);
}
public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules)
- {
+ {
m_host.AddScriptLPS(1);
List parts = GetLinkParts(linknumber);
@@ -7041,8 +7045,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
protected void SetPrimParams(SceneObjectPart part, LSL_List rules)
- {
- if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
+ {
+ if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
return;
int idx = 0;
@@ -7875,96 +7879,96 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
break;
- case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
- if (remain < 1)
- return res;
- face = (int)rules.GetLSLIntegerItem(idx++);
-
- tex = part.Shape.Textures;
- int shiny;
- if (face == ScriptBaseClass.ALL_SIDES)
- {
- for (face = 0; face < GetNumberOfSides(part); face++)
- {
- Shininess shinyness = tex.GetFace((uint)face).Shiny;
- if (shinyness == Shininess.High)
- {
- shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
- }
- else if (shinyness == Shininess.Medium)
- {
- shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
- }
- else if (shinyness == Shininess.Low)
- {
- shiny = ScriptBaseClass.PRIM_SHINY_LOW;
- }
- else
- {
- shiny = ScriptBaseClass.PRIM_SHINY_NONE;
- }
- res.Add(new LSL_Integer(shiny));
- res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
- }
- }
- else
- {
- Shininess shinyness = tex.GetFace((uint)face).Shiny;
- if (shinyness == Shininess.High)
- {
- shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
- }
- else if (shinyness == Shininess.Medium)
- {
- shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
- }
- else if (shinyness == Shininess.Low)
- {
- shiny = ScriptBaseClass.PRIM_SHINY_LOW;
- }
- else
- {
- shiny = ScriptBaseClass.PRIM_SHINY_NONE;
- }
- res.Add(new LSL_Integer(shiny));
- res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
- }
+ case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
+ if (remain < 1)
+ return res;
+ face = (int)rules.GetLSLIntegerItem(idx++);
+
+ tex = part.Shape.Textures;
+ int shiny;
+ if (face == ScriptBaseClass.ALL_SIDES)
+ {
+ for (face = 0; face < GetNumberOfSides(part); face++)
+ {
+ Shininess shinyness = tex.GetFace((uint)face).Shiny;
+ if (shinyness == Shininess.High)
+ {
+ shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
+ }
+ else if (shinyness == Shininess.Medium)
+ {
+ shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
+ }
+ else if (shinyness == Shininess.Low)
+ {
+ shiny = ScriptBaseClass.PRIM_SHINY_LOW;
+ }
+ else
+ {
+ shiny = ScriptBaseClass.PRIM_SHINY_NONE;
+ }
+ res.Add(new LSL_Integer(shiny));
+ res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
+ }
+ }
+ else
+ {
+ Shininess shinyness = tex.GetFace((uint)face).Shiny;
+ if (shinyness == Shininess.High)
+ {
+ shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
+ }
+ else if (shinyness == Shininess.Medium)
+ {
+ shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
+ }
+ else if (shinyness == Shininess.Low)
+ {
+ shiny = ScriptBaseClass.PRIM_SHINY_LOW;
+ }
+ else
+ {
+ shiny = ScriptBaseClass.PRIM_SHINY_NONE;
+ }
+ res.Add(new LSL_Integer(shiny));
+ res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
+ }
break;
- case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
- if (remain < 1)
- return res;
- face = (int)rules.GetLSLIntegerItem(idx++);
-
- tex = part.Shape.Textures;
- int fullbright;
- if (face == ScriptBaseClass.ALL_SIDES)
- {
- for (face = 0; face < GetNumberOfSides(part); face++)
- {
- if (tex.GetFace((uint)face).Fullbright == true)
- {
- fullbright = ScriptBaseClass.TRUE;
- }
- else
- {
- fullbright = ScriptBaseClass.FALSE;
- }
- res.Add(new LSL_Integer(fullbright));
- }
- }
- else
- {
- if (tex.GetFace((uint)face).Fullbright == true)
- {
- fullbright = ScriptBaseClass.TRUE;
- }
- else
- {
- fullbright = ScriptBaseClass.FALSE;
- }
- res.Add(new LSL_Integer(fullbright));
- }
+ case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
+ if (remain < 1)
+ return res;
+ face = (int)rules.GetLSLIntegerItem(idx++);
+
+ tex = part.Shape.Textures;
+ int fullbright;
+ if (face == ScriptBaseClass.ALL_SIDES)
+ {
+ for (face = 0; face < GetNumberOfSides(part); face++)
+ {
+ if (tex.GetFace((uint)face).Fullbright == true)
+ {
+ fullbright = ScriptBaseClass.TRUE;
+ }
+ else
+ {
+ fullbright = ScriptBaseClass.FALSE;
+ }
+ res.Add(new LSL_Integer(fullbright));
+ }
+ }
+ else
+ {
+ if (tex.GetFace((uint)face).Fullbright == true)
+ {
+ fullbright = ScriptBaseClass.TRUE;
+ }
+ else
+ {
+ fullbright = ScriptBaseClass.FALSE;
+ }
+ res.Add(new LSL_Integer(fullbright));
+ }
break;
case (int)ScriptBaseClass.PRIM_FLEXIBLE:
@@ -7985,37 +7989,37 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
break;
case (int)ScriptBaseClass.PRIM_TEXGEN:
- // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
- if (remain < 1)
- return res;
- face = (int)rules.GetLSLIntegerItem(idx++);
-
- tex = part.Shape.Textures;
- if (face == ScriptBaseClass.ALL_SIDES)
- {
- for (face = 0; face < GetNumberOfSides(part); face++)
- {
- if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
- {
- res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
- }
- else
- {
- res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
- }
- }
- }
- else
- {
- if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
- {
- res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
- }
- else
- {
- res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
- }
- }
+ // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
+ if (remain < 1)
+ return res;
+ face = (int)rules.GetLSLIntegerItem(idx++);
+
+ tex = part.Shape.Textures;
+ if (face == ScriptBaseClass.ALL_SIDES)
+ {
+ for (face = 0; face < GetNumberOfSides(part); face++)
+ {
+ if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
+ {
+ res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
+ }
+ else
+ {
+ res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
+ }
+ }
+ }
+ else
+ {
+ if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
+ {
+ res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
+ }
+ else
+ {
+ res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
+ }
+ }
break;
case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
@@ -8033,26 +8037,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
res.Add(new LSL_Float(shape.LightFalloff)); // falloff
break;
- case (int)ScriptBaseClass.PRIM_GLOW:
- if (remain < 1)
+ case (int)ScriptBaseClass.PRIM_GLOW:
+ if (remain < 1)
return res;
- face = (int)rules.GetLSLIntegerItem(idx++);
-
- tex = part.Shape.Textures;
- float primglow;
- if (face == ScriptBaseClass.ALL_SIDES)
- {
- for (face = 0; face < GetNumberOfSides(part); face++)
- {
- primglow = tex.GetFace((uint)face).Glow;
- res.Add(new LSL_Float(primglow));
- }
- }
- else
- {
- primglow = tex.GetFace((uint)face).Glow;
- res.Add(new LSL_Float(primglow));
- }
+ face = (int)rules.GetLSLIntegerItem(idx++);
+
+ tex = part.Shape.Textures;
+ float primglow;
+ if (face == ScriptBaseClass.ALL_SIDES)
+ {
+ for (face = 0; face < GetNumberOfSides(part); face++)
+ {
+ primglow = tex.GetFace((uint)face).Glow;
+ res.Add(new LSL_Float(primglow));
+ }
+ }
+ else
+ {
+ primglow = tex.GetFace((uint)face).Glow;
+ res.Add(new LSL_Float(primglow));
+ }
break;
case (int)ScriptBaseClass.PRIM_TEXT:
Color4 textColor = part.GetTextColor();
@@ -9214,7 +9218,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_host.AddScriptLPS(1);
if (quick_pay_buttons.Data.Length < 4)
- {
+ {
int x;
for (x=quick_pay_buttons.Data.Length; x<= 4; x++)
{
@@ -9222,12 +9226,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
}
int[] nPrice = new int[5];
- nPrice[0]=price;
- nPrice[1] = (LSL_Integer)quick_pay_buttons.Data[0];
- nPrice[2] = (LSL_Integer)quick_pay_buttons.Data[1];
- nPrice[3] = (LSL_Integer)quick_pay_buttons.Data[2];
+ nPrice[0]=price;
+ nPrice[1] = (LSL_Integer)quick_pay_buttons.Data[0];
+ nPrice[2] = (LSL_Integer)quick_pay_buttons.Data[1];
+ nPrice[3] = (LSL_Integer)quick_pay_buttons.Data[2];
nPrice[4] = (LSL_Integer)quick_pay_buttons.Data[3];
- m_host.ParentGroup.RootPart.PayPrice = nPrice;
+ m_host.ParentGroup.RootPart.PayPrice = nPrice;
m_host.ParentGroup.HasGroupChanged = true;
}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
index 3339995f66..e86d08c9aa 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
@@ -26,6 +26,7 @@
*/
using System;
+using System.Diagnostics; //for [DebuggerNonUserCode]
using System.Runtime.Remoting.Lifetime;
using System.Threading;
using System.Reflection;
@@ -309,6 +310,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
m_LSL_Functions.llDialog(avatar, message, buttons, chat_channel);
}
+ [DebuggerNonUserCode]
public void llDie()
{
m_LSL_Functions.llDie();
diff --git a/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs b/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs
index 704b74f67b..a567413ec8 100644
--- a/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs
+++ b/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs
@@ -68,7 +68,7 @@ namespace OpenSim.Region.UserStatistics
HTMLUtil.OL_O(ref output, "");
foreach (Scene scene in all_scenes)
{
- ScenePresence[] avatarInScene = scene.GetScenePresences();
+ List avatarInScene = scene.GetScenePresences();
HTMLUtil.LI_O(ref output, String.Empty);
output.Append(scene.RegionInfo.RegionName);
diff --git a/OpenSim/Server/Base/ServerUtils.cs b/OpenSim/Server/Base/ServerUtils.cs
index a399672d4d..e7a8294fef 100644
--- a/OpenSim/Server/Base/ServerUtils.cs
+++ b/OpenSim/Server/Base/ServerUtils.cs
@@ -101,10 +101,23 @@ namespace OpenSim.Server.Base
continue;
Type typeInterface = pluginType.GetInterface(interfaceName, true);
-
+
if (typeInterface != null)
{
- return (T)Activator.CreateInstance(pluginType, args);
+ T plug = null;
+ try
+ {
+ plug = (T)Activator.CreateInstance(pluginType,
+ args);
+ }
+ catch (Exception e)
+ {
+ if (!(e is System.MissingMethodException))
+ m_log.ErrorFormat("Error loading plugin from {0}, exception {1}", dllName, e.InnerException);
+ return null;
+ }
+
+ return plug;
}
}
}
diff --git a/OpenSim/Server/Handlers/Simulation/SimulationServiceInConnector.cs b/OpenSim/Server/Handlers/Simulation/SimulationServiceInConnector.cs
index 55a575c3ac..50d6fb207b 100644
--- a/OpenSim/Server/Handlers/Simulation/SimulationServiceInConnector.cs
+++ b/OpenSim/Server/Handlers/Simulation/SimulationServiceInConnector.cs
@@ -55,6 +55,7 @@ namespace OpenSim.Server.Handlers.Simulation
//Object[] args = new Object[] { config };
m_LocalSimulationService = scene.RequestModuleInterface();
+ m_LocalSimulationService = m_LocalSimulationService.GetInnerService();
//ServerUtils.LoadPlugin(simService, args);
//System.Console.WriteLine("XXXXXXXXXXXXXXXXXXX m_AssetSetvice == null? " + ((m_AssetService == null) ? "yes" : "no"));
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs
index 1c22a72bc4..c5fbc9e841 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs
@@ -85,7 +85,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
public void Initialise(IConfigSource source)
{
- if (Simian.IsSimianEnabled(source, "AssetServices"))
+ if (Simian.IsSimianEnabled(source, "AssetServices", this.Name))
{
IConfig gridConfig = source.Configs["AssetService"];
if (gridConfig == null)
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs
index 6317b8711e..cc53d6ca0f 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs
@@ -73,7 +73,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
public void Initialise(IConfigSource source)
{
- if (Simian.IsSimianEnabled(source, "AuthenticationServices"))
+ if (Simian.IsSimianEnabled(source, "AuthenticationServices", this.Name))
{
IConfig assetConfig = source.Configs["AuthenticationService"];
if (assetConfig == null)
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs
index a18cb2286e..00f9f36f6a 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs
@@ -78,7 +78,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
public void Initialise(IConfigSource source)
{
- if (Simian.IsSimianEnabled(source, "AvatarServices"))
+ if (Simian.IsSimianEnabled(source, "AvatarServices", this.Name))
{
IConfig gridConfig = source.Configs["AvatarService"];
if (gridConfig == null)
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs
index b3ecc7e907..89eb72d143 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs
@@ -76,7 +76,15 @@ namespace OpenSim.Services.Connectors.SimianGrid
public void Initialise(IConfigSource source)
{
- if (Simian.IsSimianEnabled(source, "FriendsServices"))
+ bool isSimianEnabled = false;
+
+ if (source.Configs["Friends"] != null)
+ {
+ string module = source.Configs["Friends"].GetString("Connector");
+ isSimianEnabled = !String.IsNullOrEmpty(module) && module.EndsWith(this.Name);
+ }
+
+ if (isSimianEnabled)
{
IConfig assetConfig = source.Configs["FriendsService"];
if (assetConfig == null)
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianGrid.cs b/OpenSim/Services/Connectors/SimianGrid/SimianGrid.cs
index c3de98ef58..7d97aaa3e8 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianGrid.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianGrid.cs
@@ -34,12 +34,12 @@ using Nini.Config;
public static class Simian
{
- public static bool IsSimianEnabled(IConfigSource config, string moduleName)
+ public static bool IsSimianEnabled(IConfigSource config, string moduleName, string connectorName)
{
if (config.Configs["Modules"] != null)
{
- string module = config.Configs["Modules"].GetString("AuthenticationServices");
- return !String.IsNullOrEmpty(module) && module.Contains("Simian");
+ string module = config.Configs["Modules"].GetString(moduleName);
+ return !String.IsNullOrEmpty(module) && module.EndsWith(connectorName);
}
return false;
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs
index eebdf14b92..071a481611 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs
@@ -80,7 +80,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
public void Initialise(IConfigSource source)
{
- if (Simian.IsSimianEnabled(source, "GridServices"))
+ if (Simian.IsSimianEnabled(source, "GridServices", this.Name))
{
IConfig gridConfig = source.Configs["GridService"];
if (gridConfig == null)
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs
index 891782fdad..67f8e80452 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs
@@ -92,7 +92,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
public void Initialise(IConfigSource source)
{
- if (Simian.IsSimianEnabled(source, "InventoryServices"))
+ if (Simian.IsSimianEnabled(source, "InventoryServices", this.Name))
{
IConfig gridConfig = source.Configs["InventoryService"];
if (gridConfig == null)
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs
index 1b5edf4ba2..5e0f7c25e6 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs
@@ -104,7 +104,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
public void Initialise(IConfigSource source)
{
- if (Simian.IsSimianEnabled(source, "PresenceServices"))
+ if (Simian.IsSimianEnabled(source, "PresenceServices", this.Name))
{
IConfig gridConfig = source.Configs["PresenceService"];
if (gridConfig == null)
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs b/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs
index 9c226fb5b0..0a36ae5902 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs
@@ -88,7 +88,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
public void Initialise(IConfigSource source)
{
- if (Simian.IsSimianEnabled(source, "UserAccountServices"))
+ if (Simian.IsSimianEnabled(source, "UserAccountServices", this.Name))
{
IConfig gridConfig = source.Configs["UserAccountService"];
if (gridConfig == null)
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs
index bb0ac57b98..491a9a25d8 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs
@@ -77,7 +77,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
public void Initialise(IConfigSource source)
{
- if (Simian.IsSimianEnabled(source, "UserAccountServices"))
+ if (Simian.IsSimianEnabled(source, "UserAccountServices", this.Name))
{
IConfig assetConfig = source.Configs["UserAccountService"];
if (assetConfig == null)
diff --git a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
index d3be1a8e8a..ff0dd7e622 100644
--- a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
+++ b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
@@ -63,6 +63,11 @@ namespace OpenSim.Services.Connectors.Simulation
return null;
}
+ public ISimulationService GetInnerService()
+ {
+ return null;
+ }
+
#region Agents
protected virtual string AgentPath()
diff --git a/OpenSim/Services/Interfaces/ISimulationService.cs b/OpenSim/Services/Interfaces/ISimulationService.cs
index ec24d90e45..67d7cbe71b 100644
--- a/OpenSim/Services/Interfaces/ISimulationService.cs
+++ b/OpenSim/Services/Interfaces/ISimulationService.cs
@@ -36,6 +36,7 @@ namespace OpenSim.Services.Interfaces
public interface ISimulationService
{
IScene GetScene(ulong regionHandle);
+ ISimulationService GetInnerService();
#region Agents
diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example
index 8d7c2cf467..d660f363cc 100644
--- a/bin/OpenSim.ini.example
+++ b/bin/OpenSim.ini.example
@@ -37,13 +37,6 @@
; performance on .NET/Windows
async_call_method = SmartThreadPool
- ; There are several operations on large collections (such as
- ; the current avatar list) that can be run synchronously or
- ; in parallel. Running in parallel should increase performance
- ; on a multi-core system, but will make debugging more
- ; difficult if something deadlocks or times out
- use_async_when_possible = false
-
; Max threads to allocate on the FireAndForget thread pool
; when running with the SmartThreadPool option above
MaxPoolThreads = 15
diff --git a/bin/config-include/SimianGrid.ini b/bin/config-include/SimianGrid.ini
index 58dcae9e24..064f36ec89 100644
--- a/bin/config-include/SimianGrid.ini
+++ b/bin/config-include/SimianGrid.ini
@@ -22,7 +22,7 @@
[Modules]
GridServices = "OpenSim.Services.Connectors.dll:SimianGridServiceConnector"
PresenceServices = "OpenSim.Services.Connectors.dll:SimianPresenceServiceConnector"
- UserAccountServices = "OpenSim.Services.Connectors.dll:SimianGridUserAccountServiceConnector"
+ UserAccountServices = "OpenSim.Services.Connectors.dll:SimianUserAccountServiceConnector"
AuthenticationServices = "OpenSim.Services.Connectors.dll:SimianAuthenticationServiceConnector"
AssetServices = "OpenSim.Services.Connectors.dll:SimianAssetServiceConnector"
InventoryServices = "OpenSim.Services.Connectors.dll:SimianInventoryServiceConnector"