From de20f0603fa419ba16c56d16c2ad55301cad8b83 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 24 Jun 2011 19:49:05 +0100 Subject: Tell hypergridders when their teleports fail because of the 4096 limit rather than just saying "destination not found" Instead of performing the 4096 check when the region is linked (and subsequently removing the link), leave the link in place and perform the check in the entity transfer module This allows us to explicitly tell the hypergridder why the teleport failed (region out of range). It also allows people on regions that are within range (on a large source grid) to teleport. The Check4096 config parameter in the [GridService] section is replaced by a max_distance paramter in a new [EntityTransfer] section in OpenSimDefaults.ini Since the parameter is in OpenSimDefaults.ini no action needs to be taken unless you want to increase this limit. It could also be decreased. The check is being made in the base entity transfer module, since I believe the viewer problem occurs both on extremely large grids and while hypergridding. --- .../EntityTransfer/EntityTransferModule.cs | 52 ++++++++-- .../EntityTransfer/HGEntityTransferModule.cs | 6 +- .../CoreModules/World/WorldMap/MapSearchModule.cs | 4 +- .../Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs | 8 +- OpenSim/Services/GridService/HypergridLinker.cs | 115 +++++++++++---------- 5 files changed, 113 insertions(+), 72 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 1341533..d54216a 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -50,6 +50,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + /// + /// The maximum distance, in standard region units (256m) that an agent is allowed to transfer. + /// + public int MaxTransferDistance { get; set; } + protected bool m_Enabled = false; protected Scene m_aScene; protected List m_Scenes = new List(); @@ -78,13 +83,26 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer string name = moduleConfig.GetString("EntityTransferModule", ""); if (name == Name) { - m_agentsInTransit = new List(); - m_Enabled = true; - m_log.InfoFormat("[ENTITY TRANSFER MODULE]: {0} enabled.", Name); + InitialiseCommon(source); + m_log.DebugFormat("[ENTITY TRANSFER MODULE]: {0} enabled.", Name); } } } + /// + /// Initialize config common for this module and any descendents. + /// + /// + protected virtual void InitialiseCommon(IConfigSource source) + { + IConfig transferConfig = source.Configs["EntityTransfer"]; + if (transferConfig != null) + MaxTransferDistance = transferConfig.GetInt("max_distance", 4095); + + m_agentsInTransit = new List(); + m_Enabled = true; + } + public virtual void PostInitialise() { } @@ -114,7 +132,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer return; } - public virtual void RemoveRegion(Scene scene) { if (!m_Enabled) @@ -129,7 +146,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer { if (!m_Enabled) return; - } #endregion @@ -204,8 +220,18 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer sp.ControllingClient.SendTeleportFailed("Problem at destination"); return; } - m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Final destination is x={0} y={1} {2}@{3}", - finalDestination.RegionLocX / Constants.RegionSize, finalDestination.RegionLocY / Constants.RegionSize, finalDestination.RegionID, finalDestination.ServerURI); + + uint curX = 0, curY = 0; + Utils.LongToUInts(sp.Scene.RegionInfo.RegionHandle, out curX, out curY); + int curCellX = (int)(curX / Constants.RegionSize); + int curCellY = (int)(curY / Constants.RegionSize); + int destCellX = (int)(finalDestination.RegionLocX / Constants.RegionSize); + int destCellY = (int)(finalDestination.RegionLocY / Constants.RegionSize); + +// m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Source co-ords are x={0} y={1}", curRegionX, curRegionY); +// +// m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Final dest is x={0} y={1} {2}@{3}", +// destRegionX, destRegionY, finalDestination.RegionID, finalDestination.ServerURI); // Check that these are not the same coordinates if (finalDestination.RegionLocX == sp.Scene.RegionInfo.RegionLocX && @@ -216,6 +242,18 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer return; } + if (Math.Abs(curCellX - destCellX) > MaxTransferDistance || Math.Abs(curCellY - destCellY) > MaxTransferDistance) + { + sp.ControllingClient.SendTeleportFailed( + string.Format( + "Can't teleport to {0} ({1},{2}) from {3} ({4},{5}), destination is more than {6} regions way", + finalDestination.RegionName, destCellX, destCellY, + sp.Scene.RegionInfo.RegionName, curCellX, curCellY, + MaxTransferDistance)); + + return; + } + // // This is it // diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index 4d77ef4..a87279a 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs @@ -67,10 +67,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer string name = moduleConfig.GetString("EntityTransferModule", ""); if (name == Name) { - m_agentsInTransit = new List(); - - m_Enabled = true; - m_log.InfoFormat("[HG ENTITY TRANSFER MODULE]: {0} enabled.", Name); + InitialiseCommon(source); + m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: {0} enabled.", Name); } } } diff --git a/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs index 00959b0..2e3b21f 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs @@ -91,6 +91,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap remoteClient.SendAlertMessage("Use a search string with at least 3 characters"); return; } + +m_log.DebugFormat("MAP NAME=({0})", mapName); // try to fetch from GridServer List regionInfos = m_scene.GridService.GetRegionsByName(m_scene.RegionInfo.ScopeID, mapName, 20); @@ -103,7 +105,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap if (info != null) regionInfos.Add(info); } - else if (regionInfos.Count == 0 && mapName.StartsWith("http://")) + else if (regionInfos.Count == 0) remoteClient.SendAlertMessage("Hyperlink could not be established."); m_log.DebugFormat("[MAPSEARCHMODULE]: search {0} returned {1} regions. Flags={2}", mapName, regionInfos.Count, flags); diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs index 42efd67..a5bba4f 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs @@ -417,9 +417,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice public string ParcelVoiceInfoRequest(Scene scene, string request, string path, string param, UUID agentID, Caps caps) { -// m_log.DebugFormat( -// "[FreeSwitchVoice][PARCELVOICE]: ParcelVoiceInfoRequest() on {0} for {1}", -// scene.RegionInfo.RegionName, agentID); + m_log.DebugFormat( + "[FreeSwitchVoice][PARCELVOICE]: ParcelVoiceInfoRequest() on {0} for {1}", + scene.RegionInfo.RegionName, agentID); ScenePresence avatar = scene.GetScenePresence(agentID); string avatarName = avatar.Name; @@ -885,4 +885,4 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice #endregion } -} \ No newline at end of file +} diff --git a/OpenSim/Services/GridService/HypergridLinker.cs b/OpenSim/Services/GridService/HypergridLinker.cs index 5262598..83ec122 100644 --- a/OpenSim/Services/GridService/HypergridLinker.cs +++ b/OpenSim/Services/GridService/HypergridLinker.cs @@ -63,7 +63,7 @@ namespace OpenSim.Services.GridService protected GatekeeperServiceConnector m_GatekeeperConnector; protected UUID m_ScopeID = UUID.Zero; - protected bool m_Check4096 = true; +// protected bool m_Check4096 = true; protected string m_MapTileDirectory = string.Empty; protected string m_ThisGatekeeper = string.Empty; protected Uri m_ThisGatekeeperURI = null; @@ -121,7 +121,7 @@ namespace OpenSim.Services.GridService if (scope != string.Empty) UUID.TryParse(scope, out m_ScopeID); - m_Check4096 = gridConfig.GetBoolean("Check4096", true); +// m_Check4096 = gridConfig.GetBoolean("Check4096", true); m_MapTileDirectory = gridConfig.GetString("MapTileDirectory", "maptiles"); @@ -347,14 +347,18 @@ namespace OpenSim.Services.GridService return true; } - uint x, y; - if (m_Check4096 && !Check4096(handle, out x, out y)) - { - RemoveHyperlinkRegion(regInfo.RegionID); - reason = "Region is too far (" + x + ", " + y + ")"; - m_log.Info("[HYPERGRID LINKER]: Unable to link, region is too far (" + x + ", " + y + ")"); - return false; - } + // We are now performing this check for each individual teleport in the EntityTransferModule instead. This + // allows us to give better feedback when teleports fail because of the distance reason (which can't be + // done here) and it also hypergrid teleports that are within range (possibly because the source grid + // itself has regions that are very far apart). +// uint x, y; +// if (m_Check4096 && !Check4096(handle, out x, out y)) +// { +// //RemoveHyperlinkRegion(regInfo.RegionID); +// reason = "Region is too far (" + x + ", " + y + ")"; +// m_log.Info("[HYPERGRID LINKER]: Unable to link, region is too far (" + x + ", " + y + ")"); +// //return false; +// } regInfo.RegionID = regionID; @@ -405,60 +409,59 @@ namespace OpenSim.Services.GridService } } - /// - /// Cope with this viewer limitation. - /// - /// - /// - public bool Check4096(ulong realHandle, out uint x, out uint y) - { - uint ux = 0, uy = 0; - Utils.LongToUInts(realHandle, out ux, out uy); - x = ux / Constants.RegionSize; - y = uy / Constants.RegionSize; - - const uint limit = (4096 - 1) * Constants.RegionSize; - uint xmin = ux - limit; - uint xmax = ux + limit; - uint ymin = uy - limit; - uint ymax = uy + limit; - // World map boundary checks - if (xmin < 0 || xmin > ux) - xmin = 0; - if (xmax > int.MaxValue || xmax < ux) - xmax = int.MaxValue; - if (ymin < 0 || ymin > uy) - ymin = 0; - if (ymax > int.MaxValue || ymax < uy) - ymax = int.MaxValue; - - // Check for any regions that are within the possible teleport range to the linked region - List regions = m_GridService.GetRegionRange(m_ScopeID, (int)xmin, (int)xmax, (int)ymin, (int)ymax); - if (regions.Count == 0) - { - return false; - } - else - { - // Check for regions which are not linked regions - List hyperlinks = m_GridService.GetHyperlinks(m_ScopeID); - IEnumerable availableRegions = regions.Except(hyperlinks); - if (availableRegions.Count() == 0) - return false; - } - - return true; - } +// Not currently used +// /// +// /// Cope with this viewer limitation. +// /// +// /// +// /// +// public bool Check4096(ulong realHandle, out uint x, out uint y) +// { +// uint ux = 0, uy = 0; +// Utils.LongToUInts(realHandle, out ux, out uy); +// x = ux / Constants.RegionSize; +// y = uy / Constants.RegionSize; +// +// const uint limit = (4096 - 1) * Constants.RegionSize; +// uint xmin = ux - limit; +// uint xmax = ux + limit; +// uint ymin = uy - limit; +// uint ymax = uy + limit; +// // World map boundary checks +// if (xmin < 0 || xmin > ux) +// xmin = 0; +// if (xmax > int.MaxValue || xmax < ux) +// xmax = int.MaxValue; +// if (ymin < 0 || ymin > uy) +// ymin = 0; +// if (ymax > int.MaxValue || ymax < uy) +// ymax = int.MaxValue; +// +// // Check for any regions that are within the possible teleport range to the linked region +// List regions = m_GridService.GetRegionRange(m_ScopeID, (int)xmin, (int)xmax, (int)ymin, (int)ymax); +// if (regions.Count == 0) +// { +// return false; +// } +// else +// { +// // Check for regions which are not linked regions +// List hyperlinks = m_GridService.GetHyperlinks(m_ScopeID); +// IEnumerable availableRegions = regions.Except(hyperlinks); +// if (availableRegions.Count() == 0) +// return false; +// } +// +// return true; +// } private void AddHyperlinkRegion(GridRegion regionInfo, ulong regionHandle) { - RegionData rdata = m_GridService.RegionInfo2RegionData(regionInfo); int flags = (int)OpenSim.Data.RegionFlags.Hyperlink + (int)OpenSim.Data.RegionFlags.NoDirectLogin + (int)OpenSim.Data.RegionFlags.RegionOnline; rdata.Data["flags"] = flags.ToString(); m_Database.Store(rdata); - } private void RemoveHyperlinkRegion(UUID regionID) -- cgit v1.1 From 37a7c167343d90b4fb13cd4b8254801489794410 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 24 Jun 2011 21:01:48 +0100 Subject: minor: method documentation --- .../ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs index 95713e9..d52ebda 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs @@ -439,7 +439,7 @@ namespace OpenSim.Region.ClientStack.Linden } /// - /// + /// Convert raw uploaded data into the appropriate asset and item. /// /// /// @@ -506,8 +506,6 @@ namespace OpenSim.Region.ClientStack.Linden } } - - /// /// /// @@ -632,7 +630,7 @@ namespace OpenSim.Region.ClientStack.Linden } /// - /// + /// Handle raw asset upload data via the capability. /// /// /// @@ -670,6 +668,7 @@ namespace OpenSim.Region.ClientStack.Linden return res; } + ///Left this in and commented in case there are unforseen issues //private void SaveAssetToFile(string filename, byte[] data) //{ @@ -679,6 +678,7 @@ namespace OpenSim.Region.ClientStack.Linden // bw.Close(); // fs.Close(); //} + private static void SaveAssetToFile(string filename, byte[] data) { string assetPath = "UserAssets"; @@ -719,7 +719,7 @@ namespace OpenSim.Region.ClientStack.Linden } /// - /// + /// Handle raw uploaded asset data. /// /// /// @@ -752,6 +752,7 @@ namespace OpenSim.Region.ClientStack.Linden return res; } + ///Left this in and commented in case there are unforseen issues //private void SaveAssetToFile(string filename, byte[] data) //{ @@ -761,6 +762,7 @@ namespace OpenSim.Region.ClientStack.Linden // bw.Close(); // fs.Close(); //} + private static void SaveAssetToFile(string filename, byte[] data) { string assetPath = "UserAssets"; @@ -905,7 +907,7 @@ namespace OpenSim.Region.ClientStack.Linden } /// - /// + /// Handle raw uploaded baked texture data. /// /// /// -- cgit v1.1 From 75199a0d2cc3280f3ede74ad85c773527354187d Mon Sep 17 00:00:00 2001 From: BlueWall Date: Fri, 24 Jun 2011 16:20:13 -0400 Subject: RegionReady Module: Add notification to neighbors when logins are enabled. --- .../OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'OpenSim') diff --git a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs index eed6450..05c729a 100644 --- a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs @@ -36,6 +36,7 @@ using log4net; using Nini.Config; using OpenMetaverse; using OpenMetaverse.StructuredData; +using OpenSim.Services.Interfaces; using OpenSim.Framework; using OpenSim.Region.Framework.Interfaces; @@ -175,6 +176,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady m_scene.EventManager.TriggerOnChatBroadcast(this, c); m_scene.EventManager.TriggerLoginsEnabled(m_scene.RegionInfo.RegionName); + m_scene.SceneGridService.InformNeighborsThatRegionisUp(m_scene.RequestModuleInterface(), m_scene.RegionInfo); } } -- cgit v1.1 From 1a0a9d229013ff7abba17ccd95159ca7d4b47e9f Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 24 Jun 2011 21:54:01 +0100 Subject: Implement the latest mesh mechanism so that rezzing the uploaded mesh now works again. Many thanks to the aurora project for pioneering this. This code is almost certainly not bug free, but it does at least appear to handle simple meshes (except when the viewer crashes - but it is beta!). --- .../Linden/Caps/BunchOfCaps/BunchOfCaps.cs | 192 ++++++++++++++++++++- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 9 +- 2 files changed, 195 insertions(+), 6 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs index d52ebda..6786ac5 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs @@ -1,10 +1,39 @@ -using System; +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * 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; using System.Collections.Generic; using System.IO; using System.Reflection; +using System.Text; using OpenMetaverse; +using OpenMetaverse.StructuredData; using Nini.Config; using log4net; @@ -12,11 +41,14 @@ using OpenSim.Framework; using OpenSim.Framework.Capabilities; using OpenSim.Region.Framework; using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Framework.Scenes.Serialization; using OpenSim.Framework.Servers; using OpenSim.Framework.Servers.HttpServer; using OpenSim.Services.Interfaces; using Caps = OpenSim.Framework.Capabilities.Caps; +using OSDArray = OpenMetaverse.StructuredData.OSDArray; +using OSDMap = OpenMetaverse.StructuredData.OSDMap; namespace OpenSim.Region.ClientStack.Linden { @@ -79,7 +111,7 @@ namespace OpenSim.Region.ClientStack.Linden private bool m_persistBakedTextures = false; private IAssetService m_assetService; - private bool m_dumpAssetsToFile; + private bool m_dumpAssetsToFile = false; private string m_regionName; public BunchOfCaps(Scene scene, Caps caps) @@ -448,6 +480,10 @@ namespace OpenSim.Region.ClientStack.Linden UUID inventoryItem, UUID parentFolder, byte[] data, string inventoryType, string assetType) { + m_log.DebugFormat( + "Uploaded asset {0} for inventory item {1}, inv type {2}, asset type {3}", + assetID, inventoryItem, inventoryType, assetType); + sbyte assType = 0; sbyte inType = 0; @@ -474,6 +510,156 @@ namespace OpenSim.Region.ClientStack.Linden break; } } + else if (inventoryType == "object") + { + inType = (sbyte)InventoryType.Object; + assType = (sbyte)AssetType.Object; + + List positions = new List(); + List rotations = new List(); + OSDMap request = (OSDMap)OSDParser.DeserializeLLSDXml(data); + OSDArray instance_list = (OSDArray)request["instance_list"]; + OSDArray mesh_list = (OSDArray)request["mesh_list"]; + OSDArray texture_list = (OSDArray)request["texture_list"]; + SceneObjectGroup grp = null; + + List textures = new List(); + for (int i = 0; i < texture_list.Count; i++) + { + AssetBase textureAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Texture, ""); + textureAsset.Data = texture_list[i].AsBinary(); + m_assetService.Store(textureAsset); + textures.Add(textureAsset.FullID); + } + + for (int i = 0; i < mesh_list.Count; i++) + { + PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateBox(); + + Primitive.TextureEntry textureEntry + = new Primitive.TextureEntry(Primitive.TextureEntry.WHITE_TEXTURE); + OSDMap inner_instance_list = (OSDMap)instance_list[i]; + + OSDArray face_list = (OSDArray)inner_instance_list["face_list"]; + for (uint face = 0; face < face_list.Count; face++) + { + OSDMap faceMap = (OSDMap)face_list[(int)face]; + Primitive.TextureEntryFace f = pbs.Textures.CreateFace(face); + if(faceMap.ContainsKey("fullbright")) + f.Fullbright = faceMap["fullbright"].AsBoolean(); + if (faceMap.ContainsKey ("diffuse_color")) + f.RGBA = faceMap["diffuse_color"].AsColor4(); + + int textureNum = faceMap["image"].AsInteger(); + float imagerot = faceMap["imagerot"].AsInteger(); + float offsets = (float)faceMap["offsets"].AsReal(); + float offsett = (float)faceMap["offsett"].AsReal(); + float scales = (float)faceMap["scales"].AsReal(); + float scalet = (float)faceMap["scalet"].AsReal(); + + if(imagerot != 0) + f.Rotation = imagerot; + + if(offsets != 0) + f.OffsetU = offsets; + + if (offsett != 0) + f.OffsetV = offsett; + + if (scales != 0) + f.RepeatU = scales; + + if (scalet != 0) + f.RepeatV = scalet; + + if (textures.Count > textureNum) + f.TextureID = textures[textureNum]; + else + f.TextureID = Primitive.TextureEntry.WHITE_TEXTURE; + + textureEntry.FaceTextures[face] = f; + } + + pbs.TextureEntry = textureEntry.GetBytes(); + + AssetBase meshAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Mesh, ""); + meshAsset.Data = mesh_list[i].AsBinary(); + m_assetService.Store(meshAsset); + + pbs.SculptEntry = true; + pbs.SculptTexture = meshAsset.FullID; + pbs.SculptType = (byte)SculptType.Mesh; + pbs.SculptData = meshAsset.Data; + + Vector3 position = inner_instance_list["position"].AsVector3(); + Vector3 scale = inner_instance_list["scale"].AsVector3(); + Quaternion rotation = inner_instance_list["rotation"].AsQuaternion(); + +// int physicsShapeType = inner_instance_list["physics_shape_type"].AsInteger(); +// int material = inner_instance_list["material"].AsInteger(); +// int mesh = inner_instance_list["mesh"].AsInteger(); + + OSDMap permissions = (OSDMap)inner_instance_list["permissions"]; + int base_mask = permissions["base_mask"].AsInteger(); + int everyone_mask = permissions["everyone_mask"].AsInteger(); + UUID creator_id = permissions["creator_id"].AsUUID(); + UUID group_id = permissions["group_id"].AsUUID(); + int group_mask = permissions["group_mask"].AsInteger(); +// bool is_owner_group = permissions["is_owner_group"].AsBoolean(); +// UUID last_owner_id = permissions["last_owner_id"].AsUUID(); + int next_owner_mask = permissions["next_owner_mask"].AsInteger(); + UUID owner_id = permissions["owner_id"].AsUUID(); + int owner_mask = permissions["owner_mask"].AsInteger(); + + SceneObjectPart prim + = new SceneObjectPart(owner_id, pbs, position, Quaternion.Identity, Vector3.Zero); + + prim.Scale = scale; + prim.OffsetPosition = position; + rotations.Add(rotation); + positions.Add(position); + prim.UUID = UUID.Random(); + prim.CreatorID = creator_id; + prim.OwnerID = owner_id; + prim.GroupID = group_id; + prim.LastOwnerID = prim.OwnerID; + prim.CreationDate = Util.UnixTimeSinceEpoch(); + prim.Name = assetName; + prim.Description = ""; + + prim.BaseMask = (uint)base_mask; + prim.EveryoneMask = (uint)everyone_mask; + prim.GroupMask = (uint)group_mask; + prim.NextOwnerMask = (uint)next_owner_mask; + prim.OwnerMask = (uint)owner_mask; + + if (grp == null) + grp = new SceneObjectGroup(prim); + else + grp.AddPart(prim); + } + + // Fix first link number + if (grp.Parts.Length > 1) + grp.RootPart.LinkNum++; + + Vector3 rootPos = positions[0]; + grp.AbsolutePosition = rootPos; + for (int i = 0; i < positions.Count; i++) + { + Vector3 offset = positions[i] - rootPos; + grp.Parts[i].OffsetPosition = offset; + } + + for (int i = 0; i < rotations.Count; i++) + { + if (i != 0) + grp.Parts[i].RotationOffset = rotations[i]; + } + + grp.UpdateGroupRotationR(rotations[0]); + data = ASCIIEncoding.ASCII.GetBytes(SceneObjectSerializer.ToOriginalXmlFormat(grp)); + } AssetBase asset; asset = new AssetBase(assetID, assetName, assType, m_HostCapsObj.AgentID.ToString()); @@ -841,7 +1027,7 @@ namespace OpenSim.Region.ClientStack.Linden uploadComplete.new_asset = inventoryItemID; uploadComplete.compiled = errors.Count > 0 ? false : true; uploadComplete.state = "complete"; - uploadComplete.errors = new OSDArray(); + uploadComplete.errors = new OpenSim.Framework.Capabilities.OSDArray(); uploadComplete.errors.Array = errors; res = LLSDHelpers.SerialiseLLSDReply(uploadComplete); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index c6d8c73..f3879f0 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -800,7 +800,8 @@ namespace OpenSim.Region.Framework.Scenes actor.Orientation = GetWorldRotation(); // Tell the physics engines that this prim changed. - m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); + if (m_parentGroup.Scene != null) + m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); } } } @@ -1085,11 +1086,13 @@ namespace OpenSim.Region.Framework.Scenes public Vector3 AbsolutePosition { - get { + get + { if (IsAttachment) return GroupPosition; - return m_offsetPosition + m_groupPosition; } + return m_offsetPosition + m_groupPosition; + } } public SceneObjectGroup ParentGroup -- cgit v1.1 From 0dd3281caf09090e86036d67a34939b0e31c1b16 Mon Sep 17 00:00:00 2001 From: Oren Hurvitz Date: Tue, 21 Jun 2011 12:43:44 +0300 Subject: Optionally, don't delete previously compiled scripts on startup --- .../Region/ScriptEngine/Shared/CodeTools/Compiler.cs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs index 49d6abe..734d4d5 100644 --- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs +++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs @@ -106,6 +106,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools // Get some config WriteScriptSourceToDebugFile = m_scriptEngine.Config.GetBoolean("WriteScriptSourceToDebugFile", false); CompileWithDebugInformation = m_scriptEngine.Config.GetBoolean("CompileWithDebugInformation", true); + bool DeleteScriptsOnStartup = m_scriptEngine.Config.GetBoolean("DeleteScriptsOnStartup", true); // Get file prefix from scriptengine name and make it file system safe: FilePrefix = "CommonCompiler"; @@ -114,11 +115,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools FilePrefix = FilePrefix.Replace(c, '_'); } - // First time we start? Delete old files if (in_startup) { in_startup = false; - DeleteOldFiles(); + CreateScriptsDirectory(); + + // First time we start? Delete old files + if (DeleteScriptsOnStartup) + DeleteOldFiles(); } // Map name and enum type of our supported languages @@ -187,11 +191,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools } /// - /// Delete old script files + /// Create the directory where compiled scripts are stored. /// - private void DeleteOldFiles() + private void CreateScriptsDirectory() { - // CREATE FOLDER IF IT DOESNT EXIST if (!Directory.Exists(ScriptEnginesPath)) { try @@ -218,7 +221,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools m_scriptEngine.World.RegionInfo.RegionID.ToString()) + "\": " + ex.ToString()); } } + } + /// + /// Delete old script files + /// + private void DeleteOldFiles() + { foreach (string file in Directory.GetFiles(Path.Combine(ScriptEnginesPath, m_scriptEngine.World.RegionInfo.RegionID.ToString()), FilePrefix + "_compiled*")) { -- cgit v1.1 From 7545692f32a6d5326c008464dda1bd3b0ebd5a08 Mon Sep 17 00:00:00 2001 From: Makopoppo Date: Mon, 13 Jun 2011 22:09:03 +0900 Subject: Changed actual default values of 'ServiceConnectorModule' and 'MessagingModule' in [Groups] section in accordance with OpenSim.ini.example descriptions --- .../Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs | 2 +- .../Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs | 2 +- .../Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs index 2bf8489..0800e98 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs @@ -70,7 +70,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // if groups aren't enabled, we're not needed. // if we're not specified as the connector to use, then we're not wanted if ((groupsConfig.GetBoolean("Enabled", false) == false) - || (groupsConfig.GetString("MessagingModule", "Default") != Name)) + || (groupsConfig.GetString("MessagingModule", "GroupsMessagingModule") != Name)) { m_groupMessagingEnabled = false; return; diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs index 02751ea..42008da 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs @@ -200,7 +200,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // if groups aren't enabled, we're not needed. // if we're not specified as the connector to use, then we're not wanted if ((groupsConfig.GetBoolean("Enabled", false) == false) - || (groupsConfig.GetString("ServicesConnectorModule", "Default") != Name)) + || (groupsConfig.GetString("ServicesConnectorModule", "XmlRpcGroupsServicesConnector") != Name)) { m_connectorEnabled = false; return; diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs index 2631ac1..a08bcd0 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs @@ -109,7 +109,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // if groups aren't enabled, we're not needed. // if we're not specified as the connector to use, then we're not wanted if ((groupsConfig.GetBoolean("Enabled", false) == false) - || (groupsConfig.GetString("ServicesConnectorModule", "Default") != Name)) + || (groupsConfig.GetString("ServicesConnectorModule", "XmlRpcGroupsServicesConnector") != Name)) { m_connectorEnabled = false; return; -- cgit v1.1 From 56dcc5109486e6ef721f065135b8c87c3501d8e2 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 24 Jun 2011 23:54:37 +0100 Subject: Add a command "show account " to the user account service that will show the given user details --- .../UserAccountService/UserAccountService.cs | 39 +++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Services/UserAccountService/UserAccountService.cs b/OpenSim/Services/UserAccountService/UserAccountService.cs index f376cf8..3525912 100644 --- a/OpenSim/Services/UserAccountService/UserAccountService.cs +++ b/OpenSim/Services/UserAccountService/UserAccountService.cs @@ -83,9 +83,16 @@ namespace OpenSim.Services.UserAccountService "create user", "create user [ [ [ []]]]", "Create a new user", HandleCreateUser); - MainConsole.Instance.Commands.AddCommand("UserService", false, "reset user password", + + MainConsole.Instance.Commands.AddCommand("UserService", false, + "reset user password", "reset user password [ [ []]]", "Reset a user password", HandleResetUserPassword); + + MainConsole.Instance.Commands.AddCommand("UserService", false, + "show account", + "show account ", + "Show account details for the given user", HandleShowAccount); } } @@ -318,6 +325,36 @@ namespace OpenSim.Services.UserAccountService CreateUser(firstName, lastName, password, email); } + protected void HandleShowAccount(string module, string[] cmdparams) + { + if (cmdparams.Length != 4) + { + MainConsole.Instance.Output("Usage: show account "); + return; + } + + string firstName = cmdparams[2]; + string lastName = cmdparams[3]; + + UserAccount ua = GetUserAccount(UUID.Zero, firstName, lastName); + + if (ua == null) + { + MainConsole.Instance.OutputFormat("No user named {0} {1}", firstName, lastName); + return; + } + + MainConsole.Instance.OutputFormat("Name: {0}", ua.Name); + MainConsole.Instance.OutputFormat("ID: {0}", ua.PrincipalID); + MainConsole.Instance.OutputFormat("Title: {0}", ua.UserTitle); + MainConsole.Instance.OutputFormat("E-mail: {0}", ua.Email); + MainConsole.Instance.OutputFormat("Created: {0}", Utils.UnixTimeToDateTime(ua.Created)); + MainConsole.Instance.OutputFormat("Level: {0}", ua.UserLevel); + MainConsole.Instance.OutputFormat("Flags: {0}", ua.UserFlags); + foreach (KeyValuePair kvp in ua.ServiceURLs) + MainConsole.Instance.OutputFormat("{0}: {1}", kvp.Key, kvp.Value); + } + protected void HandleResetUserPassword(string module, string[] cmdparams) { string firstName; -- cgit v1.1 From 296774495b8544cbb3463e0a0694d7de910a5d7c Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 25 Jun 2011 00:03:34 +0100 Subject: Implement "set user level" console command to set the user level (which determines whether a user has a god account) Adapted from Makopoppo's patch in http://opensimulator.org/mantis/view.php?id=5552. Thanks! --- .../UserAccountService/UserAccountService.cs | 47 ++++++++++++++++++++++ 1 file changed, 47 insertions(+) (limited to 'OpenSim') diff --git a/OpenSim/Services/UserAccountService/UserAccountService.cs b/OpenSim/Services/UserAccountService/UserAccountService.cs index 3525912..a65c04b 100644 --- a/OpenSim/Services/UserAccountService/UserAccountService.cs +++ b/OpenSim/Services/UserAccountService/UserAccountService.cs @@ -90,6 +90,14 @@ namespace OpenSim.Services.UserAccountService "Reset a user password", HandleResetUserPassword); MainConsole.Instance.Commands.AddCommand("UserService", false, + "set user level", + "set user level [ [ []]]", + "Set user level. If >= 200 and 'allow_grid_gods = true' in OpenSim.ini, " + + "this account will be treated as god-moded. " + + "It will also affect the 'login level' command. ", + HandleSetUserLevel); + + MainConsole.Instance.Commands.AddCommand("UserService", false, "show account", "show account ", "Show account details for the given user", HandleShowAccount); @@ -387,6 +395,45 @@ namespace OpenSim.Services.UserAccountService m_log.InfoFormat("[USER ACCOUNT SERVICE]: Password reset for user {0} {1}", firstName, lastName); } + protected void HandleSetUserLevel(string module, string[] cmdparams) + { + string firstName; + string lastName; + string rawLevel; + int level; + + if (cmdparams.Length < 4) + firstName = MainConsole.Instance.CmdPrompt("First name"); + else firstName = cmdparams[3]; + + if (cmdparams.Length < 5) + lastName = MainConsole.Instance.CmdPrompt("Last name"); + else lastName = cmdparams[4]; + + UserAccount account = GetUserAccount(UUID.Zero, firstName, lastName); + if (account == null) { + MainConsole.Instance.OutputFormat("No such user"); + return; + } + + if (cmdparams.Length < 6) + rawLevel = MainConsole.Instance.CmdPrompt("User level"); + else rawLevel = cmdparams[5]; + + if(int.TryParse(rawLevel, out level) == false) { + MainConsole.Instance.OutputFormat("Invalid user level"); + return; + } + + account.UserLevel = level; + + bool success = StoreUserAccount(account); + if (!success) + MainConsole.Instance.OutputFormat("Unable to set user level for account {0} {1}.", firstName, lastName); + else + MainConsole.Instance.OutputFormat("User level set for user {0} {1} to {2}", firstName, lastName, level); + } + #endregion /// -- cgit v1.1 From 5daac0584aed1a6764060b6c6a0a1f74360859f1 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 25 Jun 2011 00:08:14 +0100 Subject: Fix bug in reset user password where entering an invalid name would cause an exception. Also, convert this commands log output to console output. Console output is more appropriate for console commands. The log only gets one side of the conversation anyway (since it doesn't necessarily record command inputs). --- OpenSim/Services/UserAccountService/UserAccountService.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Services/UserAccountService/UserAccountService.cs b/OpenSim/Services/UserAccountService/UserAccountService.cs index a65c04b..8b8a8f9 100644 --- a/OpenSim/Services/UserAccountService/UserAccountService.cs +++ b/OpenSim/Services/UserAccountService/UserAccountService.cs @@ -383,16 +383,19 @@ namespace OpenSim.Services.UserAccountService UserAccount account = GetUserAccount(UUID.Zero, firstName, lastName); if (account == null) - m_log.ErrorFormat("[USER ACCOUNT SERVICE]: No such user"); + { + MainConsole.Instance.OutputFormat("No such user as {0} {1}", firstName, lastName); + return; + } bool success = false; if (m_AuthenticationService != null) success = m_AuthenticationService.SetPassword(account.PrincipalID, newPassword); + if (!success) - m_log.ErrorFormat("[USER ACCOUNT SERVICE]: Unable to reset password for account {0} {1}.", - firstName, lastName); + MainConsole.Instance.OutputFormat("Unable to reset password for account {0} {1}.", firstName, lastName); else - m_log.InfoFormat("[USER ACCOUNT SERVICE]: Password reset for user {0} {1}", firstName, lastName); + MainConsole.Instance.OutputFormat("Password reset for user {0} {1}", firstName, lastName); } protected void HandleSetUserLevel(string module, string[] cmdparams) -- cgit v1.1 From 36e205476073d1b93b8adf37ab995410f8664273 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 27 Jun 2011 23:12:54 +0100 Subject: minor: temporarily comment out the local status notify friends messages seen on login/logout, since it's a bit noisy on the console. Please uncomment if/when this is still needed. --- OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index daee4ca..3a7178c 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs @@ -830,7 +830,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends public bool LocalStatusNotification(UUID userID, UUID friendID, bool online) { - m_log.DebugFormat("[FRIENDS]: Local Status Notify {0} that user {1} is {2}", friendID, userID, online); +// m_log.DebugFormat("[FRIENDS]: Local Status Notify {0} that user {1} is {2}", friendID, userID, online); IClientAPI friendClient = LocateClientObject(friendID); if (friendClient != null) { -- cgit v1.1 From 882d5c82b308a95c4897893d2b8e6b816f827d31 Mon Sep 17 00:00:00 2001 From: Makopoppo Date: Fri, 24 Jun 2011 19:40:21 +0900 Subject: [PATCH 1/2] Fixed the function names of some OSSL functions shown as threat-level check error message Signed-off-by: BlueWall --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 64931d0..201fef4 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -970,7 +970,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public string osDrawPolygon(string drawList, LSL_List x, LSL_List y) { - CheckThreatLevel(ThreatLevel.None, "osDrawFilledPolygon"); + CheckThreatLevel(ThreatLevel.None, "osDrawPolygon"); m_host.AddScriptLPS(1); @@ -1409,7 +1409,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { // What actually is the difference to the LL function? // - CheckThreatLevel(ThreatLevel.VeryLow, "osSetParcelMediaURL"); + CheckThreatLevel(ThreatLevel.VeryLow, "osSetParcelSIPAddress"); m_host.AddScriptLPS(1); @@ -2301,7 +2301,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osSetPrimitiveParams(LSL_Key prim, LSL_List rules) { - CheckThreatLevel(ThreatLevel.High, "osGetPrimitiveParams"); + CheckThreatLevel(ThreatLevel.High, "osSetPrimitiveParams"); m_host.AddScriptLPS(1); m_LSL_Api.SetPrimitiveParamsEx(prim, rules); -- cgit v1.1 From ffa790d69d4e9b1b50470f84b0ad198098dc2736 Mon Sep 17 00:00:00 2001 From: Makopoppo Date: Mon, 27 Jun 2011 19:30:42 +0900 Subject: [PATCH] Get osGetWindParam() and osSetWindParam() accessible Signed-off-by: BlueWall --- .../Shared/Api/Implementation/OSSL_Api.cs | 6 +++--- .../ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs | 4 ++-- .../ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs | 19 +++++++++---------- 3 files changed, 14 insertions(+), 15 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 201fef4..f32ecca 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -1241,7 +1241,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return String.Empty; } - public void osSetWindParam(string plugin, string param, float value) + public void osSetWindParam(string plugin, string param, LSL_Float value) { CheckThreatLevel(ThreatLevel.VeryLow, "osSetWindParam"); m_host.AddScriptLPS(1); @@ -1251,13 +1251,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { try { - module.WindParamSet(plugin, param, value); + module.WindParamSet(plugin, param, (float)value); } catch (Exception) { } } } - public float osGetWindParam(string plugin, string param) + public LSL_Float osGetWindParam(string plugin, string param) { CheckThreatLevel(ThreatLevel.VeryLow, "osGetWindParam"); m_host.AddScriptLPS(1); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs index 63007c6..7227b40 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs @@ -129,8 +129,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces // Wind Module Functions string osWindActiveModelPluginName(); - void osSetWindParam(string plugin, string param, float value); - float osGetWindParam(string plugin, string param); + void osSetWindParam(string plugin, string param, LSL_Float value); + LSL_Float osGetWindParam(string plugin, string param); // Parcel commands void osParcelJoin(vector pos1, vector pos2); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs index e3ea556..f5bdc68 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs @@ -106,16 +106,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase return m_OSSL_Functions.osWindActiveModelPluginName(); } -// Not yet plugged in as available OSSL functions, so commented out -// void osSetWindParam(string plugin, string param, float value) -// { -// m_OSSL_Functions.osSetWindParam(plugin, param, value); -// } -// -// float osGetWindParam(string plugin, string param) -// { -// return m_OSSL_Functions.osGetWindParam(plugin, param); -// } + public void osSetWindParam(string plugin, string param, LSL_Float value) + { + m_OSSL_Functions.osSetWindParam(plugin, param, value); + } + + public LSL_Float osGetWindParam(string plugin, string param) + { + return m_OSSL_Functions.osGetWindParam(plugin, param); + } public void osParcelJoin(vector pos1, vector pos2) { -- cgit v1.1 From 80010f89085af9517e26af01dfe7cbc99788aa31 Mon Sep 17 00:00:00 2001 From: Makopoppo Date: Tue, 28 Jun 2011 22:21:53 +0900 Subject: [PATCH] osSetSpeed() will accept float number Signed-off-by: BlueWall --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs | 4 ++-- OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs | 2 +- OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index f32ecca..b098f09 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -2209,12 +2209,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return (int)pws; } - public void osSetSpeed(string UUID, float SpeedModifier) + public void osSetSpeed(string UUID, LSL_Float SpeedModifier) { CheckThreatLevel(ThreatLevel.Moderate, "osSetSpeed"); m_host.AddScriptLPS(1); ScenePresence avatar = World.GetScenePresence(new UUID(UUID)); - avatar.SpeedModifier = SpeedModifier; + avatar.SpeedModifier = (float)SpeedModifier; } public void osKickAvatar(string FirstName,string SurName,string alert) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs index 7227b40..19352f0 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs @@ -180,7 +180,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces int osGetSimulatorMemory(); void osKickAvatar(string FirstName,string SurName,string alert); - void osSetSpeed(string UUID, float SpeedModifier); + void osSetSpeed(string UUID, LSL_Float SpeedModifier); void osCauseHealing(string avatar, double healing); void osCauseDamage(string avatar, double damage); LSL_List osGetPrimitiveParams(LSL_Key prim, LSL_List rules); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs index f5bdc68..7c59098 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs @@ -713,7 +713,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase m_OSSL_Functions.osKickAvatar(FirstName, SurName, alert); } - public void osSetSpeed(string UUID, float SpeedModifier) + public void osSetSpeed(string UUID, LSL_Float SpeedModifier) { m_OSSL_Functions.osSetSpeed(UUID, SpeedModifier); } -- cgit v1.1 From ee92f22f2ab9a1f2926ac3a9d4e1b9c26945d898 Mon Sep 17 00:00:00 2001 From: Makopoppo Date: Sat, 25 Jun 2011 11:13:55 +0900 Subject: [PATCH 2/2] [FIX] osGetPrimitiveParams() and osSetPrimitiveParams() crashes throwing System.NullReferenceException Signed-off-by: BlueWall --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'OpenSim') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index b098f09..963727d 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -2295,6 +2295,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { CheckThreatLevel(ThreatLevel.High, "osGetPrimitiveParams"); m_host.AddScriptLPS(1); + InitLSL(); return m_LSL_Api.GetLinkPrimitiveParamsEx(prim, rules); } @@ -2303,6 +2304,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { CheckThreatLevel(ThreatLevel.High, "osSetPrimitiveParams"); m_host.AddScriptLPS(1); + InitLSL(); m_LSL_Api.SetPrimitiveParamsEx(prim, rules); } -- cgit v1.1 From 22f25fae387a801e8545f6ab6e2c9700926ae6e4 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 29 Jun 2011 00:28:22 +0100 Subject: Hack around with the NPC module to get osNpcCreate() partially working again. This now creates an avatar but appearance is always cloudy. Move doesn't work. Really, creating an NPC should only involve a ScenePresence rather than doing anything with IClientAPI, since an NPC has no viewer to communicate with! --- .../Avatar/AvatarFactory/AvatarFactoryModule.cs | 4 +- .../UserManagement/UserManagementModule.cs | 3 +- .../Region/Framework/Interfaces/IAvatarFactory.cs | 2 +- OpenSim/Region/Framework/Scenes/Scene.cs | 4 +- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 6 +- .../Avatar/Appearance/AppearanceInfoModule.cs | 2 +- .../Region/OptionalModules/World/NPC/NPCModule.cs | 107 ++++++++++++++------- 7 files changed, 85 insertions(+), 43 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index e92f072..d02a305 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs @@ -162,12 +162,12 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory // one and we're done otherwise, ask for a rebake if (checkonly) return false; - m_log.InfoFormat("[AVFACTORY]: missing baked texture {0}, requesting rebake",face.TextureID); + m_log.InfoFormat("[AVFACTORY]: missing baked texture {0}, requesting rebake", face.TextureID); client.SendRebakeAvatarTextures(face.TextureID); } } - m_log.DebugFormat("[AVFACTORY]: completed texture check for {0}", client.AgentId); + m_log.DebugFormat("[AVFACTORY]: Completed texture check for {0}", client.AgentId); // If we only found default textures, then the appearance is not cached return (defonly ? false : true); diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs index accd094..a4861ec 100644 --- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs +++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs @@ -297,9 +297,10 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement if (m_UserCache.ContainsKey(id)) return; +// m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, craetorData {1}", id, creatorData); + UserData user = new UserData(); user.Id = id; - UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, id); if (account != null) diff --git a/OpenSim/Region/Framework/Interfaces/IAvatarFactory.cs b/OpenSim/Region/Framework/Interfaces/IAvatarFactory.cs index 22795fc..d0e5609 100644 --- a/OpenSim/Region/Framework/Interfaces/IAvatarFactory.cs +++ b/OpenSim/Region/Framework/Interfaces/IAvatarFactory.cs @@ -36,4 +36,4 @@ namespace OpenSim.Region.Framework.Interfaces void QueueAppearanceSend(UUID agentid); void QueueAppearanceSave(UUID agentid); } -} +} \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index bdf3d1d..ad41e88 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2593,8 +2593,10 @@ namespace OpenSim.Region.Framework.Scenes { string homeURL = string.Empty; string first = aCircuit.firstname, last = aCircuit.lastname; + if (aCircuit.ServiceURLs.ContainsKey("HomeURI")) homeURL = aCircuit.ServiceURLs["HomeURI"].ToString(); + if (aCircuit.lastname.StartsWith("@")) { string[] parts = aCircuit.firstname.Split('.'); @@ -2604,6 +2606,7 @@ namespace OpenSim.Region.Framework.Scenes last = parts[1]; } } + uMan.AddUser(aCircuit.AgentID, first, last, homeURL); } } @@ -3389,7 +3392,6 @@ namespace OpenSim.Region.Framework.Scenes } } - // In all cases, add or update the circuit data with the new agent circuit data and teleport flags agent.teleportFlags = teleportFlags; m_authenticateHandler.AddNewCircuit(agent.circuitcode, agent); diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 80aafd0..83b761c 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -1944,10 +1944,9 @@ namespace OpenSim.Region.Framework.Scenes m_log.Warn("Sit requested on unknown object: " + targetID.ToString()); } - - SendSitResponse(remoteClient, targetID, offset, Quaternion.Identity); } + /* public void SitRayCastAvatarPosition(SceneObjectPart part) { @@ -2380,7 +2379,6 @@ namespace OpenSim.Region.Framework.Scenes /// public void SendTerseUpdateToClient(IClientAPI remoteClient) { - // If the client is inactive, it's getting its updates from another // server. if (remoteClient.IsActive) @@ -2495,7 +2493,7 @@ namespace OpenSim.Region.Framework.Scenes } // If we aren't using a cached appearance, then clear out the baked textures - if (! cachedappearance) + if (!cachedappearance) { m_appearance.ResetAppearance(); if (m_scene.AvatarFactory != null) diff --git a/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs b/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs index 7304145..77e7acf 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs @@ -113,7 +113,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance { bool bakedTextureValid = scene.AvatarFactory.ValidateBakedTextureCache(client); MainConsole.Instance.OutputFormat( - "{0} baked apperance texture is {1}", client.Name, bakedTextureValid ? "OK" : "corrupt"); + "{0} baked appearance texture is {1}", client.Name, bakedTextureValid ? "OK" : "corrupt"); } }); } diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs index c471636..48d236f 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs @@ -25,10 +25,13 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +using System; using System.Collections.Generic; +using System.Reflection; using System.Threading; -using OpenMetaverse; +using log4net; using Nini.Config; +using OpenMetaverse; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.CoreModules.Avatar.NPC; @@ -40,6 +43,8 @@ namespace OpenSim.Region.OptionalModules.World.NPC { public class NPCModule : IRegionModule, INPCModule { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + // private const bool m_enabled = false; private Mutex m_createMutex; @@ -59,6 +64,17 @@ namespace OpenSim.Region.OptionalModules.World.NPC private UUID p_cloneAppearanceFrom; private UUID p_returnUuid; + public void Initialise(Scene scene, IConfigSource source) + { + m_createMutex = new Mutex(false); + + m_timer = new Timer(500); + m_timer.Elapsed += m_timer_Elapsed; + m_timer.Start(); + + scene.RegisterModuleInterface(this); + } + private AvatarAppearance GetAppearance(UUID target, Scene scene) { if (m_appearanceCache.ContainsKey(target)) @@ -76,6 +92,10 @@ namespace OpenSim.Region.OptionalModules.World.NPC public UUID CreateNPC(string firstname, string lastname,Vector3 position, Scene scene, UUID cloneAppearanceFrom) { + m_log.DebugFormat( + "[NPC MODULE]: Queueing request to create NPC {0} {1} at {2} in {3} cloning appearance of {4}", + firstname, lastname, position, scene.RegionInfo.RegionName, cloneAppearanceFrom); + // Block. m_createMutex.WaitOne(); @@ -137,46 +157,67 @@ namespace OpenSim.Region.OptionalModules.World.NPC } } - - public void Initialise(Scene scene, IConfigSource source) - { - m_createMutex = new Mutex(false); - - m_timer = new Timer(500); - m_timer.Elapsed += m_timer_Elapsed; - m_timer.Start(); - - scene.RegisterModuleInterface(this); - } - void m_timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { - lock (p_lock) + try { - if (p_inUse) + lock (p_lock) { - p_inUse = false; - - NPCAvatar npcAvatar = new NPCAvatar(p_firstname, p_lastname, p_position, p_scene); - npcAvatar.CircuitCode = (uint) Util.RandomClass.Next(0, int.MaxValue); - - p_scene.AddNewClient(npcAvatar); - - ScenePresence sp; - if (p_scene.TryGetScenePresence(npcAvatar.AgentId, out sp)) + if (p_inUse) { - AvatarAppearance x = GetAppearance(p_cloneAppearanceFrom, p_scene); - - sp.Appearance.SetTextureEntries(x.Texture); - sp.Appearance.SetVisualParams((byte[])x.VisualParams.Clone()); - sp.SendAppearanceToAllOtherAgents(); + p_inUse = false; + + NPCAvatar npcAvatar = new NPCAvatar(p_firstname, p_lastname, p_position, p_scene); + npcAvatar.CircuitCode = (uint) Util.RandomClass.Next(0, int.MaxValue); + + m_log.DebugFormat( + "[NPC MODULE]: Creating NPC {0} {1} {2} at {3} in {4}", + p_firstname, p_lastname, npcAvatar.AgentId, p_position, p_scene.RegionInfo.RegionName); + + AgentCircuitData acd = new AgentCircuitData(); + acd.AgentID = npcAvatar.AgentId; + acd.firstname = p_firstname; + acd.lastname = p_lastname; + acd.ServiceURLs = new Dictionary(); + + AvatarAppearance originalAppearance = GetAppearance(p_cloneAppearanceFrom, p_scene); + AvatarAppearance npcAppearance = new AvatarAppearance(originalAppearance, true); + acd.Appearance = npcAppearance; + + p_scene.AuthenticateHandler.AddNewCircuit(npcAvatar.CircuitCode, acd); + p_scene.AddNewClient(npcAvatar); + + ScenePresence sp; + if (p_scene.TryGetScenePresence(npcAvatar.AgentId, out sp)) + { + m_log.DebugFormat( + "[NPC MODULE]: Successfully retrieved scene presence for NPC {0} {1}", sp.Name, sp.UUID); + + // Shouldn't call this - temporary. + sp.CompleteMovement(npcAvatar); + + // sp.SendAppearanceToAllOtherAgents(); + // + // // Send animations back to the avatar as well + // sp.Animator.SendAnimPack(); + } + else + { + m_log.WarnFormat("[NPC MODULE]: Could not find scene presence for NPC {0} {1}", sp.Name, sp.UUID); + } + + m_avatars.Add(npcAvatar.AgentId, npcAvatar); + + p_returnUuid = npcAvatar.AgentId; + + m_log.DebugFormat("[NPC MODULE]: Created NPC with id {0}", p_returnUuid); } - - m_avatars.Add(npcAvatar.AgentId, npcAvatar); - - p_returnUuid = npcAvatar.AgentId; } } + catch (Exception ex) + { + m_log.ErrorFormat("[NPC MODULE]: NPC creation failed with exception {0} {1}", ex.Message, ex.StackTrace); + } } public void PostInitialise() -- cgit v1.1 From 3f0b8db0c18afaa44fa2f6b453d60bec34a3cd98 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 29 Jun 2011 00:54:31 +0100 Subject: If an inventory link target is in the same folder as the source, then don't recursively request that folder. Currently, this should never actually happen but certainly best to handle this case --- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index f37f94a..8453d35 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1341,7 +1341,12 @@ namespace OpenSim.Region.Framework.Scenes // Take care of genuinely broken links where the target doesn't exist if (linkedItem != null) - linkedItemFolderIdsToSend.Add(linkedItem.Folder); + { + // We don't need to send the folder if source and destination of the link are in the same + // folder. + if (linkedItem.Folder != containingFolder.ID) + linkedItemFolderIdsToSend.Add(linkedItem.Folder); + } } } -- cgit v1.1 From 1b4c08730e068a6554befda6af728eeeea174830 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 29 Jun 2011 00:56:35 +0100 Subject: refactor: simplify redundant double containing folder check --- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 8453d35..07507b2 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1328,7 +1328,7 @@ namespace OpenSim.Region.Framework.Scenes // m_log.DebugFormat("[AGENT INVENTORY]: Sending inventory folder contents ({0} nodes) for \"{1}\" to {2} {3}", // contents.Folders.Count + contents.Items.Count, containingFolder.Name, client.FirstName, client.LastName); - if (containingFolder != null && containingFolder != null) + if (containingFolder != null) { // If the folder requested contains links, then we need to send those folders first, otherwise the links // will be broken in the viewer. @@ -1353,7 +1353,9 @@ namespace OpenSim.Region.Framework.Scenes foreach (UUID linkedItemFolderId in linkedItemFolderIdsToSend) SendInventoryUpdate(client, new InventoryFolderBase(linkedItemFolderId), false, true); - client.SendInventoryFolderDetails(client.AgentId, folder.ID, contents.Items, contents.Folders, containingFolder.Version, fetchFolders, fetchItems); + client.SendInventoryFolderDetails( + client.AgentId, folder.ID, contents.Items, contents.Folders, + containingFolder.Version, fetchFolders, fetchItems); } } -- cgit v1.1 From c84a1bd99f5f37e371135d7c3a7121841c778864 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 29 Jun 2011 01:33:41 +0100 Subject: Don't follow inventory links of links. This is to avoid problems with corrupt inventories where an inventory link target points back at the source's folder No viewer has been observed to set these up as of yet. If this ever happens, we will need a more sophisticated solution to track sent folders within the recursion --- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 07507b2..13085e3 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1340,7 +1340,10 @@ namespace OpenSim.Region.Framework.Scenes InventoryItemBase linkedItem = InventoryService.GetItem(new InventoryItemBase(item.AssetID)); // Take care of genuinely broken links where the target doesn't exist - if (linkedItem != null) + // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate, + // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles + // rather than having to keep track of every folder requested in the recursion. + if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link) { // We don't need to send the folder if source and destination of the link are in the same // folder. -- cgit v1.1 From 5c18ebf42470038720dffcf676bf3f9dd174d443 Mon Sep 17 00:00:00 2001 From: dahlia Date: Wed, 29 Jun 2011 17:36:41 -0700 Subject: Allow physics proxy generation for meshes using new asset format. Fix an invalid cast exception while decoding new mesh asset format. --- OpenSim/Region/Physics/Meshing/Meshmerizer.cs | 21 +++++++++++++++++---- OpenSim/Region/Physics/OdePlugin/OdePlugin.cs | 5 ++++- 2 files changed, 21 insertions(+), 5 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index 99b2d84..a5fe45b 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs @@ -291,7 +291,14 @@ namespace OpenSim.Region.Physics.Meshing { try { - meshOsd = (OSDMap)OSDParser.DeserializeLLSDBinary(data); + OSD osd = OSDParser.DeserializeLLSDBinary(data); + if (osd is OSDMap) + meshOsd = (OSDMap)osd; + else + { + m_log.Warn("[Mesh}: unable to cast mesh asset to OSDMap"); + return null; + } } catch (Exception e) { @@ -302,11 +309,17 @@ namespace OpenSim.Region.Physics.Meshing if (meshOsd is OSDMap) { + OSDMap physicsParms = null; OSDMap map = (OSDMap)meshOsd; - OSDMap physicsParms = (OSDMap)map["physics_shape"]; // old asset format - - if (physicsParms.Count == 0) + if (map.ContainsKey("physics_shape")) + physicsParms = (OSDMap)map["physics_shape"]; // old asset format + else if (map.ContainsKey("physics_mesh")) physicsParms = (OSDMap)map["physics_mesh"]; // new asset format + if (physicsParms == null) + { + m_log.Warn("[Mesh]: no recognized physics mesh found in mesh asset"); + return null; + } int physOffset = physicsParms["offset"].AsInteger() + (int)start; int physSize = physicsParms["size"].AsInteger(); diff --git a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs index a0101af..8d9f5f1 100644 --- a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs +++ b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs @@ -2502,7 +2502,7 @@ namespace OpenSim.Region.Physics.OdePlugin } // if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since ODE can use an internal representation for the prim - if (!forceSimplePrimMeshing) + if (!forceSimplePrimMeshing && !pbs.SculptEntry) { if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 @@ -2592,6 +2592,9 @@ namespace OpenSim.Region.Physics.OdePlugin } } + if (pbs.SculptEntry && meshSculptedPrim) + iPropertiesNotSupportedDefault++; + if (iPropertiesNotSupportedDefault == 0) { -- cgit v1.1 From 9f72fbcb7533bd960c38082cbd6956cd01fa6919 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 1 Jul 2011 21:25:40 +0100 Subject: Add an async inventory details sender to respond to FetchInventory packets. If a user with a very large inventory right-clicks on their "My Inventory" folder, viewer 1 code will send a massive number of Fetchinventory requests. Even though each is handled asynchronously via a pool thread, the sheer frequency of requests overwhelms the pool and freezes inbound packet handling. This change makes the first Fetchinventory thread also handle subsequent requests, freeing up the other threads. Further efficiencies could be made by handling all the items in a particular FetchInventory request together, rather than separately. --- OpenSim/Framework/IClientAPI.cs | 2 +- .../Framework/Scenes/AsyncInventorySender.cs | 156 +++++++++++++++++++++ OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 5 + .../Framework/Scenes/Scene.PacketHandlers.cs | 25 ---- OpenSim/Region/Framework/Scenes/Scene.cs | 5 +- 5 files changed, 165 insertions(+), 28 deletions(-) create mode 100644 OpenSim/Region/Framework/Scenes/AsyncInventorySender.cs (limited to 'OpenSim') diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 659d42f..f6e2977 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -737,7 +737,7 @@ namespace OpenSim.Framework bool IsActive { get; set; } /// - /// Determines whether the client is logging out or not. + /// Determines whether the client is or has been removed from a given scene /// bool IsLoggingOut { get; set; } diff --git a/OpenSim/Region/Framework/Scenes/AsyncInventorySender.cs b/OpenSim/Region/Framework/Scenes/AsyncInventorySender.cs new file mode 100644 index 0000000..06cd14b --- /dev/null +++ b/OpenSim/Region/Framework/Scenes/AsyncInventorySender.cs @@ -0,0 +1,156 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * 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.Reflection; +using System.Threading; +using log4net; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; + +namespace OpenSim.Region.Framework.Scenes +{ + class FetchHolder + { + public IClientAPI Client { get; private set; } + public UUID ItemID { get; private set; } + + public FetchHolder(IClientAPI client, UUID itemID) + { + Client = client; + ItemID = itemID; + } + } + + /// + /// Send FetchInventoryReply information to clients asynchronously on a single thread rather than asynchronously via + /// multiple threads. + /// + /// + /// If the main root inventory is right-clicked on a version 1 viewer for a user with a large inventory, a very + /// very large number of FetchInventory requests are sent to the simulator. Each is handled on a separate thread + /// by the IClientAPI, but the sheer number of requests overwhelms the number of threads available and ends up + /// freezing the inbound packet handling. + /// + /// This class makes the first FetchInventory packet thread process the queue. If new requests come + /// in while it is processing, then the subsequent threads just add the requests and leave it to the original + /// thread to process them. + /// + /// This might slow down outbound packets but these are limited by the IClientAPI outbound queues + /// anyway. + /// + /// It might be possible to ignore FetchInventory requests altogether, particularly as they are redundant wrt to + /// FetchInventoryDescendents requests, but this would require more investigation. + /// + public class AsyncInventorySender + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + protected Scene m_scene; + + /// + /// Queues fetch requests + /// + Queue m_fetchHolder = new Queue(); + + /// + /// Signal whether a queue is currently being processed or not. + /// + protected volatile bool m_processing; + + public AsyncInventorySender(Scene scene) + { + m_processing = false; + m_scene = scene; + } + + /// + /// Handle a fetch inventory request from the client + /// + /// + /// + /// + public void HandleFetchInventory(IClientAPI remoteClient, UUID itemID, UUID ownerID) + { + lock (m_fetchHolder) + { +// m_log.DebugFormat( +// "[ASYNC INVENTORY SENDER]: Putting request from {0} for {1} on queue", remoteClient.Name, itemID); + + m_fetchHolder.Enqueue(new FetchHolder(remoteClient, itemID)); + } + + if (!m_processing) + { + m_processing = true; + ProcessQueue(); + } + } + + /// + /// Process the queue of fetches + /// + protected void ProcessQueue() + { + FetchHolder fh = null; + + while (true) + { + lock (m_fetchHolder) + { +// m_log.DebugFormat("[ASYNC INVENTORY SENDER]: {0} items left to process", m_fetchHolder.Count); + + if (m_fetchHolder.Count == 0) + { + m_processing = false; + return; + } + else + { + fh = m_fetchHolder.Dequeue(); + } + } + + if (fh.Client.IsLoggingOut) + continue; + +// m_log.DebugFormat( +// "[ASYNC INVENTORY SENDER]: Handling request from {0} for {1} on queue", fh.Client.Name, fh.ItemID); + + InventoryItemBase item = new InventoryItemBase(fh.ItemID, fh.Client.AgentId); + item = m_scene.InventoryService.GetItem(item); + + if (item != null) + fh.Client.SendInventoryItemDetails(item.Owner, item); + + // TODO: Possibly log any failure + } + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 13085e3..30421d4 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -52,6 +52,11 @@ namespace OpenSim.Region.Framework.Scenes protected AsyncSceneObjectGroupDeleter m_asyncSceneObjectDeleter; /// + /// Allows inventory details to be sent to clients asynchronously + /// + protected AsyncInventorySender m_asyncInventorySender; + + /// /// Start all the scripts in the scene which should be started. /// public void CreateScriptInstances() diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs index e2d7208..44472b2 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs @@ -461,31 +461,6 @@ namespace OpenSim.Region.Framework.Scenes } ); } - - - /// - /// Handle a fetch inventory request from the client - /// - /// - /// - /// - public void HandleFetchInventory(IClientAPI remoteClient, UUID itemID, UUID ownerID) - { - if (LibraryService != null && LibraryService.LibraryRootFolder != null && ownerID == LibraryService.LibraryRootFolder.Owner) - { - //m_log.Debug("request info for library item"); - return; - } - - InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); - item = InventoryService.GetItem(item); - - if (item != null) - { - remoteClient.SendInventoryItemDetails(ownerID, item); - } - // else shouldn't we send an alert message? - } /// /// Tell the client about the various child items and folders contained in the requested folder. diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index ad41e88..eeb881f 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -583,6 +583,8 @@ namespace OpenSim.Region.Framework.Scenes m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this); m_asyncSceneObjectDeleter.Enabled = true; + m_asyncInventorySender = new AsyncInventorySender(this); + #region Region Settings // Load region settings @@ -2760,14 +2762,13 @@ namespace OpenSim.Region.Framework.Scenes public virtual void SubscribeToClientInventoryEvents(IClientAPI client) { - client.OnLinkInventoryItem += HandleLinkInventoryItem; client.OnCreateNewInventoryFolder += HandleCreateInventoryFolder; client.OnUpdateInventoryFolder += HandleUpdateInventoryFolder; client.OnMoveInventoryFolder += HandleMoveInventoryFolder; // 2; //!! client.OnFetchInventoryDescendents += HandleFetchInventoryDescendents; client.OnPurgeInventoryDescendents += HandlePurgeInventoryDescendents; // 2; //!! - client.OnFetchInventory += HandleFetchInventory; + client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory; client.OnUpdateInventoryItem += UpdateInventoryItemAsset; client.OnCopyInventoryItem += CopyInventoryItem; client.OnMoveInventoryItem += MoveInventoryItem; -- cgit v1.1 From e41093635aa9861e9115c8331b0cf27c0507fef3 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 1 Jul 2011 21:37:03 +0100 Subject: fix build break I just introduced --- OpenSim/Region/Framework/Scenes/Scene.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index eeb881f..ec6044b 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2887,13 +2887,12 @@ namespace OpenSim.Region.Framework.Scenes public virtual void UnSubscribeToClientInventoryEvents(IClientAPI client) { - client.OnCreateNewInventoryFolder -= HandleCreateInventoryFolder; client.OnUpdateInventoryFolder -= HandleUpdateInventoryFolder; client.OnMoveInventoryFolder -= HandleMoveInventoryFolder; // 2; //!! client.OnFetchInventoryDescendents -= HandleFetchInventoryDescendents; client.OnPurgeInventoryDescendents -= HandlePurgeInventoryDescendents; // 2; //!! - client.OnFetchInventory -= HandleFetchInventory; + client.OnFetchInventory -= m_asyncInventorySender.HandleFetchInventory; client.OnUpdateInventoryItem -= UpdateInventoryItemAsset; client.OnCopyInventoryItem -= CopyInventoryItem; client.OnMoveInventoryItem -= MoveInventoryItem; -- cgit v1.1 From 759e855566a08d965059ca08d4f4510d335f1c7d Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 1 Jul 2011 21:47:30 +0100 Subject: refactor: rename gitCommitFileName to manualVersionFileName since bin/.version doesn't necessary have to be a git hash --- OpenSim/Framework/Servers/BaseOpenSimServer.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs index 21e1e09..98a92dd 100644 --- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs +++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs @@ -460,21 +460,20 @@ namespace OpenSim.Framework.Servers // elsewhere as well string svnRevisionFileName = "svn_revision"; string svnFileName = ".svn/entries"; - string gitCommitFileName = ".version"; + string manualVersionFileName = ".version"; string inputLine; int strcmp; - if (File.Exists(gitCommitFileName)) + if (File.Exists(manualVersionFileName)) { - StreamReader CommitFile = File.OpenText(gitCommitFileName); + StreamReader CommitFile = File.OpenText(manualVersionFileName); buildVersion = CommitFile.ReadLine(); CommitFile.Close(); m_version += buildVersion ?? ""; } - - // Remove the else logic when subversion mirror is no longer used else { + // Remove the else logic when subversion mirror is no longer used if (File.Exists(svnRevisionFileName)) { StreamReader RevisionFile = File.OpenText(svnRevisionFileName); -- cgit v1.1 From e765759f504b86a643fd8843e41b0283422f7980 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 1 Jul 2011 22:48:00 +0100 Subject: If OpenSim has been built from a git tree, then include version information automatically by dereferencing .git/HEAD A blank bin/.version file will stop this being displayed. --- OpenSim/Framework/Servers/BaseOpenSimServer.cs | 43 +++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 4 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs index 98a92dd..d4c3d08 100644 --- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs +++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs @@ -31,6 +31,7 @@ using System.Diagnostics; using System.IO; using System.Reflection; using System.Text; +using System.Text.RegularExpressions; using System.Threading; using System.Timers; using log4net; @@ -124,7 +125,6 @@ namespace OpenSim.Framework.Servers m_logFileAppender = appender; } } - } /// @@ -458,6 +458,9 @@ namespace OpenSim.Framework.Servers // This allows to make the revision available in simulators not running from the source tree. // FIXME: Making an assumption about the directory we're currently in - we do this all over the place // elsewhere as well + string gitDir = "../.git/"; + string gitRefPointerPath = gitDir + "HEAD"; + string svnRevisionFileName = "svn_revision"; string svnFileName = ".svn/entries"; string manualVersionFileName = ".version"; @@ -466,13 +469,45 @@ namespace OpenSim.Framework.Servers if (File.Exists(manualVersionFileName)) { - StreamReader CommitFile = File.OpenText(manualVersionFileName); - buildVersion = CommitFile.ReadLine(); - CommitFile.Close(); + using (StreamReader CommitFile = File.OpenText(manualVersionFileName)) + buildVersion = CommitFile.ReadLine(); + m_version += buildVersion ?? ""; } + else if (File.Exists(gitRefPointerPath)) + { +// m_log.DebugFormat("[OPENSIM]: Found {0}", gitRefPointerPath); + + string rawPointer = ""; + + using (StreamReader pointerFile = File.OpenText(gitRefPointerPath)) + rawPointer = pointerFile.ReadLine(); + +// m_log.DebugFormat("[OPENSIM]: rawPointer [{0}]", rawPointer); + + Match m = Regex.Match(rawPointer, "^ref: (.+)$"); + + if (m.Success) + { +// m_log.DebugFormat("[OPENSIM]: Matched [{0}]", m.Groups[1].Value); + + string gitRef = m.Groups[1].Value; + string gitRefPath = gitDir + gitRef; + if (File.Exists(gitRefPath)) + { +// m_log.DebugFormat("[OPENSIM]: Found gitRefPath [{0}]", gitRefPath); + + using (StreamReader refFile = File.OpenText(gitRefPath)) + { + string gitHash = refFile.ReadLine(); + m_version += gitHash.Substring(0, 7); + } + } + } + } else { + m_log.DebugFormat("[OPENSIM]: Looking for SVN"); // Remove the else logic when subversion mirror is no longer used if (File.Exists(svnRevisionFileName)) { -- cgit v1.1 From fba961c63f2168eb560eec84b66203b1a875b952 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 1 Jul 2011 23:06:46 +0100 Subject: Make default serverside_object_permissions = true since this better matches user expectations. It also matches the default setting in the OpenSim.ini.example file --- OpenSim/Framework/Servers/BaseOpenSimServer.cs | 11 ----------- OpenSim/Region/Application/ConfigurationLoader.cs | 2 +- .../Region/CoreModules/World/Permissions/PermissionsModule.cs | 2 +- OpenSim/Tools/Configger/ConfigurationLoader.cs | 2 +- 4 files changed, 3 insertions(+), 14 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs index d4c3d08..688be3f 100644 --- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs +++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs @@ -443,15 +443,6 @@ namespace OpenSim.Framework.Servers { string buildVersion = string.Empty; - // Add commit hash and date information if available - // The commit hash and date are stored in a file bin/.version - // This file can automatically created by a post - // commit script in the opensim git master repository or - // by issuing the follwoing command from the top level - // directory of the opensim repository - // git log -n 1 --pretty="format:%h: %ci" >bin/.version - // For the full git commit hash use %H instead of %h - // // The subversion information is deprecated and will be removed at a later date // Add subversion revision information if available // Try file "svn_revision" in the current directory first, then the .svn info. @@ -507,7 +498,6 @@ namespace OpenSim.Framework.Servers } else { - m_log.DebugFormat("[OPENSIM]: Looking for SVN"); // Remove the else logic when subversion mirror is no longer used if (File.Exists(svnRevisionFileName)) { @@ -515,7 +505,6 @@ namespace OpenSim.Framework.Servers buildVersion = RevisionFile.ReadLine(); buildVersion.Trim(); RevisionFile.Close(); - } if (string.IsNullOrEmpty(buildVersion) && File.Exists(svnFileName)) diff --git a/OpenSim/Region/Application/ConfigurationLoader.cs b/OpenSim/Region/Application/ConfigurationLoader.cs index 2d81ea8..d19852b 100644 --- a/OpenSim/Region/Application/ConfigurationLoader.cs +++ b/OpenSim/Region/Application/ConfigurationLoader.cs @@ -328,7 +328,7 @@ namespace OpenSim config.Set("meshing", "Meshmerizer"); config.Set("physical_prim", true); config.Set("see_into_this_sim_from_neighbor", true); - config.Set("serverside_object_permissions", false); + config.Set("serverside_object_permissions", true); config.Set("storage_plugin", "OpenSim.Data.SQLite.dll"); config.Set("storage_connection_string", "URI=file:OpenSim.db,version=3"); config.Set("storage_prim_inventories", true); diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs index d7324c6..a40517c 100644 --- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs +++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs @@ -134,7 +134,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions return; m_allowGridGods = myConfig.GetBoolean("allow_grid_gods", false); - m_bypassPermissions = !myConfig.GetBoolean("serverside_object_permissions", false); + m_bypassPermissions = !myConfig.GetBoolean("serverside_object_permissions", true); m_propagatePermissions = myConfig.GetBoolean("propagate_permissions", true); m_RegionOwnerIsGod = myConfig.GetBoolean("region_owner_is_god", true); m_RegionManagerIsGod = myConfig.GetBoolean("region_manager_is_god", false); diff --git a/OpenSim/Tools/Configger/ConfigurationLoader.cs b/OpenSim/Tools/Configger/ConfigurationLoader.cs index 8e71b42..3914652 100644 --- a/OpenSim/Tools/Configger/ConfigurationLoader.cs +++ b/OpenSim/Tools/Configger/ConfigurationLoader.cs @@ -239,7 +239,7 @@ namespace OpenSim.Tools.Configger config.Set("meshing", "Meshmerizer"); config.Set("physical_prim", true); config.Set("see_into_this_sim_from_neighbor", true); - config.Set("serverside_object_permissions", false); + config.Set("serverside_object_permissions", true); config.Set("storage_plugin", "OpenSim.Data.SQLite.dll"); config.Set("storage_connection_string", "URI=file:OpenSim.db,version=3"); config.Set("storage_prim_inventories", true); -- cgit v1.1 From ed12e38480a28d5863b5777e9bbeb94ce84d3ef1 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 2 Jul 2011 00:18:15 +0100 Subject: refactor: simplify existing npc code by creating them directly rather than indirectly via a timer no obvious reason for doing this asynchonously, especially as the caller was sleeping in order to pick up the response anyway! --- .../Region/OptionalModules/World/NPC/NPCModule.cs | 139 ++++++--------------- 1 file changed, 37 insertions(+), 102 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs index 48d236f..c1ddeee 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs @@ -47,31 +47,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC // private const bool m_enabled = false; - private Mutex m_createMutex; - private Timer m_timer; - private Dictionary m_avatars = new Dictionary(); private Dictionary m_appearanceCache = new Dictionary(); - // Timer vars. - private bool p_inUse = false; - private readonly object p_lock = new object(); - // Private Temporary Variables. - private string p_firstname; - private string p_lastname; - private Vector3 p_position; - private Scene p_scene; - private UUID p_cloneAppearanceFrom; - private UUID p_returnUuid; - public void Initialise(Scene scene, IConfigSource source) { - m_createMutex = new Mutex(false); - - m_timer = new Timer(500); - m_timer.Elapsed += m_timer_Elapsed; - m_timer.Start(); - scene.RegisterModuleInterface(this); } @@ -92,33 +72,51 @@ namespace OpenSim.Region.OptionalModules.World.NPC public UUID CreateNPC(string firstname, string lastname,Vector3 position, Scene scene, UUID cloneAppearanceFrom) { + NPCAvatar npcAvatar = new NPCAvatar(firstname, lastname, position, scene); + npcAvatar.CircuitCode = (uint)Util.RandomClass.Next(0, int.MaxValue); + m_log.DebugFormat( - "[NPC MODULE]: Queueing request to create NPC {0} {1} at {2} in {3} cloning appearance of {4}", - firstname, lastname, position, scene.RegionInfo.RegionName, cloneAppearanceFrom); + "[NPC MODULE]: Creating NPC {0} {1} {2} at {3} in {4}", + firstname, lastname, npcAvatar.AgentId, position, scene.RegionInfo.RegionName); + + AgentCircuitData acd = new AgentCircuitData(); + acd.AgentID = npcAvatar.AgentId; + acd.firstname = firstname; + acd.lastname = lastname; + acd.ServiceURLs = new Dictionary(); - // Block. - m_createMutex.WaitOne(); + AvatarAppearance originalAppearance = GetAppearance(cloneAppearanceFrom, scene); + AvatarAppearance npcAppearance = new AvatarAppearance(originalAppearance, true); + acd.Appearance = npcAppearance; - // Copy Temp Variables for Timer to pick up. - lock (p_lock) + scene.AuthenticateHandler.AddNewCircuit(npcAvatar.CircuitCode, acd); + scene.AddNewClient(npcAvatar); + + ScenePresence sp; + if (scene.TryGetScenePresence(npcAvatar.AgentId, out sp)) { - p_firstname = firstname; - p_lastname = lastname; - p_position = position; - p_scene = scene; - p_cloneAppearanceFrom = cloneAppearanceFrom; - p_inUse = true; - p_returnUuid = UUID.Zero; - } + m_log.DebugFormat( + "[NPC MODULE]: Successfully retrieved scene presence for NPC {0} {1}", sp.Name, sp.UUID); + + // Shouldn't call this - temporary. + sp.CompleteMovement(npcAvatar); - while (p_returnUuid == UUID.Zero) +// sp.SendAppearanceToAllOtherAgents(); +// +// // Send animations back to the avatar as well +// sp.Animator.SendAnimPack(); + } + else { - Thread.Sleep(250); + m_log.WarnFormat("[NPC MODULE]: Could not find scene presence for NPC {0} {1}", sp.Name, sp.UUID); } - m_createMutex.ReleaseMutex(); + lock (m_avatars) + m_avatars.Add(npcAvatar.AgentId, npcAvatar); - return p_returnUuid; + m_log.DebugFormat("[NPC MODULE]: Created NPC with id {0}", npcAvatar.AgentId); + + return npcAvatar.AgentId; } public void Autopilot(UUID agentID, Scene scene, Vector3 pos) @@ -157,69 +155,6 @@ namespace OpenSim.Region.OptionalModules.World.NPC } } - void m_timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) - { - try - { - lock (p_lock) - { - if (p_inUse) - { - p_inUse = false; - - NPCAvatar npcAvatar = new NPCAvatar(p_firstname, p_lastname, p_position, p_scene); - npcAvatar.CircuitCode = (uint) Util.RandomClass.Next(0, int.MaxValue); - - m_log.DebugFormat( - "[NPC MODULE]: Creating NPC {0} {1} {2} at {3} in {4}", - p_firstname, p_lastname, npcAvatar.AgentId, p_position, p_scene.RegionInfo.RegionName); - - AgentCircuitData acd = new AgentCircuitData(); - acd.AgentID = npcAvatar.AgentId; - acd.firstname = p_firstname; - acd.lastname = p_lastname; - acd.ServiceURLs = new Dictionary(); - - AvatarAppearance originalAppearance = GetAppearance(p_cloneAppearanceFrom, p_scene); - AvatarAppearance npcAppearance = new AvatarAppearance(originalAppearance, true); - acd.Appearance = npcAppearance; - - p_scene.AuthenticateHandler.AddNewCircuit(npcAvatar.CircuitCode, acd); - p_scene.AddNewClient(npcAvatar); - - ScenePresence sp; - if (p_scene.TryGetScenePresence(npcAvatar.AgentId, out sp)) - { - m_log.DebugFormat( - "[NPC MODULE]: Successfully retrieved scene presence for NPC {0} {1}", sp.Name, sp.UUID); - - // Shouldn't call this - temporary. - sp.CompleteMovement(npcAvatar); - - // sp.SendAppearanceToAllOtherAgents(); - // - // // Send animations back to the avatar as well - // sp.Animator.SendAnimPack(); - } - else - { - m_log.WarnFormat("[NPC MODULE]: Could not find scene presence for NPC {0} {1}", sp.Name, sp.UUID); - } - - m_avatars.Add(npcAvatar.AgentId, npcAvatar); - - p_returnUuid = npcAvatar.AgentId; - - m_log.DebugFormat("[NPC MODULE]: Created NPC with id {0}", p_returnUuid); - } - } - } - catch (Exception ex) - { - m_log.ErrorFormat("[NPC MODULE]: NPC creation failed with exception {0} {1}", ex.Message, ex.StackTrace); - } - } - public void PostInitialise() { } @@ -238,4 +173,4 @@ namespace OpenSim.Region.OptionalModules.World.NPC get { return true; } } } -} +} \ No newline at end of file -- cgit v1.1 From 513d63455ed7cf1a7a859e9e8abaeff7e7c7ad4f Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 2 Jul 2011 01:01:40 +0100 Subject: Create a very basic initial test which just creates an 'npc' and tests that the scene presence exists --- .../Region/CoreModules/Avatar/NPC/INPCModule.cs | 40 ------------ OpenSim/Region/Framework/Interfaces/INPCModule.cs | 40 ++++++++++++ .../Region/OptionalModules/World/NPC/NPCModule.cs | 3 +- .../World/NPC/Tests/NPCModuleTests.cs | 71 ++++++++++++++++++++++ .../Shared/Api/Implementation/OSSL_Api.cs | 1 - 5 files changed, 112 insertions(+), 43 deletions(-) delete mode 100644 OpenSim/Region/CoreModules/Avatar/NPC/INPCModule.cs create mode 100644 OpenSim/Region/Framework/Interfaces/INPCModule.cs create mode 100644 OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Avatar/NPC/INPCModule.cs b/OpenSim/Region/CoreModules/Avatar/NPC/INPCModule.cs deleted file mode 100644 index cd2fe4f..0000000 --- a/OpenSim/Region/CoreModules/Avatar/NPC/INPCModule.cs +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * 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 OpenMetaverse; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.CoreModules.Avatar.NPC -{ - public interface INPCModule - { - UUID CreateNPC(string firstname, string lastname, Vector3 position, Scene scene, UUID cloneAppearanceFrom); - void Autopilot(UUID agentID, Scene scene, Vector3 pos); - void Say(UUID agentID, Scene scene, string text); - void DeleteNPC(UUID agentID, Scene scene); - } -} \ No newline at end of file diff --git a/OpenSim/Region/Framework/Interfaces/INPCModule.cs b/OpenSim/Region/Framework/Interfaces/INPCModule.cs new file mode 100644 index 0000000..21a755f --- /dev/null +++ b/OpenSim/Region/Framework/Interfaces/INPCModule.cs @@ -0,0 +1,40 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * 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 OpenMetaverse; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.Framework.Interfaces +{ + public interface INPCModule + { + UUID CreateNPC(string firstname, string lastname, Vector3 position, Scene scene, UUID cloneAppearanceFrom); + void Autopilot(UUID agentID, Scene scene, Vector3 pos); + void Say(UUID agentID, Scene scene, string text); + void DeleteNPC(UUID agentID, Scene scene); + } +} \ No newline at end of file diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs index c1ddeee..3cdd06d 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs @@ -34,7 +34,6 @@ using Nini.Config; using OpenMetaverse; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.CoreModules.Avatar.NPC; using OpenSim.Framework; using Timer=System.Timers.Timer; using OpenSim.Services.Interfaces; @@ -70,7 +69,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC return new AvatarAppearance(); } - public UUID CreateNPC(string firstname, string lastname,Vector3 position, Scene scene, UUID cloneAppearanceFrom) + public UUID CreateNPC(string firstname, string lastname, Vector3 position, Scene scene, UUID cloneAppearanceFrom) { NPCAvatar npcAvatar = new NPCAvatar(firstname, lastname, position, scene); npcAvatar.CircuitCode = (uint)Util.RandomClass.Next(0, int.MaxValue); diff --git a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs new file mode 100644 index 0000000..899e721 --- /dev/null +++ b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs @@ -0,0 +1,71 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * 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.Reflection; +using Nini.Config; +using NUnit.Framework; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Region.CoreModules.ServiceConnectorsOut.Avatar; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.AvatarService; +using OpenSim.Tests.Common; +using OpenSim.Tests.Common.Mock; + +namespace OpenSim.Region.OptionalModules.World.NPC.Tests +{ + [TestFixture] + public class NPCModuleTests + { + [Test] + public void TestCreate() + { + TestHelper.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + IConfigSource config = new IniConfigSource(); + + config.AddConfig("Modules"); + config.Configs["Modules"].Set("AvatarServices", "LocalAvatarServicesConnector"); + config.AddConfig("AvatarService"); + config.Configs["AvatarService"].Set("LocalServiceModule", "OpenSim.Services.AvatarService.dll:AvatarService"); + config.Configs["AvatarService"].Set("StorageProvider", "OpenSim.Data.Null.dll"); + + TestScene scene = SceneSetupHelpers.SetupScene(); + SceneSetupHelpers.SetupSceneModules(scene, config, new NPCModule(), new LocalAvatarServicesConnector()); + + INPCModule npcModule = scene.RequestModuleInterface(); + UUID npcId = npcModule.CreateNPC("John", "Smith", new Vector3(128, 128, 30), scene, UUID.Zero); + + ScenePresence npc = scene.GetScenePresence(npcId); + Assert.That(npc, Is.Not.Null); + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 963727d..1bc4534 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -38,7 +38,6 @@ using OpenSim; using OpenSim.Framework; using OpenSim.Framework.Console; -using OpenSim.Region.CoreModules.Avatar.NPC; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.ScriptEngine.Shared; -- cgit v1.1 From bb4cb165127164cbc9d907aac27c4fb3eb69d443 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 2 Jul 2011 01:05:03 +0100 Subject: Add profile, merge, noassets and skip-assets options for loading/saving oars via RemoteAdmin This is http://opensimulator.org/mantis/view.php?id=5453 Thanks Michelle Argus! --- .../RemoteController/RemoteAdminPlugin.cs | 41 ++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs index 5a011ce..93a6915 100644 --- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs +++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs @@ -2201,6 +2201,10 @@ namespace OpenSim.ApplicationPlugins.RemoteController /// UUID of the region /// region_name /// region name + /// merge + /// true if oar should be merged + /// skip-assets + /// true if assets should be skiped /// /// /// region_uuid takes precedence over @@ -2259,10 +2263,22 @@ namespace OpenSim.ApplicationPlugins.RemoteController throw new Exception(String.Format("failed to switch to region {0}", region_name)); } else throw new Exception("neither region_name nor region_uuid given"); + + bool mergeOar = false; + bool skipAssets = false; + + if ((string)requestData["merge"] == "true") + { + mergeOar = true; + } + if ((string)requestData["skip-assets"] == "true") + { + skipAssets = true; + } IRegionArchiverModule archiver = scene.RequestModuleInterface(); if (archiver != null) - archiver.DearchiveRegion(filename); + archiver.DearchiveRegion(filename, mergeOar, skipAssets, Guid.Empty); else throw new Exception("Archiver module not present for scene"); @@ -2302,6 +2318,10 @@ namespace OpenSim.ApplicationPlugins.RemoteController /// UUID of the region /// region_name /// region name + /// profile + /// profile url + /// noassets + /// true if no assets should be saved /// /// /// region_uuid takes precedence over @@ -2359,12 +2379,29 @@ namespace OpenSim.ApplicationPlugins.RemoteController } else throw new Exception("neither region_name nor region_uuid given"); + Dictionary options = new Dictionary(); + + //if (requestData.Contains("version")) + //{ + // options["version"] = (string)requestData["version"]; + //} + + if (requestData.Contains("profile")) + { + options["profile"] = (string)requestData["profile"]; + } + + if (requestData["noassets"] == "true") + { + options["noassets"] = (string)requestData["noassets"] ; + } + IRegionArchiverModule archiver = scene.RequestModuleInterface(); if (archiver != null) { scene.EventManager.OnOarFileSaved += RemoteAdminOarSaveCompleted; - archiver.ArchiveRegion(filename, new Dictionary()); + archiver.ArchiveRegion(filename, options); lock (m_saveOarLock) Monitor.Wait(m_saveOarLock,5000); scene.EventManager.OnOarFileSaved -= RemoteAdminOarSaveCompleted; } -- cgit v1.1 From b8e7258051abab3e1310dd8b08cb1d2e09fa21e3 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 2 Jul 2011 01:14:29 +0100 Subject: If a user has the rights to edit a parcel's properties, then also allow them always to enter that parcel. This is patch http://opensimulator.org/mantis/view.php?id=5567 Thanks Snoopy! --- OpenSim/Region/CoreModules/World/Land/LandObject.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index 560b862..8c40171 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -418,7 +418,7 @@ namespace OpenSim.Region.CoreModules.World.Land public bool IsBannedFromLand(UUID avatar) { - if (m_scene.Permissions.IsAdministrator(avatar)) + if (m_scene.Permissions.CanEditParcelProperties(avatar, this, 0)) return false; if ((LandData.Flags & (uint) ParcelFlags.UseBanList) > 0) @@ -429,7 +429,7 @@ namespace OpenSim.Region.CoreModules.World.Land if (e.AgentID == avatar && e.Flags == AccessList.Ban) return true; return false; - }) != -1 && LandData.OwnerID != avatar) + }) != -1) { return true; } @@ -439,7 +439,7 @@ namespace OpenSim.Region.CoreModules.World.Land public bool IsRestrictedFromLand(UUID avatar) { - if (m_scene.Permissions.IsAdministrator(avatar)) + if (m_scene.Permissions.CanEditParcelProperties(avatar, this, 0)) return false; if ((LandData.Flags & (uint) ParcelFlags.UseAccessList) > 0) @@ -450,7 +450,7 @@ namespace OpenSim.Region.CoreModules.World.Land if (e.AgentID == avatar && e.Flags == AccessList.Access) return true; return false; - }) == -1 && LandData.OwnerID != avatar) + }) == -1) { return true; } -- cgit v1.1 From 46f5893d559f87982e510d02a37856951eb1e088 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 4 Jul 2011 21:35:15 +0100 Subject: Add basic flotsam asset cache test for retrieved cached asset. Disabled temporarily since file system caching disrupts subsequent test runs --- OpenSim/Framework/AssetBase.cs | 1 + .../Region/CoreModules/Asset/FlotsamAssetCache.cs | 2 + .../Asset/Tests/FlotsamAssetCacheTests.cs | 82 ++++++++++++++++++++++ OpenSim/Tests/Common/Helpers/AssetHelpers.cs | 9 +++ OpenSim/Tests/Common/TestHelper.cs | 11 +++ 5 files changed, 105 insertions(+) create mode 100644 OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs (limited to 'OpenSim') diff --git a/OpenSim/Framework/AssetBase.cs b/OpenSim/Framework/AssetBase.cs index 5f68cda..e8c85c9 100644 --- a/OpenSim/Framework/AssetBase.cs +++ b/OpenSim/Framework/AssetBase.cs @@ -273,6 +273,7 @@ namespace OpenSim.Framework return m_id; } + set { UUID uuid = UUID.Zero; diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index 48ee277..a8f5c99 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -259,6 +259,8 @@ namespace Flotsam.RegionModules.AssetCache // TODO: Spawn this off to some seperate thread to do the actual writing if (asset != null) { + m_log.DebugFormat("[FLOTSAM ASSET CACHE]: Caching asset with id {0}", asset.ID); + UpdateMemoryCache(asset.ID, asset); string filename = GetFileName(asset.ID); diff --git a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs new file mode 100644 index 0000000..3498969 --- /dev/null +++ b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs @@ -0,0 +1,82 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * 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.IO; +using System.Reflection; +using System.Threading; +using log4net.Config; +using Nini.Config; +using NUnit.Framework; +using OpenMetaverse; +using OpenMetaverse.Assets; +using Flotsam.RegionModules.AssetCache; +using OpenSim.Framework; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Framework.Scenes.Serialization; +using OpenSim.Tests.Common; +using OpenSim.Tests.Common.Mock; + +namespace OpenSim.Region.CoreModules.Asset.Tests +{ + [TestFixture] + public class FlotsamAssetCacheTests + { +// [Test] + public void TestCacheAsset() + { + TestHelper.InMethod(); + log4net.Config.XmlConfigurator.Configure(); + + IConfigSource config = new IniConfigSource(); + + config.AddConfig("Modules"); + config.Configs["Modules"].Set("AssetCaching", "FlotsamAssetCache"); + config.AddConfig("AssetCache"); + config.Configs["AssetCache"].Set("MemoryCacheEnabled", "true"); + + FlotsamAssetCache cache = new FlotsamAssetCache(); + TestScene scene = SceneSetupHelpers.SetupScene(); + SceneSetupHelpers.SetupSceneModules(scene, config, cache); + + AssetBase asset = AssetHelpers.CreateAsset(); + asset.ID = TestHelper.ParseTail(0x1).ToString(); + + // Check we don't get anything before the asset is put in the cache + AssetBase retrievedAsset = cache.Get(asset.ID.ToString()); + Assert.That(retrievedAsset, Is.Null); + + cache.Store(asset); + + // Check that asset is now in cache + retrievedAsset = cache.Get(asset.ID.ToString()); + Assert.That(retrievedAsset, Is.Not.Null); + Assert.That(retrievedAsset.ID, Is.EqualTo(asset.ID)); + } + } +} \ No newline at end of file diff --git a/OpenSim/Tests/Common/Helpers/AssetHelpers.cs b/OpenSim/Tests/Common/Helpers/AssetHelpers.cs index aa55bcd..9b68331 100644 --- a/OpenSim/Tests/Common/Helpers/AssetHelpers.cs +++ b/OpenSim/Tests/Common/Helpers/AssetHelpers.cs @@ -37,6 +37,15 @@ namespace OpenSim.Tests.Common public class AssetHelpers { /// + /// Create a notecard asset with a random uuids and dummy text. + /// + /// + public static AssetBase CreateAsset() + { + return CreateAsset(UUID.Random(), AssetType.Notecard, "hello", UUID.Random()); + } + + /// /// Create a notecard asset with a random uuid and dummy text. /// /// /param> diff --git a/OpenSim/Tests/Common/TestHelper.cs b/OpenSim/Tests/Common/TestHelper.cs index 1722e59..86bd107 100644 --- a/OpenSim/Tests/Common/TestHelper.cs +++ b/OpenSim/Tests/Common/TestHelper.cs @@ -28,6 +28,7 @@ using System; using System.Diagnostics; using NUnit.Framework; +using OpenMetaverse; namespace OpenSim.Tests.Common { @@ -56,5 +57,15 @@ namespace OpenSim.Tests.Common Console.WriteLine(); Console.WriteLine("===> In Test Method : {0} <===", stackTrace.GetFrame(1).GetMethod().Name); } + + /// + /// Parse tail section into full UUID. + /// + /// + /// + public static UUID ParseTail(int tail) + { + return new UUID(string.Format("00000000-0000-0000-0000-{0:X12}", tail)); + } } } -- cgit v1.1 From 5dc785bbf2a0197b560e94b2aa8858ad33d58504 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 4 Jul 2011 22:30:18 +0100 Subject: refactor: Split file cache manipulation code into separate methods, as has already been done for the memory cache --- .../Region/CoreModules/Asset/FlotsamAssetCache.cs | 233 ++++++++++++--------- 1 file changed, 131 insertions(+), 102 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index a8f5c99..a72cf83 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -226,7 +226,6 @@ namespace Flotsam.RegionModules.AssetCache if (m_AssetService == null) { m_AssetService = scene.RequestModuleInterface(); - } } } @@ -250,140 +249,170 @@ namespace Flotsam.RegionModules.AssetCache private void UpdateMemoryCache(string key, AssetBase asset) { - if (m_MemoryCacheEnabled) - m_MemoryCache.AddOrUpdate(key, asset, m_MemoryExpiration); + m_MemoryCache.AddOrUpdate(key, asset, m_MemoryExpiration); } - public void Cache(AssetBase asset) + private void UpdateFileCache(string key, AssetBase asset) { - // TODO: Spawn this off to some seperate thread to do the actual writing - if (asset != null) - { - m_log.DebugFormat("[FLOTSAM ASSET CACHE]: Caching asset with id {0}", asset.ID); - - UpdateMemoryCache(asset.ID, asset); - - string filename = GetFileName(asset.ID); + string filename = GetFileName(asset.ID); - try + try + { + // If the file is already cached, don't cache it, just touch it so access time is updated + if (File.Exists(filename)) { - // If the file is already cached, don't cache it, just touch it so access time is updated - if (File.Exists(filename)) + File.SetLastAccessTime(filename, DateTime.Now); + } + else + { + // Once we start writing, make sure we flag that we're writing + // that object to the cache so that we don't try to write the + // same file multiple times. + lock (m_CurrentlyWriting) { - File.SetLastAccessTime(filename, DateTime.Now); - } else { - - // Once we start writing, make sure we flag that we're writing - // that object to the cache so that we don't try to write the - // same file multiple times. - lock (m_CurrentlyWriting) - { #if WAIT_ON_INPROGRESS_REQUESTS - if (m_CurrentlyWriting.ContainsKey(filename)) - { - return; - } - else - { - m_CurrentlyWriting.Add(filename, new ManualResetEvent(false)); - } + if (m_CurrentlyWriting.ContainsKey(filename)) + { + return; + } + else + { + m_CurrentlyWriting.Add(filename, new ManualResetEvent(false)); + } #else - if (m_CurrentlyWriting.Contains(filename)) - { - return; - } - else - { - m_CurrentlyWriting.Add(filename); - } -#endif - + if (m_CurrentlyWriting.Contains(filename)) + { + return; } - - Util.FireAndForget( - delegate { WriteFileCache(filename, asset); }); + else + { + m_CurrentlyWriting.Add(filename); + } +#endif } - } - catch (Exception e) - { - LogException(e); + + Util.FireAndForget( + delegate { WriteFileCache(filename, asset); }); } } + catch (Exception e) + { + LogException(e); + } } - public AssetBase Get(string id) + public void Cache(AssetBase asset) { - m_Requests++; + // TODO: Spawn this off to some seperate thread to do the actual writing + if (asset != null) + { + //m_log.DebugFormat("[FLOTSAM ASSET CACHE]: Caching asset with id {0}", asset.ID); + if (m_MemoryCacheEnabled) + UpdateMemoryCache(asset.ID, asset); + + UpdateFileCache(asset.ID, asset); + } + } + + /// + /// Try to get an asset from the in-memory cache. + /// + /// + /// + private AssetBase GetFromMemoryCache(string id) + { AssetBase asset = null; - if (m_MemoryCacheEnabled && m_MemoryCache.TryGetValue(id, out asset)) - { + if (m_MemoryCache.TryGetValue(id, out asset)) m_MemoryHits++; - } - else + + return asset; + } + + /// + /// Try to get an asset from the file cache. + /// + /// + /// + private AssetBase GetFromFileCache(string id) + { + AssetBase asset = null; + + string filename = GetFileName(id); + if (File.Exists(filename)) { - string filename = GetFileName(id); - if (File.Exists(filename)) + FileStream stream = null; + try { - FileStream stream = null; - try - { - stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read); - BinaryFormatter bformatter = new BinaryFormatter(); + stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read); + BinaryFormatter bformatter = new BinaryFormatter(); - asset = (AssetBase)bformatter.Deserialize(stream); + asset = (AssetBase)bformatter.Deserialize(stream); - UpdateMemoryCache(id, asset); + UpdateMemoryCache(id, asset); - m_DiskHits++; - } - catch (System.Runtime.Serialization.SerializationException e) - { - LogException(e); + m_DiskHits++; + } + catch (System.Runtime.Serialization.SerializationException e) + { + LogException(e); - // If there was a problem deserializing the asset, the asset may - // either be corrupted OR was serialized under an old format - // {different version of AssetBase} -- we should attempt to - // delete it and re-cache - File.Delete(filename); - } - catch (Exception e) - { - LogException(e); - } - finally - { - if (stream != null) - stream.Close(); - } + // If there was a problem deserializing the asset, the asset may + // either be corrupted OR was serialized under an old format + // {different version of AssetBase} -- we should attempt to + // delete it and re-cache + File.Delete(filename); + } + catch (Exception e) + { + LogException(e); } + finally + { + if (stream != null) + stream.Close(); + } + } #if WAIT_ON_INPROGRESS_REQUESTS - // Check if we're already downloading this asset. If so, try to wait for it to - // download. - if (m_WaitOnInprogressTimeout > 0) - { - m_RequestsForInprogress++; + // Check if we're already downloading this asset. If so, try to wait for it to + // download. + if (m_WaitOnInprogressTimeout > 0) + { + m_RequestsForInprogress++; - ManualResetEvent waitEvent; - if (m_CurrentlyWriting.TryGetValue(filename, out waitEvent)) - { - waitEvent.WaitOne(m_WaitOnInprogressTimeout); - return Get(id); - } - } -#else - // Track how often we have the problem that an asset is requested while - // it is still being downloaded by a previous request. - if (m_CurrentlyWriting.Contains(filename)) + ManualResetEvent waitEvent; + if (m_CurrentlyWriting.TryGetValue(filename, out waitEvent)) { - m_RequestsForInprogress++; + waitEvent.WaitOne(m_WaitOnInprogressTimeout); + return Get(id); } -#endif } +#else + // Track how often we have the problem that an asset is requested while + // it is still being downloaded by a previous request. + if (m_CurrentlyWriting.Contains(filename)) + { + m_RequestsForInprogress++; + } +#endif + + return asset; + } + + public AssetBase Get(string id) + { + m_Requests++; + + AssetBase asset = null; + + if (m_MemoryCacheEnabled) + asset = GetFromMemoryCache(id); + else + asset = GetFromFileCache(id); if (((m_LogLevel >= 1)) && (m_HitRateDisplay != 0) && (m_Requests % m_HitRateDisplay == 0)) { @@ -474,9 +503,9 @@ namespace Flotsam.RegionModules.AssetCache /// removes empty tier directories. /// /// + /// private void CleanExpiredFiles(string dir, DateTime purgeLine) { - foreach (string file in Directory.GetFiles(dir)) { if (File.GetLastAccessTime(file) < purgeLine) -- cgit v1.1 From bebc51a6e041d2bcd8fef110ea5b178ac614c59d Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 4 Jul 2011 22:51:47 +0100 Subject: Make it possible to disable the file part of the flotsam asset cache This matches the ability to disable the memory part This is controlled through the FileCacheEnabled parameter in FlotsamCache.ini Default is true, so existing installations are not affected. Improved fcache command feedback when various caches are disabled. Re-enabled test for flotsam cache with file caching disabled. --- .../Region/CoreModules/Asset/FlotsamAssetCache.cs | 110 ++++++++++++++------- .../Asset/Tests/FlotsamAssetCacheTests.cs | 3 +- 2 files changed, 74 insertions(+), 39 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index a72cf83..2b3f7f5 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -86,6 +86,8 @@ namespace Flotsam.RegionModules.AssetCache private List m_CurrentlyWriting = new List(); #endif + private bool m_FileCacheEnabled = true; + private ExpiringCache m_MemoryCache; private bool m_MemoryCacheEnabled = false; @@ -146,6 +148,7 @@ namespace Flotsam.RegionModules.AssetCache } else { + m_FileCacheEnabled = assetConfig.GetBoolean("FileCacheEnabled", m_FileCacheEnabled); m_CacheDirectory = assetConfig.GetString("CacheDirectory", m_DefaultCacheDirectory); m_MemoryCacheEnabled = assetConfig.GetBoolean("MemoryCacheEnabled", m_MemoryCacheEnabled); @@ -173,7 +176,7 @@ namespace Flotsam.RegionModules.AssetCache m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory {0}", m_CacheDirectory); - if ((m_FileExpiration > TimeSpan.Zero) && (m_FileExpirationCleanupTimer > TimeSpan.Zero)) + if (m_FileCacheEnabled && (m_FileExpiration > TimeSpan.Zero) && (m_FileExpirationCleanupTimer > TimeSpan.Zero)) { m_CacheCleanTimer = new System.Timers.Timer(m_FileExpirationCleanupTimer.TotalMilliseconds); m_CacheCleanTimer.AutoReset = true; @@ -312,7 +315,8 @@ namespace Flotsam.RegionModules.AssetCache if (m_MemoryCacheEnabled) UpdateMemoryCache(asset.ID, asset); - UpdateFileCache(asset.ID, asset); + if (m_FileCacheEnabled) + UpdateFileCache(asset.ID, asset); } } @@ -411,7 +415,7 @@ namespace Flotsam.RegionModules.AssetCache if (m_MemoryCacheEnabled) asset = GetFromMemoryCache(id); - else + else if (m_FileCacheEnabled) asset = GetFromFileCache(id); if (((m_LogLevel >= 1)) && (m_HitRateDisplay != 0) && (m_Requests % m_HitRateDisplay == 0)) @@ -446,10 +450,13 @@ namespace Flotsam.RegionModules.AssetCache try { - string filename = GetFileName(id); - if (File.Exists(filename)) + if (m_FileCacheEnabled) { - File.Delete(filename); + string filename = GetFileName(id); + if (File.Exists(filename)) + { + File.Delete(filename); + } } if (m_MemoryCacheEnabled) @@ -464,11 +471,14 @@ namespace Flotsam.RegionModules.AssetCache public void Clear() { if (m_LogLevel >= 2) - m_log.Debug("[FLOTSAM ASSET CACHE]: Clearing Cache."); + m_log.Debug("[FLOTSAM ASSET CACHE]: Clearing caches."); - foreach (string dir in Directory.GetDirectories(m_CacheDirectory)) + if (m_FileCacheEnabled) { - Directory.Delete(dir); + foreach (string dir in Directory.GetDirectories(m_CacheDirectory)) + { + Directory.Delete(dir); + } } if (m_MemoryCacheEnabled) @@ -743,18 +753,28 @@ namespace Flotsam.RegionModules.AssetCache switch (cmd) { case "status": - m_log.InfoFormat("[FLOTSAM ASSET CACHE] Memory Cache : {0} assets", m_MemoryCache.Count); - - int fileCount = GetFileCacheCount(m_CacheDirectory); - m_log.InfoFormat("[FLOTSAM ASSET CACHE] File Cache : {0} assets", fileCount); + if (m_MemoryCacheEnabled) + m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Memory Cache : {0} assets", m_MemoryCache.Count); + else + m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Memory cache disabled"); - foreach (string s in Directory.GetFiles(m_CacheDirectory, "*.fac")) + if (m_FileCacheEnabled) { - m_log.Info("[FLOTSAM ASSET CACHE] Deep Scans were performed on the following regions:"); - - string RegionID = s.Remove(0,s.IndexOf("_")).Replace(".fac",""); - DateTime RegionDeepScanTMStamp = File.GetLastWriteTime(s); - m_log.InfoFormat("[FLOTSAM ASSET CACHE] Region: {0}, {1}", RegionID, RegionDeepScanTMStamp.ToString("MM/dd/yyyy hh:mm:ss")); + int fileCount = GetFileCacheCount(m_CacheDirectory); + m_log.InfoFormat("[FLOTSAM ASSET CACHE]: File Cache : {0} assets", fileCount); + + foreach (string s in Directory.GetFiles(m_CacheDirectory, "*.fac")) + { + m_log.Info("[FLOTSAM ASSET CACHE]: Deep Scans were performed on the following regions:"); + + string RegionID = s.Remove(0,s.IndexOf("_")).Replace(".fac",""); + DateTime RegionDeepScanTMStamp = File.GetLastWriteTime(s); + m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Region: {0}, {1}", RegionID, RegionDeepScanTMStamp.ToString("MM/dd/yyyy hh:mm:ss")); + } + } + else + { + m_log.InfoFormat("[FLOTSAM ASSET CACHE]: File cache disabled"); } break; @@ -762,7 +782,7 @@ namespace Flotsam.RegionModules.AssetCache case "clear": if (cmdparams.Length < 2) { - m_log.Warn("[FLOTSAM ASSET CACHE] Usage is fcache clear [file] [memory]"); + m_log.Warn("[FLOTSAM ASSET CACHE]: Usage is fcache clear [file] [memory]"); break; } @@ -783,36 +803,48 @@ namespace Flotsam.RegionModules.AssetCache if (clearMemory) { - m_MemoryCache.Clear(); - m_log.Info("[FLOTSAM ASSET CACHE] Memory cache cleared."); + if (m_MemoryCacheEnabled) + { + m_MemoryCache.Clear(); + m_log.Info("[FLOTSAM ASSET CACHE]: Memory cache cleared."); + } + else + { + m_log.Info("[FLOTSAM ASSET CACHE]: Memory cache not enabled."); + } } if (clearFile) { - ClearFileCache(); - m_log.Info("[FLOTSAM ASSET CACHE] File cache cleared."); + if (m_FileCacheEnabled) + { + ClearFileCache(); + m_log.Info("[FLOTSAM ASSET CACHE]: File cache cleared."); + } + else + { + m_log.Info("[FLOTSAM ASSET CACHE]: File cache not enabled."); + } } break; case "assets": - m_log.Info("[FLOTSAM ASSET CACHE] Caching all assets, in all scenes."); + m_log.Info("[FLOTSAM ASSET CACHE]: Caching all assets, in all scenes."); Util.FireAndForget(delegate { int assetsCached = CacheScenes(); - m_log.InfoFormat("[FLOTSAM ASSET CACHE] Completed Scene Caching, {0} assets found.", assetsCached); + m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Completed Scene Caching, {0} assets found.", assetsCached); }); break; case "expire": - - if (cmdparams.Length < 3) { - m_log.InfoFormat("[FLOTSAM ASSET CACHE] Invalid parameters for Expire, please specify a valid date & time", cmd); + m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Invalid parameters for Expire, please specify a valid date & time", cmd); break; } @@ -830,26 +862,28 @@ namespace Flotsam.RegionModules.AssetCache if (!DateTime.TryParse(s_expirationDate, out expirationDate)) { - m_log.InfoFormat("[FLOTSAM ASSET CACHE] {0} is not a valid date & time", cmd); + m_log.InfoFormat("[FLOTSAM ASSET CACHE]: {0} is not a valid date & time", cmd); break; } - CleanExpiredFiles(m_CacheDirectory, expirationDate); + if (m_FileCacheEnabled) + CleanExpiredFiles(m_CacheDirectory, expirationDate); + else + m_log.InfoFormat("[FLOTSAM ASSET CACHE]: File cache not active, not clearing."); break; default: - m_log.InfoFormat("[FLOTSAM ASSET CACHE] Unknown command {0}", cmd); + m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Unknown command {0}", cmd); break; } } else if (cmdparams.Length == 1) { - m_log.InfoFormat("[FLOTSAM ASSET CACHE] flotsamcache status - Display cache status"); - m_log.InfoFormat("[FLOTSAM ASSET CACHE] flotsamcache clearmem - Remove all assets cached in memory"); - m_log.InfoFormat("[FLOTSAM ASSET CACHE] flotsamcache clearfile - Remove all assets cached on disk"); - m_log.InfoFormat("[FLOTSAM ASSET CACHE] flotsamcache cachescenes - Attempt a deep cache of all assets in all scenes"); - m_log.InfoFormat("[FLOTSAM ASSET CACHE] flotsamcache - Purge assets older then the specified date & time"); - + m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache status - Display cache status"); + m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache clearmem - Remove all assets cached in memory"); + m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache clearfile - Remove all assets cached on disk"); + m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache cachescenes - Attempt a deep cache of all assets in all scenes"); + m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache - Purge assets older then the specified date & time"); } } diff --git a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs index 3498969..a4aeeda 100644 --- a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs +++ b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs @@ -47,7 +47,7 @@ namespace OpenSim.Region.CoreModules.Asset.Tests [TestFixture] public class FlotsamAssetCacheTests { -// [Test] + [Test] public void TestCacheAsset() { TestHelper.InMethod(); @@ -58,6 +58,7 @@ namespace OpenSim.Region.CoreModules.Asset.Tests config.AddConfig("Modules"); config.Configs["Modules"].Set("AssetCaching", "FlotsamAssetCache"); config.AddConfig("AssetCache"); + config.Configs["AssetCache"].Set("FileCacheEnabled", "false"); config.Configs["AssetCache"].Set("MemoryCacheEnabled", "true"); FlotsamAssetCache cache = new FlotsamAssetCache(); -- cgit v1.1 From f58de55c843843775886a6227acbecd249a59e96 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 4 Jul 2011 22:59:36 +0100 Subject: refactor: Move test setup code into setup method --- .../Asset/Tests/FlotsamAssetCacheTests.cs | 33 +++++++++++++--------- 1 file changed, 20 insertions(+), 13 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs index a4aeeda..36cffd0 100644 --- a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs +++ b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs @@ -47,35 +47,42 @@ namespace OpenSim.Region.CoreModules.Asset.Tests [TestFixture] public class FlotsamAssetCacheTests { - [Test] - public void TestCacheAsset() - { - TestHelper.InMethod(); - log4net.Config.XmlConfigurator.Configure(); + protected TestScene m_scene; + protected FlotsamAssetCache m_cache; + [SetUp] + public void SetUp() + { IConfigSource config = new IniConfigSource(); - - config.AddConfig("Modules"); + + config.AddConfig("Modules"); config.Configs["Modules"].Set("AssetCaching", "FlotsamAssetCache"); config.AddConfig("AssetCache"); config.Configs["AssetCache"].Set("FileCacheEnabled", "false"); config.Configs["AssetCache"].Set("MemoryCacheEnabled", "true"); - FlotsamAssetCache cache = new FlotsamAssetCache(); - TestScene scene = SceneSetupHelpers.SetupScene(); - SceneSetupHelpers.SetupSceneModules(scene, config, cache); + m_cache = new FlotsamAssetCache(); + m_scene = SceneSetupHelpers.SetupScene(); + SceneSetupHelpers.SetupSceneModules(m_scene, config, m_cache); + } + + [Test] + public void TestCacheAsset() + { + TestHelper.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); AssetBase asset = AssetHelpers.CreateAsset(); asset.ID = TestHelper.ParseTail(0x1).ToString(); // Check we don't get anything before the asset is put in the cache - AssetBase retrievedAsset = cache.Get(asset.ID.ToString()); + AssetBase retrievedAsset = m_cache.Get(asset.ID.ToString()); Assert.That(retrievedAsset, Is.Null); - cache.Store(asset); + m_cache.Store(asset); // Check that asset is now in cache - retrievedAsset = cache.Get(asset.ID.ToString()); + retrievedAsset = m_cache.Get(asset.ID.ToString()); Assert.That(retrievedAsset, Is.Not.Null); Assert.That(retrievedAsset.ID, Is.EqualTo(asset.ID)); } -- cgit v1.1 From cb02fc44f5f80fce8fe9e1b87bcfa09df7960a13 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 4 Jul 2011 23:03:05 +0100 Subject: add TestExpireAsset() --- .../Asset/Tests/FlotsamAssetCacheTests.cs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs index 36cffd0..bbe40d1 100644 --- a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs +++ b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs @@ -44,6 +44,9 @@ using OpenSim.Tests.Common.Mock; namespace OpenSim.Region.CoreModules.Asset.Tests { + /// + /// At the moment we're only test the in-memory part of the FlotsamAssetCache. This is a considerable weakness. + /// [TestFixture] public class FlotsamAssetCacheTests { @@ -86,5 +89,22 @@ namespace OpenSim.Region.CoreModules.Asset.Tests Assert.That(retrievedAsset, Is.Not.Null); Assert.That(retrievedAsset.ID, Is.EqualTo(asset.ID)); } + + [Test] + public void TestExpireAsset() + { + TestHelper.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + AssetBase asset = AssetHelpers.CreateAsset(); + asset.ID = TestHelper.ParseTail(0x2).ToString(); + + m_cache.Store(asset); + + m_cache.Expire(asset.ID); + + AssetBase retrievedAsset = m_cache.Get(asset.ID.ToString()); + Assert.That(retrievedAsset, Is.Null); + } } } \ No newline at end of file -- cgit v1.1 From af8773d6d076f5d74133857a5074bd9e9504dd64 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 4 Jul 2011 23:05:31 +0100 Subject: Add TestClearCache() --- .../CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs index bbe40d1..63b0c31 100644 --- a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs +++ b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs @@ -106,5 +106,22 @@ namespace OpenSim.Region.CoreModules.Asset.Tests AssetBase retrievedAsset = m_cache.Get(asset.ID.ToString()); Assert.That(retrievedAsset, Is.Null); } + + [Test] + public void TestClearCache() + { + TestHelper.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + AssetBase asset = AssetHelpers.CreateAsset(); + asset.ID = TestHelper.ParseTail(0x2).ToString(); + + m_cache.Store(asset); + + m_cache.Clear(); + + AssetBase retrievedAsset = m_cache.Get(asset.ID.ToString()); + Assert.That(retrievedAsset, Is.Null); + } } } \ No newline at end of file -- cgit v1.1 From 281e80ccf3353b4876eaff97b7accaf547561634 Mon Sep 17 00:00:00 2001 From: Michael Cerquoni aka Nebadon Izumi Date: Thu, 7 Jul 2011 03:18:04 -0700 Subject: add MeshUploadFlag capability fixed mesh upload with latest mesh viewer thank you dahlia and lkalif for helping to make this happen! --- .../Linden/Caps/BunchOfCaps/BunchOfCaps.cs | 40 ++++--- .../Linden/Caps/MeshUploadFlagModule.cs | 128 +++++++++++++++++++++ 2 files changed, 150 insertions(+), 18 deletions(-) create mode 100644 OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs (limited to 'OpenSim') diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs index 6786ac5..d3bb0bc 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) Contributors, http://opensimulator.org/ * See CONTRIBUTORS.TXT for a full list of copyright holders. * @@ -595,21 +595,25 @@ namespace OpenSim.Region.ClientStack.Linden Vector3 scale = inner_instance_list["scale"].AsVector3(); Quaternion rotation = inner_instance_list["rotation"].AsQuaternion(); +// no longer used - begin ------------------------ // int physicsShapeType = inner_instance_list["physics_shape_type"].AsInteger(); // int material = inner_instance_list["material"].AsInteger(); // int mesh = inner_instance_list["mesh"].AsInteger(); - OSDMap permissions = (OSDMap)inner_instance_list["permissions"]; - int base_mask = permissions["base_mask"].AsInteger(); - int everyone_mask = permissions["everyone_mask"].AsInteger(); - UUID creator_id = permissions["creator_id"].AsUUID(); - UUID group_id = permissions["group_id"].AsUUID(); - int group_mask = permissions["group_mask"].AsInteger(); +// OSDMap permissions = (OSDMap)inner_instance_list["permissions"]; +// int base_mask = permissions["base_mask"].AsInteger(); +// int everyone_mask = permissions["everyone_mask"].AsInteger(); +// UUID creator_id = permissions["creator_id"].AsUUID(); +// UUID group_id = permissions["group_id"].AsUUID(); +// int group_mask = permissions["group_mask"].AsInteger(); // bool is_owner_group = permissions["is_owner_group"].AsBoolean(); // UUID last_owner_id = permissions["last_owner_id"].AsUUID(); - int next_owner_mask = permissions["next_owner_mask"].AsInteger(); - UUID owner_id = permissions["owner_id"].AsUUID(); - int owner_mask = permissions["owner_mask"].AsInteger(); +// int next_owner_mask = permissions["next_owner_mask"].AsInteger(); +// UUID owner_id = permissions["owner_id"].AsUUID(); +// int owner_mask = permissions["owner_mask"].AsInteger(); +// no longer used - end ------------------------ + + UUID owner_id = m_HostCapsObj.AgentID; SceneObjectPart prim = new SceneObjectPart(owner_id, pbs, position, Quaternion.Identity, Vector3.Zero); @@ -619,19 +623,19 @@ namespace OpenSim.Region.ClientStack.Linden rotations.Add(rotation); positions.Add(position); prim.UUID = UUID.Random(); - prim.CreatorID = creator_id; + prim.CreatorID = owner_id; prim.OwnerID = owner_id; - prim.GroupID = group_id; + prim.GroupID = UUID.Zero; prim.LastOwnerID = prim.OwnerID; prim.CreationDate = Util.UnixTimeSinceEpoch(); prim.Name = assetName; prim.Description = ""; - prim.BaseMask = (uint)base_mask; - prim.EveryoneMask = (uint)everyone_mask; - prim.GroupMask = (uint)group_mask; - prim.NextOwnerMask = (uint)next_owner_mask; - prim.OwnerMask = (uint)owner_mask; +// prim.BaseMask = (uint)base_mask; +// prim.EveryoneMask = (uint)everyone_mask; +// prim.GroupMask = (uint)group_mask; +// prim.NextOwnerMask = (uint)next_owner_mask; +// prim.OwnerMask = (uint)owner_mask; if (grp == null) grp = new SceneObjectGroup(prim); @@ -1123,4 +1127,4 @@ namespace OpenSim.Region.ClientStack.Linden } } -} +} \ No newline at end of file diff --git a/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs new file mode 100644 index 0000000..98f9663 --- /dev/null +++ b/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs @@ -0,0 +1,128 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * 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; +using System.Reflection; +using log4net; +using Nini.Config; +using Mono.Addins; +using OpenMetaverse; +using OpenMetaverse.StructuredData; +using OpenSim.Framework; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; +using Caps = OpenSim.Framework.Capabilities.Caps; + +namespace OpenSim.Region.ClientStack.Linden +{ + /// + /// MeshUploadFlag capability. This is required for uploading Mesh. + /// + /// + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] + public class MeshUploadFlagModule : ISharedRegionModule + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private Scene m_scene; + private UUID m_agentID; + + + #region ISharedRegionModule Members + + public void Initialise(IConfigSource source) + { + IConfig config = source.Configs["MeshUploadFlag"]; + if (config == null) + return; + } + + public void AddRegion(Scene s) + { + m_scene = s; + m_scene.EventManager.OnRegisterCaps += RegisterCaps; + } + + public void RemoveRegion(Scene s) + { + m_scene.EventManager.OnRegisterCaps -= RegisterCaps; + } + + public void RegionLoaded(Scene s) + { + } + + public void PostInitialise() + { + } + + public void Close() { } + + public string Name { get { return "MeshUploadFlagModule"; } } + + public Type ReplaceableInterface + { + get { return null; } + } + + #endregion + + public void RegisterCaps(UUID agentID, Caps caps) + { + IRequestHandler reqHandler = new RestHTTPHandler("GET", "/CAPS/" + UUID.Random(), MeshUploadFlag); + caps.RegisterHandler("MeshUploadFlag", reqHandler); + m_agentID = agentID; + } + + private Hashtable MeshUploadFlag(Hashtable mDhttpMethod) + { + m_log.DebugFormat("[SIMULATOR FEATURES MODULE]: MeshUploadFlag request"); + OSDMap data = new OSDMap(); + ScenePresence sp = m_scene.GetScenePresence(m_agentID); + data["username"] = sp.Firstname + "." + sp.Lastname; + data["display_name_next_update"] = new OSDDate(DateTime.Now); + data["legacy_first_name"] = sp.Firstname; + data["mesh_upload_status"] = "valid"; + data["display_name"] = sp.Firstname + " " + sp.Lastname; + data["legacy_last_name"] = sp.Lastname; + data["id"] = m_agentID; + data["is_display_name_default"] = true; + + //Send back data + Hashtable responsedata = new Hashtable(); + responsedata["int_response_code"] = 200; + responsedata["content_type"] = "text/plain"; + responsedata["keepalive"] = false; + responsedata["str_response_string"] = OSDParser.SerializeLLSDXmlString(data); + return responsedata; + } + + } +} \ No newline at end of file -- cgit v1.1 From e91861fff2fa4475da23e12fe1e89100c1c8a246 Mon Sep 17 00:00:00 2001 From: Mic Bowman Date: Thu, 7 Jul 2011 09:12:57 -0700 Subject: Ensure that the max transfer distance is initialized correctly. --- .../CoreModules/Framework/EntityTransfer/EntityTransferModule.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index d54216a..457ee33 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -53,7 +53,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer /// /// The maximum distance, in standard region units (256m) that an agent is allowed to transfer. /// - public int MaxTransferDistance { get; set; } + private int m_MaxTransferDistance = 4095; + public int MaxTransferDistance + { + get { return m_MaxTransferDistance; } + set { m_MaxTransferDistance = value; } + } + protected bool m_Enabled = false; protected Scene m_aScene; -- cgit v1.1 From 2fbc98fa5c518d549768899573fa506a22f529e6 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 7 Jul 2011 23:37:23 +0100 Subject: Make MeshUploadFlagModule non-shared rather than shared (since each scene needs its own cap) --- OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs index 98f9663..2d15ca5 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs @@ -47,7 +47,7 @@ namespace OpenSim.Region.ClientStack.Linden /// /// [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class MeshUploadFlagModule : ISharedRegionModule + public class MeshUploadFlagModule : INonSharedRegionModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); -- cgit v1.1 From 3bda7711b3998d21d0ce78d99273f83d6ee73991 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 7 Jul 2011 23:49:19 +0100 Subject: Switch the MeshUploadFlag CAP module on and off with the existing config AllowMeshUpload flag in [Mesh] (in OpenSimDefaults.ini) Default is on. --- .../Linden/Caps/MeshUploadFlagModule.cs | 49 +++++++++++++++------- 1 file changed, 35 insertions(+), 14 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs index 2d15ca5..c9d7ae1 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs @@ -45,33 +45,54 @@ namespace OpenSim.Region.ClientStack.Linden /// /// MeshUploadFlag capability. This is required for uploading Mesh. /// - /// [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] public class MeshUploadFlagModule : INonSharedRegionModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// Is this module enabled? + /// + public bool Enabled { get; private set; } + private Scene m_scene; private UUID m_agentID; - #region ISharedRegionModule Members + public MeshUploadFlagModule() + { + Enabled = true; + } + public void Initialise(IConfigSource source) { - IConfig config = source.Configs["MeshUploadFlag"]; + IConfig config = source.Configs["Mesh"]; if (config == null) + { return; + } + else + { + Enabled = config.GetBoolean("AllowMeshUpload", Enabled); + } } public void AddRegion(Scene s) { + if (!Enabled) + return; + m_scene = s; m_scene.EventManager.OnRegisterCaps += RegisterCaps; } public void RemoveRegion(Scene s) { + if (!Enabled) + return; + m_scene.EventManager.OnRegisterCaps -= RegisterCaps; } @@ -98,22 +119,23 @@ namespace OpenSim.Region.ClientStack.Linden { IRequestHandler reqHandler = new RestHTTPHandler("GET", "/CAPS/" + UUID.Random(), MeshUploadFlag); caps.RegisterHandler("MeshUploadFlag", reqHandler); - m_agentID = agentID; + m_agentID = agentID; } private Hashtable MeshUploadFlag(Hashtable mDhttpMethod) { m_log.DebugFormat("[SIMULATOR FEATURES MODULE]: MeshUploadFlag request"); + OSDMap data = new OSDMap(); - ScenePresence sp = m_scene.GetScenePresence(m_agentID); - data["username"] = sp.Firstname + "." + sp.Lastname; - data["display_name_next_update"] = new OSDDate(DateTime.Now); - data["legacy_first_name"] = sp.Firstname; - data["mesh_upload_status"] = "valid"; - data["display_name"] = sp.Firstname + " " + sp.Lastname; - data["legacy_last_name"] = sp.Lastname; - data["id"] = m_agentID; - data["is_display_name_default"] = true; + ScenePresence sp = m_scene.GetScenePresence(m_agentID); + data["username"] = sp.Firstname + "." + sp.Lastname; + data["display_name_next_update"] = new OSDDate(DateTime.Now); + data["legacy_first_name"] = sp.Firstname; + data["mesh_upload_status"] = "valid"; + data["display_name"] = sp.Firstname + " " + sp.Lastname; + data["legacy_last_name"] = sp.Lastname; + data["id"] = m_agentID; + data["is_display_name_default"] = true; //Send back data Hashtable responsedata = new Hashtable(); @@ -123,6 +145,5 @@ namespace OpenSim.Region.ClientStack.Linden responsedata["str_response_string"] = OSDParser.SerializeLLSDXmlString(data); return responsedata; } - } } \ No newline at end of file -- cgit v1.1 From 1dcad4ac6616a21216eeb139c901d98eed9169db Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 8 Jul 2011 17:58:01 +0100 Subject: minor: commented out log lines for future use and very small code tidy --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 4 ++++ OpenSim/Region/Physics/Manager/PhysicsScene.cs | 5 ++++- OpenSim/Region/Physics/Meshing/Meshmerizer.cs | 2 ++ OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | 10 ++++++---- OpenSim/Region/Physics/OdePlugin/OdePlugin.cs | 2 ++ 5 files changed, 18 insertions(+), 5 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index f3879f0..cd5046a 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -1564,6 +1564,8 @@ namespace OpenSim.Region.Framework.Scenes /// public void ApplyPhysics(uint rootObjectFlags, bool VolumeDetectActive, bool m_physicalPrim) { +// m_log.DebugFormat("[SCENE OBJECT PART]: Applying physics to {0} {1} {2}", Name, LocalId, UUID); + bool isPhysical = (((rootObjectFlags & (uint) PrimFlags.Physics) != 0) && m_physicalPrim); bool isPhantom = ((rootObjectFlags & (uint) PrimFlags.Phantom) != 0); @@ -1584,6 +1586,8 @@ namespace OpenSim.Region.Framework.Scenes // or flexible if (!isPhantom && !IsAttachment && !(Shape.PathCurve == (byte) Extrusion.Flexible)) { +// m_log.DebugFormat("[SCENE OBJECT PART]: Creating PhysActor for {0} {1} {2}", Name, LocalId, UUID); + PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape( LocalId, string.Format("{0}/{1}", Name, UUID), diff --git a/OpenSim/Region/Physics/Manager/PhysicsScene.cs b/OpenSim/Region/Physics/Manager/PhysicsScene.cs index 54c50f8..13ea084 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsScene.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsScene.cs @@ -86,7 +86,10 @@ namespace OpenSim.Region.Physics.Manager Vector3 size, Quaternion rotation, bool isPhysical) { PhysicsActor ret = AddPrimShape(primName, pbs, position, size, rotation, isPhysical); - if (ret != null) ret.LocalID = localID; + + if (ret != null) + ret.LocalID = localID; + return ret; } diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index a5fe45b..be4ee41 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs @@ -643,6 +643,8 @@ namespace OpenSim.Region.Physics.Meshing public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical) { +// m_log.DebugFormat("[MESH]: Creating mesh for {0}", primName); + Mesh mesh = null; ulong key = 0; diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index c91658e..1060278 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs @@ -791,6 +791,8 @@ namespace OpenSim.Region.Physics.OdePlugin public void setMesh(OdeScene parent_scene, IMesh mesh) { +// m_log.DebugFormat("[ODE PRIM]: Setting mesh on {0} to {1}", Name, mesh); + // This sleeper is there to moderate how long it takes between // setting up the mesh and pre-processing it when we get rapid fire mesh requests on a single object @@ -1398,7 +1400,6 @@ namespace OpenSim.Region.Physics.OdePlugin } } } - else { _parent_scene.waitForSpaceUnlock(m_targetSpace); @@ -1960,7 +1961,7 @@ Console.WriteLine(" JointCreateFixed"); mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); //IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); -//Console.WriteLine("changesize 1"); +Console.WriteLine("changesize 1"); CreateGeom(m_targetSpace, mesh); @@ -1968,7 +1969,7 @@ Console.WriteLine(" JointCreateFixed"); else { _mesh = null; -//Console.WriteLine("changesize 2"); +Console.WriteLine("changesize 2"); CreateGeom(m_targetSpace, _mesh); } @@ -2070,12 +2071,13 @@ Console.WriteLine(" JointCreateFixed"); IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); // createmesh returns null when it doesn't mesh. +Console.WriteLine("changeshape needed meshing"); CreateGeom(m_targetSpace, mesh); } else { _mesh = null; -//Console.WriteLine("changeshape"); +Console.WriteLine("changeshape not need meshing"); CreateGeom(m_targetSpace, null); } diff --git a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs index 8d9f5f1..ae9c377 100644 --- a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs +++ b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs @@ -1770,6 +1770,8 @@ namespace OpenSim.Region.Physics.OdePlugin public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, Vector3 size, Quaternion rotation, bool isPhysical) { +// m_log.DebugFormat("[PHYSICS]: Adding physics actor to {0}", primName); + PhysicsActor result; IMesh mesh = null; -- cgit v1.1 From 36df9ae79a8cd1d4964a42c79e26ad2a226be0ba Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 8 Jul 2011 18:16:48 +0100 Subject: refactor: Separate the OdeScene class into its own file from OdePlugin.cs, to improve code readability --- OpenSim/Region/Physics/OdePlugin/OdePlugin.cs | 3832 +----------------------- OpenSim/Region/Physics/OdePlugin/OdeScene.cs | 3866 +++++++++++++++++++++++++ 2 files changed, 3873 insertions(+), 3825 deletions(-) create mode 100644 OpenSim/Region/Physics/OdePlugin/OdeScene.cs (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs index ae9c377..ebd46ab 100644 --- a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs +++ b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs @@ -25,8 +25,6 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -//#define USE_DRAWSTUFF - using System; using System.Collections.Generic; using System.Reflection; @@ -37,15 +35,10 @@ using System.Diagnostics; using log4net; using Nini.Config; using Ode.NET; -#if USE_DRAWSTUFF -using Drawstuff.NET; -#endif using OpenSim.Framework; using OpenSim.Region.Physics.Manager; using OpenMetaverse; -//using OpenSim.Region.Physics.OdePlugin.Meshing; - namespace OpenSim.Region.Physics.OdePlugin { /// @@ -55,12 +48,12 @@ namespace OpenSim.Region.Physics.OdePlugin { //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - private CollisionLocker ode; - private OdeScene _mScene; + private CollisionLocker m_ode; + private OdeScene m_scene; public OdePlugin() { - ode = new CollisionLocker(); + m_ode = new CollisionLocker(); } public bool Init() @@ -70,15 +63,15 @@ namespace OpenSim.Region.Physics.OdePlugin public PhysicsScene GetScene(String sceneIdentifier) { - if (_mScene == null) + if (m_scene == null) { // Initializing ODE only when a scene is created allows alternative ODE plugins to co-habit (according to // http://opensimulator.org/mantis/view.php?id=2750). d.InitODE(); - _mScene = new OdeScene(ode, sceneIdentifier); + m_scene = new OdeScene(m_ode, sceneIdentifier); } - return (_mScene); + return (m_scene); } public string GetName() @@ -90,3815 +83,4 @@ namespace OpenSim.Region.Physics.OdePlugin { } } - - public enum StatusIndicators : int - { - Generic = 0, - Start = 1, - End = 2 - } - - public struct sCollisionData - { - public uint ColliderLocalId; - public uint CollidedWithLocalId; - public int NumberOfCollisions; - public int CollisionType; - public int StatusIndicator; - public int lastframe; - } - - [Flags] - public enum CollisionCategories : int - { - Disabled = 0, - Geom = 0x00000001, - Body = 0x00000002, - Space = 0x00000004, - Character = 0x00000008, - Land = 0x00000010, - Water = 0x00000020, - Wind = 0x00000040, - Sensor = 0x00000080, - Selected = 0x00000100 - } - - /// - /// Material type for a primitive - /// - public enum Material : int - { - /// - Stone = 0, - /// - Metal = 1, - /// - Glass = 2, - /// - Wood = 3, - /// - Flesh = 4, - /// - Plastic = 5, - /// - Rubber = 6 - - } - - public sealed class OdeScene : PhysicsScene - { - private readonly ILog m_log; - // private Dictionary m_storedCollisions = new Dictionary(); - - CollisionLocker ode; - - private Random fluidRandomizer = new Random(Environment.TickCount); - - private const uint m_regionWidth = Constants.RegionSize; - private const uint m_regionHeight = Constants.RegionSize; - - private float ODE_STEPSIZE = 0.020f; - private float metersInSpace = 29.9f; - private float m_timeDilation = 1.0f; - - public float gravityx = 0f; - public float gravityy = 0f; - public float gravityz = -9.8f; - - private float contactsurfacelayer = 0.001f; - - private int worldHashspaceLow = -4; - private int worldHashspaceHigh = 128; - - private int smallHashspaceLow = -4; - private int smallHashspaceHigh = 66; - - private float waterlevel = 0f; - private int framecount = 0; - //private int m_returncollisions = 10; - - private readonly IntPtr contactgroup; - - internal IntPtr LandGeom; - internal IntPtr WaterGeom; - - private float nmTerrainContactFriction = 255.0f; - private float nmTerrainContactBounce = 0.1f; - private float nmTerrainContactERP = 0.1025f; - - private float mTerrainContactFriction = 75f; - private float mTerrainContactBounce = 0.1f; - private float mTerrainContactERP = 0.05025f; - - private float nmAvatarObjectContactFriction = 250f; - private float nmAvatarObjectContactBounce = 0.1f; - - private float mAvatarObjectContactFriction = 75f; - private float mAvatarObjectContactBounce = 0.1f; - - private float avPIDD = 3200f; - private float avPIDP = 1400f; - private float avCapRadius = 0.37f; - private float avStandupTensor = 2000000f; - private bool avCapsuleTilted = true; // true = old compatibility mode with leaning capsule; false = new corrected mode - public bool IsAvCapsuleTilted { get { return avCapsuleTilted; } set { avCapsuleTilted = value; } } - private float avDensity = 80f; - private float avHeightFudgeFactor = 0.52f; - private float avMovementDivisorWalk = 1.3f; - private float avMovementDivisorRun = 0.8f; - private float minimumGroundFlightOffset = 3f; - public float maximumMassObject = 10000.01f; - - public bool meshSculptedPrim = true; - public bool forceSimplePrimMeshing = false; - - public float meshSculptLOD = 32; - public float MeshSculptphysicalLOD = 16; - - public float geomDefaultDensity = 10.000006836f; - - public int geomContactPointsStartthrottle = 3; - public int geomUpdatesPerThrottledUpdate = 15; - - public float bodyPIDD = 35f; - public float bodyPIDG = 25; - - public int geomCrossingFailuresBeforeOutofbounds = 5; - - public float bodyMotorJointMaxforceTensor = 2; - - public int bodyFramesAutoDisable = 20; - - - - private float[] _watermap; - private bool m_filterCollisions = true; - - private d.NearCallback nearCallback; - public d.TriCallback triCallback; - public d.TriArrayCallback triArrayCallback; - private readonly HashSet _characters = new HashSet(); - private readonly HashSet _prims = new HashSet(); - private readonly HashSet _activeprims = new HashSet(); - private readonly HashSet _taintedPrimH = new HashSet(); - private readonly Object _taintedPrimLock = new Object(); - private readonly List _taintedPrimL = new List(); - private readonly HashSet _taintedActors = new HashSet(); - private readonly List _perloopContact = new List(); - private readonly List _collisionEventPrim = new List(); - private readonly HashSet _badCharacter = new HashSet(); - public Dictionary geom_name_map = new Dictionary(); - public Dictionary actor_name_map = new Dictionary(); - private bool m_NINJA_physics_joints_enabled = false; - //private Dictionary jointpart_name_map = new Dictionary(); - private readonly Dictionary> joints_connecting_actor = new Dictionary>(); - private d.ContactGeom[] contacts; - private readonly List requestedJointsToBeCreated = new List(); // lock only briefly. accessed by external code (to request new joints) and by OdeScene.Simulate() to move those joints into pending/active - private readonly List pendingJoints = new List(); // can lock for longer. accessed only by OdeScene. - private readonly List activeJoints = new List(); // can lock for longer. accessed only by OdeScene. - private readonly List requestedJointsToBeDeleted = new List(); // lock only briefly. accessed by external code (to request deletion of joints) and by OdeScene.Simulate() to move those joints out of pending/active - private Object externalJointRequestsLock = new Object(); - private readonly Dictionary SOPName_to_activeJoint = new Dictionary(); - private readonly Dictionary SOPName_to_pendingJoint = new Dictionary(); - private readonly DoubleDictionary RegionTerrain = new DoubleDictionary(); - private readonly Dictionary TerrainHeightFieldHeights = new Dictionary(); - - private d.Contact contact; - private d.Contact TerrainContact; - private d.Contact AvatarMovementprimContact; - private d.Contact AvatarMovementTerrainContact; - private d.Contact WaterContact; - private d.Contact[,] m_materialContacts; - -//Ckrinke: Comment out until used. We declare it, initialize it, but do not use it -//Ckrinke private int m_randomizeWater = 200; - private int m_physicsiterations = 10; - private const float m_SkipFramesAtms = 0.40f; // Drop frames gracefully at a 400 ms lag - private readonly PhysicsActor PANull = new NullPhysicsActor(); - private float step_time = 0.0f; -//Ckrinke: Comment out until used. We declare it, initialize it, but do not use it -//Ckrinke private int ms = 0; - public IntPtr world; - //private bool returncollisions = false; - // private uint obj1LocalID = 0; - private uint obj2LocalID = 0; - //private int ctype = 0; - private OdeCharacter cc1; - private OdePrim cp1; - private OdeCharacter cc2; - private OdePrim cp2; - private int tickCountFrameRun; - - private int latertickcount=0; - //private int cStartStop = 0; - //private string cDictKey = ""; - - public IntPtr space; - - //private IntPtr tmpSpace; - // split static geometry collision handling into spaces of 30 meters - public IntPtr[,] staticPrimspace; - - public Object OdeLock; - - public IMesher mesher; - - private IConfigSource m_config; - - public bool physics_logging = false; - public int physics_logging_interval = 0; - public bool physics_logging_append_existing_logfile = false; - - public d.Vector3 xyz = new d.Vector3(128.1640f, 128.3079f, 25.7600f); - public d.Vector3 hpr = new d.Vector3(125.5000f, -17.0000f, 0.0000f); - - // TODO: unused: private uint heightmapWidth = m_regionWidth + 1; - // TODO: unused: private uint heightmapHeight = m_regionHeight + 1; - // TODO: unused: private uint heightmapWidthSamples; - // TODO: unused: private uint heightmapHeightSamples; - - private volatile int m_global_contactcount = 0; - - private Vector3 m_worldOffset = Vector3.Zero; - public Vector2 WorldExtents = new Vector2((int)Constants.RegionSize, (int)Constants.RegionSize); - private PhysicsScene m_parentScene = null; - - private ODERayCastRequestManager m_rayCastManager; - - /// - /// Initiailizes the scene - /// Sets many properties that ODE requires to be stable - /// These settings need to be tweaked 'exactly' right or weird stuff happens. - /// - public OdeScene(CollisionLocker dode, string sceneIdentifier) - { - m_log - = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType.ToString() + "." + sceneIdentifier); - - OdeLock = new Object(); - ode = dode; - nearCallback = near; - triCallback = TriCallback; - triArrayCallback = TriArrayCallback; - m_rayCastManager = new ODERayCastRequestManager(this); - lock (OdeLock) - { - // Create the world and the first space - world = d.WorldCreate(); - space = d.HashSpaceCreate(IntPtr.Zero); - - - contactgroup = d.JointGroupCreate(0); - //contactgroup - - d.WorldSetAutoDisableFlag(world, false); - #if USE_DRAWSTUFF - - Thread viewthread = new Thread(new ParameterizedThreadStart(startvisualization)); - viewthread.Start(); - #endif - } - - - _watermap = new float[258 * 258]; - - // Zero out the prim spaces array (we split our space into smaller spaces so - // we can hit test less. - } - -#if USE_DRAWSTUFF - public void startvisualization(object o) - { - ds.Functions fn; - fn.version = ds.VERSION; - fn.start = new ds.CallbackFunction(start); - fn.step = new ds.CallbackFunction(step); - fn.command = new ds.CallbackFunction(command); - fn.stop = null; - fn.path_to_textures = "./textures"; - string[] args = new string[0]; - ds.SimulationLoop(args.Length, args, 352, 288, ref fn); - } -#endif - - // Initialize the mesh plugin - public override void Initialise(IMesher meshmerizer, IConfigSource config) - { - mesher = meshmerizer; - m_config = config; - // Defaults - - if (Environment.OSVersion.Platform == PlatformID.Unix) - { - avPIDD = 3200.0f; - avPIDP = 1400.0f; - avStandupTensor = 2000000f; - } - else - { - avPIDD = 2200.0f; - avPIDP = 900.0f; - avStandupTensor = 550000f; - } - - int contactsPerCollision = 80; - - if (m_config != null) - { - IConfig physicsconfig = m_config.Configs["ODEPhysicsSettings"]; - if (physicsconfig != null) - { - gravityx = physicsconfig.GetFloat("world_gravityx", 0f); - gravityy = physicsconfig.GetFloat("world_gravityy", 0f); - gravityz = physicsconfig.GetFloat("world_gravityz", -9.8f); - - worldHashspaceLow = physicsconfig.GetInt("world_hashspace_size_low", -4); - worldHashspaceHigh = physicsconfig.GetInt("world_hashspace_size_high", 128); - - metersInSpace = physicsconfig.GetFloat("meters_in_small_space", 29.9f); - smallHashspaceLow = physicsconfig.GetInt("small_hashspace_size_low", -4); - smallHashspaceHigh = physicsconfig.GetInt("small_hashspace_size_high", 66); - - contactsurfacelayer = physicsconfig.GetFloat("world_contact_surface_layer", 0.001f); - - nmTerrainContactFriction = physicsconfig.GetFloat("nm_terraincontact_friction", 255.0f); - nmTerrainContactBounce = physicsconfig.GetFloat("nm_terraincontact_bounce", 0.1f); - nmTerrainContactERP = physicsconfig.GetFloat("nm_terraincontact_erp", 0.1025f); - - mTerrainContactFriction = physicsconfig.GetFloat("m_terraincontact_friction", 75f); - mTerrainContactBounce = physicsconfig.GetFloat("m_terraincontact_bounce", 0.05f); - mTerrainContactERP = physicsconfig.GetFloat("m_terraincontact_erp", 0.05025f); - - nmAvatarObjectContactFriction = physicsconfig.GetFloat("objectcontact_friction", 250f); - nmAvatarObjectContactBounce = physicsconfig.GetFloat("objectcontact_bounce", 0.2f); - - mAvatarObjectContactFriction = physicsconfig.GetFloat("m_avatarobjectcontact_friction", 75f); - mAvatarObjectContactBounce = physicsconfig.GetFloat("m_avatarobjectcontact_bounce", 0.1f); - - ODE_STEPSIZE = physicsconfig.GetFloat("world_stepsize", 0.020f); - m_physicsiterations = physicsconfig.GetInt("world_internal_steps_without_collisions", 10); - - avDensity = physicsconfig.GetFloat("av_density", 80f); - avHeightFudgeFactor = physicsconfig.GetFloat("av_height_fudge_factor", 0.52f); - avMovementDivisorWalk = physicsconfig.GetFloat("av_movement_divisor_walk", 1.3f); - avMovementDivisorRun = physicsconfig.GetFloat("av_movement_divisor_run", 0.8f); - avCapRadius = physicsconfig.GetFloat("av_capsule_radius", 0.37f); - avCapsuleTilted = physicsconfig.GetBoolean("av_capsule_tilted", false); - - contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", 80); - - geomContactPointsStartthrottle = physicsconfig.GetInt("geom_contactpoints_start_throttling", 3); - geomUpdatesPerThrottledUpdate = physicsconfig.GetInt("geom_updates_before_throttled_update", 15); - geomCrossingFailuresBeforeOutofbounds = physicsconfig.GetInt("geom_crossing_failures_before_outofbounds", 5); - - geomDefaultDensity = physicsconfig.GetFloat("geometry_default_density", 10.000006836f); - bodyFramesAutoDisable = physicsconfig.GetInt("body_frames_auto_disable", 20); - - bodyPIDD = physicsconfig.GetFloat("body_pid_derivative", 35f); - bodyPIDG = physicsconfig.GetFloat("body_pid_gain", 25f); - - forceSimplePrimMeshing = physicsconfig.GetBoolean("force_simple_prim_meshing", forceSimplePrimMeshing); - meshSculptedPrim = physicsconfig.GetBoolean("mesh_sculpted_prim", true); - meshSculptLOD = physicsconfig.GetFloat("mesh_lod", 32f); - MeshSculptphysicalLOD = physicsconfig.GetFloat("mesh_physical_lod", 16f); - m_filterCollisions = physicsconfig.GetBoolean("filter_collisions", false); - - if (Environment.OSVersion.Platform == PlatformID.Unix) - { - avPIDD = physicsconfig.GetFloat("av_pid_derivative_linux", 2200.0f); - avPIDP = physicsconfig.GetFloat("av_pid_proportional_linux", 900.0f); - avStandupTensor = physicsconfig.GetFloat("av_capsule_standup_tensor_linux", 550000f); - bodyMotorJointMaxforceTensor = physicsconfig.GetFloat("body_motor_joint_maxforce_tensor_linux", 5f); - } - else - { - avPIDD = physicsconfig.GetFloat("av_pid_derivative_win", 2200.0f); - avPIDP = physicsconfig.GetFloat("av_pid_proportional_win", 900.0f); - avStandupTensor = physicsconfig.GetFloat("av_capsule_standup_tensor_win", 550000f); - bodyMotorJointMaxforceTensor = physicsconfig.GetFloat("body_motor_joint_maxforce_tensor_win", 5f); - } - - physics_logging = physicsconfig.GetBoolean("physics_logging", false); - physics_logging_interval = physicsconfig.GetInt("physics_logging_interval", 0); - physics_logging_append_existing_logfile = physicsconfig.GetBoolean("physics_logging_append_existing_logfile", false); - - m_NINJA_physics_joints_enabled = physicsconfig.GetBoolean("use_NINJA_physics_joints", false); - minimumGroundFlightOffset = physicsconfig.GetFloat("minimum_ground_flight_offset", 3f); - maximumMassObject = physicsconfig.GetFloat("maximum_mass_object", 10000.01f); - } - } - - contacts = new d.ContactGeom[contactsPerCollision]; - - staticPrimspace = new IntPtr[(int)(300 / metersInSpace), (int)(300 / metersInSpace)]; - - // Centeral contact friction and bounce - // ckrinke 11/10/08 Enabling soft_erp but not soft_cfm until I figure out why - // an avatar falls through in Z but not in X or Y when walking on a prim. - contact.surface.mode |= d.ContactFlags.SoftERP; - contact.surface.mu = nmAvatarObjectContactFriction; - contact.surface.bounce = nmAvatarObjectContactBounce; - contact.surface.soft_cfm = 0.010f; - contact.surface.soft_erp = 0.010f; - - // Terrain contact friction and Bounce - // This is the *non* moving version. Use this when an avatar - // isn't moving to keep it in place better - TerrainContact.surface.mode |= d.ContactFlags.SoftERP; - TerrainContact.surface.mu = nmTerrainContactFriction; - TerrainContact.surface.bounce = nmTerrainContactBounce; - TerrainContact.surface.soft_erp = nmTerrainContactERP; - - WaterContact.surface.mode |= (d.ContactFlags.SoftERP | d.ContactFlags.SoftCFM); - WaterContact.surface.mu = 0f; // No friction - WaterContact.surface.bounce = 0.0f; // No bounce - WaterContact.surface.soft_cfm = 0.010f; - WaterContact.surface.soft_erp = 0.010f; - - // Prim contact friction and bounce - // THis is the *non* moving version of friction and bounce - // Use this when an avatar comes in contact with a prim - // and is moving - AvatarMovementprimContact.surface.mu = mAvatarObjectContactFriction; - AvatarMovementprimContact.surface.bounce = mAvatarObjectContactBounce; - - // Terrain contact friction bounce and various error correcting calculations - // Use this when an avatar is in contact with the terrain and moving. - AvatarMovementTerrainContact.surface.mode |= d.ContactFlags.SoftERP; - AvatarMovementTerrainContact.surface.mu = mTerrainContactFriction; - AvatarMovementTerrainContact.surface.bounce = mTerrainContactBounce; - AvatarMovementTerrainContact.surface.soft_erp = mTerrainContactERP; - - - /* - - Stone = 0, - /// - Metal = 1, - /// - Glass = 2, - /// - Wood = 3, - /// - Flesh = 4, - /// - Plastic = 5, - /// - Rubber = 6 - */ - - m_materialContacts = new d.Contact[7,2]; - - m_materialContacts[(int)Material.Stone, 0] = new d.Contact(); - m_materialContacts[(int)Material.Stone, 0].surface.mode |= d.ContactFlags.SoftERP; - m_materialContacts[(int)Material.Stone, 0].surface.mu = nmAvatarObjectContactFriction; - m_materialContacts[(int)Material.Stone, 0].surface.bounce = nmAvatarObjectContactBounce; - m_materialContacts[(int)Material.Stone, 0].surface.soft_cfm = 0.010f; - m_materialContacts[(int)Material.Stone, 0].surface.soft_erp = 0.010f; - - m_materialContacts[(int)Material.Stone, 1] = new d.Contact(); - m_materialContacts[(int)Material.Stone, 1].surface.mode |= d.ContactFlags.SoftERP; - m_materialContacts[(int)Material.Stone, 1].surface.mu = mAvatarObjectContactFriction; - m_materialContacts[(int)Material.Stone, 1].surface.bounce = mAvatarObjectContactBounce; - m_materialContacts[(int)Material.Stone, 1].surface.soft_cfm = 0.010f; - m_materialContacts[(int)Material.Stone, 1].surface.soft_erp = 0.010f; - - m_materialContacts[(int)Material.Metal, 0] = new d.Contact(); - m_materialContacts[(int)Material.Metal, 0].surface.mode |= d.ContactFlags.SoftERP; - m_materialContacts[(int)Material.Metal, 0].surface.mu = nmAvatarObjectContactFriction; - m_materialContacts[(int)Material.Metal, 0].surface.bounce = nmAvatarObjectContactBounce; - m_materialContacts[(int)Material.Metal, 0].surface.soft_cfm = 0.010f; - m_materialContacts[(int)Material.Metal, 0].surface.soft_erp = 0.010f; - - m_materialContacts[(int)Material.Metal, 1] = new d.Contact(); - m_materialContacts[(int)Material.Metal, 1].surface.mode |= d.ContactFlags.SoftERP; - m_materialContacts[(int)Material.Metal, 1].surface.mu = mAvatarObjectContactFriction; - m_materialContacts[(int)Material.Metal, 1].surface.bounce = mAvatarObjectContactBounce; - m_materialContacts[(int)Material.Metal, 1].surface.soft_cfm = 0.010f; - m_materialContacts[(int)Material.Metal, 1].surface.soft_erp = 0.010f; - - m_materialContacts[(int)Material.Glass, 0] = new d.Contact(); - m_materialContacts[(int)Material.Glass, 0].surface.mode |= d.ContactFlags.SoftERP; - m_materialContacts[(int)Material.Glass, 0].surface.mu = 1f; - m_materialContacts[(int)Material.Glass, 0].surface.bounce = 0.5f; - m_materialContacts[(int)Material.Glass, 0].surface.soft_cfm = 0.010f; - m_materialContacts[(int)Material.Glass, 0].surface.soft_erp = 0.010f; - - /* - private float nmAvatarObjectContactFriction = 250f; - private float nmAvatarObjectContactBounce = 0.1f; - - private float mAvatarObjectContactFriction = 75f; - private float mAvatarObjectContactBounce = 0.1f; - */ - m_materialContacts[(int)Material.Glass, 1] = new d.Contact(); - m_materialContacts[(int)Material.Glass, 1].surface.mode |= d.ContactFlags.SoftERP; - m_materialContacts[(int)Material.Glass, 1].surface.mu = 1f; - m_materialContacts[(int)Material.Glass, 1].surface.bounce = 0.5f; - m_materialContacts[(int)Material.Glass, 1].surface.soft_cfm = 0.010f; - m_materialContacts[(int)Material.Glass, 1].surface.soft_erp = 0.010f; - - m_materialContacts[(int)Material.Wood, 0] = new d.Contact(); - m_materialContacts[(int)Material.Wood, 0].surface.mode |= d.ContactFlags.SoftERP; - m_materialContacts[(int)Material.Wood, 0].surface.mu = nmAvatarObjectContactFriction; - m_materialContacts[(int)Material.Wood, 0].surface.bounce = nmAvatarObjectContactBounce; - m_materialContacts[(int)Material.Wood, 0].surface.soft_cfm = 0.010f; - m_materialContacts[(int)Material.Wood, 0].surface.soft_erp = 0.010f; - - m_materialContacts[(int)Material.Wood, 1] = new d.Contact(); - m_materialContacts[(int)Material.Wood, 1].surface.mode |= d.ContactFlags.SoftERP; - m_materialContacts[(int)Material.Wood, 1].surface.mu = mAvatarObjectContactFriction; - m_materialContacts[(int)Material.Wood, 1].surface.bounce = mAvatarObjectContactBounce; - m_materialContacts[(int)Material.Wood, 1].surface.soft_cfm = 0.010f; - m_materialContacts[(int)Material.Wood, 1].surface.soft_erp = 0.010f; - - m_materialContacts[(int)Material.Flesh, 0] = new d.Contact(); - m_materialContacts[(int)Material.Flesh, 0].surface.mode |= d.ContactFlags.SoftERP; - m_materialContacts[(int)Material.Flesh, 0].surface.mu = nmAvatarObjectContactFriction; - m_materialContacts[(int)Material.Flesh, 0].surface.bounce = nmAvatarObjectContactBounce; - m_materialContacts[(int)Material.Flesh, 0].surface.soft_cfm = 0.010f; - m_materialContacts[(int)Material.Flesh, 0].surface.soft_erp = 0.010f; - - m_materialContacts[(int)Material.Flesh, 1] = new d.Contact(); - m_materialContacts[(int)Material.Flesh, 1].surface.mode |= d.ContactFlags.SoftERP; - m_materialContacts[(int)Material.Flesh, 1].surface.mu = mAvatarObjectContactFriction; - m_materialContacts[(int)Material.Flesh, 1].surface.bounce = mAvatarObjectContactBounce; - m_materialContacts[(int)Material.Flesh, 1].surface.soft_cfm = 0.010f; - m_materialContacts[(int)Material.Flesh, 1].surface.soft_erp = 0.010f; - - m_materialContacts[(int)Material.Plastic, 0] = new d.Contact(); - m_materialContacts[(int)Material.Plastic, 0].surface.mode |= d.ContactFlags.SoftERP; - m_materialContacts[(int)Material.Plastic, 0].surface.mu = nmAvatarObjectContactFriction; - m_materialContacts[(int)Material.Plastic, 0].surface.bounce = nmAvatarObjectContactBounce; - m_materialContacts[(int)Material.Plastic, 0].surface.soft_cfm = 0.010f; - m_materialContacts[(int)Material.Plastic, 0].surface.soft_erp = 0.010f; - - m_materialContacts[(int)Material.Plastic, 1] = new d.Contact(); - m_materialContacts[(int)Material.Plastic, 1].surface.mode |= d.ContactFlags.SoftERP; - m_materialContacts[(int)Material.Plastic, 1].surface.mu = mAvatarObjectContactFriction; - m_materialContacts[(int)Material.Plastic, 1].surface.bounce = mAvatarObjectContactBounce; - m_materialContacts[(int)Material.Plastic, 1].surface.soft_cfm = 0.010f; - m_materialContacts[(int)Material.Plastic, 1].surface.soft_erp = 0.010f; - - m_materialContacts[(int)Material.Rubber, 0] = new d.Contact(); - m_materialContacts[(int)Material.Rubber, 0].surface.mode |= d.ContactFlags.SoftERP; - m_materialContacts[(int)Material.Rubber, 0].surface.mu = nmAvatarObjectContactFriction; - m_materialContacts[(int)Material.Rubber, 0].surface.bounce = nmAvatarObjectContactBounce; - m_materialContacts[(int)Material.Rubber, 0].surface.soft_cfm = 0.010f; - m_materialContacts[(int)Material.Rubber, 0].surface.soft_erp = 0.010f; - - m_materialContacts[(int)Material.Rubber, 1] = new d.Contact(); - m_materialContacts[(int)Material.Rubber, 1].surface.mode |= d.ContactFlags.SoftERP; - m_materialContacts[(int)Material.Rubber, 1].surface.mu = mAvatarObjectContactFriction; - m_materialContacts[(int)Material.Rubber, 1].surface.bounce = mAvatarObjectContactBounce; - m_materialContacts[(int)Material.Rubber, 1].surface.soft_cfm = 0.010f; - m_materialContacts[(int)Material.Rubber, 1].surface.soft_erp = 0.010f; - - d.HashSpaceSetLevels(space, worldHashspaceLow, worldHashspaceHigh); - - // Set the gravity,, don't disable things automatically (we set it explicitly on some things) - - d.WorldSetGravity(world, gravityx, gravityy, gravityz); - d.WorldSetContactSurfaceLayer(world, contactsurfacelayer); - - d.WorldSetLinearDamping(world, 256f); - d.WorldSetAngularDamping(world, 256f); - d.WorldSetAngularDampingThreshold(world, 256f); - d.WorldSetLinearDampingThreshold(world, 256f); - d.WorldSetMaxAngularSpeed(world, 256f); - - // Set how many steps we go without running collision testing - // This is in addition to the step size. - // Essentially Steps * m_physicsiterations - d.WorldSetQuickStepNumIterations(world, m_physicsiterations); - //d.WorldSetContactMaxCorrectingVel(world, 1000.0f); - - - - for (int i = 0; i < staticPrimspace.GetLength(0); i++) - { - for (int j = 0; j < staticPrimspace.GetLength(1); j++) - { - staticPrimspace[i, j] = IntPtr.Zero; - } - } - } - - internal void waitForSpaceUnlock(IntPtr space) - { - //if (space != IntPtr.Zero) - //while (d.SpaceLockQuery(space)) { } // Wait and do nothing - } - - /// - /// Debug space message for printing the space that a prim/avatar is in. - /// - /// - /// Returns which split up space the given position is in. - public string whichspaceamIin(Vector3 pos) - { - return calculateSpaceForGeom(pos).ToString(); - } - - #region Collision Detection - - /// - /// This is our near callback. A geometry is near a body - /// - /// The space that contains the geoms. Remember, spaces are also geoms - /// a geometry or space - /// another geometry or space - private void near(IntPtr space, IntPtr g1, IntPtr g2) - { - // no lock here! It's invoked from within Simulate(), which is thread-locked - - // Test if we're colliding a geom with a space. - // If so we have to drill down into the space recursively - - if (d.GeomIsSpace(g1) || d.GeomIsSpace(g2)) - { - if (g1 == IntPtr.Zero || g2 == IntPtr.Zero) - return; - - // Separating static prim geometry spaces. - // We'll be calling near recursivly if one - // of them is a space to find all of the - // contact points in the space - try - { - d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback); - } - catch (AccessViolationException) - { - m_log.Warn("[PHYSICS]: Unable to collide test a space"); - return; - } - //Colliding a space or a geom with a space or a geom. so drill down - - //Collide all geoms in each space.. - //if (d.GeomIsSpace(g1)) d.SpaceCollide(g1, IntPtr.Zero, nearCallback); - //if (d.GeomIsSpace(g2)) d.SpaceCollide(g2, IntPtr.Zero, nearCallback); - return; - } - - if (g1 == IntPtr.Zero || g2 == IntPtr.Zero) - return; - - IntPtr b1 = d.GeomGetBody(g1); - IntPtr b2 = d.GeomGetBody(g2); - - // d.GeomClassID id = d.GeomGetClass(g1); - - String name1 = null; - String name2 = null; - - if (!geom_name_map.TryGetValue(g1, out name1)) - { - name1 = "null"; - } - if (!geom_name_map.TryGetValue(g2, out name2)) - { - name2 = "null"; - } - - //if (id == d.GeomClassId.TriMeshClass) - //{ - // m_log.InfoFormat("near: A collision was detected between {1} and {2}", 0, name1, name2); - //m_log.Debug("near: A collision was detected between {1} and {2}", 0, name1, name2); - //} - - // Figure out how many contact points we have - int count = 0; - try - { - // Colliding Geom To Geom - // This portion of the function 'was' blatantly ripped off from BoxStack.cs - - if (g1 == g2) - return; // Can't collide with yourself - - if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact)) - return; - - lock (contacts) - { - count = d.Collide(g1, g2, contacts.Length, contacts, d.ContactGeom.SizeOf); - if (count > contacts.Length) - m_log.Error("[PHYSICS]: Got " + count + " contacts when we asked for a maximum of " + contacts.Length); - } - } - catch (SEHException) - { - m_log.Error("[PHYSICS]: The Operating system shut down ODE because of corrupt memory. This could be a result of really irregular terrain. If this repeats continuously, restart using Basic Physics and terrain fill your terrain. Restarting the sim."); - ode.drelease(world); - base.TriggerPhysicsBasedRestart(); - } - catch (Exception e) - { - m_log.WarnFormat("[PHYSICS]: Unable to collide test an object: {0}", e.Message); - return; - } - - PhysicsActor p1; - PhysicsActor p2; - - if (!actor_name_map.TryGetValue(g1, out p1)) - { - p1 = PANull; - } - - if (!actor_name_map.TryGetValue(g2, out p2)) - { - p2 = PANull; - } - - ContactPoint maxDepthContact = new ContactPoint(); - if (p1.CollisionScore + count >= float.MaxValue) - p1.CollisionScore = 0; - p1.CollisionScore += count; - - if (p2.CollisionScore + count >= float.MaxValue) - p2.CollisionScore = 0; - p2.CollisionScore += count; - - for (int i = 0; i < count; i++) - { - d.ContactGeom curContact = contacts[i]; - - if (curContact.depth > maxDepthContact.PenetrationDepth) - { - maxDepthContact = new ContactPoint( - new Vector3(curContact.pos.X, curContact.pos.Y, curContact.pos.Z), - new Vector3(curContact.normal.X, curContact.normal.Y, curContact.normal.Z), - curContact.depth - ); - } - - //m_log.Warn("[CCOUNT]: " + count); - IntPtr joint; - // If we're colliding with terrain, use 'TerrainContact' instead of contact. - // allows us to have different settings - - // We only need to test p2 for 'jump crouch purposes' - if (p2 is OdeCharacter && p1.PhysicsActorType == (int)ActorTypes.Prim) - { - // Testing if the collision is at the feet of the avatar - - //m_log.DebugFormat("[PHYSICS]: {0} - {1} - {2} - {3}", curContact.pos.Z, p2.Position.Z, (p2.Position.Z - curContact.pos.Z), (p2.Size.Z * 0.6f)); - if ((p2.Position.Z - curContact.pos.Z) > (p2.Size.Z * 0.6f)) - p2.IsColliding = true; - } - else - { - p2.IsColliding = true; - } - - //if ((framecount % m_returncollisions) == 0) - - switch (p1.PhysicsActorType) - { - case (int)ActorTypes.Agent: - p2.CollidingObj = true; - break; - case (int)ActorTypes.Prim: - if (p2.Velocity.LengthSquared() > 0.0f) - p2.CollidingObj = true; - break; - case (int)ActorTypes.Unknown: - p2.CollidingGround = true; - break; - default: - p2.CollidingGround = true; - break; - } - - // we don't want prim or avatar to explode - - #region InterPenetration Handling - Unintended physics explosions -# region disabled code1 - - if (curContact.depth >= 0.08f) - { - //This is disabled at the moment only because it needs more tweaking - //It will eventually be uncommented - /* - if (contact.depth >= 1.00f) - { - //m_log.Debug("[PHYSICS]: " + contact.depth.ToString()); - } - - //If you interpenetrate a prim with an agent - if ((p2.PhysicsActorType == (int) ActorTypes.Agent && - p1.PhysicsActorType == (int) ActorTypes.Prim) || - (p1.PhysicsActorType == (int) ActorTypes.Agent && - p2.PhysicsActorType == (int) ActorTypes.Prim)) - { - - //contact.depth = contact.depth * 4.15f; - /* - if (p2.PhysicsActorType == (int) ActorTypes.Agent) - { - p2.CollidingObj = true; - contact.depth = 0.003f; - p2.Velocity = p2.Velocity + new PhysicsVector(0, 0, 2.5f); - OdeCharacter character = (OdeCharacter) p2; - character.SetPidStatus(true); - contact.pos = new d.Vector3(contact.pos.X + (p1.Size.X / 2), contact.pos.Y + (p1.Size.Y / 2), contact.pos.Z + (p1.Size.Z / 2)); - - } - else - { - - //contact.depth = 0.0000000f; - } - if (p1.PhysicsActorType == (int) ActorTypes.Agent) - { - - p1.CollidingObj = true; - contact.depth = 0.003f; - p1.Velocity = p1.Velocity + new PhysicsVector(0, 0, 2.5f); - contact.pos = new d.Vector3(contact.pos.X + (p2.Size.X / 2), contact.pos.Y + (p2.Size.Y / 2), contact.pos.Z + (p2.Size.Z / 2)); - OdeCharacter character = (OdeCharacter)p1; - character.SetPidStatus(true); - } - else - { - - //contact.depth = 0.0000000f; - } - - - - } -*/ - // If you interpenetrate a prim with another prim - /* - if (p1.PhysicsActorType == (int) ActorTypes.Prim && p2.PhysicsActorType == (int) ActorTypes.Prim) - { - #region disabledcode2 - //OdePrim op1 = (OdePrim)p1; - //OdePrim op2 = (OdePrim)p2; - //op1.m_collisionscore++; - //op2.m_collisionscore++; - - //if (op1.m_collisionscore > 8000 || op2.m_collisionscore > 8000) - //{ - //op1.m_taintdisable = true; - //AddPhysicsActorTaint(p1); - //op2.m_taintdisable = true; - //AddPhysicsActorTaint(p2); - //} - - //if (contact.depth >= 0.25f) - //{ - // Don't collide, one or both prim will expld. - - //op1.m_interpenetrationcount++; - //op2.m_interpenetrationcount++; - //interpenetrations_before_disable = 200; - //if (op1.m_interpenetrationcount >= interpenetrations_before_disable) - //{ - //op1.m_taintdisable = true; - //AddPhysicsActorTaint(p1); - //} - //if (op2.m_interpenetrationcount >= interpenetrations_before_disable) - //{ - // op2.m_taintdisable = true; - //AddPhysicsActorTaint(p2); - //} - - //contact.depth = contact.depth / 8f; - //contact.normal = new d.Vector3(0, 0, 1); - //} - //if (op1.m_disabled || op2.m_disabled) - //{ - //Manually disabled objects stay disabled - //contact.depth = 0f; - //} - #endregion - } - */ -#endregion - if (curContact.depth >= 1.00f) - { - //m_log.Info("[P]: " + contact.depth.ToString()); - if ((p2.PhysicsActorType == (int) ActorTypes.Agent && - p1.PhysicsActorType == (int) ActorTypes.Unknown) || - (p1.PhysicsActorType == (int) ActorTypes.Agent && - p2.PhysicsActorType == (int) ActorTypes.Unknown)) - { - if (p2.PhysicsActorType == (int) ActorTypes.Agent) - { - if (p2 is OdeCharacter) - { - OdeCharacter character = (OdeCharacter) p2; - - //p2.CollidingObj = true; - curContact.depth = 0.00000003f; - p2.Velocity = p2.Velocity + new Vector3(0f, 0f, 0.5f); - curContact.pos = - new d.Vector3(curContact.pos.X + (p1.Size.X/2), - curContact.pos.Y + (p1.Size.Y/2), - curContact.pos.Z + (p1.Size.Z/2)); - character.SetPidStatus(true); - } - } - - - if (p1.PhysicsActorType == (int) ActorTypes.Agent) - { - if (p1 is OdeCharacter) - { - OdeCharacter character = (OdeCharacter) p1; - - //p2.CollidingObj = true; - curContact.depth = 0.00000003f; - p1.Velocity = p1.Velocity + new Vector3(0f, 0f, 0.5f); - curContact.pos = - new d.Vector3(curContact.pos.X + (p1.Size.X/2), - curContact.pos.Y + (p1.Size.Y/2), - curContact.pos.Z + (p1.Size.Z/2)); - character.SetPidStatus(true); - } - } - } - } - } - - #endregion - - // Logic for collision handling - // Note, that if *all* contacts are skipped (VolumeDetect) - // The prim still detects (and forwards) collision events but - // appears to be phantom for the world - Boolean skipThisContact = false; - - if ((p1 is OdePrim) && (((OdePrim)p1).m_isVolumeDetect)) - skipThisContact = true; // No collision on volume detect prims - - if (!skipThisContact && (p2 is OdePrim) && (((OdePrim)p2).m_isVolumeDetect)) - skipThisContact = true; // No collision on volume detect prims - - if (!skipThisContact && curContact.depth < 0f) - skipThisContact = true; - - if (!skipThisContact && checkDupe(curContact, p2.PhysicsActorType)) - skipThisContact = true; - - const int maxContactsbeforedeath = 4000; - joint = IntPtr.Zero; - - if (!skipThisContact) - { - // If we're colliding against terrain - if (name1 == "Terrain" || name2 == "Terrain") - { - // If we're moving - if ((p2.PhysicsActorType == (int) ActorTypes.Agent) && - (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) - { - // Use the movement terrain contact - AvatarMovementTerrainContact.geom = curContact; - _perloopContact.Add(curContact); - if (m_global_contactcount < maxContactsbeforedeath) - { - joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementTerrainContact); - m_global_contactcount++; - } - } - else - { - if (p2.PhysicsActorType == (int)ActorTypes.Agent) - { - // Use the non moving terrain contact - TerrainContact.geom = curContact; - _perloopContact.Add(curContact); - if (m_global_contactcount < maxContactsbeforedeath) - { - joint = d.JointCreateContact(world, contactgroup, ref TerrainContact); - m_global_contactcount++; - } - } - else - { - if (p2.PhysicsActorType == (int)ActorTypes.Prim && p1.PhysicsActorType == (int)ActorTypes.Prim) - { - // prim prim contact - // int pj294950 = 0; - int movintYN = 0; - int material = (int) Material.Wood; - // prim terrain contact - if (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f) - { - movintYN = 1; - } - - if (p2 is OdePrim) - material = ((OdePrim)p2).m_material; - - //m_log.DebugFormat("Material: {0}", material); - m_materialContacts[material, movintYN].geom = curContact; - _perloopContact.Add(curContact); - - if (m_global_contactcount < maxContactsbeforedeath) - { - joint = d.JointCreateContact(world, contactgroup, ref m_materialContacts[material, movintYN]); - m_global_contactcount++; - - } - - } - else - { - - int movintYN = 0; - // prim terrain contact - if (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f) - { - movintYN = 1; - } - - int material = (int)Material.Wood; - - if (p2 is OdePrim) - material = ((OdePrim)p2).m_material; - //m_log.DebugFormat("Material: {0}", material); - m_materialContacts[material, movintYN].geom = curContact; - _perloopContact.Add(curContact); - - if (m_global_contactcount < maxContactsbeforedeath) - { - joint = d.JointCreateContact(world, contactgroup, ref m_materialContacts[material, movintYN]); - m_global_contactcount++; - - } - } - } - } - //if (p2.PhysicsActorType == (int)ActorTypes.Prim) - //{ - //m_log.Debug("[PHYSICS]: prim contacting with ground"); - //} - } - else if (name1 == "Water" || name2 == "Water") - { - /* - if ((p2.PhysicsActorType == (int) ActorTypes.Prim)) - { - } - else - { - } - */ - //WaterContact.surface.soft_cfm = 0.0000f; - //WaterContact.surface.soft_erp = 0.00000f; - if (curContact.depth > 0.1f) - { - curContact.depth *= 52; - //contact.normal = new d.Vector3(0, 0, 1); - //contact.pos = new d.Vector3(0, 0, contact.pos.Z - 5f); - } - WaterContact.geom = curContact; - _perloopContact.Add(curContact); - if (m_global_contactcount < maxContactsbeforedeath) - { - joint = d.JointCreateContact(world, contactgroup, ref WaterContact); - m_global_contactcount++; - } - //m_log.Info("[PHYSICS]: Prim Water Contact" + contact.depth); - } - else - { - // we're colliding with prim or avatar - // check if we're moving - if ((p2.PhysicsActorType == (int)ActorTypes.Agent)) - { - if ((Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) - { - // Use the Movement prim contact - AvatarMovementprimContact.geom = curContact; - _perloopContact.Add(curContact); - if (m_global_contactcount < maxContactsbeforedeath) - { - joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementprimContact); - m_global_contactcount++; - } - } - else - { - // Use the non movement contact - contact.geom = curContact; - _perloopContact.Add(curContact); - - if (m_global_contactcount < maxContactsbeforedeath) - { - joint = d.JointCreateContact(world, contactgroup, ref contact); - m_global_contactcount++; - } - } - } - else if (p2.PhysicsActorType == (int)ActorTypes.Prim) - { - //p1.PhysicsActorType - int material = (int)Material.Wood; - - if (p2 is OdePrim) - material = ((OdePrim)p2).m_material; - - //m_log.DebugFormat("Material: {0}", material); - m_materialContacts[material, 0].geom = curContact; - _perloopContact.Add(curContact); - - if (m_global_contactcount < maxContactsbeforedeath) - { - joint = d.JointCreateContact(world, contactgroup, ref m_materialContacts[material, 0]); - m_global_contactcount++; - - } - } - } - - if (m_global_contactcount < maxContactsbeforedeath && joint != IntPtr.Zero) // stack collide! - { - d.JointAttach(joint, b1, b2); - m_global_contactcount++; - } - - } - collision_accounting_events(p1, p2, maxDepthContact); - if (count > geomContactPointsStartthrottle) - { - // If there are more then 3 contact points, it's likely - // that we've got a pile of objects, so ... - // We don't want to send out hundreds of terse updates over and over again - // so lets throttle them and send them again after it's somewhat sorted out. - p2.ThrottleUpdates = true; - } - //m_log.Debug(count.ToString()); - //m_log.Debug("near: A collision was detected between {1} and {2}", 0, name1, name2); - } - } - - private bool checkDupe(d.ContactGeom contactGeom, int atype) - { - bool result = false; - //return result; - if (!m_filterCollisions) - return false; - - ActorTypes at = (ActorTypes)atype; - lock (_perloopContact) - { - foreach (d.ContactGeom contact in _perloopContact) - { - //if ((contact.g1 == contactGeom.g1 && contact.g2 == contactGeom.g2)) - //{ - // || (contact.g2 == contactGeom.g1 && contact.g1 == contactGeom.g2) - if (at == ActorTypes.Agent) - { - if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f) && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f) && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f)) && contactGeom.g1 != LandGeom && contactGeom.g2 != LandGeom) - { - - if (Math.Abs(contact.depth - contactGeom.depth) < 0.052f) - { - //contactGeom.depth *= .00005f; - //m_log.DebugFormat("[Collsion]: Depth {0}", Math.Abs(contact.depth - contactGeom.depth)); - // m_log.DebugFormat("[Collision]: <{0},{1},{2}>", Math.Abs(contactGeom.normal.X - contact.normal.X), Math.Abs(contactGeom.normal.Y - contact.normal.Y), Math.Abs(contactGeom.normal.Z - contact.normal.Z)); - result = true; - break; - } - else - { - //m_log.DebugFormat("[Collsion]: Depth {0}", Math.Abs(contact.depth - contactGeom.depth)); - } - } - else - { - //m_log.DebugFormat("[Collision]: <{0},{1},{2}>", Math.Abs(contactGeom.normal.X - contact.normal.X), Math.Abs(contactGeom.normal.Y - contact.normal.Y), Math.Abs(contactGeom.normal.Z - contact.normal.Z)); - //int i = 0; - } - } - else if (at == ActorTypes.Prim) - { - //d.AABB aabb1 = new d.AABB(); - //d.AABB aabb2 = new d.AABB(); - - //d.GeomGetAABB(contactGeom.g2, out aabb2); - //d.GeomGetAABB(contactGeom.g1, out aabb1); - //aabb1. - if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f) && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f) && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f)) && contactGeom.g1 != LandGeom && contactGeom.g2 != LandGeom) - { - if (contactGeom.normal.X == contact.normal.X && contactGeom.normal.Y == contact.normal.Y && contactGeom.normal.Z == contact.normal.Z) - { - if (Math.Abs(contact.depth - contactGeom.depth) < 0.272f) - { - result = true; - break; - } - } - //m_log.DebugFormat("[Collsion]: Depth {0}", Math.Abs(contact.depth - contactGeom.depth)); - //m_log.DebugFormat("[Collision]: <{0},{1},{2}>", Math.Abs(contactGeom.normal.X - contact.normal.X), Math.Abs(contactGeom.normal.Y - contact.normal.Y), Math.Abs(contactGeom.normal.Z - contact.normal.Z)); - } - - } - - //} - - } - } - return result; - } - - private void collision_accounting_events(PhysicsActor p1, PhysicsActor p2, ContactPoint contact) - { - // obj1LocalID = 0; - //returncollisions = false; - obj2LocalID = 0; - //ctype = 0; - //cStartStop = 0; - if (!p2.SubscribedEvents() && !p1.SubscribedEvents()) - return; - - switch ((ActorTypes)p2.PhysicsActorType) - { - case ActorTypes.Agent: - cc2 = (OdeCharacter)p2; - - // obj1LocalID = cc2.m_localID; - switch ((ActorTypes)p1.PhysicsActorType) - { - case ActorTypes.Agent: - cc1 = (OdeCharacter)p1; - obj2LocalID = cc1.m_localID; - cc1.AddCollisionEvent(cc2.m_localID, contact); - //ctype = (int)CollisionCategories.Character; - - //if (cc1.CollidingObj) - //cStartStop = (int)StatusIndicators.Generic; - //else - //cStartStop = (int)StatusIndicators.Start; - - //returncollisions = true; - break; - case ActorTypes.Prim: - if (p1 is OdePrim) - { - cp1 = (OdePrim) p1; - obj2LocalID = cp1.m_localID; - cp1.AddCollisionEvent(cc2.m_localID, contact); - } - //ctype = (int)CollisionCategories.Geom; - - //if (cp1.CollidingObj) - //cStartStop = (int)StatusIndicators.Generic; - //else - //cStartStop = (int)StatusIndicators.Start; - - //returncollisions = true; - break; - - case ActorTypes.Ground: - case ActorTypes.Unknown: - obj2LocalID = 0; - //ctype = (int)CollisionCategories.Land; - //returncollisions = true; - break; - } - - cc2.AddCollisionEvent(obj2LocalID, contact); - break; - case ActorTypes.Prim: - - if (p2 is OdePrim) - { - cp2 = (OdePrim) p2; - - // obj1LocalID = cp2.m_localID; - switch ((ActorTypes) p1.PhysicsActorType) - { - case ActorTypes.Agent: - if (p1 is OdeCharacter) - { - cc1 = (OdeCharacter) p1; - obj2LocalID = cc1.m_localID; - cc1.AddCollisionEvent(cp2.m_localID, contact); - //ctype = (int)CollisionCategories.Character; - - //if (cc1.CollidingObj) - //cStartStop = (int)StatusIndicators.Generic; - //else - //cStartStop = (int)StatusIndicators.Start; - //returncollisions = true; - } - break; - case ActorTypes.Prim: - - if (p1 is OdePrim) - { - cp1 = (OdePrim) p1; - obj2LocalID = cp1.m_localID; - cp1.AddCollisionEvent(cp2.m_localID, contact); - //ctype = (int)CollisionCategories.Geom; - - //if (cp1.CollidingObj) - //cStartStop = (int)StatusIndicators.Generic; - //else - //cStartStop = (int)StatusIndicators.Start; - - //returncollisions = true; - } - break; - - case ActorTypes.Ground: - case ActorTypes.Unknown: - obj2LocalID = 0; - //ctype = (int)CollisionCategories.Land; - - //returncollisions = true; - break; - } - - cp2.AddCollisionEvent(obj2LocalID, contact); - } - break; - } - //if (returncollisions) - //{ - - //lock (m_storedCollisions) - //{ - //cDictKey = obj1LocalID.ToString() + obj2LocalID.ToString() + cStartStop.ToString() + ctype.ToString(); - //if (m_storedCollisions.ContainsKey(cDictKey)) - //{ - //sCollisionData objd = m_storedCollisions[cDictKey]; - //objd.NumberOfCollisions += 1; - //objd.lastframe = framecount; - //m_storedCollisions[cDictKey] = objd; - //} - //else - //{ - //sCollisionData objd = new sCollisionData(); - //objd.ColliderLocalId = obj1LocalID; - //objd.CollidedWithLocalId = obj2LocalID; - //objd.CollisionType = ctype; - //objd.NumberOfCollisions = 1; - //objd.lastframe = framecount; - //objd.StatusIndicator = cStartStop; - //m_storedCollisions.Add(cDictKey, objd); - //} - //} - // } - } - - public int TriArrayCallback(IntPtr trimesh, IntPtr refObject, int[] triangleIndex, int triCount) - { - /* String name1 = null; - String name2 = null; - - if (!geom_name_map.TryGetValue(trimesh, out name1)) - { - name1 = "null"; - } - if (!geom_name_map.TryGetValue(refObject, out name2)) - { - name2 = "null"; - } - - m_log.InfoFormat("TriArrayCallback: A collision was detected between {1} and {2}", 0, name1, name2); - */ - return 1; - } - - public int TriCallback(IntPtr trimesh, IntPtr refObject, int triangleIndex) - { - String name1 = null; - String name2 = null; - - if (!geom_name_map.TryGetValue(trimesh, out name1)) - { - name1 = "null"; - } - - if (!geom_name_map.TryGetValue(refObject, out name2)) - { - name2 = "null"; - } - - // m_log.InfoFormat("TriCallback: A collision was detected between {1} and {2}. Index was {3}", 0, name1, name2, triangleIndex); - - d.Vector3 v0 = new d.Vector3(); - d.Vector3 v1 = new d.Vector3(); - d.Vector3 v2 = new d.Vector3(); - - d.GeomTriMeshGetTriangle(trimesh, 0, ref v0, ref v1, ref v2); - // m_log.DebugFormat("Triangle {0} is <{1},{2},{3}>, <{4},{5},{6}>, <{7},{8},{9}>", triangleIndex, v0.X, v0.Y, v0.Z, v1.X, v1.Y, v1.Z, v2.X, v2.Y, v2.Z); - - return 1; - } - - /// - /// This is our collision testing routine in ODE - /// - /// - private void collision_optimized(float timeStep) - { - _perloopContact.Clear(); - - lock (_characters) - { - foreach (OdeCharacter chr in _characters) - { - // Reset the collision values to false - // since we don't know if we're colliding yet - - // For some reason this can happen. Don't ask... - // - if (chr == null) - continue; - - if (chr.Shell == IntPtr.Zero || chr.Body == IntPtr.Zero) - continue; - - chr.IsColliding = false; - chr.CollidingGround = false; - chr.CollidingObj = false; - - // test the avatar's geometry for collision with the space - // This will return near and the space that they are the closest to - // And we'll run this again against the avatar and the space segment - // This will return with a bunch of possible objects in the space segment - // and we'll run it again on all of them. - try - { - d.SpaceCollide2(space, chr.Shell, IntPtr.Zero, nearCallback); - } - catch (AccessViolationException) - { - m_log.Warn("[PHYSICS]: Unable to space collide"); - } - //float terrainheight = GetTerrainHeightAtXY(chr.Position.X, chr.Position.Y); - //if (chr.Position.Z + (chr.Velocity.Z * timeStep) < terrainheight + 10) - //{ - //chr.Position.Z = terrainheight + 10.0f; - //forcedZ = true; - //} - } - } - - lock (_activeprims) - { - List removeprims = null; - foreach (OdePrim chr in _activeprims) - { - if (chr.Body != IntPtr.Zero && d.BodyIsEnabled(chr.Body) && (!chr.m_disabled)) - { - try - { - lock (chr) - { - if (space != IntPtr.Zero && chr.prim_geom != IntPtr.Zero && chr.m_taintremove == false) - { - d.SpaceCollide2(space, chr.prim_geom, IntPtr.Zero, nearCallback); - } - else - { - if (removeprims == null) - { - removeprims = new List(); - } - removeprims.Add(chr); - m_log.Debug("[PHYSICS]: unable to collide test active prim against space. The space was zero, the geom was zero or it was in the process of being removed. Removed it from the active prim list. This needs to be fixed!"); - } - } - } - catch (AccessViolationException) - { - m_log.Warn("[PHYSICS]: Unable to space collide"); - } - } - } - if (removeprims != null) - { - foreach (OdePrim chr in removeprims) - { - _activeprims.Remove(chr); - } - } - } - - _perloopContact.Clear(); - } - - #endregion - - public override void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents) - { - m_worldOffset = offset; - WorldExtents = new Vector2(extents.X, extents.Y); - m_parentScene = pScene; - - } - - // Recovered for use by fly height. Kitto Flora - public float GetTerrainHeightAtXY(float x, float y) - { - - int offsetX = ((int)(x / (int)Constants.RegionSize)) * (int)Constants.RegionSize; - int offsetY = ((int)(y / (int)Constants.RegionSize)) * (int)Constants.RegionSize; - - IntPtr heightFieldGeom = IntPtr.Zero; - - if (RegionTerrain.TryGetValue(new Vector3(offsetX,offsetY,0), out heightFieldGeom)) - { - if (heightFieldGeom != IntPtr.Zero) - { - if (TerrainHeightFieldHeights.ContainsKey(heightFieldGeom)) - { - - int index; - - - if ((int)x > WorldExtents.X || (int)y > WorldExtents.Y || - (int)x < 0.001f || (int)y < 0.001f) - return 0; - - x = x - offsetX; - y = y - offsetY; - - index = (int)((int)x * ((int)Constants.RegionSize + 2) + (int)y); - - if (index < TerrainHeightFieldHeights[heightFieldGeom].Length) - { - //m_log.DebugFormat("x{0} y{1} = {2}", x, y, (float)TerrainHeightFieldHeights[heightFieldGeom][index]); - return (float)TerrainHeightFieldHeights[heightFieldGeom][index]; - } - - else - return 0f; - } - else - { - return 0f; - } - - } - else - { - return 0f; - } - - } - else - { - return 0f; - } - - - } -// End recovered. Kitto Flora - - public void addCollisionEventReporting(PhysicsActor obj) - { - lock (_collisionEventPrim) - { - if (!_collisionEventPrim.Contains(obj)) - _collisionEventPrim.Add(obj); - } - } - - public void remCollisionEventReporting(PhysicsActor obj) - { - lock (_collisionEventPrim) - { - if (!_collisionEventPrim.Contains(obj)) - _collisionEventPrim.Remove(obj); - } - } - - #region Add/Remove Entities - - public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying) - { - Vector3 pos; - pos.X = position.X; - pos.Y = position.Y; - pos.Z = position.Z; - OdeCharacter newAv = new OdeCharacter(avName, this, pos, ode, size, avPIDD, avPIDP, avCapRadius, avStandupTensor, avDensity, avHeightFudgeFactor, avMovementDivisorWalk, avMovementDivisorRun); - newAv.Flying = isFlying; - newAv.MinimumGroundFlightOffset = minimumGroundFlightOffset; - - return newAv; - } - - public void AddCharacter(OdeCharacter chr) - { - lock (_characters) - { - if (!_characters.Contains(chr)) - { - _characters.Add(chr); - if (chr.bad) - m_log.DebugFormat("[PHYSICS] Added BAD actor {0} to characters list", chr.m_uuid); - } - } - } - - public void RemoveCharacter(OdeCharacter chr) - { - lock (_characters) - { - if (_characters.Contains(chr)) - { - _characters.Remove(chr); - } - } - } - public void BadCharacter(OdeCharacter chr) - { - lock (_badCharacter) - { - if (!_badCharacter.Contains(chr)) - _badCharacter.Add(chr); - } - } - - public override void RemoveAvatar(PhysicsActor actor) - { - //m_log.Debug("[PHYSICS]:ODELOCK"); - ((OdeCharacter) actor).Destroy(); - - } - - private PhysicsActor AddPrim(String name, Vector3 position, Vector3 size, Quaternion rotation, - IMesh mesh, PrimitiveBaseShape pbs, bool isphysical) - { - - Vector3 pos = position; - Vector3 siz = size; - Quaternion rot = rotation; - - OdePrim newPrim; - lock (OdeLock) - { - newPrim = new OdePrim(name, this, pos, siz, rot, mesh, pbs, isphysical, ode); - - lock (_prims) - _prims.Add(newPrim); - } - - return newPrim; - } - - public void addActivePrim(OdePrim activatePrim) - { - // adds active prim.. (ones that should be iterated over in collisions_optimized - lock (_activeprims) - { - if (!_activeprims.Contains(activatePrim)) - _activeprims.Add(activatePrim); - //else - // m_log.Warn("[PHYSICS]: Double Entry in _activeprims detected, potential crash immenent"); - } - } - - public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, - Vector3 size, Quaternion rotation) //To be removed - { - return AddPrimShape(primName, pbs, position, size, rotation, false); - } - - public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, - Vector3 size, Quaternion rotation, bool isPhysical) - { -// m_log.DebugFormat("[PHYSICS]: Adding physics actor to {0}", primName); - - PhysicsActor result; - IMesh mesh = null; - - if (needsMeshing(pbs)) - { - try - { - mesh = mesher.CreateMesh(primName, pbs, size, 32f, isPhysical); - } - catch(Exception e) - { - m_log.ErrorFormat("[PHYSICS]: Exception while meshing prim {0}.", primName); - m_log.Debug(e.ToString()); - mesh = null; - return null; - } - } - - result = AddPrim(primName, position, size, rotation, mesh, pbs, isPhysical); - - return result; - } - - public override float TimeDilation - { - get { return m_timeDilation; } - } - - public override bool SupportsNINJAJoints - { - get { return m_NINJA_physics_joints_enabled; } - } - - // internal utility function: must be called within a lock (OdeLock) - private void InternalAddActiveJoint(PhysicsJoint joint) - { - activeJoints.Add(joint); - SOPName_to_activeJoint.Add(joint.ObjectNameInScene, joint); - } - - // internal utility function: must be called within a lock (OdeLock) - private void InternalAddPendingJoint(OdePhysicsJoint joint) - { - pendingJoints.Add(joint); - SOPName_to_pendingJoint.Add(joint.ObjectNameInScene, joint); - } - - // internal utility function: must be called within a lock (OdeLock) - private void InternalRemovePendingJoint(PhysicsJoint joint) - { - pendingJoints.Remove(joint); - SOPName_to_pendingJoint.Remove(joint.ObjectNameInScene); - } - - // internal utility function: must be called within a lock (OdeLock) - private void InternalRemoveActiveJoint(PhysicsJoint joint) - { - activeJoints.Remove(joint); - SOPName_to_activeJoint.Remove(joint.ObjectNameInScene); - } - - public override void DumpJointInfo() - { - string hdr = "[NINJA] JOINTINFO: "; - foreach (PhysicsJoint j in pendingJoints) - { - m_log.Debug(hdr + " pending joint, Name: " + j.ObjectNameInScene + " raw parms:" + j.RawParams); - } - m_log.Debug(hdr + pendingJoints.Count + " total pending joints"); - foreach (string jointName in SOPName_to_pendingJoint.Keys) - { - m_log.Debug(hdr + " pending joints dict contains Name: " + jointName); - } - m_log.Debug(hdr + SOPName_to_pendingJoint.Keys.Count + " total pending joints dict entries"); - foreach (PhysicsJoint j in activeJoints) - { - m_log.Debug(hdr + " active joint, Name: " + j.ObjectNameInScene + " raw parms:" + j.RawParams); - } - m_log.Debug(hdr + activeJoints.Count + " total active joints"); - foreach (string jointName in SOPName_to_activeJoint.Keys) - { - m_log.Debug(hdr + " active joints dict contains Name: " + jointName); - } - m_log.Debug(hdr + SOPName_to_activeJoint.Keys.Count + " total active joints dict entries"); - - m_log.Debug(hdr + " Per-body joint connectivity information follows."); - m_log.Debug(hdr + joints_connecting_actor.Keys.Count + " bodies are connected by joints."); - foreach (string actorName in joints_connecting_actor.Keys) - { - m_log.Debug(hdr + " Actor " + actorName + " has the following joints connecting it"); - foreach (PhysicsJoint j in joints_connecting_actor[actorName]) - { - m_log.Debug(hdr + " * joint Name: " + j.ObjectNameInScene + " raw parms:" + j.RawParams); - } - m_log.Debug(hdr + joints_connecting_actor[actorName].Count + " connecting joints total for this actor"); - } - } - - public override void RequestJointDeletion(string ObjectNameInScene) - { - lock (externalJointRequestsLock) - { - if (!requestedJointsToBeDeleted.Contains(ObjectNameInScene)) // forbid same deletion request from entering twice to prevent spurious deletions processed asynchronously - { - requestedJointsToBeDeleted.Add(ObjectNameInScene); - } - } - } - - private void DeleteRequestedJoints() - { - List myRequestedJointsToBeDeleted; - lock (externalJointRequestsLock) - { - // make a local copy of the shared list for processing (threading issues) - myRequestedJointsToBeDeleted = new List(requestedJointsToBeDeleted); - } - - foreach (string jointName in myRequestedJointsToBeDeleted) - { - lock (OdeLock) - { - //m_log.Debug("[NINJA] trying to deleting requested joint " + jointName); - if (SOPName_to_activeJoint.ContainsKey(jointName) || SOPName_to_pendingJoint.ContainsKey(jointName)) - { - OdePhysicsJoint joint = null; - if (SOPName_to_activeJoint.ContainsKey(jointName)) - { - joint = SOPName_to_activeJoint[jointName] as OdePhysicsJoint; - InternalRemoveActiveJoint(joint); - } - else if (SOPName_to_pendingJoint.ContainsKey(jointName)) - { - joint = SOPName_to_pendingJoint[jointName] as OdePhysicsJoint; - InternalRemovePendingJoint(joint); - } - - if (joint != null) - { - //m_log.Debug("joint.BodyNames.Count is " + joint.BodyNames.Count + " and contents " + joint.BodyNames); - for (int iBodyName = 0; iBodyName < 2; iBodyName++) - { - string bodyName = joint.BodyNames[iBodyName]; - if (bodyName != "NULL") - { - joints_connecting_actor[bodyName].Remove(joint); - if (joints_connecting_actor[bodyName].Count == 0) - { - joints_connecting_actor.Remove(bodyName); - } - } - } - - DoJointDeactivated(joint); - if (joint.jointID != IntPtr.Zero) - { - d.JointDestroy(joint.jointID); - joint.jointID = IntPtr.Zero; - //DoJointErrorMessage(joint, "successfully destroyed joint " + jointName); - } - else - { - //m_log.Warn("[NINJA] Ignoring re-request to destroy joint " + jointName); - } - } - else - { - // DoJointErrorMessage(joint, "coult not find joint to destroy based on name " + jointName); - } - } - else - { - // DoJointErrorMessage(joint, "WARNING - joint removal failed, joint " + jointName); - } - } - } - - // remove processed joints from the shared list - lock (externalJointRequestsLock) - { - foreach (string jointName in myRequestedJointsToBeDeleted) - { - requestedJointsToBeDeleted.Remove(jointName); - } - } - } - - // for pending joints we don't know if their associated bodies exist yet or not. - // the joint is actually created during processing of the taints - private void CreateRequestedJoints() - { - List myRequestedJointsToBeCreated; - lock (externalJointRequestsLock) - { - // make a local copy of the shared list for processing (threading issues) - myRequestedJointsToBeCreated = new List(requestedJointsToBeCreated); - } - - foreach (PhysicsJoint joint in myRequestedJointsToBeCreated) - { - lock (OdeLock) - { - if (SOPName_to_pendingJoint.ContainsKey(joint.ObjectNameInScene) && SOPName_to_pendingJoint[joint.ObjectNameInScene] != null) - { - DoJointErrorMessage(joint, "WARNING: ignoring request to re-add already pending joint Name:" + joint.ObjectNameInScene + " type:" + joint.Type + " parms: " + joint.RawParams + " pos: " + joint.Position + " rot:" + joint.Rotation); - continue; - } - if (SOPName_to_activeJoint.ContainsKey(joint.ObjectNameInScene) && SOPName_to_activeJoint[joint.ObjectNameInScene] != null) - { - DoJointErrorMessage(joint, "WARNING: ignoring request to re-add already active joint Name:" + joint.ObjectNameInScene + " type:" + joint.Type + " parms: " + joint.RawParams + " pos: " + joint.Position + " rot:" + joint.Rotation); - continue; - } - - InternalAddPendingJoint(joint as OdePhysicsJoint); - - if (joint.BodyNames.Count >= 2) - { - for (int iBodyName = 0; iBodyName < 2; iBodyName++) - { - string bodyName = joint.BodyNames[iBodyName]; - if (bodyName != "NULL") - { - if (!joints_connecting_actor.ContainsKey(bodyName)) - { - joints_connecting_actor.Add(bodyName, new List()); - } - joints_connecting_actor[bodyName].Add(joint); - } - } - } - } - } - - // remove processed joints from shared list - lock (externalJointRequestsLock) - { - foreach (PhysicsJoint joint in myRequestedJointsToBeCreated) - { - requestedJointsToBeCreated.Remove(joint); - } - } - - } - - // public function to add an request for joint creation - // this joint will just be added to a waiting list that is NOT processed during the main - // Simulate() loop (to avoid deadlocks). After Simulate() is finished, we handle unprocessed joint requests. - - public override PhysicsJoint RequestJointCreation(string objectNameInScene, PhysicsJointType jointType, Vector3 position, - Quaternion rotation, string parms, List bodyNames, string trackedBodyName, Quaternion localRotation) - - { - - OdePhysicsJoint joint = new OdePhysicsJoint(); - joint.ObjectNameInScene = objectNameInScene; - joint.Type = jointType; - joint.Position = position; - joint.Rotation = rotation; - joint.RawParams = parms; - joint.BodyNames = new List(bodyNames); - joint.TrackedBodyName = trackedBodyName; - joint.LocalRotation = localRotation; - joint.jointID = IntPtr.Zero; - joint.ErrorMessageCount = 0; - - lock (externalJointRequestsLock) - { - if (!requestedJointsToBeCreated.Contains(joint)) // forbid same creation request from entering twice - { - requestedJointsToBeCreated.Add(joint); - } - } - return joint; - } - - private void RemoveAllJointsConnectedToActor(PhysicsActor actor) - { - //m_log.Debug("RemoveAllJointsConnectedToActor: start"); - if (actor.SOPName != null && joints_connecting_actor.ContainsKey(actor.SOPName) && joints_connecting_actor[actor.SOPName] != null) - { - - List jointsToRemove = new List(); - //TODO: merge these 2 loops (originally it was needed to avoid altering a list being iterated over, but it is no longer needed due to the joint request queue mechanism) - foreach (PhysicsJoint j in joints_connecting_actor[actor.SOPName]) - { - jointsToRemove.Add(j); - } - foreach (PhysicsJoint j in jointsToRemove) - { - //m_log.Debug("RemoveAllJointsConnectedToActor: about to request deletion of " + j.ObjectNameInScene); - RequestJointDeletion(j.ObjectNameInScene); - //m_log.Debug("RemoveAllJointsConnectedToActor: done request deletion of " + j.ObjectNameInScene); - j.TrackedBodyName = null; // *IMMEDIATELY* prevent any further movement of this joint (else a deleted actor might cause spurious tracking motion of the joint for a few frames, leading to the joint proxy object disappearing) - } - } - } - - public override void RemoveAllJointsConnectedToActorThreadLocked(PhysicsActor actor) - { - //m_log.Debug("RemoveAllJointsConnectedToActorThreadLocked: start"); - lock (OdeLock) - { - //m_log.Debug("RemoveAllJointsConnectedToActorThreadLocked: got lock"); - RemoveAllJointsConnectedToActor(actor); - } - } - - // normally called from within OnJointMoved, which is called from within a lock (OdeLock) - public override Vector3 GetJointAnchor(PhysicsJoint joint) - { - Debug.Assert(joint.IsInPhysicsEngine); - d.Vector3 pos = new d.Vector3(); - - if (!(joint is OdePhysicsJoint)) - { - DoJointErrorMessage(joint, "warning: non-ODE joint requesting anchor: " + joint.ObjectNameInScene); - } - else - { - OdePhysicsJoint odeJoint = (OdePhysicsJoint)joint; - switch (odeJoint.Type) - { - case PhysicsJointType.Ball: - d.JointGetBallAnchor(odeJoint.jointID, out pos); - break; - case PhysicsJointType.Hinge: - d.JointGetHingeAnchor(odeJoint.jointID, out pos); - break; - } - } - return new Vector3(pos.X, pos.Y, pos.Z); - } - - // normally called from within OnJointMoved, which is called from within a lock (OdeLock) - // WARNING: ODE sometimes returns <0,0,0> as the joint axis! Therefore this function - // appears to be unreliable. Fortunately we can compute the joint axis ourselves by - // keeping track of the joint's original orientation relative to one of the involved bodies. - public override Vector3 GetJointAxis(PhysicsJoint joint) - { - Debug.Assert(joint.IsInPhysicsEngine); - d.Vector3 axis = new d.Vector3(); - - if (!(joint is OdePhysicsJoint)) - { - DoJointErrorMessage(joint, "warning: non-ODE joint requesting anchor: " + joint.ObjectNameInScene); - } - else - { - OdePhysicsJoint odeJoint = (OdePhysicsJoint)joint; - switch (odeJoint.Type) - { - case PhysicsJointType.Ball: - DoJointErrorMessage(joint, "warning - axis requested for ball joint: " + joint.ObjectNameInScene); - break; - case PhysicsJointType.Hinge: - d.JointGetHingeAxis(odeJoint.jointID, out axis); - break; - } - } - return new Vector3(axis.X, axis.Y, axis.Z); - } - - - public void remActivePrim(OdePrim deactivatePrim) - { - lock (_activeprims) - { - _activeprims.Remove(deactivatePrim); - } - } - - public override void RemovePrim(PhysicsActor prim) - { - if (prim is OdePrim) - { - lock (OdeLock) - { - OdePrim p = (OdePrim) prim; - - p.setPrimForRemoval(); - AddPhysicsActorTaint(prim); - //RemovePrimThreadLocked(p); - } - } - } - - /// - /// This is called from within simulate but outside the locked portion - /// We need to do our own locking here - /// Essentially, we need to remove the prim from our space segment, whatever segment it's in. - /// - /// If there are no more prim in the segment, we need to empty (spacedestroy)the segment and reclaim memory - /// that the space was using. - /// - /// - public void RemovePrimThreadLocked(OdePrim prim) - { -//Console.WriteLine("RemovePrimThreadLocked " + prim.m_primName); - lock (prim) - { - remCollisionEventReporting(prim); - lock (ode) - { - if (prim.prim_geom != IntPtr.Zero) - { - prim.ResetTaints(); - - if (prim.IsPhysical) - { - prim.disableBody(); - if (prim.childPrim) - { - prim.childPrim = false; - prim.Body = IntPtr.Zero; - prim.m_disabled = true; - prim.IsPhysical = false; - } - - - } - // we don't want to remove the main space - - // If the geometry is in the targetspace, remove it from the target space - //m_log.Warn(prim.m_targetSpace); - - //if (prim.m_targetSpace != IntPtr.Zero) - //{ - //if (d.SpaceQuery(prim.m_targetSpace, prim.prim_geom)) - //{ - - //if (d.GeomIsSpace(prim.m_targetSpace)) - //{ - //waitForSpaceUnlock(prim.m_targetSpace); - //d.SpaceRemove(prim.m_targetSpace, prim.prim_geom); - prim.m_targetSpace = IntPtr.Zero; - //} - //else - //{ - // m_log.Info("[Physics]: Invalid Scene passed to 'removeprim from scene':" + - //((OdePrim)prim).m_targetSpace.ToString()); - //} - - //} - //} - //m_log.Warn(prim.prim_geom); - try - { - if (prim.prim_geom != IntPtr.Zero) - { - d.GeomDestroy(prim.prim_geom); - prim.prim_geom = IntPtr.Zero; - } - else - { - m_log.Warn("[PHYSICS]: Unable to remove prim from physics scene"); - } - } - catch (AccessViolationException) - { - m_log.Info("[PHYSICS]: Couldn't remove prim from physics scene, it was already be removed."); - } - lock (_prims) - _prims.Remove(prim); - - //If there are no more geometries in the sub-space, we don't need it in the main space anymore - //if (d.SpaceGetNumGeoms(prim.m_targetSpace) == 0) - //{ - //if (prim.m_targetSpace != null) - //{ - //if (d.GeomIsSpace(prim.m_targetSpace)) - //{ - //waitForSpaceUnlock(prim.m_targetSpace); - //d.SpaceRemove(space, prim.m_targetSpace); - // free up memory used by the space. - //d.SpaceDestroy(prim.m_targetSpace); - //int[] xyspace = calculateSpaceArrayItemFromPos(prim.Position); - //resetSpaceArrayItemToZero(xyspace[0], xyspace[1]); - //} - //else - //{ - //m_log.Info("[Physics]: Invalid Scene passed to 'removeprim from scene':" + - //((OdePrim) prim).m_targetSpace.ToString()); - //} - //} - //} - - if (SupportsNINJAJoints) - { - RemoveAllJointsConnectedToActorThreadLocked(prim); - } - } - } - } - } - - #endregion - - #region Space Separation Calculation - - /// - /// Takes a space pointer and zeros out the array we're using to hold the spaces - /// - /// - public void resetSpaceArrayItemToZero(IntPtr pSpace) - { - for (int x = 0; x < staticPrimspace.GetLength(0); x++) - { - for (int y = 0; y < staticPrimspace.GetLength(1); y++) - { - if (staticPrimspace[x, y] == pSpace) - staticPrimspace[x, y] = IntPtr.Zero; - } - } - } - - public void resetSpaceArrayItemToZero(int arrayitemX, int arrayitemY) - { - staticPrimspace[arrayitemX, arrayitemY] = IntPtr.Zero; - } - - /// - /// Called when a static prim moves. Allocates a space for the prim based on its position - /// - /// the pointer to the geom that moved - /// the position that the geom moved to - /// a pointer to the space it was in before it was moved. - /// a pointer to the new space it's in - public IntPtr recalculateSpaceForGeom(IntPtr geom, Vector3 pos, IntPtr currentspace) - { - // Called from setting the Position and Size of an ODEPrim so - // it's already in locked space. - - // we don't want to remove the main space - // we don't need to test physical here because this function should - // never be called if the prim is physical(active) - - // All physical prim end up in the root space - //Thread.Sleep(20); - if (currentspace != space) - { - //m_log.Info("[SPACE]: C:" + currentspace.ToString() + " g:" + geom.ToString()); - //if (currentspace == IntPtr.Zero) - //{ - //int adfadf = 0; - //} - if (d.SpaceQuery(currentspace, geom) && currentspace != IntPtr.Zero) - { - if (d.GeomIsSpace(currentspace)) - { - waitForSpaceUnlock(currentspace); - d.SpaceRemove(currentspace, geom); - } - else - { - m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" + currentspace + - " Geom:" + geom); - } - } - else - { - IntPtr sGeomIsIn = d.GeomGetSpace(geom); - if (sGeomIsIn != IntPtr.Zero) - { - if (d.GeomIsSpace(currentspace)) - { - waitForSpaceUnlock(sGeomIsIn); - d.SpaceRemove(sGeomIsIn, geom); - } - else - { - m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" + - sGeomIsIn + " Geom:" + geom); - } - } - } - - //If there are no more geometries in the sub-space, we don't need it in the main space anymore - if (d.SpaceGetNumGeoms(currentspace) == 0) - { - if (currentspace != IntPtr.Zero) - { - if (d.GeomIsSpace(currentspace)) - { - waitForSpaceUnlock(currentspace); - waitForSpaceUnlock(space); - d.SpaceRemove(space, currentspace); - // free up memory used by the space. - - //d.SpaceDestroy(currentspace); - resetSpaceArrayItemToZero(currentspace); - } - else - { - m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" + - currentspace + " Geom:" + geom); - } - } - } - } - else - { - // this is a physical object that got disabled. ;.; - if (currentspace != IntPtr.Zero && geom != IntPtr.Zero) - { - if (d.SpaceQuery(currentspace, geom)) - { - if (d.GeomIsSpace(currentspace)) - { - waitForSpaceUnlock(currentspace); - d.SpaceRemove(currentspace, geom); - } - else - { - m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" + - currentspace + " Geom:" + geom); - } - } - else - { - IntPtr sGeomIsIn = d.GeomGetSpace(geom); - if (sGeomIsIn != IntPtr.Zero) - { - if (d.GeomIsSpace(sGeomIsIn)) - { - waitForSpaceUnlock(sGeomIsIn); - d.SpaceRemove(sGeomIsIn, geom); - } - else - { - m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" + - sGeomIsIn + " Geom:" + geom); - } - } - } - } - } - - // The routines in the Position and Size sections do the 'inserting' into the space, - // so all we have to do is make sure that the space that we're putting the prim into - // is in the 'main' space. - int[] iprimspaceArrItem = calculateSpaceArrayItemFromPos(pos); - IntPtr newspace = calculateSpaceForGeom(pos); - - if (newspace == IntPtr.Zero) - { - newspace = createprimspace(iprimspaceArrItem[0], iprimspaceArrItem[1]); - d.HashSpaceSetLevels(newspace, smallHashspaceLow, smallHashspaceHigh); - } - - return newspace; - } - - /// - /// Creates a new space at X Y - /// - /// - /// - /// A pointer to the created space - public IntPtr createprimspace(int iprimspaceArrItemX, int iprimspaceArrItemY) - { - // creating a new space for prim and inserting it into main space. - staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY] = d.HashSpaceCreate(IntPtr.Zero); - d.GeomSetCategoryBits(staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY], (int)CollisionCategories.Space); - waitForSpaceUnlock(space); - d.SpaceSetSublevel(space, 1); - d.SpaceAdd(space, staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY]); - return staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY]; - } - - /// - /// Calculates the space the prim should be in by its position - /// - /// - /// a pointer to the space. This could be a new space or reused space. - public IntPtr calculateSpaceForGeom(Vector3 pos) - { - int[] xyspace = calculateSpaceArrayItemFromPos(pos); - //m_log.Info("[Physics]: Attempting to use arrayItem: " + xyspace[0].ToString() + "," + xyspace[1].ToString()); - return staticPrimspace[xyspace[0], xyspace[1]]; - } - - /// - /// Holds the space allocation logic - /// - /// - /// an array item based on the position - public int[] calculateSpaceArrayItemFromPos(Vector3 pos) - { - int[] returnint = new int[2]; - - returnint[0] = (int) (pos.X/metersInSpace); - - if (returnint[0] > ((int) (259f/metersInSpace))) - returnint[0] = ((int) (259f/metersInSpace)); - if (returnint[0] < 0) - returnint[0] = 0; - - returnint[1] = (int) (pos.Y/metersInSpace); - if (returnint[1] > ((int) (259f/metersInSpace))) - returnint[1] = ((int) (259f/metersInSpace)); - if (returnint[1] < 0) - returnint[1] = 0; - - return returnint; - } - - #endregion - - /// - /// Routine to figure out if we need to mesh this prim with our mesher - /// - /// - /// - public bool needsMeshing(PrimitiveBaseShape pbs) - { - // most of this is redundant now as the mesher will return null if it cant mesh a prim - // but we still need to check for sculptie meshing being enabled so this is the most - // convenient place to do it for now... - - // //if (pbs.PathCurve == (byte)Primitive.PathCurve.Circle && pbs.ProfileCurve == (byte)Primitive.ProfileCurve.Circle && pbs.PathScaleY <= 0.75f) - // //m_log.Debug("needsMeshing: " + " pathCurve: " + pbs.PathCurve.ToString() + " profileCurve: " + pbs.ProfileCurve.ToString() + " pathScaleY: " + Primitive.UnpackPathScale(pbs.PathScaleY).ToString()); - int iPropertiesNotSupportedDefault = 0; - - if (pbs.SculptEntry && !meshSculptedPrim) - { -#if SPAM - m_log.Warn("NonMesh"); -#endif - return false; - } - - // if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since ODE can use an internal representation for the prim - if (!forceSimplePrimMeshing && !pbs.SculptEntry) - { - if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) - || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 - && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z)) - { - - if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0 - && pbs.ProfileHollow == 0 - && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0 - && pbs.PathBegin == 0 && pbs.PathEnd == 0 - && pbs.PathTaperX == 0 && pbs.PathTaperY == 0 - && pbs.PathScaleX == 100 && pbs.PathScaleY == 100 - && pbs.PathShearX == 0 && pbs.PathShearY == 0) - { -#if SPAM - m_log.Warn("NonMesh"); -#endif - return false; - } - } - } - - if (pbs.ProfileHollow != 0) - iPropertiesNotSupportedDefault++; - - if ((pbs.PathBegin != 0) || pbs.PathEnd != 0) - iPropertiesNotSupportedDefault++; - - if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0)) - iPropertiesNotSupportedDefault++; - - if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0) - iPropertiesNotSupportedDefault++; - - if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100)) - iPropertiesNotSupportedDefault++; - - if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0)) - iPropertiesNotSupportedDefault++; - - if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight) - iPropertiesNotSupportedDefault++; - - if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 && (pbs.Scale.X != pbs.Scale.Y || pbs.Scale.Y != pbs.Scale.Z || pbs.Scale.Z != pbs.Scale.X)) - iPropertiesNotSupportedDefault++; - - if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte) Extrusion.Curve1) - iPropertiesNotSupportedDefault++; - - // test for torus - if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Square) - { - if (pbs.PathCurve == (byte)Extrusion.Curve1) - { - iPropertiesNotSupportedDefault++; - } - } - else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Circle) - { - if (pbs.PathCurve == (byte)Extrusion.Straight) - { - iPropertiesNotSupportedDefault++; - } - - // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits - else if (pbs.PathCurve == (byte)Extrusion.Curve1) - { - iPropertiesNotSupportedDefault++; - } - } - else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle) - { - if (pbs.PathCurve == (byte)Extrusion.Curve1 || pbs.PathCurve == (byte)Extrusion.Curve2) - { - iPropertiesNotSupportedDefault++; - } - } - else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle) - { - if (pbs.PathCurve == (byte)Extrusion.Straight) - { - iPropertiesNotSupportedDefault++; - } - else if (pbs.PathCurve == (byte)Extrusion.Curve1) - { - iPropertiesNotSupportedDefault++; - } - } - - if (pbs.SculptEntry && meshSculptedPrim) - iPropertiesNotSupportedDefault++; - - - if (iPropertiesNotSupportedDefault == 0) - { -#if SPAM - m_log.Warn("NonMesh"); -#endif - return false; - } -#if SPAM - m_log.Debug("Mesh"); -#endif - return true; - } - - /// - /// Called after our prim properties are set Scale, position etc. - /// We use this event queue like method to keep changes to the physical scene occuring in the threadlocked mutex - /// This assures us that we have no race conditions - /// - /// - public override void AddPhysicsActorTaint(PhysicsActor prim) - { - - if (prim is OdePrim) - { - OdePrim taintedprim = ((OdePrim) prim); - lock (_taintedPrimLock) - { - if (!(_taintedPrimH.Contains(taintedprim))) - { -//Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.m_primName); - _taintedPrimH.Add(taintedprim); // HashSet for searching - _taintedPrimL.Add(taintedprim); // List for ordered readout - } - } - return; - } - else if (prim is OdeCharacter) - { - OdeCharacter taintedchar = ((OdeCharacter)prim); - lock (_taintedActors) - { - if (!(_taintedActors.Contains(taintedchar))) - { - _taintedActors.Add(taintedchar); - if (taintedchar.bad) - m_log.DebugFormat("[PHYSICS]: Added BAD actor {0} to tainted actors", taintedchar.m_uuid); - } - } - } - } - - /// - /// This is our main simulate loop - /// It's thread locked by a Mutex in the scene. - /// It holds Collisions, it instructs ODE to step through the physical reactions - /// It moves the objects around in memory - /// It calls the methods that report back to the object owners.. (scenepresence, SceneObjectGroup) - /// - /// - /// - public override float Simulate(float timeStep) - { - if (framecount >= int.MaxValue) - framecount = 0; - - //if (m_worldOffset != Vector3.Zero) - // return 0; - - framecount++; - - float fps = 0; - //m_log.Info(timeStep.ToString()); - step_time += timeStep; - - // If We're loaded down by something else, - // or debugging with the Visual Studio project on pause - // skip a few frames to catch up gracefully. - // without shooting the physicsactors all over the place - - if (step_time >= m_SkipFramesAtms) - { - // Instead of trying to catch up, it'll do 5 physics frames only - step_time = ODE_STEPSIZE; - m_physicsiterations = 5; - } - else - { - m_physicsiterations = 10; - } - - if (SupportsNINJAJoints) - { - DeleteRequestedJoints(); // this must be outside of the lock (OdeLock) to avoid deadlocks - CreateRequestedJoints(); // this must be outside of the lock (OdeLock) to avoid deadlocks - } - - lock (OdeLock) - { - // Process 10 frames if the sim is running normal.. - // process 5 frames if the sim is running slow - //try - //{ - //d.WorldSetQuickStepNumIterations(world, m_physicsiterations); - //} - //catch (StackOverflowException) - //{ - // m_log.Error("[PHYSICS]: The operating system wasn't able to allocate enough memory for the simulation. Restarting the sim."); - // ode.drelease(world); - //base.TriggerPhysicsBasedRestart(); - //} - - int i = 0; - - // Figure out the Frames Per Second we're going at. - //(step_time == 0.004f, there's 250 of those per second. Times the step time/step size - - fps = (step_time / ODE_STEPSIZE) * 1000; - // HACK: Using a time dilation of 1.0 to debug rubberbanding issues - //m_timeDilation = Math.Min((step_time / ODE_STEPSIZE) / (0.09375f / ODE_STEPSIZE), 1.0f); - - step_time = 0.09375f; - - while (step_time > 0.0f) - { - //lock (ode) - //{ - //if (!ode.lockquery()) - //{ - // ode.dlock(world); - try - { - // Insert, remove Characters - bool processedtaints = false; - - lock (_taintedActors) - { - if (_taintedActors.Count > 0) - { - foreach (OdeCharacter character in _taintedActors) - { - - character.ProcessTaints(timeStep); - - processedtaints = true; - //character.m_collisionscore = 0; - } - - if (processedtaints) - _taintedActors.Clear(); - } - } - - // Modify other objects in the scene. - processedtaints = false; - - lock (_taintedPrimLock) - { - foreach (OdePrim prim in _taintedPrimL) - { - if (prim.m_taintremove) - { - //Console.WriteLine("Simulate calls RemovePrimThreadLocked"); - RemovePrimThreadLocked(prim); - } - else - { - //Console.WriteLine("Simulate calls ProcessTaints"); - prim.ProcessTaints(timeStep); - } - processedtaints = true; - prim.m_collisionscore = 0; - - // This loop can block up the Heartbeat for a very long time on large regions. - // We need to let the Watchdog know that the Heartbeat is not dead - // NOTE: This is currently commented out, but if things like OAR loading are - // timing the heartbeat out we will need to uncomment it - //Watchdog.UpdateThread(); - } - - if (SupportsNINJAJoints) - { - // Create pending joints, if possible - - // joints can only be processed after ALL bodies are processed (and exist in ODE), since creating - // a joint requires specifying the body id of both involved bodies - if (pendingJoints.Count > 0) - { - List successfullyProcessedPendingJoints = new List(); - //DoJointErrorMessage(joints_connecting_actor, "taint: " + pendingJoints.Count + " pending joints"); - foreach (PhysicsJoint joint in pendingJoints) - { - //DoJointErrorMessage(joint, "taint: time to create joint with parms: " + joint.RawParams); - string[] jointParams = joint.RawParams.Split(" ".ToCharArray(), System.StringSplitOptions.RemoveEmptyEntries); - List jointBodies = new List(); - bool allJointBodiesAreReady = true; - foreach (string jointParam in jointParams) - { - if (jointParam == "NULL") - { - //DoJointErrorMessage(joint, "attaching NULL joint to world"); - jointBodies.Add(IntPtr.Zero); - } - else - { - //DoJointErrorMessage(joint, "looking for prim name: " + jointParam); - bool foundPrim = false; - lock (_prims) - { - foreach (OdePrim prim in _prims) // FIXME: inefficient - { - if (prim.SOPName == jointParam) - { - //DoJointErrorMessage(joint, "found for prim name: " + jointParam); - if (prim.IsPhysical && prim.Body != IntPtr.Zero) - { - jointBodies.Add(prim.Body); - foundPrim = true; - break; - } - else - { - DoJointErrorMessage(joint, "prim name " + jointParam + - " exists but is not (yet) physical; deferring joint creation. " + - "IsPhysical property is " + prim.IsPhysical + - " and body is " + prim.Body); - foundPrim = false; - break; - } - } - } - } - if (foundPrim) - { - // all is fine - } - else - { - allJointBodiesAreReady = false; - break; - } - } - } - if (allJointBodiesAreReady) - { - //DoJointErrorMessage(joint, "allJointBodiesAreReady for " + joint.ObjectNameInScene + " with parms " + joint.RawParams); - if (jointBodies[0] == jointBodies[1]) - { - DoJointErrorMessage(joint, "ERROR: joint cannot be created; the joint bodies are the same, body1==body2. Raw body is " + jointBodies[0] + ". raw parms: " + joint.RawParams); - } - else - { - switch (joint.Type) - { - case PhysicsJointType.Ball: - { - IntPtr odeJoint; - //DoJointErrorMessage(joint, "ODE creating ball joint "); - odeJoint = d.JointCreateBall(world, IntPtr.Zero); - //DoJointErrorMessage(joint, "ODE attaching ball joint: " + odeJoint + " with b1:" + jointBodies[0] + " b2:" + jointBodies[1]); - d.JointAttach(odeJoint, jointBodies[0], jointBodies[1]); - //DoJointErrorMessage(joint, "ODE setting ball anchor: " + odeJoint + " to vec:" + joint.Position); - d.JointSetBallAnchor(odeJoint, - joint.Position.X, - joint.Position.Y, - joint.Position.Z); - //DoJointErrorMessage(joint, "ODE joint setting OK"); - //DoJointErrorMessage(joint, "The ball joint's bodies are here: b0: "); - //DoJointErrorMessage(joint, "" + (jointBodies[0] != IntPtr.Zero ? "" + d.BodyGetPosition(jointBodies[0]) : "fixed environment")); - //DoJointErrorMessage(joint, "The ball joint's bodies are here: b1: "); - //DoJointErrorMessage(joint, "" + (jointBodies[1] != IntPtr.Zero ? "" + d.BodyGetPosition(jointBodies[1]) : "fixed environment")); - - if (joint is OdePhysicsJoint) - { - ((OdePhysicsJoint)joint).jointID = odeJoint; - } - else - { - DoJointErrorMessage(joint, "WARNING: non-ode joint in ODE!"); - } - } - break; - case PhysicsJointType.Hinge: - { - IntPtr odeJoint; - //DoJointErrorMessage(joint, "ODE creating hinge joint "); - odeJoint = d.JointCreateHinge(world, IntPtr.Zero); - //DoJointErrorMessage(joint, "ODE attaching hinge joint: " + odeJoint + " with b1:" + jointBodies[0] + " b2:" + jointBodies[1]); - d.JointAttach(odeJoint, jointBodies[0], jointBodies[1]); - //DoJointErrorMessage(joint, "ODE setting hinge anchor: " + odeJoint + " to vec:" + joint.Position); - d.JointSetHingeAnchor(odeJoint, - joint.Position.X, - joint.Position.Y, - joint.Position.Z); - // We use the orientation of the x-axis of the joint's coordinate frame - // as the axis for the hinge. - - // Therefore, we must get the joint's coordinate frame based on the - // joint.Rotation field, which originates from the orientation of the - // joint's proxy object in the scene. - - // The joint's coordinate frame is defined as the transformation matrix - // that converts a vector from joint-local coordinates into world coordinates. - // World coordinates are defined as the XYZ coordinate system of the sim, - // as shown in the top status-bar of the viewer. - - // Once we have the joint's coordinate frame, we extract its X axis (AtAxis) - // and use that as the hinge axis. - - //joint.Rotation.Normalize(); - Matrix4 proxyFrame = Matrix4.CreateFromQuaternion(joint.Rotation); - - // Now extract the X axis of the joint's coordinate frame. - - // Do not try to use proxyFrame.AtAxis or you will become mired in the - // tar pit of transposed, inverted, and generally messed-up orientations. - // (In other words, Matrix4.AtAxis() is borked.) - // Vector3 jointAxis = proxyFrame.AtAxis; <--- this path leadeth to madness - - // Instead, compute the X axis of the coordinate frame by transforming - // the (1,0,0) vector. At least that works. - - //m_log.Debug("PHY: making axis: complete matrix is " + proxyFrame); - Vector3 jointAxis = Vector3.Transform(Vector3.UnitX, proxyFrame); - //m_log.Debug("PHY: making axis: hinge joint axis is " + jointAxis); - //DoJointErrorMessage(joint, "ODE setting hinge axis: " + odeJoint + " to vec:" + jointAxis); - d.JointSetHingeAxis(odeJoint, - jointAxis.X, - jointAxis.Y, - jointAxis.Z); - //d.JointSetHingeParam(odeJoint, (int)dParam.CFM, 0.1f); - if (joint is OdePhysicsJoint) - { - ((OdePhysicsJoint)joint).jointID = odeJoint; - } - else - { - DoJointErrorMessage(joint, "WARNING: non-ode joint in ODE!"); - } - } - break; - } - successfullyProcessedPendingJoints.Add(joint); - } - } - else - { - DoJointErrorMessage(joint, "joint could not yet be created; still pending"); - } - } - foreach (PhysicsJoint successfullyProcessedJoint in successfullyProcessedPendingJoints) - { - //DoJointErrorMessage(successfullyProcessedJoint, "finalizing succesfully procsssed joint " + successfullyProcessedJoint.ObjectNameInScene + " parms " + successfullyProcessedJoint.RawParams); - //DoJointErrorMessage(successfullyProcessedJoint, "removing from pending"); - InternalRemovePendingJoint(successfullyProcessedJoint); - //DoJointErrorMessage(successfullyProcessedJoint, "adding to active"); - InternalAddActiveJoint(successfullyProcessedJoint); - //DoJointErrorMessage(successfullyProcessedJoint, "done"); - } - } - } - - if (processedtaints) -//Console.WriteLine("Simulate calls Clear of _taintedPrim list"); - _taintedPrimH.Clear(); - _taintedPrimL.Clear(); - } - - // Move characters - lock (_characters) - { - List defects = new List(); - foreach (OdeCharacter actor in _characters) - { - if (actor != null) - actor.Move(timeStep, defects); - } - if (0 != defects.Count) - { - foreach (OdeCharacter defect in defects) - { - RemoveCharacter(defect); - } - } - } - - // Move other active objects - lock (_activeprims) - { - foreach (OdePrim prim in _activeprims) - { - prim.m_collisionscore = 0; - prim.Move(timeStep); - } - } - - //if ((framecount % m_randomizeWater) == 0) - // randomizeWater(waterlevel); - - //int RayCastTimeMS = m_rayCastManager.ProcessQueuedRequests(); - m_rayCastManager.ProcessQueuedRequests(); - - collision_optimized(timeStep); - - lock (_collisionEventPrim) - { - foreach (PhysicsActor obj in _collisionEventPrim) - { - if (obj == null) - continue; - - switch ((ActorTypes)obj.PhysicsActorType) - { - case ActorTypes.Agent: - OdeCharacter cobj = (OdeCharacter)obj; - cobj.AddCollisionFrameTime(100); - cobj.SendCollisions(); - break; - case ActorTypes.Prim: - OdePrim pobj = (OdePrim)obj; - pobj.SendCollisions(); - break; - } - } - } - - //if (m_global_contactcount > 5) - //{ - // m_log.DebugFormat("[PHYSICS]: Contacts:{0}", m_global_contactcount); - //} - - m_global_contactcount = 0; - - d.WorldQuickStep(world, ODE_STEPSIZE); - d.JointGroupEmpty(contactgroup); - //ode.dunlock(world); - } - catch (Exception e) - { - m_log.ErrorFormat("[PHYSICS]: {0}, {1}, {2}", e.Message, e.TargetSite, e); - ode.dunlock(world); - } - - step_time -= ODE_STEPSIZE; - i++; - //} - //else - //{ - //fps = 0; - //} - //} - } - - lock (_characters) - { - foreach (OdeCharacter actor in _characters) - { - if (actor != null) - { - if (actor.bad) - m_log.WarnFormat("[PHYSICS]: BAD Actor {0} in _characters list was not removed?", actor.m_uuid); - actor.UpdatePositionAndVelocity(); - } - } - } - - lock (_badCharacter) - { - if (_badCharacter.Count > 0) - { - foreach (OdeCharacter chr in _badCharacter) - { - RemoveCharacter(chr); - } - _badCharacter.Clear(); - } - } - - lock (_activeprims) - { - //if (timeStep < 0.2f) - { - foreach (OdePrim actor in _activeprims) - { - if (actor.IsPhysical && (d.BodyIsEnabled(actor.Body) || !actor._zeroFlag)) - { - actor.UpdatePositionAndVelocity(); - - if (SupportsNINJAJoints) - { - // If an actor moved, move its joint proxy objects as well. - // There seems to be an event PhysicsActor.OnPositionUpdate that could be used - // for this purpose but it is never called! So we just do the joint - // movement code here. - - if (actor.SOPName != null && - joints_connecting_actor.ContainsKey(actor.SOPName) && - joints_connecting_actor[actor.SOPName] != null && - joints_connecting_actor[actor.SOPName].Count > 0) - { - foreach (PhysicsJoint affectedJoint in joints_connecting_actor[actor.SOPName]) - { - if (affectedJoint.IsInPhysicsEngine) - { - DoJointMoved(affectedJoint); - } - else - { - DoJointErrorMessage(affectedJoint, "a body connected to a joint was moved, but the joint doesn't exist yet! this will lead to joint error. joint was: " + affectedJoint.ObjectNameInScene + " parms:" + affectedJoint.RawParams); - } - } - } - } - } - } - } - } - - //DumpJointInfo(); - - // Finished with all sim stepping. If requested, dump world state to file for debugging. - // TODO: This call to the export function is already inside lock (OdeLock) - but is an extra lock needed? - // TODO: This overwrites all dump files in-place. Should this be a growing logfile, or separate snapshots? - if (physics_logging && (physics_logging_interval>0) && (framecount % physics_logging_interval == 0)) - { - string fname = "state-" + world.ToString() + ".DIF"; // give each physics world a separate filename - string prefix = "world" + world.ToString(); // prefix for variable names in exported .DIF file - - if (physics_logging_append_existing_logfile) - { - string header = "-------------- START OF PHYSICS FRAME " + framecount.ToString() + " --------------"; - TextWriter fwriter = File.AppendText(fname); - fwriter.WriteLine(header); - fwriter.Close(); - } - d.WorldExportDIF(world, fname, physics_logging_append_existing_logfile, prefix); - } - latertickcount = Util.EnvironmentTickCount() - tickCountFrameRun; - - // OpenSimulator above does 10 fps. 10 fps = means that the main thread loop and physics - // has a max of 100 ms to run theoretically. - // If the main loop stalls, it calls Simulate later which makes the tick count ms larger. - // If Physics stalls, it takes longer which makes the tick count ms larger. - - if (latertickcount < 100) - m_timeDilation = 1.0f; - else - { - m_timeDilation = 100f / latertickcount; - //m_timeDilation = Math.Min((Math.Max(100 - (Util.EnvironmentTickCount() - tickCountFrameRun), 1) / 100f), 1.0f); - } - - tickCountFrameRun = Util.EnvironmentTickCount(); - } - - return fps; - } - - public override void GetResults() - { - } - - public override bool IsThreaded - { - // for now we won't be multithreaded - get { return (false); } - } - - #region ODE Specific Terrain Fixes - public float[] ResizeTerrain512NearestNeighbour(float[] heightMap) - { - float[] returnarr = new float[262144]; - float[,] resultarr = new float[(int)WorldExtents.X, (int)WorldExtents.Y]; - - // Filling out the array into its multi-dimensional components - for (int y = 0; y < WorldExtents.Y; y++) - { - for (int x = 0; x < WorldExtents.X; x++) - { - resultarr[y, x] = heightMap[y * (int)WorldExtents.Y + x]; - } - } - - // Resize using Nearest Neighbour - - // This particular way is quick but it only works on a multiple of the original - - // The idea behind this method can be described with the following diagrams - // second pass and third pass happen in the same loop really.. just separated - // them to show what this does. - - // First Pass - // ResultArr: - // 1,1,1,1,1,1 - // 1,1,1,1,1,1 - // 1,1,1,1,1,1 - // 1,1,1,1,1,1 - // 1,1,1,1,1,1 - // 1,1,1,1,1,1 - - // Second Pass - // ResultArr2: - // 1,,1,,1,,1,,1,,1, - // ,,,,,,,,,, - // 1,,1,,1,,1,,1,,1, - // ,,,,,,,,,, - // 1,,1,,1,,1,,1,,1, - // ,,,,,,,,,, - // 1,,1,,1,,1,,1,,1, - // ,,,,,,,,,, - // 1,,1,,1,,1,,1,,1, - // ,,,,,,,,,, - // 1,,1,,1,,1,,1,,1, - - // Third pass fills in the blanks - // ResultArr2: - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - - // X,Y = . - // X+1,y = ^ - // X,Y+1 = * - // X+1,Y+1 = # - - // Filling in like this; - // .* - // ^# - // 1st . - // 2nd * - // 3rd ^ - // 4th # - // on single loop. - - float[,] resultarr2 = new float[512, 512]; - for (int y = 0; y < WorldExtents.Y; y++) - { - for (int x = 0; x < WorldExtents.X; x++) - { - resultarr2[y * 2, x * 2] = resultarr[y, x]; - - if (y < WorldExtents.Y) - { - resultarr2[(y * 2) + 1, x * 2] = resultarr[y, x]; - } - if (x < WorldExtents.X) - { - resultarr2[y * 2, (x * 2) + 1] = resultarr[y, x]; - } - if (x < WorldExtents.X && y < WorldExtents.Y) - { - resultarr2[(y * 2) + 1, (x * 2) + 1] = resultarr[y, x]; - } - } - } - - //Flatten out the array - int i = 0; - for (int y = 0; y < 512; y++) - { - for (int x = 0; x < 512; x++) - { - if (resultarr2[y, x] <= 0) - returnarr[i] = 0.0000001f; - else - returnarr[i] = resultarr2[y, x]; - - i++; - } - } - - return returnarr; - } - - public float[] ResizeTerrain512Interpolation(float[] heightMap) - { - float[] returnarr = new float[262144]; - float[,] resultarr = new float[512,512]; - - // Filling out the array into its multi-dimensional components - for (int y = 0; y < 256; y++) - { - for (int x = 0; x < 256; x++) - { - resultarr[y, x] = heightMap[y * 256 + x]; - } - } - - // Resize using interpolation - - // This particular way is quick but it only works on a multiple of the original - - // The idea behind this method can be described with the following diagrams - // second pass and third pass happen in the same loop really.. just separated - // them to show what this does. - - // First Pass - // ResultArr: - // 1,1,1,1,1,1 - // 1,1,1,1,1,1 - // 1,1,1,1,1,1 - // 1,1,1,1,1,1 - // 1,1,1,1,1,1 - // 1,1,1,1,1,1 - - // Second Pass - // ResultArr2: - // 1,,1,,1,,1,,1,,1, - // ,,,,,,,,,, - // 1,,1,,1,,1,,1,,1, - // ,,,,,,,,,, - // 1,,1,,1,,1,,1,,1, - // ,,,,,,,,,, - // 1,,1,,1,,1,,1,,1, - // ,,,,,,,,,, - // 1,,1,,1,,1,,1,,1, - // ,,,,,,,,,, - // 1,,1,,1,,1,,1,,1, - - // Third pass fills in the blanks - // ResultArr2: - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - - // X,Y = . - // X+1,y = ^ - // X,Y+1 = * - // X+1,Y+1 = # - - // Filling in like this; - // .* - // ^# - // 1st . - // 2nd * - // 3rd ^ - // 4th # - // on single loop. - - float[,] resultarr2 = new float[512,512]; - for (int y = 0; y < (int)Constants.RegionSize; y++) - { - for (int x = 0; x < (int)Constants.RegionSize; x++) - { - resultarr2[y*2, x*2] = resultarr[y, x]; - - if (y < (int)Constants.RegionSize) - { - if (y + 1 < (int)Constants.RegionSize) - { - if (x + 1 < (int)Constants.RegionSize) - { - resultarr2[(y*2) + 1, x*2] = ((resultarr[y, x] + resultarr[y + 1, x] + - resultarr[y, x + 1] + resultarr[y + 1, x + 1])/4); - } - else - { - resultarr2[(y*2) + 1, x*2] = ((resultarr[y, x] + resultarr[y + 1, x])/2); - } - } - else - { - resultarr2[(y*2) + 1, x*2] = resultarr[y, x]; - } - } - if (x < (int)Constants.RegionSize) - { - if (x + 1 < (int)Constants.RegionSize) - { - if (y + 1 < (int)Constants.RegionSize) - { - resultarr2[y*2, (x*2) + 1] = ((resultarr[y, x] + resultarr[y + 1, x] + - resultarr[y, x + 1] + resultarr[y + 1, x + 1])/4); - } - else - { - resultarr2[y*2, (x*2) + 1] = ((resultarr[y, x] + resultarr[y, x + 1])/2); - } - } - else - { - resultarr2[y*2, (x*2) + 1] = resultarr[y, x]; - } - } - if (x < (int)Constants.RegionSize && y < (int)Constants.RegionSize) - { - if ((x + 1 < (int)Constants.RegionSize) && (y + 1 < (int)Constants.RegionSize)) - { - resultarr2[(y*2) + 1, (x*2) + 1] = ((resultarr[y, x] + resultarr[y + 1, x] + - resultarr[y, x + 1] + resultarr[y + 1, x + 1])/4); - } - else - { - resultarr2[(y*2) + 1, (x*2) + 1] = resultarr[y, x]; - } - } - } - } - //Flatten out the array - int i = 0; - for (int y = 0; y < 512; y++) - { - for (int x = 0; x < 512; x++) - { - if (Single.IsNaN(resultarr2[y, x]) || Single.IsInfinity(resultarr2[y, x])) - { - m_log.Warn("[PHYSICS]: Non finite heightfield element detected. Setting it to 0"); - resultarr2[y, x] = 0; - } - returnarr[i] = resultarr2[y, x]; - i++; - } - } - - return returnarr; - } - - #endregion - - public override void SetTerrain(float[] heightMap) - { - if (m_worldOffset != Vector3.Zero && m_parentScene != null) - { - if (m_parentScene is OdeScene) - { - ((OdeScene)m_parentScene).SetTerrain(heightMap, m_worldOffset); - } - } - else - { - SetTerrain(heightMap, m_worldOffset); - } - } - - public void SetTerrain(float[] heightMap, Vector3 pOffset) - { - // this._heightmap[i] = (double)heightMap[i]; - // dbm (danx0r) -- creating a buffer zone of one extra sample all around - //_origheightmap = heightMap; - - float[] _heightmap; - - // zero out a heightmap array float array (single dimension [flattened])) - //if ((int)Constants.RegionSize == 256) - // _heightmap = new float[514 * 514]; - //else - - _heightmap = new float[(((int)Constants.RegionSize + 2) * ((int)Constants.RegionSize + 2))]; - - uint heightmapWidth = Constants.RegionSize + 1; - uint heightmapHeight = Constants.RegionSize + 1; - - uint heightmapWidthSamples; - - uint heightmapHeightSamples; - - //if (((int)Constants.RegionSize) == 256) - //{ - // heightmapWidthSamples = 2 * (uint)Constants.RegionSize + 2; - // heightmapHeightSamples = 2 * (uint)Constants.RegionSize + 2; - // heightmapWidth++; - // heightmapHeight++; - //} - //else - //{ - - heightmapWidthSamples = (uint)Constants.RegionSize + 1; - heightmapHeightSamples = (uint)Constants.RegionSize + 1; - //} - - const float scale = 1.0f; - const float offset = 0.0f; - const float thickness = 0.2f; - const int wrap = 0; - - int regionsize = (int) Constants.RegionSize + 2; - //Double resolution - //if (((int)Constants.RegionSize) == 256) - // heightMap = ResizeTerrain512Interpolation(heightMap); - - - // if (((int)Constants.RegionSize) == 256 && (int)Constants.RegionSize == 256) - // regionsize = 512; - - float hfmin = 2000; - float hfmax = -2000; - - for (int x = 0; x < heightmapWidthSamples; x++) - { - for (int y = 0; y < heightmapHeightSamples; y++) - { - int xx = Util.Clip(x - 1, 0, regionsize - 1); - int yy = Util.Clip(y - 1, 0, regionsize - 1); - - - float val= heightMap[yy * (int)Constants.RegionSize + xx]; - _heightmap[x * ((int)Constants.RegionSize + 2) + y] = val; - - hfmin = (val < hfmin) ? val : hfmin; - hfmax = (val > hfmax) ? val : hfmax; - } - } - - - - - lock (OdeLock) - { - IntPtr GroundGeom = IntPtr.Zero; - if (RegionTerrain.TryGetValue(pOffset, out GroundGeom)) - { - RegionTerrain.Remove(pOffset); - if (GroundGeom != IntPtr.Zero) - { - if (TerrainHeightFieldHeights.ContainsKey(GroundGeom)) - { - TerrainHeightFieldHeights.Remove(GroundGeom); - } - d.SpaceRemove(space, GroundGeom); - d.GeomDestroy(GroundGeom); - } - - } - IntPtr HeightmapData = d.GeomHeightfieldDataCreate(); - d.GeomHeightfieldDataBuildSingle(HeightmapData, _heightmap, 0, heightmapWidth + 1, heightmapHeight + 1, - (int)heightmapWidthSamples + 1, (int)heightmapHeightSamples + 1, scale, - offset, thickness, wrap); - d.GeomHeightfieldDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1); - GroundGeom = d.CreateHeightfield(space, HeightmapData, 1); - if (GroundGeom != IntPtr.Zero) - { - d.GeomSetCategoryBits(GroundGeom, (int)(CollisionCategories.Land)); - d.GeomSetCollideBits(GroundGeom, (int)(CollisionCategories.Space)); - - } - geom_name_map[GroundGeom] = "Terrain"; - - d.Matrix3 R = new d.Matrix3(); - - Quaternion q1 = Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), 1.5707f); - Quaternion q2 = Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), 1.5707f); - //Axiom.Math.Quaternion q3 = Axiom.Math.Quaternion.FromAngleAxis(3.14f, new Axiom.Math.Vector3(0, 0, 1)); - - q1 = q1 * q2; - //q1 = q1 * q3; - Vector3 v3; - float angle; - q1.GetAxisAngle(out v3, out angle); - - d.RFromAxisAndAngle(out R, v3.X, v3.Y, v3.Z, angle); - d.GeomSetRotation(GroundGeom, ref R); - d.GeomSetPosition(GroundGeom, (pOffset.X + ((int)Constants.RegionSize * 0.5f)) - 1, (pOffset.Y + ((int)Constants.RegionSize * 0.5f)) - 1, 0); - IntPtr testGround = IntPtr.Zero; - if (RegionTerrain.TryGetValue(pOffset, out testGround)) - { - RegionTerrain.Remove(pOffset); - } - RegionTerrain.Add(pOffset, GroundGeom, GroundGeom); - TerrainHeightFieldHeights.Add(GroundGeom,_heightmap); - - } - } - - public override void DeleteTerrain() - { - } - - public float GetWaterLevel() - { - return waterlevel; - } - - public override bool SupportsCombining() - { - return true; - } - - public override void UnCombine(PhysicsScene pScene) - { - IntPtr localGround = IntPtr.Zero; -// float[] localHeightfield; - bool proceed = false; - List geomDestroyList = new List(); - - lock (OdeLock) - { - if (RegionTerrain.TryGetValue(Vector3.Zero, out localGround)) - { - foreach (IntPtr geom in TerrainHeightFieldHeights.Keys) - { - if (geom == localGround) - { -// localHeightfield = TerrainHeightFieldHeights[geom]; - proceed = true; - } - else - { - geomDestroyList.Add(geom); - } - } - - if (proceed) - { - m_worldOffset = Vector3.Zero; - WorldExtents = new Vector2((int)Constants.RegionSize, (int)Constants.RegionSize); - m_parentScene = null; - - foreach (IntPtr g in geomDestroyList) - { - // removingHeightField needs to be done or the garbage collector will - // collect the terrain data before we tell ODE to destroy it causing - // memory corruption - if (TerrainHeightFieldHeights.ContainsKey(g)) - { -// float[] removingHeightField = TerrainHeightFieldHeights[g]; - TerrainHeightFieldHeights.Remove(g); - - if (RegionTerrain.ContainsKey(g)) - { - RegionTerrain.Remove(g); - } - - d.GeomDestroy(g); - //removingHeightField = new float[0]; - } - } - - } - else - { - m_log.Warn("[PHYSICS]: Couldn't proceed with UnCombine. Region has inconsistant data."); - - } - } - } - } - - public override void SetWaterLevel(float baseheight) - { - waterlevel = baseheight; - randomizeWater(waterlevel); - } - - public void randomizeWater(float baseheight) - { - const uint heightmapWidth = m_regionWidth + 2; - const uint heightmapHeight = m_regionHeight + 2; - const uint heightmapWidthSamples = m_regionWidth + 2; - const uint heightmapHeightSamples = m_regionHeight + 2; - const float scale = 1.0f; - const float offset = 0.0f; - const float thickness = 2.9f; - const int wrap = 0; - - for (int i = 0; i < (258 * 258); i++) - { - _watermap[i] = (baseheight-0.1f) + ((float)fluidRandomizer.Next(1,9) / 10f); - // m_log.Info((baseheight - 0.1f) + ((float)fluidRandomizer.Next(1, 9) / 10f)); - } - - lock (OdeLock) - { - if (WaterGeom != IntPtr.Zero) - { - d.SpaceRemove(space, WaterGeom); - } - IntPtr HeightmapData = d.GeomHeightfieldDataCreate(); - d.GeomHeightfieldDataBuildSingle(HeightmapData, _watermap, 0, heightmapWidth, heightmapHeight, - (int)heightmapWidthSamples, (int)heightmapHeightSamples, scale, - offset, thickness, wrap); - d.GeomHeightfieldDataSetBounds(HeightmapData, m_regionWidth, m_regionHeight); - WaterGeom = d.CreateHeightfield(space, HeightmapData, 1); - if (WaterGeom != IntPtr.Zero) - { - d.GeomSetCategoryBits(WaterGeom, (int)(CollisionCategories.Water)); - d.GeomSetCollideBits(WaterGeom, (int)(CollisionCategories.Space)); - - } - geom_name_map[WaterGeom] = "Water"; - - d.Matrix3 R = new d.Matrix3(); - - Quaternion q1 = Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), 1.5707f); - Quaternion q2 = Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), 1.5707f); - //Axiom.Math.Quaternion q3 = Axiom.Math.Quaternion.FromAngleAxis(3.14f, new Axiom.Math.Vector3(0, 0, 1)); - - q1 = q1 * q2; - //q1 = q1 * q3; - Vector3 v3; - float angle; - q1.GetAxisAngle(out v3, out angle); - - d.RFromAxisAndAngle(out R, v3.X, v3.Y, v3.Z, angle); - d.GeomSetRotation(WaterGeom, ref R); - d.GeomSetPosition(WaterGeom, 128, 128, 0); - - } - - } - - public override void Dispose() - { - m_rayCastManager.Dispose(); - m_rayCastManager = null; - - lock (OdeLock) - { - lock (_prims) - { - foreach (OdePrim prm in _prims) - { - RemovePrim(prm); - } - } - - //foreach (OdeCharacter act in _characters) - //{ - //RemoveAvatar(act); - //} - d.WorldDestroy(world); - //d.CloseODE(); - } - } - public override Dictionary GetTopColliders() - { - Dictionary returncolliders = new Dictionary(); - int cnt = 0; - lock (_prims) - { - foreach (OdePrim prm in _prims) - { - if (prm.CollisionScore > 0) - { - returncolliders.Add(prm.m_localID, prm.CollisionScore); - cnt++; - prm.CollisionScore = 0f; - if (cnt > 25) - { - break; - } - } - } - } - return returncolliders; - } - - public override bool SupportsRayCast() - { - return true; - } - - public override void RaycastWorld(Vector3 position, Vector3 direction, float length, RaycastCallback retMethod) - { - if (retMethod != null) - { - m_rayCastManager.QueueRequest(position, direction, length, retMethod); - } - } - -#if USE_DRAWSTUFF - // Keyboard callback - public void command(int cmd) - { - IntPtr geom; - d.Mass mass; - d.Vector3 sides = new d.Vector3(d.RandReal() * 0.5f + 0.1f, d.RandReal() * 0.5f + 0.1f, d.RandReal() * 0.5f + 0.1f); - - - - Char ch = Char.ToLower((Char)cmd); - switch ((Char)ch) - { - case 'w': - try - { - Vector3 rotate = (new Vector3(1, 0, 0) * Quaternion.CreateFromEulers(hpr.Z * Utils.DEG_TO_RAD, hpr.Y * Utils.DEG_TO_RAD, hpr.X * Utils.DEG_TO_RAD)); - - xyz.X += rotate.X; xyz.Y += rotate.Y; xyz.Z += rotate.Z; - ds.SetViewpoint(ref xyz, ref hpr); - } - catch (ArgumentException) - { hpr.X = 0; } - break; - - case 'a': - hpr.X++; - ds.SetViewpoint(ref xyz, ref hpr); - break; - - case 's': - try - { - Vector3 rotate2 = (new Vector3(-1, 0, 0) * Quaternion.CreateFromEulers(hpr.Z * Utils.DEG_TO_RAD, hpr.Y * Utils.DEG_TO_RAD, hpr.X * Utils.DEG_TO_RAD)); - - xyz.X += rotate2.X; xyz.Y += rotate2.Y; xyz.Z += rotate2.Z; - ds.SetViewpoint(ref xyz, ref hpr); - } - catch (ArgumentException) - { hpr.X = 0; } - break; - case 'd': - hpr.X--; - ds.SetViewpoint(ref xyz, ref hpr); - break; - case 'r': - xyz.Z++; - ds.SetViewpoint(ref xyz, ref hpr); - break; - case 'f': - xyz.Z--; - ds.SetViewpoint(ref xyz, ref hpr); - break; - case 'e': - xyz.Y++; - ds.SetViewpoint(ref xyz, ref hpr); - break; - case 'q': - xyz.Y--; - ds.SetViewpoint(ref xyz, ref hpr); - break; - } - } - - public void step(int pause) - { - - ds.SetColor(1.0f, 1.0f, 0.0f); - ds.SetTexture(ds.Texture.Wood); - lock (_prims) - { - foreach (OdePrim prm in _prims) - { - //IntPtr body = d.GeomGetBody(prm.prim_geom); - if (prm.prim_geom != IntPtr.Zero) - { - d.Vector3 pos; - d.GeomCopyPosition(prm.prim_geom, out pos); - //d.BodyCopyPosition(body, out pos); - - d.Matrix3 R; - d.GeomCopyRotation(prm.prim_geom, out R); - //d.BodyCopyRotation(body, out R); - - - d.Vector3 sides = new d.Vector3(); - sides.X = prm.Size.X; - sides.Y = prm.Size.Y; - sides.Z = prm.Size.Z; - - ds.DrawBox(ref pos, ref R, ref sides); - } - } - } - ds.SetColor(1.0f, 0.0f, 0.0f); - lock (_characters) - { - foreach (OdeCharacter chr in _characters) - { - if (chr.Shell != IntPtr.Zero) - { - IntPtr body = d.GeomGetBody(chr.Shell); - - d.Vector3 pos; - d.GeomCopyPosition(chr.Shell, out pos); - //d.BodyCopyPosition(body, out pos); - - d.Matrix3 R; - d.GeomCopyRotation(chr.Shell, out R); - //d.BodyCopyRotation(body, out R); - - ds.DrawCapsule(ref pos, ref R, chr.Size.Z, 0.35f); - d.Vector3 sides = new d.Vector3(); - sides.X = 0.5f; - sides.Y = 0.5f; - sides.Z = 0.5f; - - ds.DrawBox(ref pos, ref R, ref sides); - } - } - } - } - - public void start(int unused) - { - ds.SetViewpoint(ref xyz, ref hpr); - } -#endif - } -} +} \ No newline at end of file diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs new file mode 100644 index 0000000..234af00 --- /dev/null +++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs @@ -0,0 +1,3866 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * 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. + */ + +//#define USE_DRAWSTUFF + +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Threading; +using System.IO; +using System.Diagnostics; +using log4net; +using Nini.Config; +using Ode.NET; +#if USE_DRAWSTUFF +using Drawstuff.NET; +#endif +using OpenSim.Framework; +using OpenSim.Region.Physics.Manager; +using OpenMetaverse; + +namespace OpenSim.Region.Physics.OdePlugin +{ + public enum StatusIndicators : int + { + Generic = 0, + Start = 1, + End = 2 + } + + public struct sCollisionData + { + public uint ColliderLocalId; + public uint CollidedWithLocalId; + public int NumberOfCollisions; + public int CollisionType; + public int StatusIndicator; + public int lastframe; + } + + [Flags] + public enum CollisionCategories : int + { + Disabled = 0, + Geom = 0x00000001, + Body = 0x00000002, + Space = 0x00000004, + Character = 0x00000008, + Land = 0x00000010, + Water = 0x00000020, + Wind = 0x00000040, + Sensor = 0x00000080, + Selected = 0x00000100 + } + + /// + /// Material type for a primitive + /// + public enum Material : int + { + /// + Stone = 0, + /// + Metal = 1, + /// + Glass = 2, + /// + Wood = 3, + /// + Flesh = 4, + /// + Plastic = 5, + /// + Rubber = 6 + } + + public sealed class OdeScene : PhysicsScene + { + private readonly ILog m_log; + // private Dictionary m_storedCollisions = new Dictionary(); + + CollisionLocker ode; + + private Random fluidRandomizer = new Random(Environment.TickCount); + + private const uint m_regionWidth = Constants.RegionSize; + private const uint m_regionHeight = Constants.RegionSize; + + private float ODE_STEPSIZE = 0.020f; + private float metersInSpace = 29.9f; + private float m_timeDilation = 1.0f; + + public float gravityx = 0f; + public float gravityy = 0f; + public float gravityz = -9.8f; + + private float contactsurfacelayer = 0.001f; + + private int worldHashspaceLow = -4; + private int worldHashspaceHigh = 128; + + private int smallHashspaceLow = -4; + private int smallHashspaceHigh = 66; + + private float waterlevel = 0f; + private int framecount = 0; + //private int m_returncollisions = 10; + + private readonly IntPtr contactgroup; + + internal IntPtr LandGeom; + internal IntPtr WaterGeom; + + private float nmTerrainContactFriction = 255.0f; + private float nmTerrainContactBounce = 0.1f; + private float nmTerrainContactERP = 0.1025f; + + private float mTerrainContactFriction = 75f; + private float mTerrainContactBounce = 0.1f; + private float mTerrainContactERP = 0.05025f; + + private float nmAvatarObjectContactFriction = 250f; + private float nmAvatarObjectContactBounce = 0.1f; + + private float mAvatarObjectContactFriction = 75f; + private float mAvatarObjectContactBounce = 0.1f; + + private float avPIDD = 3200f; + private float avPIDP = 1400f; + private float avCapRadius = 0.37f; + private float avStandupTensor = 2000000f; + private bool avCapsuleTilted = true; // true = old compatibility mode with leaning capsule; false = new corrected mode + public bool IsAvCapsuleTilted { get { return avCapsuleTilted; } set { avCapsuleTilted = value; } } + private float avDensity = 80f; + private float avHeightFudgeFactor = 0.52f; + private float avMovementDivisorWalk = 1.3f; + private float avMovementDivisorRun = 0.8f; + private float minimumGroundFlightOffset = 3f; + public float maximumMassObject = 10000.01f; + + public bool meshSculptedPrim = true; + public bool forceSimplePrimMeshing = false; + + public float meshSculptLOD = 32; + public float MeshSculptphysicalLOD = 16; + + public float geomDefaultDensity = 10.000006836f; + + public int geomContactPointsStartthrottle = 3; + public int geomUpdatesPerThrottledUpdate = 15; + + public float bodyPIDD = 35f; + public float bodyPIDG = 25; + + public int geomCrossingFailuresBeforeOutofbounds = 5; + + public float bodyMotorJointMaxforceTensor = 2; + + public int bodyFramesAutoDisable = 20; + + private float[] _watermap; + private bool m_filterCollisions = true; + + private d.NearCallback nearCallback; + public d.TriCallback triCallback; + public d.TriArrayCallback triArrayCallback; + private readonly HashSet _characters = new HashSet(); + private readonly HashSet _prims = new HashSet(); + private readonly HashSet _activeprims = new HashSet(); + private readonly HashSet _taintedPrimH = new HashSet(); + private readonly Object _taintedPrimLock = new Object(); + private readonly List _taintedPrimL = new List(); + private readonly HashSet _taintedActors = new HashSet(); + private readonly List _perloopContact = new List(); + private readonly List _collisionEventPrim = new List(); + private readonly HashSet _badCharacter = new HashSet(); + public Dictionary geom_name_map = new Dictionary(); + public Dictionary actor_name_map = new Dictionary(); + private bool m_NINJA_physics_joints_enabled = false; + //private Dictionary jointpart_name_map = new Dictionary(); + private readonly Dictionary> joints_connecting_actor = new Dictionary>(); + private d.ContactGeom[] contacts; + private readonly List requestedJointsToBeCreated = new List(); // lock only briefly. accessed by external code (to request new joints) and by OdeScene.Simulate() to move those joints into pending/active + private readonly List pendingJoints = new List(); // can lock for longer. accessed only by OdeScene. + private readonly List activeJoints = new List(); // can lock for longer. accessed only by OdeScene. + private readonly List requestedJointsToBeDeleted = new List(); // lock only briefly. accessed by external code (to request deletion of joints) and by OdeScene.Simulate() to move those joints out of pending/active + private Object externalJointRequestsLock = new Object(); + private readonly Dictionary SOPName_to_activeJoint = new Dictionary(); + private readonly Dictionary SOPName_to_pendingJoint = new Dictionary(); + private readonly DoubleDictionary RegionTerrain = new DoubleDictionary(); + private readonly Dictionary TerrainHeightFieldHeights = new Dictionary(); + + private d.Contact contact; + private d.Contact TerrainContact; + private d.Contact AvatarMovementprimContact; + private d.Contact AvatarMovementTerrainContact; + private d.Contact WaterContact; + private d.Contact[,] m_materialContacts; + +//Ckrinke: Comment out until used. We declare it, initialize it, but do not use it +//Ckrinke private int m_randomizeWater = 200; + private int m_physicsiterations = 10; + private const float m_SkipFramesAtms = 0.40f; // Drop frames gracefully at a 400 ms lag + private readonly PhysicsActor PANull = new NullPhysicsActor(); + private float step_time = 0.0f; +//Ckrinke: Comment out until used. We declare it, initialize it, but do not use it +//Ckrinke private int ms = 0; + public IntPtr world; + //private bool returncollisions = false; + // private uint obj1LocalID = 0; + private uint obj2LocalID = 0; + //private int ctype = 0; + private OdeCharacter cc1; + private OdePrim cp1; + private OdeCharacter cc2; + private OdePrim cp2; + private int tickCountFrameRun; + + private int latertickcount=0; + //private int cStartStop = 0; + //private string cDictKey = ""; + + public IntPtr space; + + //private IntPtr tmpSpace; + // split static geometry collision handling into spaces of 30 meters + public IntPtr[,] staticPrimspace; + + public Object OdeLock; + + public IMesher mesher; + + private IConfigSource m_config; + + public bool physics_logging = false; + public int physics_logging_interval = 0; + public bool physics_logging_append_existing_logfile = false; + + public d.Vector3 xyz = new d.Vector3(128.1640f, 128.3079f, 25.7600f); + public d.Vector3 hpr = new d.Vector3(125.5000f, -17.0000f, 0.0000f); + + // TODO: unused: private uint heightmapWidth = m_regionWidth + 1; + // TODO: unused: private uint heightmapHeight = m_regionHeight + 1; + // TODO: unused: private uint heightmapWidthSamples; + // TODO: unused: private uint heightmapHeightSamples; + + private volatile int m_global_contactcount = 0; + + private Vector3 m_worldOffset = Vector3.Zero; + public Vector2 WorldExtents = new Vector2((int)Constants.RegionSize, (int)Constants.RegionSize); + private PhysicsScene m_parentScene = null; + + private ODERayCastRequestManager m_rayCastManager; + + /// + /// Initiailizes the scene + /// Sets many properties that ODE requires to be stable + /// These settings need to be tweaked 'exactly' right or weird stuff happens. + /// + public OdeScene(CollisionLocker dode, string sceneIdentifier) + { + m_log + = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType.ToString() + "." + sceneIdentifier); + + OdeLock = new Object(); + ode = dode; + nearCallback = near; + triCallback = TriCallback; + triArrayCallback = TriArrayCallback; + m_rayCastManager = new ODERayCastRequestManager(this); + lock (OdeLock) + { + // Create the world and the first space + world = d.WorldCreate(); + space = d.HashSpaceCreate(IntPtr.Zero); + + + contactgroup = d.JointGroupCreate(0); + //contactgroup + + d.WorldSetAutoDisableFlag(world, false); + #if USE_DRAWSTUFF + + Thread viewthread = new Thread(new ParameterizedThreadStart(startvisualization)); + viewthread.Start(); + #endif + } + + + _watermap = new float[258 * 258]; + + // Zero out the prim spaces array (we split our space into smaller spaces so + // we can hit test less. + } + +#if USE_DRAWSTUFF + public void startvisualization(object o) + { + ds.Functions fn; + fn.version = ds.VERSION; + fn.start = new ds.CallbackFunction(start); + fn.step = new ds.CallbackFunction(step); + fn.command = new ds.CallbackFunction(command); + fn.stop = null; + fn.path_to_textures = "./textures"; + string[] args = new string[0]; + ds.SimulationLoop(args.Length, args, 352, 288, ref fn); + } +#endif + + // Initialize the mesh plugin + public override void Initialise(IMesher meshmerizer, IConfigSource config) + { + mesher = meshmerizer; + m_config = config; + // Defaults + + if (Environment.OSVersion.Platform == PlatformID.Unix) + { + avPIDD = 3200.0f; + avPIDP = 1400.0f; + avStandupTensor = 2000000f; + } + else + { + avPIDD = 2200.0f; + avPIDP = 900.0f; + avStandupTensor = 550000f; + } + + int contactsPerCollision = 80; + + if (m_config != null) + { + IConfig physicsconfig = m_config.Configs["ODEPhysicsSettings"]; + if (physicsconfig != null) + { + gravityx = physicsconfig.GetFloat("world_gravityx", 0f); + gravityy = physicsconfig.GetFloat("world_gravityy", 0f); + gravityz = physicsconfig.GetFloat("world_gravityz", -9.8f); + + worldHashspaceLow = physicsconfig.GetInt("world_hashspace_size_low", -4); + worldHashspaceHigh = physicsconfig.GetInt("world_hashspace_size_high", 128); + + metersInSpace = physicsconfig.GetFloat("meters_in_small_space", 29.9f); + smallHashspaceLow = physicsconfig.GetInt("small_hashspace_size_low", -4); + smallHashspaceHigh = physicsconfig.GetInt("small_hashspace_size_high", 66); + + contactsurfacelayer = physicsconfig.GetFloat("world_contact_surface_layer", 0.001f); + + nmTerrainContactFriction = physicsconfig.GetFloat("nm_terraincontact_friction", 255.0f); + nmTerrainContactBounce = physicsconfig.GetFloat("nm_terraincontact_bounce", 0.1f); + nmTerrainContactERP = physicsconfig.GetFloat("nm_terraincontact_erp", 0.1025f); + + mTerrainContactFriction = physicsconfig.GetFloat("m_terraincontact_friction", 75f); + mTerrainContactBounce = physicsconfig.GetFloat("m_terraincontact_bounce", 0.05f); + mTerrainContactERP = physicsconfig.GetFloat("m_terraincontact_erp", 0.05025f); + + nmAvatarObjectContactFriction = physicsconfig.GetFloat("objectcontact_friction", 250f); + nmAvatarObjectContactBounce = physicsconfig.GetFloat("objectcontact_bounce", 0.2f); + + mAvatarObjectContactFriction = physicsconfig.GetFloat("m_avatarobjectcontact_friction", 75f); + mAvatarObjectContactBounce = physicsconfig.GetFloat("m_avatarobjectcontact_bounce", 0.1f); + + ODE_STEPSIZE = physicsconfig.GetFloat("world_stepsize", 0.020f); + m_physicsiterations = physicsconfig.GetInt("world_internal_steps_without_collisions", 10); + + avDensity = physicsconfig.GetFloat("av_density", 80f); + avHeightFudgeFactor = physicsconfig.GetFloat("av_height_fudge_factor", 0.52f); + avMovementDivisorWalk = physicsconfig.GetFloat("av_movement_divisor_walk", 1.3f); + avMovementDivisorRun = physicsconfig.GetFloat("av_movement_divisor_run", 0.8f); + avCapRadius = physicsconfig.GetFloat("av_capsule_radius", 0.37f); + avCapsuleTilted = physicsconfig.GetBoolean("av_capsule_tilted", false); + + contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", 80); + + geomContactPointsStartthrottle = physicsconfig.GetInt("geom_contactpoints_start_throttling", 3); + geomUpdatesPerThrottledUpdate = physicsconfig.GetInt("geom_updates_before_throttled_update", 15); + geomCrossingFailuresBeforeOutofbounds = physicsconfig.GetInt("geom_crossing_failures_before_outofbounds", 5); + + geomDefaultDensity = physicsconfig.GetFloat("geometry_default_density", 10.000006836f); + bodyFramesAutoDisable = physicsconfig.GetInt("body_frames_auto_disable", 20); + + bodyPIDD = physicsconfig.GetFloat("body_pid_derivative", 35f); + bodyPIDG = physicsconfig.GetFloat("body_pid_gain", 25f); + + forceSimplePrimMeshing = physicsconfig.GetBoolean("force_simple_prim_meshing", forceSimplePrimMeshing); + meshSculptedPrim = physicsconfig.GetBoolean("mesh_sculpted_prim", true); + meshSculptLOD = physicsconfig.GetFloat("mesh_lod", 32f); + MeshSculptphysicalLOD = physicsconfig.GetFloat("mesh_physical_lod", 16f); + m_filterCollisions = physicsconfig.GetBoolean("filter_collisions", false); + + if (Environment.OSVersion.Platform == PlatformID.Unix) + { + avPIDD = physicsconfig.GetFloat("av_pid_derivative_linux", 2200.0f); + avPIDP = physicsconfig.GetFloat("av_pid_proportional_linux", 900.0f); + avStandupTensor = physicsconfig.GetFloat("av_capsule_standup_tensor_linux", 550000f); + bodyMotorJointMaxforceTensor = physicsconfig.GetFloat("body_motor_joint_maxforce_tensor_linux", 5f); + } + else + { + avPIDD = physicsconfig.GetFloat("av_pid_derivative_win", 2200.0f); + avPIDP = physicsconfig.GetFloat("av_pid_proportional_win", 900.0f); + avStandupTensor = physicsconfig.GetFloat("av_capsule_standup_tensor_win", 550000f); + bodyMotorJointMaxforceTensor = physicsconfig.GetFloat("body_motor_joint_maxforce_tensor_win", 5f); + } + + physics_logging = physicsconfig.GetBoolean("physics_logging", false); + physics_logging_interval = physicsconfig.GetInt("physics_logging_interval", 0); + physics_logging_append_existing_logfile = physicsconfig.GetBoolean("physics_logging_append_existing_logfile", false); + + m_NINJA_physics_joints_enabled = physicsconfig.GetBoolean("use_NINJA_physics_joints", false); + minimumGroundFlightOffset = physicsconfig.GetFloat("minimum_ground_flight_offset", 3f); + maximumMassObject = physicsconfig.GetFloat("maximum_mass_object", 10000.01f); + } + } + + contacts = new d.ContactGeom[contactsPerCollision]; + + staticPrimspace = new IntPtr[(int)(300 / metersInSpace), (int)(300 / metersInSpace)]; + + // Centeral contact friction and bounce + // ckrinke 11/10/08 Enabling soft_erp but not soft_cfm until I figure out why + // an avatar falls through in Z but not in X or Y when walking on a prim. + contact.surface.mode |= d.ContactFlags.SoftERP; + contact.surface.mu = nmAvatarObjectContactFriction; + contact.surface.bounce = nmAvatarObjectContactBounce; + contact.surface.soft_cfm = 0.010f; + contact.surface.soft_erp = 0.010f; + + // Terrain contact friction and Bounce + // This is the *non* moving version. Use this when an avatar + // isn't moving to keep it in place better + TerrainContact.surface.mode |= d.ContactFlags.SoftERP; + TerrainContact.surface.mu = nmTerrainContactFriction; + TerrainContact.surface.bounce = nmTerrainContactBounce; + TerrainContact.surface.soft_erp = nmTerrainContactERP; + + WaterContact.surface.mode |= (d.ContactFlags.SoftERP | d.ContactFlags.SoftCFM); + WaterContact.surface.mu = 0f; // No friction + WaterContact.surface.bounce = 0.0f; // No bounce + WaterContact.surface.soft_cfm = 0.010f; + WaterContact.surface.soft_erp = 0.010f; + + // Prim contact friction and bounce + // THis is the *non* moving version of friction and bounce + // Use this when an avatar comes in contact with a prim + // and is moving + AvatarMovementprimContact.surface.mu = mAvatarObjectContactFriction; + AvatarMovementprimContact.surface.bounce = mAvatarObjectContactBounce; + + // Terrain contact friction bounce and various error correcting calculations + // Use this when an avatar is in contact with the terrain and moving. + AvatarMovementTerrainContact.surface.mode |= d.ContactFlags.SoftERP; + AvatarMovementTerrainContact.surface.mu = mTerrainContactFriction; + AvatarMovementTerrainContact.surface.bounce = mTerrainContactBounce; + AvatarMovementTerrainContact.surface.soft_erp = mTerrainContactERP; + + /* + + Stone = 0, + /// + Metal = 1, + /// + Glass = 2, + /// + Wood = 3, + /// + Flesh = 4, + /// + Plastic = 5, + /// + Rubber = 6 + */ + + m_materialContacts = new d.Contact[7,2]; + + m_materialContacts[(int)Material.Stone, 0] = new d.Contact(); + m_materialContacts[(int)Material.Stone, 0].surface.mode |= d.ContactFlags.SoftERP; + m_materialContacts[(int)Material.Stone, 0].surface.mu = nmAvatarObjectContactFriction; + m_materialContacts[(int)Material.Stone, 0].surface.bounce = nmAvatarObjectContactBounce; + m_materialContacts[(int)Material.Stone, 0].surface.soft_cfm = 0.010f; + m_materialContacts[(int)Material.Stone, 0].surface.soft_erp = 0.010f; + + m_materialContacts[(int)Material.Stone, 1] = new d.Contact(); + m_materialContacts[(int)Material.Stone, 1].surface.mode |= d.ContactFlags.SoftERP; + m_materialContacts[(int)Material.Stone, 1].surface.mu = mAvatarObjectContactFriction; + m_materialContacts[(int)Material.Stone, 1].surface.bounce = mAvatarObjectContactBounce; + m_materialContacts[(int)Material.Stone, 1].surface.soft_cfm = 0.010f; + m_materialContacts[(int)Material.Stone, 1].surface.soft_erp = 0.010f; + + m_materialContacts[(int)Material.Metal, 0] = new d.Contact(); + m_materialContacts[(int)Material.Metal, 0].surface.mode |= d.ContactFlags.SoftERP; + m_materialContacts[(int)Material.Metal, 0].surface.mu = nmAvatarObjectContactFriction; + m_materialContacts[(int)Material.Metal, 0].surface.bounce = nmAvatarObjectContactBounce; + m_materialContacts[(int)Material.Metal, 0].surface.soft_cfm = 0.010f; + m_materialContacts[(int)Material.Metal, 0].surface.soft_erp = 0.010f; + + m_materialContacts[(int)Material.Metal, 1] = new d.Contact(); + m_materialContacts[(int)Material.Metal, 1].surface.mode |= d.ContactFlags.SoftERP; + m_materialContacts[(int)Material.Metal, 1].surface.mu = mAvatarObjectContactFriction; + m_materialContacts[(int)Material.Metal, 1].surface.bounce = mAvatarObjectContactBounce; + m_materialContacts[(int)Material.Metal, 1].surface.soft_cfm = 0.010f; + m_materialContacts[(int)Material.Metal, 1].surface.soft_erp = 0.010f; + + m_materialContacts[(int)Material.Glass, 0] = new d.Contact(); + m_materialContacts[(int)Material.Glass, 0].surface.mode |= d.ContactFlags.SoftERP; + m_materialContacts[(int)Material.Glass, 0].surface.mu = 1f; + m_materialContacts[(int)Material.Glass, 0].surface.bounce = 0.5f; + m_materialContacts[(int)Material.Glass, 0].surface.soft_cfm = 0.010f; + m_materialContacts[(int)Material.Glass, 0].surface.soft_erp = 0.010f; + + /* + private float nmAvatarObjectContactFriction = 250f; + private float nmAvatarObjectContactBounce = 0.1f; + + private float mAvatarObjectContactFriction = 75f; + private float mAvatarObjectContactBounce = 0.1f; + */ + m_materialContacts[(int)Material.Glass, 1] = new d.Contact(); + m_materialContacts[(int)Material.Glass, 1].surface.mode |= d.ContactFlags.SoftERP; + m_materialContacts[(int)Material.Glass, 1].surface.mu = 1f; + m_materialContacts[(int)Material.Glass, 1].surface.bounce = 0.5f; + m_materialContacts[(int)Material.Glass, 1].surface.soft_cfm = 0.010f; + m_materialContacts[(int)Material.Glass, 1].surface.soft_erp = 0.010f; + + m_materialContacts[(int)Material.Wood, 0] = new d.Contact(); + m_materialContacts[(int)Material.Wood, 0].surface.mode |= d.ContactFlags.SoftERP; + m_materialContacts[(int)Material.Wood, 0].surface.mu = nmAvatarObjectContactFriction; + m_materialContacts[(int)Material.Wood, 0].surface.bounce = nmAvatarObjectContactBounce; + m_materialContacts[(int)Material.Wood, 0].surface.soft_cfm = 0.010f; + m_materialContacts[(int)Material.Wood, 0].surface.soft_erp = 0.010f; + + m_materialContacts[(int)Material.Wood, 1] = new d.Contact(); + m_materialContacts[(int)Material.Wood, 1].surface.mode |= d.ContactFlags.SoftERP; + m_materialContacts[(int)Material.Wood, 1].surface.mu = mAvatarObjectContactFriction; + m_materialContacts[(int)Material.Wood, 1].surface.bounce = mAvatarObjectContactBounce; + m_materialContacts[(int)Material.Wood, 1].surface.soft_cfm = 0.010f; + m_materialContacts[(int)Material.Wood, 1].surface.soft_erp = 0.010f; + + m_materialContacts[(int)Material.Flesh, 0] = new d.Contact(); + m_materialContacts[(int)Material.Flesh, 0].surface.mode |= d.ContactFlags.SoftERP; + m_materialContacts[(int)Material.Flesh, 0].surface.mu = nmAvatarObjectContactFriction; + m_materialContacts[(int)Material.Flesh, 0].surface.bounce = nmAvatarObjectContactBounce; + m_materialContacts[(int)Material.Flesh, 0].surface.soft_cfm = 0.010f; + m_materialContacts[(int)Material.Flesh, 0].surface.soft_erp = 0.010f; + + m_materialContacts[(int)Material.Flesh, 1] = new d.Contact(); + m_materialContacts[(int)Material.Flesh, 1].surface.mode |= d.ContactFlags.SoftERP; + m_materialContacts[(int)Material.Flesh, 1].surface.mu = mAvatarObjectContactFriction; + m_materialContacts[(int)Material.Flesh, 1].surface.bounce = mAvatarObjectContactBounce; + m_materialContacts[(int)Material.Flesh, 1].surface.soft_cfm = 0.010f; + m_materialContacts[(int)Material.Flesh, 1].surface.soft_erp = 0.010f; + + m_materialContacts[(int)Material.Plastic, 0] = new d.Contact(); + m_materialContacts[(int)Material.Plastic, 0].surface.mode |= d.ContactFlags.SoftERP; + m_materialContacts[(int)Material.Plastic, 0].surface.mu = nmAvatarObjectContactFriction; + m_materialContacts[(int)Material.Plastic, 0].surface.bounce = nmAvatarObjectContactBounce; + m_materialContacts[(int)Material.Plastic, 0].surface.soft_cfm = 0.010f; + m_materialContacts[(int)Material.Plastic, 0].surface.soft_erp = 0.010f; + + m_materialContacts[(int)Material.Plastic, 1] = new d.Contact(); + m_materialContacts[(int)Material.Plastic, 1].surface.mode |= d.ContactFlags.SoftERP; + m_materialContacts[(int)Material.Plastic, 1].surface.mu = mAvatarObjectContactFriction; + m_materialContacts[(int)Material.Plastic, 1].surface.bounce = mAvatarObjectContactBounce; + m_materialContacts[(int)Material.Plastic, 1].surface.soft_cfm = 0.010f; + m_materialContacts[(int)Material.Plastic, 1].surface.soft_erp = 0.010f; + + m_materialContacts[(int)Material.Rubber, 0] = new d.Contact(); + m_materialContacts[(int)Material.Rubber, 0].surface.mode |= d.ContactFlags.SoftERP; + m_materialContacts[(int)Material.Rubber, 0].surface.mu = nmAvatarObjectContactFriction; + m_materialContacts[(int)Material.Rubber, 0].surface.bounce = nmAvatarObjectContactBounce; + m_materialContacts[(int)Material.Rubber, 0].surface.soft_cfm = 0.010f; + m_materialContacts[(int)Material.Rubber, 0].surface.soft_erp = 0.010f; + + m_materialContacts[(int)Material.Rubber, 1] = new d.Contact(); + m_materialContacts[(int)Material.Rubber, 1].surface.mode |= d.ContactFlags.SoftERP; + m_materialContacts[(int)Material.Rubber, 1].surface.mu = mAvatarObjectContactFriction; + m_materialContacts[(int)Material.Rubber, 1].surface.bounce = mAvatarObjectContactBounce; + m_materialContacts[(int)Material.Rubber, 1].surface.soft_cfm = 0.010f; + m_materialContacts[(int)Material.Rubber, 1].surface.soft_erp = 0.010f; + + d.HashSpaceSetLevels(space, worldHashspaceLow, worldHashspaceHigh); + + // Set the gravity,, don't disable things automatically (we set it explicitly on some things) + + d.WorldSetGravity(world, gravityx, gravityy, gravityz); + d.WorldSetContactSurfaceLayer(world, contactsurfacelayer); + + d.WorldSetLinearDamping(world, 256f); + d.WorldSetAngularDamping(world, 256f); + d.WorldSetAngularDampingThreshold(world, 256f); + d.WorldSetLinearDampingThreshold(world, 256f); + d.WorldSetMaxAngularSpeed(world, 256f); + + // Set how many steps we go without running collision testing + // This is in addition to the step size. + // Essentially Steps * m_physicsiterations + d.WorldSetQuickStepNumIterations(world, m_physicsiterations); + //d.WorldSetContactMaxCorrectingVel(world, 1000.0f); + + for (int i = 0; i < staticPrimspace.GetLength(0); i++) + { + for (int j = 0; j < staticPrimspace.GetLength(1); j++) + { + staticPrimspace[i, j] = IntPtr.Zero; + } + } + } + + internal void waitForSpaceUnlock(IntPtr space) + { + //if (space != IntPtr.Zero) + //while (d.SpaceLockQuery(space)) { } // Wait and do nothing + } + + /// + /// Debug space message for printing the space that a prim/avatar is in. + /// + /// + /// Returns which split up space the given position is in. + public string whichspaceamIin(Vector3 pos) + { + return calculateSpaceForGeom(pos).ToString(); + } + + #region Collision Detection + + /// + /// This is our near callback. A geometry is near a body + /// + /// The space that contains the geoms. Remember, spaces are also geoms + /// a geometry or space + /// another geometry or space + private void near(IntPtr space, IntPtr g1, IntPtr g2) + { + // no lock here! It's invoked from within Simulate(), which is thread-locked + + // Test if we're colliding a geom with a space. + // If so we have to drill down into the space recursively + + if (d.GeomIsSpace(g1) || d.GeomIsSpace(g2)) + { + if (g1 == IntPtr.Zero || g2 == IntPtr.Zero) + return; + + // Separating static prim geometry spaces. + // We'll be calling near recursivly if one + // of them is a space to find all of the + // contact points in the space + try + { + d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback); + } + catch (AccessViolationException) + { + m_log.Warn("[PHYSICS]: Unable to collide test a space"); + return; + } + //Colliding a space or a geom with a space or a geom. so drill down + + //Collide all geoms in each space.. + //if (d.GeomIsSpace(g1)) d.SpaceCollide(g1, IntPtr.Zero, nearCallback); + //if (d.GeomIsSpace(g2)) d.SpaceCollide(g2, IntPtr.Zero, nearCallback); + return; + } + + if (g1 == IntPtr.Zero || g2 == IntPtr.Zero) + return; + + IntPtr b1 = d.GeomGetBody(g1); + IntPtr b2 = d.GeomGetBody(g2); + + // d.GeomClassID id = d.GeomGetClass(g1); + + String name1 = null; + String name2 = null; + + if (!geom_name_map.TryGetValue(g1, out name1)) + { + name1 = "null"; + } + if (!geom_name_map.TryGetValue(g2, out name2)) + { + name2 = "null"; + } + + //if (id == d.GeomClassId.TriMeshClass) + //{ + // m_log.InfoFormat("near: A collision was detected between {1} and {2}", 0, name1, name2); + //m_log.Debug("near: A collision was detected between {1} and {2}", 0, name1, name2); + //} + + // Figure out how many contact points we have + int count = 0; + try + { + // Colliding Geom To Geom + // This portion of the function 'was' blatantly ripped off from BoxStack.cs + + if (g1 == g2) + return; // Can't collide with yourself + + if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact)) + return; + + lock (contacts) + { + count = d.Collide(g1, g2, contacts.Length, contacts, d.ContactGeom.SizeOf); + if (count > contacts.Length) + m_log.Error("[PHYSICS]: Got " + count + " contacts when we asked for a maximum of " + contacts.Length); + } + } + catch (SEHException) + { + m_log.Error("[PHYSICS]: The Operating system shut down ODE because of corrupt memory. This could be a result of really irregular terrain. If this repeats continuously, restart using Basic Physics and terrain fill your terrain. Restarting the sim."); + ode.drelease(world); + base.TriggerPhysicsBasedRestart(); + } + catch (Exception e) + { + m_log.WarnFormat("[PHYSICS]: Unable to collide test an object: {0}", e.Message); + return; + } + + PhysicsActor p1; + PhysicsActor p2; + + if (!actor_name_map.TryGetValue(g1, out p1)) + { + p1 = PANull; + } + + if (!actor_name_map.TryGetValue(g2, out p2)) + { + p2 = PANull; + } + + ContactPoint maxDepthContact = new ContactPoint(); + if (p1.CollisionScore + count >= float.MaxValue) + p1.CollisionScore = 0; + p1.CollisionScore += count; + + if (p2.CollisionScore + count >= float.MaxValue) + p2.CollisionScore = 0; + p2.CollisionScore += count; + + for (int i = 0; i < count; i++) + { + d.ContactGeom curContact = contacts[i]; + + if (curContact.depth > maxDepthContact.PenetrationDepth) + { + maxDepthContact = new ContactPoint( + new Vector3(curContact.pos.X, curContact.pos.Y, curContact.pos.Z), + new Vector3(curContact.normal.X, curContact.normal.Y, curContact.normal.Z), + curContact.depth + ); + } + + //m_log.Warn("[CCOUNT]: " + count); + IntPtr joint; + // If we're colliding with terrain, use 'TerrainContact' instead of contact. + // allows us to have different settings + + // We only need to test p2 for 'jump crouch purposes' + if (p2 is OdeCharacter && p1.PhysicsActorType == (int)ActorTypes.Prim) + { + // Testing if the collision is at the feet of the avatar + + //m_log.DebugFormat("[PHYSICS]: {0} - {1} - {2} - {3}", curContact.pos.Z, p2.Position.Z, (p2.Position.Z - curContact.pos.Z), (p2.Size.Z * 0.6f)); + if ((p2.Position.Z - curContact.pos.Z) > (p2.Size.Z * 0.6f)) + p2.IsColliding = true; + } + else + { + p2.IsColliding = true; + } + + //if ((framecount % m_returncollisions) == 0) + + switch (p1.PhysicsActorType) + { + case (int)ActorTypes.Agent: + p2.CollidingObj = true; + break; + case (int)ActorTypes.Prim: + if (p2.Velocity.LengthSquared() > 0.0f) + p2.CollidingObj = true; + break; + case (int)ActorTypes.Unknown: + p2.CollidingGround = true; + break; + default: + p2.CollidingGround = true; + break; + } + + // we don't want prim or avatar to explode + + #region InterPenetration Handling - Unintended physics explosions +# region disabled code1 + + if (curContact.depth >= 0.08f) + { + //This is disabled at the moment only because it needs more tweaking + //It will eventually be uncommented + /* + if (contact.depth >= 1.00f) + { + //m_log.Debug("[PHYSICS]: " + contact.depth.ToString()); + } + + //If you interpenetrate a prim with an agent + if ((p2.PhysicsActorType == (int) ActorTypes.Agent && + p1.PhysicsActorType == (int) ActorTypes.Prim) || + (p1.PhysicsActorType == (int) ActorTypes.Agent && + p2.PhysicsActorType == (int) ActorTypes.Prim)) + { + + //contact.depth = contact.depth * 4.15f; + /* + if (p2.PhysicsActorType == (int) ActorTypes.Agent) + { + p2.CollidingObj = true; + contact.depth = 0.003f; + p2.Velocity = p2.Velocity + new PhysicsVector(0, 0, 2.5f); + OdeCharacter character = (OdeCharacter) p2; + character.SetPidStatus(true); + contact.pos = new d.Vector3(contact.pos.X + (p1.Size.X / 2), contact.pos.Y + (p1.Size.Y / 2), contact.pos.Z + (p1.Size.Z / 2)); + + } + else + { + + //contact.depth = 0.0000000f; + } + if (p1.PhysicsActorType == (int) ActorTypes.Agent) + { + + p1.CollidingObj = true; + contact.depth = 0.003f; + p1.Velocity = p1.Velocity + new PhysicsVector(0, 0, 2.5f); + contact.pos = new d.Vector3(contact.pos.X + (p2.Size.X / 2), contact.pos.Y + (p2.Size.Y / 2), contact.pos.Z + (p2.Size.Z / 2)); + OdeCharacter character = (OdeCharacter)p1; + character.SetPidStatus(true); + } + else + { + + //contact.depth = 0.0000000f; + } + + + + } +*/ + // If you interpenetrate a prim with another prim + /* + if (p1.PhysicsActorType == (int) ActorTypes.Prim && p2.PhysicsActorType == (int) ActorTypes.Prim) + { + #region disabledcode2 + //OdePrim op1 = (OdePrim)p1; + //OdePrim op2 = (OdePrim)p2; + //op1.m_collisionscore++; + //op2.m_collisionscore++; + + //if (op1.m_collisionscore > 8000 || op2.m_collisionscore > 8000) + //{ + //op1.m_taintdisable = true; + //AddPhysicsActorTaint(p1); + //op2.m_taintdisable = true; + //AddPhysicsActorTaint(p2); + //} + + //if (contact.depth >= 0.25f) + //{ + // Don't collide, one or both prim will expld. + + //op1.m_interpenetrationcount++; + //op2.m_interpenetrationcount++; + //interpenetrations_before_disable = 200; + //if (op1.m_interpenetrationcount >= interpenetrations_before_disable) + //{ + //op1.m_taintdisable = true; + //AddPhysicsActorTaint(p1); + //} + //if (op2.m_interpenetrationcount >= interpenetrations_before_disable) + //{ + // op2.m_taintdisable = true; + //AddPhysicsActorTaint(p2); + //} + + //contact.depth = contact.depth / 8f; + //contact.normal = new d.Vector3(0, 0, 1); + //} + //if (op1.m_disabled || op2.m_disabled) + //{ + //Manually disabled objects stay disabled + //contact.depth = 0f; + //} + #endregion + } + */ +#endregion + if (curContact.depth >= 1.00f) + { + //m_log.Info("[P]: " + contact.depth.ToString()); + if ((p2.PhysicsActorType == (int) ActorTypes.Agent && + p1.PhysicsActorType == (int) ActorTypes.Unknown) || + (p1.PhysicsActorType == (int) ActorTypes.Agent && + p2.PhysicsActorType == (int) ActorTypes.Unknown)) + { + if (p2.PhysicsActorType == (int) ActorTypes.Agent) + { + if (p2 is OdeCharacter) + { + OdeCharacter character = (OdeCharacter) p2; + + //p2.CollidingObj = true; + curContact.depth = 0.00000003f; + p2.Velocity = p2.Velocity + new Vector3(0f, 0f, 0.5f); + curContact.pos = + new d.Vector3(curContact.pos.X + (p1.Size.X/2), + curContact.pos.Y + (p1.Size.Y/2), + curContact.pos.Z + (p1.Size.Z/2)); + character.SetPidStatus(true); + } + } + + + if (p1.PhysicsActorType == (int) ActorTypes.Agent) + { + if (p1 is OdeCharacter) + { + OdeCharacter character = (OdeCharacter) p1; + + //p2.CollidingObj = true; + curContact.depth = 0.00000003f; + p1.Velocity = p1.Velocity + new Vector3(0f, 0f, 0.5f); + curContact.pos = + new d.Vector3(curContact.pos.X + (p1.Size.X/2), + curContact.pos.Y + (p1.Size.Y/2), + curContact.pos.Z + (p1.Size.Z/2)); + character.SetPidStatus(true); + } + } + } + } + } + + #endregion + + // Logic for collision handling + // Note, that if *all* contacts are skipped (VolumeDetect) + // The prim still detects (and forwards) collision events but + // appears to be phantom for the world + Boolean skipThisContact = false; + + if ((p1 is OdePrim) && (((OdePrim)p1).m_isVolumeDetect)) + skipThisContact = true; // No collision on volume detect prims + + if (!skipThisContact && (p2 is OdePrim) && (((OdePrim)p2).m_isVolumeDetect)) + skipThisContact = true; // No collision on volume detect prims + + if (!skipThisContact && curContact.depth < 0f) + skipThisContact = true; + + if (!skipThisContact && checkDupe(curContact, p2.PhysicsActorType)) + skipThisContact = true; + + const int maxContactsbeforedeath = 4000; + joint = IntPtr.Zero; + + if (!skipThisContact) + { + // If we're colliding against terrain + if (name1 == "Terrain" || name2 == "Terrain") + { + // If we're moving + if ((p2.PhysicsActorType == (int) ActorTypes.Agent) && + (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) + { + // Use the movement terrain contact + AvatarMovementTerrainContact.geom = curContact; + _perloopContact.Add(curContact); + if (m_global_contactcount < maxContactsbeforedeath) + { + joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementTerrainContact); + m_global_contactcount++; + } + } + else + { + if (p2.PhysicsActorType == (int)ActorTypes.Agent) + { + // Use the non moving terrain contact + TerrainContact.geom = curContact; + _perloopContact.Add(curContact); + if (m_global_contactcount < maxContactsbeforedeath) + { + joint = d.JointCreateContact(world, contactgroup, ref TerrainContact); + m_global_contactcount++; + } + } + else + { + if (p2.PhysicsActorType == (int)ActorTypes.Prim && p1.PhysicsActorType == (int)ActorTypes.Prim) + { + // prim prim contact + // int pj294950 = 0; + int movintYN = 0; + int material = (int) Material.Wood; + // prim terrain contact + if (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f) + { + movintYN = 1; + } + + if (p2 is OdePrim) + material = ((OdePrim)p2).m_material; + + //m_log.DebugFormat("Material: {0}", material); + m_materialContacts[material, movintYN].geom = curContact; + _perloopContact.Add(curContact); + + if (m_global_contactcount < maxContactsbeforedeath) + { + joint = d.JointCreateContact(world, contactgroup, ref m_materialContacts[material, movintYN]); + m_global_contactcount++; + + } + + } + else + { + int movintYN = 0; + // prim terrain contact + if (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f) + { + movintYN = 1; + } + + int material = (int)Material.Wood; + + if (p2 is OdePrim) + material = ((OdePrim)p2).m_material; + //m_log.DebugFormat("Material: {0}", material); + m_materialContacts[material, movintYN].geom = curContact; + _perloopContact.Add(curContact); + + if (m_global_contactcount < maxContactsbeforedeath) + { + joint = d.JointCreateContact(world, contactgroup, ref m_materialContacts[material, movintYN]); + m_global_contactcount++; + + } + } + } + } + //if (p2.PhysicsActorType == (int)ActorTypes.Prim) + //{ + //m_log.Debug("[PHYSICS]: prim contacting with ground"); + //} + } + else if (name1 == "Water" || name2 == "Water") + { + /* + if ((p2.PhysicsActorType == (int) ActorTypes.Prim)) + { + } + else + { + } + */ + //WaterContact.surface.soft_cfm = 0.0000f; + //WaterContact.surface.soft_erp = 0.00000f; + if (curContact.depth > 0.1f) + { + curContact.depth *= 52; + //contact.normal = new d.Vector3(0, 0, 1); + //contact.pos = new d.Vector3(0, 0, contact.pos.Z - 5f); + } + WaterContact.geom = curContact; + _perloopContact.Add(curContact); + if (m_global_contactcount < maxContactsbeforedeath) + { + joint = d.JointCreateContact(world, contactgroup, ref WaterContact); + m_global_contactcount++; + } + //m_log.Info("[PHYSICS]: Prim Water Contact" + contact.depth); + } + else + { + // we're colliding with prim or avatar + // check if we're moving + if ((p2.PhysicsActorType == (int)ActorTypes.Agent)) + { + if ((Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) + { + // Use the Movement prim contact + AvatarMovementprimContact.geom = curContact; + _perloopContact.Add(curContact); + if (m_global_contactcount < maxContactsbeforedeath) + { + joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementprimContact); + m_global_contactcount++; + } + } + else + { + // Use the non movement contact + contact.geom = curContact; + _perloopContact.Add(curContact); + + if (m_global_contactcount < maxContactsbeforedeath) + { + joint = d.JointCreateContact(world, contactgroup, ref contact); + m_global_contactcount++; + } + } + } + else if (p2.PhysicsActorType == (int)ActorTypes.Prim) + { + //p1.PhysicsActorType + int material = (int)Material.Wood; + + if (p2 is OdePrim) + material = ((OdePrim)p2).m_material; + + //m_log.DebugFormat("Material: {0}", material); + m_materialContacts[material, 0].geom = curContact; + _perloopContact.Add(curContact); + + if (m_global_contactcount < maxContactsbeforedeath) + { + joint = d.JointCreateContact(world, contactgroup, ref m_materialContacts[material, 0]); + m_global_contactcount++; + + } + } + } + + if (m_global_contactcount < maxContactsbeforedeath && joint != IntPtr.Zero) // stack collide! + { + d.JointAttach(joint, b1, b2); + m_global_contactcount++; + } + } + + collision_accounting_events(p1, p2, maxDepthContact); + + if (count > geomContactPointsStartthrottle) + { + // If there are more then 3 contact points, it's likely + // that we've got a pile of objects, so ... + // We don't want to send out hundreds of terse updates over and over again + // so lets throttle them and send them again after it's somewhat sorted out. + p2.ThrottleUpdates = true; + } + //m_log.Debug(count.ToString()); + //m_log.Debug("near: A collision was detected between {1} and {2}", 0, name1, name2); + } + } + + private bool checkDupe(d.ContactGeom contactGeom, int atype) + { + bool result = false; + //return result; + if (!m_filterCollisions) + return false; + + ActorTypes at = (ActorTypes)atype; + lock (_perloopContact) + { + foreach (d.ContactGeom contact in _perloopContact) + { + //if ((contact.g1 == contactGeom.g1 && contact.g2 == contactGeom.g2)) + //{ + // || (contact.g2 == contactGeom.g1 && contact.g1 == contactGeom.g2) + if (at == ActorTypes.Agent) + { + if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f) && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f) && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f)) && contactGeom.g1 != LandGeom && contactGeom.g2 != LandGeom) + { + + if (Math.Abs(contact.depth - contactGeom.depth) < 0.052f) + { + //contactGeom.depth *= .00005f; + //m_log.DebugFormat("[Collsion]: Depth {0}", Math.Abs(contact.depth - contactGeom.depth)); + // m_log.DebugFormat("[Collision]: <{0},{1},{2}>", Math.Abs(contactGeom.normal.X - contact.normal.X), Math.Abs(contactGeom.normal.Y - contact.normal.Y), Math.Abs(contactGeom.normal.Z - contact.normal.Z)); + result = true; + break; + } + else + { + //m_log.DebugFormat("[Collsion]: Depth {0}", Math.Abs(contact.depth - contactGeom.depth)); + } + } + else + { + //m_log.DebugFormat("[Collision]: <{0},{1},{2}>", Math.Abs(contactGeom.normal.X - contact.normal.X), Math.Abs(contactGeom.normal.Y - contact.normal.Y), Math.Abs(contactGeom.normal.Z - contact.normal.Z)); + //int i = 0; + } + } + else if (at == ActorTypes.Prim) + { + //d.AABB aabb1 = new d.AABB(); + //d.AABB aabb2 = new d.AABB(); + + //d.GeomGetAABB(contactGeom.g2, out aabb2); + //d.GeomGetAABB(contactGeom.g1, out aabb1); + //aabb1. + if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f) && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f) && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f)) && contactGeom.g1 != LandGeom && contactGeom.g2 != LandGeom) + { + if (contactGeom.normal.X == contact.normal.X && contactGeom.normal.Y == contact.normal.Y && contactGeom.normal.Z == contact.normal.Z) + { + if (Math.Abs(contact.depth - contactGeom.depth) < 0.272f) + { + result = true; + break; + } + } + //m_log.DebugFormat("[Collsion]: Depth {0}", Math.Abs(contact.depth - contactGeom.depth)); + //m_log.DebugFormat("[Collision]: <{0},{1},{2}>", Math.Abs(contactGeom.normal.X - contact.normal.X), Math.Abs(contactGeom.normal.Y - contact.normal.Y), Math.Abs(contactGeom.normal.Z - contact.normal.Z)); + } + + } + + //} + + } + } + + return result; + } + + private void collision_accounting_events(PhysicsActor p1, PhysicsActor p2, ContactPoint contact) + { + // obj1LocalID = 0; + //returncollisions = false; + obj2LocalID = 0; + //ctype = 0; + //cStartStop = 0; + if (!p2.SubscribedEvents() && !p1.SubscribedEvents()) + return; + + switch ((ActorTypes)p2.PhysicsActorType) + { + case ActorTypes.Agent: + cc2 = (OdeCharacter)p2; + + // obj1LocalID = cc2.m_localID; + switch ((ActorTypes)p1.PhysicsActorType) + { + case ActorTypes.Agent: + cc1 = (OdeCharacter)p1; + obj2LocalID = cc1.m_localID; + cc1.AddCollisionEvent(cc2.m_localID, contact); + //ctype = (int)CollisionCategories.Character; + + //if (cc1.CollidingObj) + //cStartStop = (int)StatusIndicators.Generic; + //else + //cStartStop = (int)StatusIndicators.Start; + + //returncollisions = true; + break; + case ActorTypes.Prim: + if (p1 is OdePrim) + { + cp1 = (OdePrim) p1; + obj2LocalID = cp1.m_localID; + cp1.AddCollisionEvent(cc2.m_localID, contact); + } + //ctype = (int)CollisionCategories.Geom; + + //if (cp1.CollidingObj) + //cStartStop = (int)StatusIndicators.Generic; + //else + //cStartStop = (int)StatusIndicators.Start; + + //returncollisions = true; + break; + + case ActorTypes.Ground: + case ActorTypes.Unknown: + obj2LocalID = 0; + //ctype = (int)CollisionCategories.Land; + //returncollisions = true; + break; + } + + cc2.AddCollisionEvent(obj2LocalID, contact); + break; + case ActorTypes.Prim: + + if (p2 is OdePrim) + { + cp2 = (OdePrim) p2; + + // obj1LocalID = cp2.m_localID; + switch ((ActorTypes) p1.PhysicsActorType) + { + case ActorTypes.Agent: + if (p1 is OdeCharacter) + { + cc1 = (OdeCharacter) p1; + obj2LocalID = cc1.m_localID; + cc1.AddCollisionEvent(cp2.m_localID, contact); + //ctype = (int)CollisionCategories.Character; + + //if (cc1.CollidingObj) + //cStartStop = (int)StatusIndicators.Generic; + //else + //cStartStop = (int)StatusIndicators.Start; + //returncollisions = true; + } + break; + case ActorTypes.Prim: + + if (p1 is OdePrim) + { + cp1 = (OdePrim) p1; + obj2LocalID = cp1.m_localID; + cp1.AddCollisionEvent(cp2.m_localID, contact); + //ctype = (int)CollisionCategories.Geom; + + //if (cp1.CollidingObj) + //cStartStop = (int)StatusIndicators.Generic; + //else + //cStartStop = (int)StatusIndicators.Start; + + //returncollisions = true; + } + break; + + case ActorTypes.Ground: + case ActorTypes.Unknown: + obj2LocalID = 0; + //ctype = (int)CollisionCategories.Land; + + //returncollisions = true; + break; + } + + cp2.AddCollisionEvent(obj2LocalID, contact); + } + break; + } + //if (returncollisions) + //{ + + //lock (m_storedCollisions) + //{ + //cDictKey = obj1LocalID.ToString() + obj2LocalID.ToString() + cStartStop.ToString() + ctype.ToString(); + //if (m_storedCollisions.ContainsKey(cDictKey)) + //{ + //sCollisionData objd = m_storedCollisions[cDictKey]; + //objd.NumberOfCollisions += 1; + //objd.lastframe = framecount; + //m_storedCollisions[cDictKey] = objd; + //} + //else + //{ + //sCollisionData objd = new sCollisionData(); + //objd.ColliderLocalId = obj1LocalID; + //objd.CollidedWithLocalId = obj2LocalID; + //objd.CollisionType = ctype; + //objd.NumberOfCollisions = 1; + //objd.lastframe = framecount; + //objd.StatusIndicator = cStartStop; + //m_storedCollisions.Add(cDictKey, objd); + //} + //} + // } + } + + public int TriArrayCallback(IntPtr trimesh, IntPtr refObject, int[] triangleIndex, int triCount) + { + /* String name1 = null; + String name2 = null; + + if (!geom_name_map.TryGetValue(trimesh, out name1)) + { + name1 = "null"; + } + if (!geom_name_map.TryGetValue(refObject, out name2)) + { + name2 = "null"; + } + + m_log.InfoFormat("TriArrayCallback: A collision was detected between {1} and {2}", 0, name1, name2); + */ + return 1; + } + + public int TriCallback(IntPtr trimesh, IntPtr refObject, int triangleIndex) + { + String name1 = null; + String name2 = null; + + if (!geom_name_map.TryGetValue(trimesh, out name1)) + { + name1 = "null"; + } + + if (!geom_name_map.TryGetValue(refObject, out name2)) + { + name2 = "null"; + } + + // m_log.InfoFormat("TriCallback: A collision was detected between {1} and {2}. Index was {3}", 0, name1, name2, triangleIndex); + + d.Vector3 v0 = new d.Vector3(); + d.Vector3 v1 = new d.Vector3(); + d.Vector3 v2 = new d.Vector3(); + + d.GeomTriMeshGetTriangle(trimesh, 0, ref v0, ref v1, ref v2); + // m_log.DebugFormat("Triangle {0} is <{1},{2},{3}>, <{4},{5},{6}>, <{7},{8},{9}>", triangleIndex, v0.X, v0.Y, v0.Z, v1.X, v1.Y, v1.Z, v2.X, v2.Y, v2.Z); + + return 1; + } + + /// + /// This is our collision testing routine in ODE + /// + /// + private void collision_optimized(float timeStep) + { + _perloopContact.Clear(); + + lock (_characters) + { + foreach (OdeCharacter chr in _characters) + { + // Reset the collision values to false + // since we don't know if we're colliding yet + + // For some reason this can happen. Don't ask... + // + if (chr == null) + continue; + + if (chr.Shell == IntPtr.Zero || chr.Body == IntPtr.Zero) + continue; + + chr.IsColliding = false; + chr.CollidingGround = false; + chr.CollidingObj = false; + + // test the avatar's geometry for collision with the space + // This will return near and the space that they are the closest to + // And we'll run this again against the avatar and the space segment + // This will return with a bunch of possible objects in the space segment + // and we'll run it again on all of them. + try + { + d.SpaceCollide2(space, chr.Shell, IntPtr.Zero, nearCallback); + } + catch (AccessViolationException) + { + m_log.Warn("[PHYSICS]: Unable to space collide"); + } + //float terrainheight = GetTerrainHeightAtXY(chr.Position.X, chr.Position.Y); + //if (chr.Position.Z + (chr.Velocity.Z * timeStep) < terrainheight + 10) + //{ + //chr.Position.Z = terrainheight + 10.0f; + //forcedZ = true; + //} + } + } + + lock (_activeprims) + { + List removeprims = null; + foreach (OdePrim chr in _activeprims) + { + if (chr.Body != IntPtr.Zero && d.BodyIsEnabled(chr.Body) && (!chr.m_disabled)) + { + try + { + lock (chr) + { + if (space != IntPtr.Zero && chr.prim_geom != IntPtr.Zero && chr.m_taintremove == false) + { + d.SpaceCollide2(space, chr.prim_geom, IntPtr.Zero, nearCallback); + } + else + { + if (removeprims == null) + { + removeprims = new List(); + } + removeprims.Add(chr); + m_log.Debug("[PHYSICS]: unable to collide test active prim against space. The space was zero, the geom was zero or it was in the process of being removed. Removed it from the active prim list. This needs to be fixed!"); + } + } + } + catch (AccessViolationException) + { + m_log.Warn("[PHYSICS]: Unable to space collide"); + } + } + } + + if (removeprims != null) + { + foreach (OdePrim chr in removeprims) + { + _activeprims.Remove(chr); + } + } + } + + _perloopContact.Clear(); + } + + #endregion + + public override void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents) + { + m_worldOffset = offset; + WorldExtents = new Vector2(extents.X, extents.Y); + m_parentScene = pScene; + } + + // Recovered for use by fly height. Kitto Flora + public float GetTerrainHeightAtXY(float x, float y) + { + int offsetX = ((int)(x / (int)Constants.RegionSize)) * (int)Constants.RegionSize; + int offsetY = ((int)(y / (int)Constants.RegionSize)) * (int)Constants.RegionSize; + + IntPtr heightFieldGeom = IntPtr.Zero; + + if (RegionTerrain.TryGetValue(new Vector3(offsetX,offsetY,0), out heightFieldGeom)) + { + if (heightFieldGeom != IntPtr.Zero) + { + if (TerrainHeightFieldHeights.ContainsKey(heightFieldGeom)) + { + + int index; + + + if ((int)x > WorldExtents.X || (int)y > WorldExtents.Y || + (int)x < 0.001f || (int)y < 0.001f) + return 0; + + x = x - offsetX; + y = y - offsetY; + + index = (int)((int)x * ((int)Constants.RegionSize + 2) + (int)y); + + if (index < TerrainHeightFieldHeights[heightFieldGeom].Length) + { + //m_log.DebugFormat("x{0} y{1} = {2}", x, y, (float)TerrainHeightFieldHeights[heightFieldGeom][index]); + return (float)TerrainHeightFieldHeights[heightFieldGeom][index]; + } + + else + return 0f; + } + else + { + return 0f; + } + + } + else + { + return 0f; + } + + } + else + { + return 0f; + } + } +// End recovered. Kitto Flora + + public void addCollisionEventReporting(PhysicsActor obj) + { + lock (_collisionEventPrim) + { + if (!_collisionEventPrim.Contains(obj)) + _collisionEventPrim.Add(obj); + } + } + + public void remCollisionEventReporting(PhysicsActor obj) + { + lock (_collisionEventPrim) + { + if (!_collisionEventPrim.Contains(obj)) + _collisionEventPrim.Remove(obj); + } + } + + #region Add/Remove Entities + + public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying) + { + Vector3 pos; + pos.X = position.X; + pos.Y = position.Y; + pos.Z = position.Z; + OdeCharacter newAv = new OdeCharacter(avName, this, pos, ode, size, avPIDD, avPIDP, avCapRadius, avStandupTensor, avDensity, avHeightFudgeFactor, avMovementDivisorWalk, avMovementDivisorRun); + newAv.Flying = isFlying; + newAv.MinimumGroundFlightOffset = minimumGroundFlightOffset; + + return newAv; + } + + public void AddCharacter(OdeCharacter chr) + { + lock (_characters) + { + if (!_characters.Contains(chr)) + { + _characters.Add(chr); + if (chr.bad) + m_log.DebugFormat("[PHYSICS] Added BAD actor {0} to characters list", chr.m_uuid); + } + } + } + + public void RemoveCharacter(OdeCharacter chr) + { + lock (_characters) + { + if (_characters.Contains(chr)) + { + _characters.Remove(chr); + } + } + } + + public void BadCharacter(OdeCharacter chr) + { + lock (_badCharacter) + { + if (!_badCharacter.Contains(chr)) + _badCharacter.Add(chr); + } + } + + public override void RemoveAvatar(PhysicsActor actor) + { + //m_log.Debug("[PHYSICS]:ODELOCK"); + ((OdeCharacter) actor).Destroy(); + } + + private PhysicsActor AddPrim(String name, Vector3 position, Vector3 size, Quaternion rotation, + IMesh mesh, PrimitiveBaseShape pbs, bool isphysical) + { + Vector3 pos = position; + Vector3 siz = size; + Quaternion rot = rotation; + + OdePrim newPrim; + lock (OdeLock) + { + newPrim = new OdePrim(name, this, pos, siz, rot, mesh, pbs, isphysical, ode); + + lock (_prims) + _prims.Add(newPrim); + } + + return newPrim; + } + + public void addActivePrim(OdePrim activatePrim) + { + // adds active prim.. (ones that should be iterated over in collisions_optimized + lock (_activeprims) + { + if (!_activeprims.Contains(activatePrim)) + _activeprims.Add(activatePrim); + //else + // m_log.Warn("[PHYSICS]: Double Entry in _activeprims detected, potential crash immenent"); + } + } + + public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, + Vector3 size, Quaternion rotation) //To be removed + { + return AddPrimShape(primName, pbs, position, size, rotation, false); + } + + public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, + Vector3 size, Quaternion rotation, bool isPhysical) + { +// m_log.DebugFormat("[PHYSICS]: Adding physics actor to {0}", primName); + + PhysicsActor result; + IMesh mesh = null; + + if (needsMeshing(pbs)) + { + try + { + mesh = mesher.CreateMesh(primName, pbs, size, 32f, isPhysical); + } + catch(Exception e) + { + m_log.ErrorFormat("[PHYSICS]: Exception while meshing prim {0}.", primName); + m_log.Debug(e.ToString()); + mesh = null; + return null; + } + } + + result = AddPrim(primName, position, size, rotation, mesh, pbs, isPhysical); + + return result; + } + + public override float TimeDilation + { + get { return m_timeDilation; } + } + + public override bool SupportsNINJAJoints + { + get { return m_NINJA_physics_joints_enabled; } + } + + // internal utility function: must be called within a lock (OdeLock) + private void InternalAddActiveJoint(PhysicsJoint joint) + { + activeJoints.Add(joint); + SOPName_to_activeJoint.Add(joint.ObjectNameInScene, joint); + } + + // internal utility function: must be called within a lock (OdeLock) + private void InternalAddPendingJoint(OdePhysicsJoint joint) + { + pendingJoints.Add(joint); + SOPName_to_pendingJoint.Add(joint.ObjectNameInScene, joint); + } + + // internal utility function: must be called within a lock (OdeLock) + private void InternalRemovePendingJoint(PhysicsJoint joint) + { + pendingJoints.Remove(joint); + SOPName_to_pendingJoint.Remove(joint.ObjectNameInScene); + } + + // internal utility function: must be called within a lock (OdeLock) + private void InternalRemoveActiveJoint(PhysicsJoint joint) + { + activeJoints.Remove(joint); + SOPName_to_activeJoint.Remove(joint.ObjectNameInScene); + } + + public override void DumpJointInfo() + { + string hdr = "[NINJA] JOINTINFO: "; + foreach (PhysicsJoint j in pendingJoints) + { + m_log.Debug(hdr + " pending joint, Name: " + j.ObjectNameInScene + " raw parms:" + j.RawParams); + } + m_log.Debug(hdr + pendingJoints.Count + " total pending joints"); + foreach (string jointName in SOPName_to_pendingJoint.Keys) + { + m_log.Debug(hdr + " pending joints dict contains Name: " + jointName); + } + m_log.Debug(hdr + SOPName_to_pendingJoint.Keys.Count + " total pending joints dict entries"); + foreach (PhysicsJoint j in activeJoints) + { + m_log.Debug(hdr + " active joint, Name: " + j.ObjectNameInScene + " raw parms:" + j.RawParams); + } + m_log.Debug(hdr + activeJoints.Count + " total active joints"); + foreach (string jointName in SOPName_to_activeJoint.Keys) + { + m_log.Debug(hdr + " active joints dict contains Name: " + jointName); + } + m_log.Debug(hdr + SOPName_to_activeJoint.Keys.Count + " total active joints dict entries"); + + m_log.Debug(hdr + " Per-body joint connectivity information follows."); + m_log.Debug(hdr + joints_connecting_actor.Keys.Count + " bodies are connected by joints."); + foreach (string actorName in joints_connecting_actor.Keys) + { + m_log.Debug(hdr + " Actor " + actorName + " has the following joints connecting it"); + foreach (PhysicsJoint j in joints_connecting_actor[actorName]) + { + m_log.Debug(hdr + " * joint Name: " + j.ObjectNameInScene + " raw parms:" + j.RawParams); + } + m_log.Debug(hdr + joints_connecting_actor[actorName].Count + " connecting joints total for this actor"); + } + } + + public override void RequestJointDeletion(string ObjectNameInScene) + { + lock (externalJointRequestsLock) + { + if (!requestedJointsToBeDeleted.Contains(ObjectNameInScene)) // forbid same deletion request from entering twice to prevent spurious deletions processed asynchronously + { + requestedJointsToBeDeleted.Add(ObjectNameInScene); + } + } + } + + private void DeleteRequestedJoints() + { + List myRequestedJointsToBeDeleted; + lock (externalJointRequestsLock) + { + // make a local copy of the shared list for processing (threading issues) + myRequestedJointsToBeDeleted = new List(requestedJointsToBeDeleted); + } + + foreach (string jointName in myRequestedJointsToBeDeleted) + { + lock (OdeLock) + { + //m_log.Debug("[NINJA] trying to deleting requested joint " + jointName); + if (SOPName_to_activeJoint.ContainsKey(jointName) || SOPName_to_pendingJoint.ContainsKey(jointName)) + { + OdePhysicsJoint joint = null; + if (SOPName_to_activeJoint.ContainsKey(jointName)) + { + joint = SOPName_to_activeJoint[jointName] as OdePhysicsJoint; + InternalRemoveActiveJoint(joint); + } + else if (SOPName_to_pendingJoint.ContainsKey(jointName)) + { + joint = SOPName_to_pendingJoint[jointName] as OdePhysicsJoint; + InternalRemovePendingJoint(joint); + } + + if (joint != null) + { + //m_log.Debug("joint.BodyNames.Count is " + joint.BodyNames.Count + " and contents " + joint.BodyNames); + for (int iBodyName = 0; iBodyName < 2; iBodyName++) + { + string bodyName = joint.BodyNames[iBodyName]; + if (bodyName != "NULL") + { + joints_connecting_actor[bodyName].Remove(joint); + if (joints_connecting_actor[bodyName].Count == 0) + { + joints_connecting_actor.Remove(bodyName); + } + } + } + + DoJointDeactivated(joint); + if (joint.jointID != IntPtr.Zero) + { + d.JointDestroy(joint.jointID); + joint.jointID = IntPtr.Zero; + //DoJointErrorMessage(joint, "successfully destroyed joint " + jointName); + } + else + { + //m_log.Warn("[NINJA] Ignoring re-request to destroy joint " + jointName); + } + } + else + { + // DoJointErrorMessage(joint, "coult not find joint to destroy based on name " + jointName); + } + } + else + { + // DoJointErrorMessage(joint, "WARNING - joint removal failed, joint " + jointName); + } + } + } + + // remove processed joints from the shared list + lock (externalJointRequestsLock) + { + foreach (string jointName in myRequestedJointsToBeDeleted) + { + requestedJointsToBeDeleted.Remove(jointName); + } + } + } + + // for pending joints we don't know if their associated bodies exist yet or not. + // the joint is actually created during processing of the taints + private void CreateRequestedJoints() + { + List myRequestedJointsToBeCreated; + lock (externalJointRequestsLock) + { + // make a local copy of the shared list for processing (threading issues) + myRequestedJointsToBeCreated = new List(requestedJointsToBeCreated); + } + + foreach (PhysicsJoint joint in myRequestedJointsToBeCreated) + { + lock (OdeLock) + { + if (SOPName_to_pendingJoint.ContainsKey(joint.ObjectNameInScene) && SOPName_to_pendingJoint[joint.ObjectNameInScene] != null) + { + DoJointErrorMessage(joint, "WARNING: ignoring request to re-add already pending joint Name:" + joint.ObjectNameInScene + " type:" + joint.Type + " parms: " + joint.RawParams + " pos: " + joint.Position + " rot:" + joint.Rotation); + continue; + } + if (SOPName_to_activeJoint.ContainsKey(joint.ObjectNameInScene) && SOPName_to_activeJoint[joint.ObjectNameInScene] != null) + { + DoJointErrorMessage(joint, "WARNING: ignoring request to re-add already active joint Name:" + joint.ObjectNameInScene + " type:" + joint.Type + " parms: " + joint.RawParams + " pos: " + joint.Position + " rot:" + joint.Rotation); + continue; + } + + InternalAddPendingJoint(joint as OdePhysicsJoint); + + if (joint.BodyNames.Count >= 2) + { + for (int iBodyName = 0; iBodyName < 2; iBodyName++) + { + string bodyName = joint.BodyNames[iBodyName]; + if (bodyName != "NULL") + { + if (!joints_connecting_actor.ContainsKey(bodyName)) + { + joints_connecting_actor.Add(bodyName, new List()); + } + joints_connecting_actor[bodyName].Add(joint); + } + } + } + } + } + + // remove processed joints from shared list + lock (externalJointRequestsLock) + { + foreach (PhysicsJoint joint in myRequestedJointsToBeCreated) + { + requestedJointsToBeCreated.Remove(joint); + } + } + } + + /// + /// Add a request for joint creation. + /// + /// + /// this joint will just be added to a waiting list that is NOT processed during the main + /// Simulate() loop (to avoid deadlocks). After Simulate() is finished, we handle unprocessed joint requests. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public override PhysicsJoint RequestJointCreation( + string objectNameInScene, PhysicsJointType jointType, Vector3 position, + Quaternion rotation, string parms, List bodyNames, string trackedBodyName, Quaternion localRotation) + { + OdePhysicsJoint joint = new OdePhysicsJoint(); + joint.ObjectNameInScene = objectNameInScene; + joint.Type = jointType; + joint.Position = position; + joint.Rotation = rotation; + joint.RawParams = parms; + joint.BodyNames = new List(bodyNames); + joint.TrackedBodyName = trackedBodyName; + joint.LocalRotation = localRotation; + joint.jointID = IntPtr.Zero; + joint.ErrorMessageCount = 0; + + lock (externalJointRequestsLock) + { + if (!requestedJointsToBeCreated.Contains(joint)) // forbid same creation request from entering twice + { + requestedJointsToBeCreated.Add(joint); + } + } + + return joint; + } + + private void RemoveAllJointsConnectedToActor(PhysicsActor actor) + { + //m_log.Debug("RemoveAllJointsConnectedToActor: start"); + if (actor.SOPName != null && joints_connecting_actor.ContainsKey(actor.SOPName) && joints_connecting_actor[actor.SOPName] != null) + { + + List jointsToRemove = new List(); + //TODO: merge these 2 loops (originally it was needed to avoid altering a list being iterated over, but it is no longer needed due to the joint request queue mechanism) + foreach (PhysicsJoint j in joints_connecting_actor[actor.SOPName]) + { + jointsToRemove.Add(j); + } + foreach (PhysicsJoint j in jointsToRemove) + { + //m_log.Debug("RemoveAllJointsConnectedToActor: about to request deletion of " + j.ObjectNameInScene); + RequestJointDeletion(j.ObjectNameInScene); + //m_log.Debug("RemoveAllJointsConnectedToActor: done request deletion of " + j.ObjectNameInScene); + j.TrackedBodyName = null; // *IMMEDIATELY* prevent any further movement of this joint (else a deleted actor might cause spurious tracking motion of the joint for a few frames, leading to the joint proxy object disappearing) + } + } + } + + public override void RemoveAllJointsConnectedToActorThreadLocked(PhysicsActor actor) + { + //m_log.Debug("RemoveAllJointsConnectedToActorThreadLocked: start"); + lock (OdeLock) + { + //m_log.Debug("RemoveAllJointsConnectedToActorThreadLocked: got lock"); + RemoveAllJointsConnectedToActor(actor); + } + } + + // normally called from within OnJointMoved, which is called from within a lock (OdeLock) + public override Vector3 GetJointAnchor(PhysicsJoint joint) + { + Debug.Assert(joint.IsInPhysicsEngine); + d.Vector3 pos = new d.Vector3(); + + if (!(joint is OdePhysicsJoint)) + { + DoJointErrorMessage(joint, "warning: non-ODE joint requesting anchor: " + joint.ObjectNameInScene); + } + else + { + OdePhysicsJoint odeJoint = (OdePhysicsJoint)joint; + switch (odeJoint.Type) + { + case PhysicsJointType.Ball: + d.JointGetBallAnchor(odeJoint.jointID, out pos); + break; + case PhysicsJointType.Hinge: + d.JointGetHingeAnchor(odeJoint.jointID, out pos); + break; + } + } + return new Vector3(pos.X, pos.Y, pos.Z); + } + + /// + /// Get joint axis. + /// + /// + /// normally called from within OnJointMoved, which is called from within a lock (OdeLock) + /// WARNING: ODE sometimes returns <0,0,0> as the joint axis! Therefore this function + /// appears to be unreliable. Fortunately we can compute the joint axis ourselves by + /// keeping track of the joint's original orientation relative to one of the involved bodies. + /// + /// + /// + public override Vector3 GetJointAxis(PhysicsJoint joint) + { + Debug.Assert(joint.IsInPhysicsEngine); + d.Vector3 axis = new d.Vector3(); + + if (!(joint is OdePhysicsJoint)) + { + DoJointErrorMessage(joint, "warning: non-ODE joint requesting anchor: " + joint.ObjectNameInScene); + } + else + { + OdePhysicsJoint odeJoint = (OdePhysicsJoint)joint; + switch (odeJoint.Type) + { + case PhysicsJointType.Ball: + DoJointErrorMessage(joint, "warning - axis requested for ball joint: " + joint.ObjectNameInScene); + break; + case PhysicsJointType.Hinge: + d.JointGetHingeAxis(odeJoint.jointID, out axis); + break; + } + } + return new Vector3(axis.X, axis.Y, axis.Z); + } + + public void remActivePrim(OdePrim deactivatePrim) + { + lock (_activeprims) + { + _activeprims.Remove(deactivatePrim); + } + } + + public override void RemovePrim(PhysicsActor prim) + { + if (prim is OdePrim) + { + lock (OdeLock) + { + OdePrim p = (OdePrim) prim; + + p.setPrimForRemoval(); + AddPhysicsActorTaint(prim); + //RemovePrimThreadLocked(p); + } + } + } + + /// + /// This is called from within simulate but outside the locked portion + /// We need to do our own locking here + /// Essentially, we need to remove the prim from our space segment, whatever segment it's in. + /// + /// If there are no more prim in the segment, we need to empty (spacedestroy)the segment and reclaim memory + /// that the space was using. + /// + /// + public void RemovePrimThreadLocked(OdePrim prim) + { +//Console.WriteLine("RemovePrimThreadLocked " + prim.m_primName); + lock (prim) + { + remCollisionEventReporting(prim); + lock (ode) + { + if (prim.prim_geom != IntPtr.Zero) + { + prim.ResetTaints(); + + if (prim.IsPhysical) + { + prim.disableBody(); + if (prim.childPrim) + { + prim.childPrim = false; + prim.Body = IntPtr.Zero; + prim.m_disabled = true; + prim.IsPhysical = false; + } + + + } + // we don't want to remove the main space + + // If the geometry is in the targetspace, remove it from the target space + //m_log.Warn(prim.m_targetSpace); + + //if (prim.m_targetSpace != IntPtr.Zero) + //{ + //if (d.SpaceQuery(prim.m_targetSpace, prim.prim_geom)) + //{ + + //if (d.GeomIsSpace(prim.m_targetSpace)) + //{ + //waitForSpaceUnlock(prim.m_targetSpace); + //d.SpaceRemove(prim.m_targetSpace, prim.prim_geom); + prim.m_targetSpace = IntPtr.Zero; + //} + //else + //{ + // m_log.Info("[Physics]: Invalid Scene passed to 'removeprim from scene':" + + //((OdePrim)prim).m_targetSpace.ToString()); + //} + + //} + //} + //m_log.Warn(prim.prim_geom); + try + { + if (prim.prim_geom != IntPtr.Zero) + { + d.GeomDestroy(prim.prim_geom); + prim.prim_geom = IntPtr.Zero; + } + else + { + m_log.Warn("[PHYSICS]: Unable to remove prim from physics scene"); + } + } + catch (AccessViolationException) + { + m_log.Info("[PHYSICS]: Couldn't remove prim from physics scene, it was already be removed."); + } + lock (_prims) + _prims.Remove(prim); + + //If there are no more geometries in the sub-space, we don't need it in the main space anymore + //if (d.SpaceGetNumGeoms(prim.m_targetSpace) == 0) + //{ + //if (prim.m_targetSpace != null) + //{ + //if (d.GeomIsSpace(prim.m_targetSpace)) + //{ + //waitForSpaceUnlock(prim.m_targetSpace); + //d.SpaceRemove(space, prim.m_targetSpace); + // free up memory used by the space. + //d.SpaceDestroy(prim.m_targetSpace); + //int[] xyspace = calculateSpaceArrayItemFromPos(prim.Position); + //resetSpaceArrayItemToZero(xyspace[0], xyspace[1]); + //} + //else + //{ + //m_log.Info("[Physics]: Invalid Scene passed to 'removeprim from scene':" + + //((OdePrim) prim).m_targetSpace.ToString()); + //} + //} + //} + + if (SupportsNINJAJoints) + { + RemoveAllJointsConnectedToActorThreadLocked(prim); + } + } + } + } + } + + #endregion + + #region Space Separation Calculation + + /// + /// Takes a space pointer and zeros out the array we're using to hold the spaces + /// + /// + public void resetSpaceArrayItemToZero(IntPtr pSpace) + { + for (int x = 0; x < staticPrimspace.GetLength(0); x++) + { + for (int y = 0; y < staticPrimspace.GetLength(1); y++) + { + if (staticPrimspace[x, y] == pSpace) + staticPrimspace[x, y] = IntPtr.Zero; + } + } + } + + public void resetSpaceArrayItemToZero(int arrayitemX, int arrayitemY) + { + staticPrimspace[arrayitemX, arrayitemY] = IntPtr.Zero; + } + + /// + /// Called when a static prim moves. Allocates a space for the prim based on its position + /// + /// the pointer to the geom that moved + /// the position that the geom moved to + /// a pointer to the space it was in before it was moved. + /// a pointer to the new space it's in + public IntPtr recalculateSpaceForGeom(IntPtr geom, Vector3 pos, IntPtr currentspace) + { + // Called from setting the Position and Size of an ODEPrim so + // it's already in locked space. + + // we don't want to remove the main space + // we don't need to test physical here because this function should + // never be called if the prim is physical(active) + + // All physical prim end up in the root space + //Thread.Sleep(20); + if (currentspace != space) + { + //m_log.Info("[SPACE]: C:" + currentspace.ToString() + " g:" + geom.ToString()); + //if (currentspace == IntPtr.Zero) + //{ + //int adfadf = 0; + //} + if (d.SpaceQuery(currentspace, geom) && currentspace != IntPtr.Zero) + { + if (d.GeomIsSpace(currentspace)) + { + waitForSpaceUnlock(currentspace); + d.SpaceRemove(currentspace, geom); + } + else + { + m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" + currentspace + + " Geom:" + geom); + } + } + else + { + IntPtr sGeomIsIn = d.GeomGetSpace(geom); + if (sGeomIsIn != IntPtr.Zero) + { + if (d.GeomIsSpace(currentspace)) + { + waitForSpaceUnlock(sGeomIsIn); + d.SpaceRemove(sGeomIsIn, geom); + } + else + { + m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" + + sGeomIsIn + " Geom:" + geom); + } + } + } + + //If there are no more geometries in the sub-space, we don't need it in the main space anymore + if (d.SpaceGetNumGeoms(currentspace) == 0) + { + if (currentspace != IntPtr.Zero) + { + if (d.GeomIsSpace(currentspace)) + { + waitForSpaceUnlock(currentspace); + waitForSpaceUnlock(space); + d.SpaceRemove(space, currentspace); + // free up memory used by the space. + + //d.SpaceDestroy(currentspace); + resetSpaceArrayItemToZero(currentspace); + } + else + { + m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" + + currentspace + " Geom:" + geom); + } + } + } + } + else + { + // this is a physical object that got disabled. ;.; + if (currentspace != IntPtr.Zero && geom != IntPtr.Zero) + { + if (d.SpaceQuery(currentspace, geom)) + { + if (d.GeomIsSpace(currentspace)) + { + waitForSpaceUnlock(currentspace); + d.SpaceRemove(currentspace, geom); + } + else + { + m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" + + currentspace + " Geom:" + geom); + } + } + else + { + IntPtr sGeomIsIn = d.GeomGetSpace(geom); + if (sGeomIsIn != IntPtr.Zero) + { + if (d.GeomIsSpace(sGeomIsIn)) + { + waitForSpaceUnlock(sGeomIsIn); + d.SpaceRemove(sGeomIsIn, geom); + } + else + { + m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" + + sGeomIsIn + " Geom:" + geom); + } + } + } + } + } + + // The routines in the Position and Size sections do the 'inserting' into the space, + // so all we have to do is make sure that the space that we're putting the prim into + // is in the 'main' space. + int[] iprimspaceArrItem = calculateSpaceArrayItemFromPos(pos); + IntPtr newspace = calculateSpaceForGeom(pos); + + if (newspace == IntPtr.Zero) + { + newspace = createprimspace(iprimspaceArrItem[0], iprimspaceArrItem[1]); + d.HashSpaceSetLevels(newspace, smallHashspaceLow, smallHashspaceHigh); + } + + return newspace; + } + + /// + /// Creates a new space at X Y + /// + /// + /// + /// A pointer to the created space + public IntPtr createprimspace(int iprimspaceArrItemX, int iprimspaceArrItemY) + { + // creating a new space for prim and inserting it into main space. + staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY] = d.HashSpaceCreate(IntPtr.Zero); + d.GeomSetCategoryBits(staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY], (int)CollisionCategories.Space); + waitForSpaceUnlock(space); + d.SpaceSetSublevel(space, 1); + d.SpaceAdd(space, staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY]); + return staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY]; + } + + /// + /// Calculates the space the prim should be in by its position + /// + /// + /// a pointer to the space. This could be a new space or reused space. + public IntPtr calculateSpaceForGeom(Vector3 pos) + { + int[] xyspace = calculateSpaceArrayItemFromPos(pos); + //m_log.Info("[Physics]: Attempting to use arrayItem: " + xyspace[0].ToString() + "," + xyspace[1].ToString()); + return staticPrimspace[xyspace[0], xyspace[1]]; + } + + /// + /// Holds the space allocation logic + /// + /// + /// an array item based on the position + public int[] calculateSpaceArrayItemFromPos(Vector3 pos) + { + int[] returnint = new int[2]; + + returnint[0] = (int) (pos.X/metersInSpace); + + if (returnint[0] > ((int) (259f/metersInSpace))) + returnint[0] = ((int) (259f/metersInSpace)); + if (returnint[0] < 0) + returnint[0] = 0; + + returnint[1] = (int) (pos.Y/metersInSpace); + if (returnint[1] > ((int) (259f/metersInSpace))) + returnint[1] = ((int) (259f/metersInSpace)); + if (returnint[1] < 0) + returnint[1] = 0; + + return returnint; + } + + #endregion + + /// + /// Routine to figure out if we need to mesh this prim with our mesher + /// + /// + /// + public bool needsMeshing(PrimitiveBaseShape pbs) + { + // most of this is redundant now as the mesher will return null if it cant mesh a prim + // but we still need to check for sculptie meshing being enabled so this is the most + // convenient place to do it for now... + + // //if (pbs.PathCurve == (byte)Primitive.PathCurve.Circle && pbs.ProfileCurve == (byte)Primitive.ProfileCurve.Circle && pbs.PathScaleY <= 0.75f) + // //m_log.Debug("needsMeshing: " + " pathCurve: " + pbs.PathCurve.ToString() + " profileCurve: " + pbs.ProfileCurve.ToString() + " pathScaleY: " + Primitive.UnpackPathScale(pbs.PathScaleY).ToString()); + int iPropertiesNotSupportedDefault = 0; + + if (pbs.SculptEntry && !meshSculptedPrim) + { +#if SPAM + m_log.Warn("NonMesh"); +#endif + return false; + } + + // if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since ODE can use an internal representation for the prim + if (!forceSimplePrimMeshing && !pbs.SculptEntry) + { + if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) + || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 + && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z)) + { + + if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0 + && pbs.ProfileHollow == 0 + && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0 + && pbs.PathBegin == 0 && pbs.PathEnd == 0 + && pbs.PathTaperX == 0 && pbs.PathTaperY == 0 + && pbs.PathScaleX == 100 && pbs.PathScaleY == 100 + && pbs.PathShearX == 0 && pbs.PathShearY == 0) + { +#if SPAM + m_log.Warn("NonMesh"); +#endif + return false; + } + } + } + + if (pbs.ProfileHollow != 0) + iPropertiesNotSupportedDefault++; + + if ((pbs.PathBegin != 0) || pbs.PathEnd != 0) + iPropertiesNotSupportedDefault++; + + if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0)) + iPropertiesNotSupportedDefault++; + + if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0) + iPropertiesNotSupportedDefault++; + + if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100)) + iPropertiesNotSupportedDefault++; + + if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0)) + iPropertiesNotSupportedDefault++; + + if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight) + iPropertiesNotSupportedDefault++; + + if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 && (pbs.Scale.X != pbs.Scale.Y || pbs.Scale.Y != pbs.Scale.Z || pbs.Scale.Z != pbs.Scale.X)) + iPropertiesNotSupportedDefault++; + + if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte) Extrusion.Curve1) + iPropertiesNotSupportedDefault++; + + // test for torus + if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Square) + { + if (pbs.PathCurve == (byte)Extrusion.Curve1) + { + iPropertiesNotSupportedDefault++; + } + } + else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Circle) + { + if (pbs.PathCurve == (byte)Extrusion.Straight) + { + iPropertiesNotSupportedDefault++; + } + + // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits + else if (pbs.PathCurve == (byte)Extrusion.Curve1) + { + iPropertiesNotSupportedDefault++; + } + } + else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle) + { + if (pbs.PathCurve == (byte)Extrusion.Curve1 || pbs.PathCurve == (byte)Extrusion.Curve2) + { + iPropertiesNotSupportedDefault++; + } + } + else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle) + { + if (pbs.PathCurve == (byte)Extrusion.Straight) + { + iPropertiesNotSupportedDefault++; + } + else if (pbs.PathCurve == (byte)Extrusion.Curve1) + { + iPropertiesNotSupportedDefault++; + } + } + + if (pbs.SculptEntry && meshSculptedPrim) + iPropertiesNotSupportedDefault++; + + + if (iPropertiesNotSupportedDefault == 0) + { +#if SPAM + m_log.Warn("NonMesh"); +#endif + return false; + } +#if SPAM + m_log.Debug("Mesh"); +#endif + return true; + } + + /// + /// Called after our prim properties are set Scale, position etc. + /// We use this event queue like method to keep changes to the physical scene occuring in the threadlocked mutex + /// This assures us that we have no race conditions + /// + /// + public override void AddPhysicsActorTaint(PhysicsActor prim) + { + if (prim is OdePrim) + { + OdePrim taintedprim = ((OdePrim) prim); + lock (_taintedPrimLock) + { + if (!(_taintedPrimH.Contains(taintedprim))) + { +//Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.m_primName); + _taintedPrimH.Add(taintedprim); // HashSet for searching + _taintedPrimL.Add(taintedprim); // List for ordered readout + } + } + return; + } + else if (prim is OdeCharacter) + { + OdeCharacter taintedchar = ((OdeCharacter)prim); + lock (_taintedActors) + { + if (!(_taintedActors.Contains(taintedchar))) + { + _taintedActors.Add(taintedchar); + if (taintedchar.bad) + m_log.DebugFormat("[PHYSICS]: Added BAD actor {0} to tainted actors", taintedchar.m_uuid); + } + } + } + } + + /// + /// This is our main simulate loop + /// It's thread locked by a Mutex in the scene. + /// It holds Collisions, it instructs ODE to step through the physical reactions + /// It moves the objects around in memory + /// It calls the methods that report back to the object owners.. (scenepresence, SceneObjectGroup) + /// + /// + /// + public override float Simulate(float timeStep) + { + if (framecount >= int.MaxValue) + framecount = 0; + + //if (m_worldOffset != Vector3.Zero) + // return 0; + + framecount++; + + float fps = 0; + //m_log.Info(timeStep.ToString()); + step_time += timeStep; + + // If We're loaded down by something else, + // or debugging with the Visual Studio project on pause + // skip a few frames to catch up gracefully. + // without shooting the physicsactors all over the place + + if (step_time >= m_SkipFramesAtms) + { + // Instead of trying to catch up, it'll do 5 physics frames only + step_time = ODE_STEPSIZE; + m_physicsiterations = 5; + } + else + { + m_physicsiterations = 10; + } + + if (SupportsNINJAJoints) + { + DeleteRequestedJoints(); // this must be outside of the lock (OdeLock) to avoid deadlocks + CreateRequestedJoints(); // this must be outside of the lock (OdeLock) to avoid deadlocks + } + + lock (OdeLock) + { + // Process 10 frames if the sim is running normal.. + // process 5 frames if the sim is running slow + //try + //{ + //d.WorldSetQuickStepNumIterations(world, m_physicsiterations); + //} + //catch (StackOverflowException) + //{ + // m_log.Error("[PHYSICS]: The operating system wasn't able to allocate enough memory for the simulation. Restarting the sim."); + // ode.drelease(world); + //base.TriggerPhysicsBasedRestart(); + //} + + int i = 0; + + // Figure out the Frames Per Second we're going at. + //(step_time == 0.004f, there's 250 of those per second. Times the step time/step size + + fps = (step_time / ODE_STEPSIZE) * 1000; + // HACK: Using a time dilation of 1.0 to debug rubberbanding issues + //m_timeDilation = Math.Min((step_time / ODE_STEPSIZE) / (0.09375f / ODE_STEPSIZE), 1.0f); + + step_time = 0.09375f; + + while (step_time > 0.0f) + { + //lock (ode) + //{ + //if (!ode.lockquery()) + //{ + // ode.dlock(world); + try + { + // Insert, remove Characters + bool processedtaints = false; + + lock (_taintedActors) + { + if (_taintedActors.Count > 0) + { + foreach (OdeCharacter character in _taintedActors) + { + + character.ProcessTaints(timeStep); + + processedtaints = true; + //character.m_collisionscore = 0; + } + + if (processedtaints) + _taintedActors.Clear(); + } + } + + // Modify other objects in the scene. + processedtaints = false; + + lock (_taintedPrimLock) + { + foreach (OdePrim prim in _taintedPrimL) + { + if (prim.m_taintremove) + { + //Console.WriteLine("Simulate calls RemovePrimThreadLocked"); + RemovePrimThreadLocked(prim); + } + else + { + //Console.WriteLine("Simulate calls ProcessTaints"); + prim.ProcessTaints(timeStep); + } + processedtaints = true; + prim.m_collisionscore = 0; + + // This loop can block up the Heartbeat for a very long time on large regions. + // We need to let the Watchdog know that the Heartbeat is not dead + // NOTE: This is currently commented out, but if things like OAR loading are + // timing the heartbeat out we will need to uncomment it + //Watchdog.UpdateThread(); + } + + if (SupportsNINJAJoints) + { + // Create pending joints, if possible + + // joints can only be processed after ALL bodies are processed (and exist in ODE), since creating + // a joint requires specifying the body id of both involved bodies + if (pendingJoints.Count > 0) + { + List successfullyProcessedPendingJoints = new List(); + //DoJointErrorMessage(joints_connecting_actor, "taint: " + pendingJoints.Count + " pending joints"); + foreach (PhysicsJoint joint in pendingJoints) + { + //DoJointErrorMessage(joint, "taint: time to create joint with parms: " + joint.RawParams); + string[] jointParams = joint.RawParams.Split(" ".ToCharArray(), System.StringSplitOptions.RemoveEmptyEntries); + List jointBodies = new List(); + bool allJointBodiesAreReady = true; + foreach (string jointParam in jointParams) + { + if (jointParam == "NULL") + { + //DoJointErrorMessage(joint, "attaching NULL joint to world"); + jointBodies.Add(IntPtr.Zero); + } + else + { + //DoJointErrorMessage(joint, "looking for prim name: " + jointParam); + bool foundPrim = false; + lock (_prims) + { + foreach (OdePrim prim in _prims) // FIXME: inefficient + { + if (prim.SOPName == jointParam) + { + //DoJointErrorMessage(joint, "found for prim name: " + jointParam); + if (prim.IsPhysical && prim.Body != IntPtr.Zero) + { + jointBodies.Add(prim.Body); + foundPrim = true; + break; + } + else + { + DoJointErrorMessage(joint, "prim name " + jointParam + + " exists but is not (yet) physical; deferring joint creation. " + + "IsPhysical property is " + prim.IsPhysical + + " and body is " + prim.Body); + foundPrim = false; + break; + } + } + } + } + if (foundPrim) + { + // all is fine + } + else + { + allJointBodiesAreReady = false; + break; + } + } + } + if (allJointBodiesAreReady) + { + //DoJointErrorMessage(joint, "allJointBodiesAreReady for " + joint.ObjectNameInScene + " with parms " + joint.RawParams); + if (jointBodies[0] == jointBodies[1]) + { + DoJointErrorMessage(joint, "ERROR: joint cannot be created; the joint bodies are the same, body1==body2. Raw body is " + jointBodies[0] + ". raw parms: " + joint.RawParams); + } + else + { + switch (joint.Type) + { + case PhysicsJointType.Ball: + { + IntPtr odeJoint; + //DoJointErrorMessage(joint, "ODE creating ball joint "); + odeJoint = d.JointCreateBall(world, IntPtr.Zero); + //DoJointErrorMessage(joint, "ODE attaching ball joint: " + odeJoint + " with b1:" + jointBodies[0] + " b2:" + jointBodies[1]); + d.JointAttach(odeJoint, jointBodies[0], jointBodies[1]); + //DoJointErrorMessage(joint, "ODE setting ball anchor: " + odeJoint + " to vec:" + joint.Position); + d.JointSetBallAnchor(odeJoint, + joint.Position.X, + joint.Position.Y, + joint.Position.Z); + //DoJointErrorMessage(joint, "ODE joint setting OK"); + //DoJointErrorMessage(joint, "The ball joint's bodies are here: b0: "); + //DoJointErrorMessage(joint, "" + (jointBodies[0] != IntPtr.Zero ? "" + d.BodyGetPosition(jointBodies[0]) : "fixed environment")); + //DoJointErrorMessage(joint, "The ball joint's bodies are here: b1: "); + //DoJointErrorMessage(joint, "" + (jointBodies[1] != IntPtr.Zero ? "" + d.BodyGetPosition(jointBodies[1]) : "fixed environment")); + + if (joint is OdePhysicsJoint) + { + ((OdePhysicsJoint)joint).jointID = odeJoint; + } + else + { + DoJointErrorMessage(joint, "WARNING: non-ode joint in ODE!"); + } + } + break; + case PhysicsJointType.Hinge: + { + IntPtr odeJoint; + //DoJointErrorMessage(joint, "ODE creating hinge joint "); + odeJoint = d.JointCreateHinge(world, IntPtr.Zero); + //DoJointErrorMessage(joint, "ODE attaching hinge joint: " + odeJoint + " with b1:" + jointBodies[0] + " b2:" + jointBodies[1]); + d.JointAttach(odeJoint, jointBodies[0], jointBodies[1]); + //DoJointErrorMessage(joint, "ODE setting hinge anchor: " + odeJoint + " to vec:" + joint.Position); + d.JointSetHingeAnchor(odeJoint, + joint.Position.X, + joint.Position.Y, + joint.Position.Z); + // We use the orientation of the x-axis of the joint's coordinate frame + // as the axis for the hinge. + + // Therefore, we must get the joint's coordinate frame based on the + // joint.Rotation field, which originates from the orientation of the + // joint's proxy object in the scene. + + // The joint's coordinate frame is defined as the transformation matrix + // that converts a vector from joint-local coordinates into world coordinates. + // World coordinates are defined as the XYZ coordinate system of the sim, + // as shown in the top status-bar of the viewer. + + // Once we have the joint's coordinate frame, we extract its X axis (AtAxis) + // and use that as the hinge axis. + + //joint.Rotation.Normalize(); + Matrix4 proxyFrame = Matrix4.CreateFromQuaternion(joint.Rotation); + + // Now extract the X axis of the joint's coordinate frame. + + // Do not try to use proxyFrame.AtAxis or you will become mired in the + // tar pit of transposed, inverted, and generally messed-up orientations. + // (In other words, Matrix4.AtAxis() is borked.) + // Vector3 jointAxis = proxyFrame.AtAxis; <--- this path leadeth to madness + + // Instead, compute the X axis of the coordinate frame by transforming + // the (1,0,0) vector. At least that works. + + //m_log.Debug("PHY: making axis: complete matrix is " + proxyFrame); + Vector3 jointAxis = Vector3.Transform(Vector3.UnitX, proxyFrame); + //m_log.Debug("PHY: making axis: hinge joint axis is " + jointAxis); + //DoJointErrorMessage(joint, "ODE setting hinge axis: " + odeJoint + " to vec:" + jointAxis); + d.JointSetHingeAxis(odeJoint, + jointAxis.X, + jointAxis.Y, + jointAxis.Z); + //d.JointSetHingeParam(odeJoint, (int)dParam.CFM, 0.1f); + if (joint is OdePhysicsJoint) + { + ((OdePhysicsJoint)joint).jointID = odeJoint; + } + else + { + DoJointErrorMessage(joint, "WARNING: non-ode joint in ODE!"); + } + } + break; + } + successfullyProcessedPendingJoints.Add(joint); + } + } + else + { + DoJointErrorMessage(joint, "joint could not yet be created; still pending"); + } + } + foreach (PhysicsJoint successfullyProcessedJoint in successfullyProcessedPendingJoints) + { + //DoJointErrorMessage(successfullyProcessedJoint, "finalizing succesfully procsssed joint " + successfullyProcessedJoint.ObjectNameInScene + " parms " + successfullyProcessedJoint.RawParams); + //DoJointErrorMessage(successfullyProcessedJoint, "removing from pending"); + InternalRemovePendingJoint(successfullyProcessedJoint); + //DoJointErrorMessage(successfullyProcessedJoint, "adding to active"); + InternalAddActiveJoint(successfullyProcessedJoint); + //DoJointErrorMessage(successfullyProcessedJoint, "done"); + } + } + } + + if (processedtaints) +//Console.WriteLine("Simulate calls Clear of _taintedPrim list"); + _taintedPrimH.Clear(); + _taintedPrimL.Clear(); + } + + // Move characters + lock (_characters) + { + List defects = new List(); + foreach (OdeCharacter actor in _characters) + { + if (actor != null) + actor.Move(timeStep, defects); + } + if (0 != defects.Count) + { + foreach (OdeCharacter defect in defects) + { + RemoveCharacter(defect); + } + } + } + + // Move other active objects + lock (_activeprims) + { + foreach (OdePrim prim in _activeprims) + { + prim.m_collisionscore = 0; + prim.Move(timeStep); + } + } + + //if ((framecount % m_randomizeWater) == 0) + // randomizeWater(waterlevel); + + //int RayCastTimeMS = m_rayCastManager.ProcessQueuedRequests(); + m_rayCastManager.ProcessQueuedRequests(); + + collision_optimized(timeStep); + + lock (_collisionEventPrim) + { + foreach (PhysicsActor obj in _collisionEventPrim) + { + if (obj == null) + continue; + + switch ((ActorTypes)obj.PhysicsActorType) + { + case ActorTypes.Agent: + OdeCharacter cobj = (OdeCharacter)obj; + cobj.AddCollisionFrameTime(100); + cobj.SendCollisions(); + break; + case ActorTypes.Prim: + OdePrim pobj = (OdePrim)obj; + pobj.SendCollisions(); + break; + } + } + } + + //if (m_global_contactcount > 5) + //{ + // m_log.DebugFormat("[PHYSICS]: Contacts:{0}", m_global_contactcount); + //} + + m_global_contactcount = 0; + + d.WorldQuickStep(world, ODE_STEPSIZE); + d.JointGroupEmpty(contactgroup); + //ode.dunlock(world); + } + catch (Exception e) + { + m_log.ErrorFormat("[PHYSICS]: {0}, {1}, {2}", e.Message, e.TargetSite, e); + ode.dunlock(world); + } + + step_time -= ODE_STEPSIZE; + i++; + //} + //else + //{ + //fps = 0; + //} + //} + } + + lock (_characters) + { + foreach (OdeCharacter actor in _characters) + { + if (actor != null) + { + if (actor.bad) + m_log.WarnFormat("[PHYSICS]: BAD Actor {0} in _characters list was not removed?", actor.m_uuid); + actor.UpdatePositionAndVelocity(); + } + } + } + + lock (_badCharacter) + { + if (_badCharacter.Count > 0) + { + foreach (OdeCharacter chr in _badCharacter) + { + RemoveCharacter(chr); + } + _badCharacter.Clear(); + } + } + + lock (_activeprims) + { + //if (timeStep < 0.2f) + { + foreach (OdePrim actor in _activeprims) + { + if (actor.IsPhysical && (d.BodyIsEnabled(actor.Body) || !actor._zeroFlag)) + { + actor.UpdatePositionAndVelocity(); + + if (SupportsNINJAJoints) + { + // If an actor moved, move its joint proxy objects as well. + // There seems to be an event PhysicsActor.OnPositionUpdate that could be used + // for this purpose but it is never called! So we just do the joint + // movement code here. + + if (actor.SOPName != null && + joints_connecting_actor.ContainsKey(actor.SOPName) && + joints_connecting_actor[actor.SOPName] != null && + joints_connecting_actor[actor.SOPName].Count > 0) + { + foreach (PhysicsJoint affectedJoint in joints_connecting_actor[actor.SOPName]) + { + if (affectedJoint.IsInPhysicsEngine) + { + DoJointMoved(affectedJoint); + } + else + { + DoJointErrorMessage(affectedJoint, "a body connected to a joint was moved, but the joint doesn't exist yet! this will lead to joint error. joint was: " + affectedJoint.ObjectNameInScene + " parms:" + affectedJoint.RawParams); + } + } + } + } + } + } + } + } + + //DumpJointInfo(); + + // Finished with all sim stepping. If requested, dump world state to file for debugging. + // TODO: This call to the export function is already inside lock (OdeLock) - but is an extra lock needed? + // TODO: This overwrites all dump files in-place. Should this be a growing logfile, or separate snapshots? + if (physics_logging && (physics_logging_interval>0) && (framecount % physics_logging_interval == 0)) + { + string fname = "state-" + world.ToString() + ".DIF"; // give each physics world a separate filename + string prefix = "world" + world.ToString(); // prefix for variable names in exported .DIF file + + if (physics_logging_append_existing_logfile) + { + string header = "-------------- START OF PHYSICS FRAME " + framecount.ToString() + " --------------"; + TextWriter fwriter = File.AppendText(fname); + fwriter.WriteLine(header); + fwriter.Close(); + } + d.WorldExportDIF(world, fname, physics_logging_append_existing_logfile, prefix); + } + latertickcount = Util.EnvironmentTickCount() - tickCountFrameRun; + + // OpenSimulator above does 10 fps. 10 fps = means that the main thread loop and physics + // has a max of 100 ms to run theoretically. + // If the main loop stalls, it calls Simulate later which makes the tick count ms larger. + // If Physics stalls, it takes longer which makes the tick count ms larger. + + if (latertickcount < 100) + m_timeDilation = 1.0f; + else + { + m_timeDilation = 100f / latertickcount; + //m_timeDilation = Math.Min((Math.Max(100 - (Util.EnvironmentTickCount() - tickCountFrameRun), 1) / 100f), 1.0f); + } + + tickCountFrameRun = Util.EnvironmentTickCount(); + } + + return fps; + } + + public override void GetResults() + { + } + + public override bool IsThreaded + { + // for now we won't be multithreaded + get { return (false); } + } + + #region ODE Specific Terrain Fixes + public float[] ResizeTerrain512NearestNeighbour(float[] heightMap) + { + float[] returnarr = new float[262144]; + float[,] resultarr = new float[(int)WorldExtents.X, (int)WorldExtents.Y]; + + // Filling out the array into its multi-dimensional components + for (int y = 0; y < WorldExtents.Y; y++) + { + for (int x = 0; x < WorldExtents.X; x++) + { + resultarr[y, x] = heightMap[y * (int)WorldExtents.Y + x]; + } + } + + // Resize using Nearest Neighbour + + // This particular way is quick but it only works on a multiple of the original + + // The idea behind this method can be described with the following diagrams + // second pass and third pass happen in the same loop really.. just separated + // them to show what this does. + + // First Pass + // ResultArr: + // 1,1,1,1,1,1 + // 1,1,1,1,1,1 + // 1,1,1,1,1,1 + // 1,1,1,1,1,1 + // 1,1,1,1,1,1 + // 1,1,1,1,1,1 + + // Second Pass + // ResultArr2: + // 1,,1,,1,,1,,1,,1, + // ,,,,,,,,,, + // 1,,1,,1,,1,,1,,1, + // ,,,,,,,,,, + // 1,,1,,1,,1,,1,,1, + // ,,,,,,,,,, + // 1,,1,,1,,1,,1,,1, + // ,,,,,,,,,, + // 1,,1,,1,,1,,1,,1, + // ,,,,,,,,,, + // 1,,1,,1,,1,,1,,1, + + // Third pass fills in the blanks + // ResultArr2: + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + + // X,Y = . + // X+1,y = ^ + // X,Y+1 = * + // X+1,Y+1 = # + + // Filling in like this; + // .* + // ^# + // 1st . + // 2nd * + // 3rd ^ + // 4th # + // on single loop. + + float[,] resultarr2 = new float[512, 512]; + for (int y = 0; y < WorldExtents.Y; y++) + { + for (int x = 0; x < WorldExtents.X; x++) + { + resultarr2[y * 2, x * 2] = resultarr[y, x]; + + if (y < WorldExtents.Y) + { + resultarr2[(y * 2) + 1, x * 2] = resultarr[y, x]; + } + if (x < WorldExtents.X) + { + resultarr2[y * 2, (x * 2) + 1] = resultarr[y, x]; + } + if (x < WorldExtents.X && y < WorldExtents.Y) + { + resultarr2[(y * 2) + 1, (x * 2) + 1] = resultarr[y, x]; + } + } + } + + //Flatten out the array + int i = 0; + for (int y = 0; y < 512; y++) + { + for (int x = 0; x < 512; x++) + { + if (resultarr2[y, x] <= 0) + returnarr[i] = 0.0000001f; + else + returnarr[i] = resultarr2[y, x]; + + i++; + } + } + + return returnarr; + } + + public float[] ResizeTerrain512Interpolation(float[] heightMap) + { + float[] returnarr = new float[262144]; + float[,] resultarr = new float[512,512]; + + // Filling out the array into its multi-dimensional components + for (int y = 0; y < 256; y++) + { + for (int x = 0; x < 256; x++) + { + resultarr[y, x] = heightMap[y * 256 + x]; + } + } + + // Resize using interpolation + + // This particular way is quick but it only works on a multiple of the original + + // The idea behind this method can be described with the following diagrams + // second pass and third pass happen in the same loop really.. just separated + // them to show what this does. + + // First Pass + // ResultArr: + // 1,1,1,1,1,1 + // 1,1,1,1,1,1 + // 1,1,1,1,1,1 + // 1,1,1,1,1,1 + // 1,1,1,1,1,1 + // 1,1,1,1,1,1 + + // Second Pass + // ResultArr2: + // 1,,1,,1,,1,,1,,1, + // ,,,,,,,,,, + // 1,,1,,1,,1,,1,,1, + // ,,,,,,,,,, + // 1,,1,,1,,1,,1,,1, + // ,,,,,,,,,, + // 1,,1,,1,,1,,1,,1, + // ,,,,,,,,,, + // 1,,1,,1,,1,,1,,1, + // ,,,,,,,,,, + // 1,,1,,1,,1,,1,,1, + + // Third pass fills in the blanks + // ResultArr2: + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + + // X,Y = . + // X+1,y = ^ + // X,Y+1 = * + // X+1,Y+1 = # + + // Filling in like this; + // .* + // ^# + // 1st . + // 2nd * + // 3rd ^ + // 4th # + // on single loop. + + float[,] resultarr2 = new float[512,512]; + for (int y = 0; y < (int)Constants.RegionSize; y++) + { + for (int x = 0; x < (int)Constants.RegionSize; x++) + { + resultarr2[y*2, x*2] = resultarr[y, x]; + + if (y < (int)Constants.RegionSize) + { + if (y + 1 < (int)Constants.RegionSize) + { + if (x + 1 < (int)Constants.RegionSize) + { + resultarr2[(y*2) + 1, x*2] = ((resultarr[y, x] + resultarr[y + 1, x] + + resultarr[y, x + 1] + resultarr[y + 1, x + 1])/4); + } + else + { + resultarr2[(y*2) + 1, x*2] = ((resultarr[y, x] + resultarr[y + 1, x])/2); + } + } + else + { + resultarr2[(y*2) + 1, x*2] = resultarr[y, x]; + } + } + if (x < (int)Constants.RegionSize) + { + if (x + 1 < (int)Constants.RegionSize) + { + if (y + 1 < (int)Constants.RegionSize) + { + resultarr2[y*2, (x*2) + 1] = ((resultarr[y, x] + resultarr[y + 1, x] + + resultarr[y, x + 1] + resultarr[y + 1, x + 1])/4); + } + else + { + resultarr2[y*2, (x*2) + 1] = ((resultarr[y, x] + resultarr[y, x + 1])/2); + } + } + else + { + resultarr2[y*2, (x*2) + 1] = resultarr[y, x]; + } + } + if (x < (int)Constants.RegionSize && y < (int)Constants.RegionSize) + { + if ((x + 1 < (int)Constants.RegionSize) && (y + 1 < (int)Constants.RegionSize)) + { + resultarr2[(y*2) + 1, (x*2) + 1] = ((resultarr[y, x] + resultarr[y + 1, x] + + resultarr[y, x + 1] + resultarr[y + 1, x + 1])/4); + } + else + { + resultarr2[(y*2) + 1, (x*2) + 1] = resultarr[y, x]; + } + } + } + } + //Flatten out the array + int i = 0; + for (int y = 0; y < 512; y++) + { + for (int x = 0; x < 512; x++) + { + if (Single.IsNaN(resultarr2[y, x]) || Single.IsInfinity(resultarr2[y, x])) + { + m_log.Warn("[PHYSICS]: Non finite heightfield element detected. Setting it to 0"); + resultarr2[y, x] = 0; + } + returnarr[i] = resultarr2[y, x]; + i++; + } + } + + return returnarr; + } + + #endregion + + public override void SetTerrain(float[] heightMap) + { + if (m_worldOffset != Vector3.Zero && m_parentScene != null) + { + if (m_parentScene is OdeScene) + { + ((OdeScene)m_parentScene).SetTerrain(heightMap, m_worldOffset); + } + } + else + { + SetTerrain(heightMap, m_worldOffset); + } + } + + public void SetTerrain(float[] heightMap, Vector3 pOffset) + { + // this._heightmap[i] = (double)heightMap[i]; + // dbm (danx0r) -- creating a buffer zone of one extra sample all around + //_origheightmap = heightMap; + + float[] _heightmap; + + // zero out a heightmap array float array (single dimension [flattened])) + //if ((int)Constants.RegionSize == 256) + // _heightmap = new float[514 * 514]; + //else + + _heightmap = new float[(((int)Constants.RegionSize + 2) * ((int)Constants.RegionSize + 2))]; + + uint heightmapWidth = Constants.RegionSize + 1; + uint heightmapHeight = Constants.RegionSize + 1; + + uint heightmapWidthSamples; + + uint heightmapHeightSamples; + + //if (((int)Constants.RegionSize) == 256) + //{ + // heightmapWidthSamples = 2 * (uint)Constants.RegionSize + 2; + // heightmapHeightSamples = 2 * (uint)Constants.RegionSize + 2; + // heightmapWidth++; + // heightmapHeight++; + //} + //else + //{ + + heightmapWidthSamples = (uint)Constants.RegionSize + 1; + heightmapHeightSamples = (uint)Constants.RegionSize + 1; + //} + + const float scale = 1.0f; + const float offset = 0.0f; + const float thickness = 0.2f; + const int wrap = 0; + + int regionsize = (int) Constants.RegionSize + 2; + //Double resolution + //if (((int)Constants.RegionSize) == 256) + // heightMap = ResizeTerrain512Interpolation(heightMap); + + + // if (((int)Constants.RegionSize) == 256 && (int)Constants.RegionSize == 256) + // regionsize = 512; + + float hfmin = 2000; + float hfmax = -2000; + + for (int x = 0; x < heightmapWidthSamples; x++) + { + for (int y = 0; y < heightmapHeightSamples; y++) + { + int xx = Util.Clip(x - 1, 0, regionsize - 1); + int yy = Util.Clip(y - 1, 0, regionsize - 1); + + + float val= heightMap[yy * (int)Constants.RegionSize + xx]; + _heightmap[x * ((int)Constants.RegionSize + 2) + y] = val; + + hfmin = (val < hfmin) ? val : hfmin; + hfmax = (val > hfmax) ? val : hfmax; + } + } + + + + + lock (OdeLock) + { + IntPtr GroundGeom = IntPtr.Zero; + if (RegionTerrain.TryGetValue(pOffset, out GroundGeom)) + { + RegionTerrain.Remove(pOffset); + if (GroundGeom != IntPtr.Zero) + { + if (TerrainHeightFieldHeights.ContainsKey(GroundGeom)) + { + TerrainHeightFieldHeights.Remove(GroundGeom); + } + d.SpaceRemove(space, GroundGeom); + d.GeomDestroy(GroundGeom); + } + + } + IntPtr HeightmapData = d.GeomHeightfieldDataCreate(); + d.GeomHeightfieldDataBuildSingle(HeightmapData, _heightmap, 0, heightmapWidth + 1, heightmapHeight + 1, + (int)heightmapWidthSamples + 1, (int)heightmapHeightSamples + 1, scale, + offset, thickness, wrap); + d.GeomHeightfieldDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1); + GroundGeom = d.CreateHeightfield(space, HeightmapData, 1); + if (GroundGeom != IntPtr.Zero) + { + d.GeomSetCategoryBits(GroundGeom, (int)(CollisionCategories.Land)); + d.GeomSetCollideBits(GroundGeom, (int)(CollisionCategories.Space)); + + } + geom_name_map[GroundGeom] = "Terrain"; + + d.Matrix3 R = new d.Matrix3(); + + Quaternion q1 = Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), 1.5707f); + Quaternion q2 = Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), 1.5707f); + //Axiom.Math.Quaternion q3 = Axiom.Math.Quaternion.FromAngleAxis(3.14f, new Axiom.Math.Vector3(0, 0, 1)); + + q1 = q1 * q2; + //q1 = q1 * q3; + Vector3 v3; + float angle; + q1.GetAxisAngle(out v3, out angle); + + d.RFromAxisAndAngle(out R, v3.X, v3.Y, v3.Z, angle); + d.GeomSetRotation(GroundGeom, ref R); + d.GeomSetPosition(GroundGeom, (pOffset.X + ((int)Constants.RegionSize * 0.5f)) - 1, (pOffset.Y + ((int)Constants.RegionSize * 0.5f)) - 1, 0); + IntPtr testGround = IntPtr.Zero; + if (RegionTerrain.TryGetValue(pOffset, out testGround)) + { + RegionTerrain.Remove(pOffset); + } + RegionTerrain.Add(pOffset, GroundGeom, GroundGeom); + TerrainHeightFieldHeights.Add(GroundGeom,_heightmap); + + } + } + + public override void DeleteTerrain() + { + } + + public float GetWaterLevel() + { + return waterlevel; + } + + public override bool SupportsCombining() + { + return true; + } + + public override void UnCombine(PhysicsScene pScene) + { + IntPtr localGround = IntPtr.Zero; +// float[] localHeightfield; + bool proceed = false; + List geomDestroyList = new List(); + + lock (OdeLock) + { + if (RegionTerrain.TryGetValue(Vector3.Zero, out localGround)) + { + foreach (IntPtr geom in TerrainHeightFieldHeights.Keys) + { + if (geom == localGround) + { +// localHeightfield = TerrainHeightFieldHeights[geom]; + proceed = true; + } + else + { + geomDestroyList.Add(geom); + } + } + + if (proceed) + { + m_worldOffset = Vector3.Zero; + WorldExtents = new Vector2((int)Constants.RegionSize, (int)Constants.RegionSize); + m_parentScene = null; + + foreach (IntPtr g in geomDestroyList) + { + // removingHeightField needs to be done or the garbage collector will + // collect the terrain data before we tell ODE to destroy it causing + // memory corruption + if (TerrainHeightFieldHeights.ContainsKey(g)) + { +// float[] removingHeightField = TerrainHeightFieldHeights[g]; + TerrainHeightFieldHeights.Remove(g); + + if (RegionTerrain.ContainsKey(g)) + { + RegionTerrain.Remove(g); + } + + d.GeomDestroy(g); + //removingHeightField = new float[0]; + } + } + + } + else + { + m_log.Warn("[PHYSICS]: Couldn't proceed with UnCombine. Region has inconsistant data."); + + } + } + } + } + + public override void SetWaterLevel(float baseheight) + { + waterlevel = baseheight; + randomizeWater(waterlevel); + } + + public void randomizeWater(float baseheight) + { + const uint heightmapWidth = m_regionWidth + 2; + const uint heightmapHeight = m_regionHeight + 2; + const uint heightmapWidthSamples = m_regionWidth + 2; + const uint heightmapHeightSamples = m_regionHeight + 2; + const float scale = 1.0f; + const float offset = 0.0f; + const float thickness = 2.9f; + const int wrap = 0; + + for (int i = 0; i < (258 * 258); i++) + { + _watermap[i] = (baseheight-0.1f) + ((float)fluidRandomizer.Next(1,9) / 10f); + // m_log.Info((baseheight - 0.1f) + ((float)fluidRandomizer.Next(1, 9) / 10f)); + } + + lock (OdeLock) + { + if (WaterGeom != IntPtr.Zero) + { + d.SpaceRemove(space, WaterGeom); + } + IntPtr HeightmapData = d.GeomHeightfieldDataCreate(); + d.GeomHeightfieldDataBuildSingle(HeightmapData, _watermap, 0, heightmapWidth, heightmapHeight, + (int)heightmapWidthSamples, (int)heightmapHeightSamples, scale, + offset, thickness, wrap); + d.GeomHeightfieldDataSetBounds(HeightmapData, m_regionWidth, m_regionHeight); + WaterGeom = d.CreateHeightfield(space, HeightmapData, 1); + if (WaterGeom != IntPtr.Zero) + { + d.GeomSetCategoryBits(WaterGeom, (int)(CollisionCategories.Water)); + d.GeomSetCollideBits(WaterGeom, (int)(CollisionCategories.Space)); + + } + geom_name_map[WaterGeom] = "Water"; + + d.Matrix3 R = new d.Matrix3(); + + Quaternion q1 = Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), 1.5707f); + Quaternion q2 = Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), 1.5707f); + //Axiom.Math.Quaternion q3 = Axiom.Math.Quaternion.FromAngleAxis(3.14f, new Axiom.Math.Vector3(0, 0, 1)); + + q1 = q1 * q2; + //q1 = q1 * q3; + Vector3 v3; + float angle; + q1.GetAxisAngle(out v3, out angle); + + d.RFromAxisAndAngle(out R, v3.X, v3.Y, v3.Z, angle); + d.GeomSetRotation(WaterGeom, ref R); + d.GeomSetPosition(WaterGeom, 128, 128, 0); + + } + + } + + public override void Dispose() + { + m_rayCastManager.Dispose(); + m_rayCastManager = null; + + lock (OdeLock) + { + lock (_prims) + { + foreach (OdePrim prm in _prims) + { + RemovePrim(prm); + } + } + + //foreach (OdeCharacter act in _characters) + //{ + //RemoveAvatar(act); + //} + d.WorldDestroy(world); + //d.CloseODE(); + } + } + public override Dictionary GetTopColliders() + { + Dictionary returncolliders = new Dictionary(); + int cnt = 0; + lock (_prims) + { + foreach (OdePrim prm in _prims) + { + if (prm.CollisionScore > 0) + { + returncolliders.Add(prm.m_localID, prm.CollisionScore); + cnt++; + prm.CollisionScore = 0f; + if (cnt > 25) + { + break; + } + } + } + } + return returncolliders; + } + + public override bool SupportsRayCast() + { + return true; + } + + public override void RaycastWorld(Vector3 position, Vector3 direction, float length, RaycastCallback retMethod) + { + if (retMethod != null) + { + m_rayCastManager.QueueRequest(position, direction, length, retMethod); + } + } + +#if USE_DRAWSTUFF + // Keyboard callback + public void command(int cmd) + { + IntPtr geom; + d.Mass mass; + d.Vector3 sides = new d.Vector3(d.RandReal() * 0.5f + 0.1f, d.RandReal() * 0.5f + 0.1f, d.RandReal() * 0.5f + 0.1f); + + + + Char ch = Char.ToLower((Char)cmd); + switch ((Char)ch) + { + case 'w': + try + { + Vector3 rotate = (new Vector3(1, 0, 0) * Quaternion.CreateFromEulers(hpr.Z * Utils.DEG_TO_RAD, hpr.Y * Utils.DEG_TO_RAD, hpr.X * Utils.DEG_TO_RAD)); + + xyz.X += rotate.X; xyz.Y += rotate.Y; xyz.Z += rotate.Z; + ds.SetViewpoint(ref xyz, ref hpr); + } + catch (ArgumentException) + { hpr.X = 0; } + break; + + case 'a': + hpr.X++; + ds.SetViewpoint(ref xyz, ref hpr); + break; + + case 's': + try + { + Vector3 rotate2 = (new Vector3(-1, 0, 0) * Quaternion.CreateFromEulers(hpr.Z * Utils.DEG_TO_RAD, hpr.Y * Utils.DEG_TO_RAD, hpr.X * Utils.DEG_TO_RAD)); + + xyz.X += rotate2.X; xyz.Y += rotate2.Y; xyz.Z += rotate2.Z; + ds.SetViewpoint(ref xyz, ref hpr); + } + catch (ArgumentException) + { hpr.X = 0; } + break; + case 'd': + hpr.X--; + ds.SetViewpoint(ref xyz, ref hpr); + break; + case 'r': + xyz.Z++; + ds.SetViewpoint(ref xyz, ref hpr); + break; + case 'f': + xyz.Z--; + ds.SetViewpoint(ref xyz, ref hpr); + break; + case 'e': + xyz.Y++; + ds.SetViewpoint(ref xyz, ref hpr); + break; + case 'q': + xyz.Y--; + ds.SetViewpoint(ref xyz, ref hpr); + break; + } + } + + public void step(int pause) + { + + ds.SetColor(1.0f, 1.0f, 0.0f); + ds.SetTexture(ds.Texture.Wood); + lock (_prims) + { + foreach (OdePrim prm in _prims) + { + //IntPtr body = d.GeomGetBody(prm.prim_geom); + if (prm.prim_geom != IntPtr.Zero) + { + d.Vector3 pos; + d.GeomCopyPosition(prm.prim_geom, out pos); + //d.BodyCopyPosition(body, out pos); + + d.Matrix3 R; + d.GeomCopyRotation(prm.prim_geom, out R); + //d.BodyCopyRotation(body, out R); + + + d.Vector3 sides = new d.Vector3(); + sides.X = prm.Size.X; + sides.Y = prm.Size.Y; + sides.Z = prm.Size.Z; + + ds.DrawBox(ref pos, ref R, ref sides); + } + } + } + ds.SetColor(1.0f, 0.0f, 0.0f); + lock (_characters) + { + foreach (OdeCharacter chr in _characters) + { + if (chr.Shell != IntPtr.Zero) + { + IntPtr body = d.GeomGetBody(chr.Shell); + + d.Vector3 pos; + d.GeomCopyPosition(chr.Shell, out pos); + //d.BodyCopyPosition(body, out pos); + + d.Matrix3 R; + d.GeomCopyRotation(chr.Shell, out R); + //d.BodyCopyRotation(body, out R); + + ds.DrawCapsule(ref pos, ref R, chr.Size.Z, 0.35f); + d.Vector3 sides = new d.Vector3(); + sides.X = 0.5f; + sides.Y = 0.5f; + sides.Z = 0.5f; + + ds.DrawBox(ref pos, ref R, ref sides); + } + } + } + } + + public void start(int unused) + { + ds.SetViewpoint(ref xyz, ref hpr); + } +#endif + } +} \ No newline at end of file -- cgit v1.1 From 29034bc0e0a8c24d7f2b8de8544d593ed5ac663f Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 8 Jul 2011 18:34:44 +0100 Subject: minor: code tidy up - remove a couple of Console.WriteLine() accidentally added in the last commit --- OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | 62 +++++++--------------------- OpenSim/Region/Physics/OdePlugin/OdeScene.cs | 14 ++++--- 2 files changed, 23 insertions(+), 53 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index 1060278..bc839e0 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs @@ -54,7 +54,6 @@ namespace OpenSim.Region.Physics.OdePlugin /// /// Various properties that ODE uses for AMotors but isn't exposed in ODE.NET so we must define them ourselves. /// - public class OdePrim : PhysicsActor { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -279,14 +278,14 @@ namespace OpenSim.Region.Physics.OdePlugin public override bool Selected { - set { - - + set + { // This only makes the object not collidable if the object // is physical or the object is modified somehow *IN THE FUTURE* // without this, if an avatar selects prim, they can walk right // through it while it's selected m_collisionscore = 0; + if ((m_isphysical && !_zeroFlag) || !value) { m_taintselected = value; @@ -297,7 +296,9 @@ namespace OpenSim.Region.Physics.OdePlugin m_taintselected = value; m_isSelected = value; } - if (m_isSelected) disableBodySoft(); + + if (m_isSelected) + disableBodySoft(); } } @@ -324,8 +325,6 @@ namespace OpenSim.Region.Physics.OdePlugin //m_log.Warn("Setting Geom to: " + prim_geom); } - - public void enableBodySoft() { if (!childPrim) @@ -626,8 +625,6 @@ namespace OpenSim.Region.Physics.OdePlugin break; } - - float taperX1; float taperY1; float taperX; @@ -682,9 +679,6 @@ namespace OpenSim.Region.Physics.OdePlugin // else if (returnMass > _parent_scene.maximumMassObject) // returnMass = _parent_scene.maximumMassObject; - - - // Recursively calculate mass bool HasChildPrim = false; lock (childrenPrim) @@ -693,8 +687,8 @@ namespace OpenSim.Region.Physics.OdePlugin { HasChildPrim = true; } - } + if (HasChildPrim) { OdePrim[] childPrimArr = new OdePrim[0]; @@ -711,10 +705,12 @@ namespace OpenSim.Region.Physics.OdePlugin break; } } + if (returnMass > _parent_scene.maximumMassObject) returnMass = _parent_scene.maximumMassObject; + return returnMass; - }// end CalculateMass + } #endregion @@ -937,7 +933,6 @@ namespace OpenSim.Region.Physics.OdePlugin } } - private void changeAngularLock(float timestep) { // do we have a Physical object? @@ -965,7 +960,6 @@ namespace OpenSim.Region.Physics.OdePlugin } // Store this for later in case we get turned into a separate body m_angularlock = m_taintAngularLock; - } private void changelink(float timestep) @@ -1104,7 +1098,6 @@ namespace OpenSim.Region.Physics.OdePlugin m_log.DebugFormat("[PHYSICS]: {0} ain't got no boooooooooddy, no body", Name); } - prm.m_interpenetrationcount = 0; prm.m_collisionscore = 0; prm.m_disabled = false; @@ -1164,7 +1157,6 @@ namespace OpenSim.Region.Physics.OdePlugin } } } - } private void ChildSetGeom(OdePrim odePrim) @@ -1225,17 +1217,12 @@ namespace OpenSim.Region.Physics.OdePlugin //Console.WriteLine("childrenPrim.Remove " + odePrim); childrenPrim.Remove(odePrim); } - - - if (Body != IntPtr.Zero) { _parent_scene.remActivePrim(this); } - - lock (childrenPrim) { foreach (OdePrim prm in childrenPrim) @@ -1244,8 +1231,6 @@ namespace OpenSim.Region.Physics.OdePlugin ParentPrim(prm); } } - - } private void changeSelectedStatus(float timestep) @@ -1685,13 +1670,11 @@ Console.WriteLine(" JointCreateFixed"); { PID_G = m_PIDTau + 1; } - // Where are we, and where are we headed? d.Vector3 pos = d.BodyGetPosition(Body); d.Vector3 vel = d.BodyGetLinearVel(Body); - // Non-Vehicles have a limited set of Hover options. // determine what our target height really is based on HoverType switch (m_PIDHoverType) @@ -1797,8 +1780,6 @@ Console.WriteLine(" JointCreateFixed"); } } - - public void rotate(float timestep) { d.Quaternion myrot = new d.Quaternion(); @@ -1909,7 +1890,6 @@ Console.WriteLine(" JointCreateFixed"); public void changesize(float timestamp) { - string oldname = _parent_scene.geom_name_map[prim_geom]; if (_size.X <= 0) _size.X = 0.01f; @@ -1961,15 +1941,13 @@ Console.WriteLine(" JointCreateFixed"); mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); //IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); -Console.WriteLine("changesize 1"); +//Console.WriteLine("changesize 1"); CreateGeom(m_targetSpace, mesh); - - } else { _mesh = null; -Console.WriteLine("changesize 2"); +//Console.WriteLine("changesize 2"); CreateGeom(m_targetSpace, _mesh); } @@ -2005,8 +1983,6 @@ Console.WriteLine("changesize 2"); m_taintsize = _size; } - - public void changefloatonwater(float timestep) { m_collidesWater = m_taintCollidesWater; @@ -2071,13 +2047,13 @@ Console.WriteLine("changesize 2"); IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); // createmesh returns null when it doesn't mesh. -Console.WriteLine("changeshape needed meshing"); +//Console.WriteLine("changeshape needed meshing"); CreateGeom(m_targetSpace, mesh); } else { _mesh = null; -Console.WriteLine("changeshape not need meshing"); +//Console.WriteLine("changeshape not need meshing"); CreateGeom(m_targetSpace, null); } @@ -2162,11 +2138,8 @@ Console.WriteLine("changeshape not need meshing"); } m_taintforce = false; - } - - public void changeSetTorque(float timestamp) { if (!m_isSelected) @@ -2835,7 +2808,6 @@ Console.WriteLine("changeshape not need meshing"); public override float APIDDamping{ set { return; } } - private void createAMotor(Vector3 axis) { if (Body == IntPtr.Zero) @@ -2955,7 +2927,6 @@ Console.WriteLine("changeshape not need meshing"); //d.JointSetAMotorParam(Amotor, (int) dParam.Vel, 9000f); d.JointSetAMotorParam(Amotor, (int)dParam.FudgeFactor, 0f); d.JointSetAMotorParam(Amotor, (int)dParam.FMax, Mass * 50f);// - } public Matrix4 FromDMass(d.Mass pMass) @@ -3040,8 +3011,6 @@ Console.WriteLine("changeshape not need meshing"); return Matrix4.Identity; // should probably throw an error. singluar matrix inverse not possible } - - return (Adjoint(pMat) / determinant3x3(pMat)); } @@ -3078,6 +3047,7 @@ Console.WriteLine("changeshape not need meshing"); } m++; } + return minor; } @@ -3180,7 +3150,6 @@ Console.WriteLine("changeshape not need meshing"); det = diag1 + diag2 + diag3 - (diag4 + diag5 + diag6); return det; - } private static void DMassCopy(ref d.Mass src, ref d.Mass dst) @@ -3205,6 +3174,5 @@ Console.WriteLine("changeshape not need meshing"); { m_material = pMaterial; } - } } diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs index 234af00..b09e69e 100644 --- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs +++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs @@ -26,6 +26,7 @@ */ //#define USE_DRAWSTUFF +//#define DEBUG using System; using System.Collections.Generic; @@ -1716,7 +1717,9 @@ namespace OpenSim.Region.Physics.OdePlugin public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, Vector3 size, Quaternion rotation, bool isPhysical) { -// m_log.DebugFormat("[PHYSICS]: Adding physics actor to {0}", primName); +#if SPAM + m_log.DebugFormat("[PHYSICS]: Adding physics actor to {0}", primName); +#endif PhysicsActor result; IMesh mesh = null; @@ -2460,7 +2463,7 @@ namespace OpenSim.Region.Physics.OdePlugin if (pbs.SculptEntry && !meshSculptedPrim) { -#if SPAM +#if DEBUG m_log.Warn("NonMesh"); #endif return false; @@ -2482,7 +2485,7 @@ namespace OpenSim.Region.Physics.OdePlugin && pbs.PathScaleX == 100 && pbs.PathScaleY == 100 && pbs.PathShearX == 0 && pbs.PathShearY == 0) { -#if SPAM +#if DEBUG m_log.Warn("NonMesh"); #endif return false; @@ -2563,12 +2566,12 @@ namespace OpenSim.Region.Physics.OdePlugin if (iPropertiesNotSupportedDefault == 0) { -#if SPAM +#if DEBUG m_log.Warn("NonMesh"); #endif return false; } -#if SPAM +#if DEBUG m_log.Debug("Mesh"); #endif return true; @@ -3606,7 +3609,6 @@ namespace OpenSim.Region.Physics.OdePlugin else { m_log.Warn("[PHYSICS]: Couldn't proceed with UnCombine. Region has inconsistant data."); - } } } -- cgit v1.1 From b18ef976ff0e8bf2bc2fd8d8002007fcaafd0ed7 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 8 Jul 2011 19:43:22 +0100 Subject: Fix interpretation of physics mesh proxies from mesh data As per http://wiki.secondlife.com/wiki/Mesh/Mesh_Asset_Format, some submesh blocks may just have the flag "NoGeometry" to signal that they provide no mesh data. If a block contains this, ignore it for meshing purposes rather than suffer a ClassCastException This fixes physics proxy meshing, so you can now walk through mesh doorways, properly stand on the trailer of mesh trucks, etc. To get mesh physics proxy, the UseMeshiesPhysicsMesh must be true in a [Mesh] config section in OpenSim.ini (example in OpenSimDefaults.ini). Convex hull physics not currently supported. --- OpenSim/Framework/Util.cs | 19 +++++++++++++++++-- OpenSim/Region/Physics/Meshing/Meshmerizer.cs | 10 ++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index e5ff27a..039b926 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs @@ -324,10 +324,25 @@ namespace OpenSim.Framework } /// + /// Debug utility function to convert OSD into formatted XML for debugging purposes. + /// + /// + /// A + /// + /// + /// A + /// + public static string GetFormattedXml(OSD osd) + { + return GetFormattedXml(OSDParser.SerializeLLSDXmlString(osd)); + } + + /// /// Debug utility function to convert unbroken strings of XML into something human readable for occasional debugging purposes. - /// - /// Please don't delete me even if I appear currently unused! /// + /// + /// Please don't delete me even if I appear currently unused! + /// /// /// public static string GetFormattedXml(string rawXml) diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index be4ee41..38b9112 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs @@ -366,6 +366,8 @@ namespace OpenSim.Region.Physics.Meshing // physics_shape is an array of OSDMaps, one for each submesh if (decodedMeshOsd is OSDArray) { +// Console.WriteLine("decodedMeshOsd for {0} - {1}", primName, Util.GetFormattedXml(decodedMeshOsd)); + decodedMeshOsdArray = (OSDArray)decodedMeshOsd; foreach (OSD subMeshOsd in decodedMeshOsdArray) { @@ -373,6 +375,14 @@ namespace OpenSim.Region.Physics.Meshing { OSDMap subMeshMap = (OSDMap)subMeshOsd; +// Console.WriteLine("subMeshMap for {0} - {1}", primName, Util.GetFormattedXml((OSD)subMeshMap)); + + // As per http://wiki.secondlife.com/wiki/Mesh/Mesh_Asset_Format, some Mesh Level + // of Detail Blocks (maps) contain just a NoGeometry key to signal there is no + // geometry for this submesh. + if (subMeshMap.ContainsKey("NoGeometry") && ((OSDBoolean)subMeshMap["NoGeometry"])) + continue; + OpenMetaverse.Vector3 posMax = ((OSDMap)subMeshMap["PositionDomain"])["Max"].AsVector3(); OpenMetaverse.Vector3 posMin = ((OSDMap)subMeshMap["PositionDomain"])["Min"].AsVector3(); ushort faceIndexOffset = (ushort)coords.Count; -- cgit v1.1 From 40300c886cb84715bf1a81d90c4144dc44bbe8f7 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 8 Jul 2011 20:36:01 +0100 Subject: refactor: Factor out AddSubMesh() method from long CraeteMeshFromPrimMesher() method Also remove some of the logging spam left in from the last commit. --- OpenSim/Region/Physics/Meshing/Meshmerizer.cs | 97 +++++++++++++++------------ OpenSim/Region/Physics/OdePlugin/OdeScene.cs | 10 +-- 2 files changed, 58 insertions(+), 49 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index 38b9112..ad03cc8 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs @@ -100,7 +100,6 @@ namespace OpenSim.Region.Physics.Meshing { m_log.WarnFormat("[SCULPT]: Unable to create {0} directory: ", decodedSculptMapPath, e.Message); } - } /// @@ -156,7 +155,6 @@ namespace OpenSim.Region.Physics.Meshing return box; } - /// /// Creates a simple bounding box mesh for a complex input mesh /// @@ -193,7 +191,6 @@ namespace OpenSim.Region.Physics.Meshing m_log.Error(message); m_log.Error("\nPrim Name: " + primName); m_log.Error("****** PrimMesh Parameters ******\n" + primMesh.ParamsToDisplayString()); - } private ulong GetMeshKey(PrimitiveBaseShape pbs, Vector3 size, float lod) @@ -257,6 +254,54 @@ namespace OpenSim.Region.Physics.Meshing return ((hash << 5) + hash) + (ulong)(c >> 8); } + /// + /// Add a submesh to an existing list of coords and faces. + /// + /// + /// Size of entire object + /// + /// + private void AddSubMesh(OSDMap subMeshData, Vector3 size, List coords, List faces) + { + // Console.WriteLine("subMeshMap for {0} - {1}", primName, Util.GetFormattedXml((OSD)subMeshMap)); + + // As per http://wiki.secondlife.com/wiki/Mesh/Mesh_Asset_Format, some Mesh Level + // of Detail Blocks (maps) contain just a NoGeometry key to signal there is no + // geometry for this submesh. + if (subMeshData.ContainsKey("NoGeometry") && ((OSDBoolean)subMeshData["NoGeometry"])) + return; + + OpenMetaverse.Vector3 posMax = ((OSDMap)subMeshData["PositionDomain"])["Max"].AsVector3(); + OpenMetaverse.Vector3 posMin = ((OSDMap)subMeshData["PositionDomain"])["Min"].AsVector3(); + ushort faceIndexOffset = (ushort)coords.Count; + + byte[] posBytes = subMeshData["Position"].AsBinary(); + for (int i = 0; i < posBytes.Length; i += 6) + { + ushort uX = Utils.BytesToUInt16(posBytes, i); + ushort uY = Utils.BytesToUInt16(posBytes, i + 2); + ushort uZ = Utils.BytesToUInt16(posBytes, i + 4); + + Coord c = new Coord( + Utils.UInt16ToFloat(uX, posMin.X, posMax.X) * size.X, + Utils.UInt16ToFloat(uY, posMin.Y, posMax.Y) * size.Y, + Utils.UInt16ToFloat(uZ, posMin.Z, posMax.Z) * size.Z); + + coords.Add(c); + } + + byte[] triangleBytes = subMeshData["TriangleList"].AsBinary(); + for (int i = 0; i < triangleBytes.Length; i += 6) + { + ushort v1 = (ushort)(Utils.BytesToUInt16(triangleBytes, i) + faceIndexOffset); + ushort v2 = (ushort)(Utils.BytesToUInt16(triangleBytes, i + 2) + faceIndexOffset); + ushort v3 = (ushort)(Utils.BytesToUInt16(triangleBytes, i + 4) + faceIndexOffset); + Face f = new Face(v1, v2, v3); + faces.Add(f); + } + + return; + } private Mesh CreateMeshFromPrimMesher(string primName, PrimitiveBaseShape primShape, Vector3 size, float lod) { @@ -304,6 +349,7 @@ namespace OpenSim.Region.Physics.Meshing { m_log.Error("[MESH]: Exception deserializing mesh asset header:" + e.ToString()); } + start = data.Position; } @@ -315,9 +361,10 @@ namespace OpenSim.Region.Physics.Meshing physicsParms = (OSDMap)map["physics_shape"]; // old asset format else if (map.ContainsKey("physics_mesh")) physicsParms = (OSDMap)map["physics_mesh"]; // new asset format + if (physicsParms == null) { - m_log.Warn("[Mesh]: no recognized physics mesh found in mesh asset"); + m_log.Warn("[MESH]: no recognized physics mesh found in mesh asset"); return null; } @@ -372,46 +419,7 @@ namespace OpenSim.Region.Physics.Meshing foreach (OSD subMeshOsd in decodedMeshOsdArray) { if (subMeshOsd is OSDMap) - { - OSDMap subMeshMap = (OSDMap)subMeshOsd; - -// Console.WriteLine("subMeshMap for {0} - {1}", primName, Util.GetFormattedXml((OSD)subMeshMap)); - - // As per http://wiki.secondlife.com/wiki/Mesh/Mesh_Asset_Format, some Mesh Level - // of Detail Blocks (maps) contain just a NoGeometry key to signal there is no - // geometry for this submesh. - if (subMeshMap.ContainsKey("NoGeometry") && ((OSDBoolean)subMeshMap["NoGeometry"])) - continue; - - OpenMetaverse.Vector3 posMax = ((OSDMap)subMeshMap["PositionDomain"])["Max"].AsVector3(); - OpenMetaverse.Vector3 posMin = ((OSDMap)subMeshMap["PositionDomain"])["Min"].AsVector3(); - ushort faceIndexOffset = (ushort)coords.Count; - - byte[] posBytes = subMeshMap["Position"].AsBinary(); - for (int i = 0; i < posBytes.Length; i += 6) - { - ushort uX = Utils.BytesToUInt16(posBytes, i); - ushort uY = Utils.BytesToUInt16(posBytes, i + 2); - ushort uZ = Utils.BytesToUInt16(posBytes, i + 4); - - Coord c = new Coord( - Utils.UInt16ToFloat(uX, posMin.X, posMax.X) * size.X, - Utils.UInt16ToFloat(uY, posMin.Y, posMax.Y) * size.Y, - Utils.UInt16ToFloat(uZ, posMin.Z, posMax.Z) * size.Z); - - coords.Add(c); - } - - byte[] triangleBytes = subMeshMap["TriangleList"].AsBinary(); - for (int i = 0; i < triangleBytes.Length; i += 6) - { - ushort v1 = (ushort)(Utils.BytesToUInt16(triangleBytes, i) + faceIndexOffset); - ushort v2 = (ushort)(Utils.BytesToUInt16(triangleBytes, i + 2) + faceIndexOffset); - ushort v3 = (ushort)(Utils.BytesToUInt16(triangleBytes, i + 4) + faceIndexOffset); - Face f = new Face(v1, v2, v3); - faces.Add(f); - } - } + AddSubMesh(subMeshOsd as OSDMap, size, coords, faces); } } } @@ -643,6 +651,7 @@ namespace OpenSim.Region.Physics.Meshing Face f = faces[i]; mesh.Add(new Triangle(vertices[f.v1], vertices[f.v2], vertices[f.v3])); } + return mesh; } diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs index b09e69e..87d22af 100644 --- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs +++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs @@ -26,7 +26,7 @@ */ //#define USE_DRAWSTUFF -//#define DEBUG +//#define SPAM using System; using System.Collections.Generic; @@ -2463,7 +2463,7 @@ namespace OpenSim.Region.Physics.OdePlugin if (pbs.SculptEntry && !meshSculptedPrim) { -#if DEBUG +#if SPAM m_log.Warn("NonMesh"); #endif return false; @@ -2485,7 +2485,7 @@ namespace OpenSim.Region.Physics.OdePlugin && pbs.PathScaleX == 100 && pbs.PathScaleY == 100 && pbs.PathShearX == 0 && pbs.PathShearY == 0) { -#if DEBUG +#if SPAM m_log.Warn("NonMesh"); #endif return false; @@ -2566,12 +2566,12 @@ namespace OpenSim.Region.Physics.OdePlugin if (iPropertiesNotSupportedDefault == 0) { -#if DEBUG +#if SPAM m_log.Warn("NonMesh"); #endif return false; } -#if DEBUG +#if SPAM m_log.Debug("Mesh"); #endif return true; -- cgit v1.1 From e8ad8593b65e0d82d9ddf1ff4ea3536489856d72 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 8 Jul 2011 20:58:44 +0100 Subject: refactor: eliminate redundant return statement --- OpenSim/Region/Physics/Meshing/Meshmerizer.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index ad03cc8..e92e97b 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs @@ -299,8 +299,6 @@ namespace OpenSim.Region.Physics.Meshing Face f = new Face(v1, v2, v3); faces.Add(f); } - - return; } private Mesh CreateMeshFromPrimMesher(string primName, PrimitiveBaseShape primShape, Vector3 size, float lod) @@ -361,7 +359,7 @@ namespace OpenSim.Region.Physics.Meshing physicsParms = (OSDMap)map["physics_shape"]; // old asset format else if (map.ContainsKey("physics_mesh")) physicsParms = (OSDMap)map["physics_mesh"]; // new asset format - + if (physicsParms == null) { m_log.Warn("[MESH]: no recognized physics mesh found in mesh asset"); -- cgit v1.1 From 5700c582ba3727678dfd87f80dab8d09da88df63 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 8 Jul 2011 22:28:17 +0100 Subject: refactor: rename bool returning GetAgentInventoryItem() to CanGetAgentInventoryItem() to improve code readability --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 7 +++---- .../Framework/InventoryAccess/InventoryAccessModule.cs | 2 +- OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs | 10 +++++++++- 3 files changed, 13 insertions(+), 6 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index f53e236..c176c2b 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -7548,13 +7548,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP IInventoryAccessModule invAccess = m_scene.RequestModuleInterface(); if (invAccess != null) { - if (!invAccess.GetAgentInventoryItem(this, itemID, requestID)) + if (!invAccess.CanGetAgentInventoryItem(this, itemID, requestID)) return false; - } else + { return false; - + } } } } @@ -7568,7 +7568,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP { AssetUploadRequestPacket request = (AssetUploadRequestPacket)Pack; - // m_log.Debug("upload request " + request.ToString()); // m_log.Debug("upload request was for assetid: " + request.AssetBlock.TransactionID.Combine(this.SecureSessionId).ToString()); UUID temp = UUID.Combine(request.AssetBlock.TransactionID, SecureSessionId); diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 2930303..f7d187d 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -978,7 +978,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess { } - public virtual bool GetAgentInventoryItem(IClientAPI remoteClient, UUID itemID, UUID requestID) + public virtual bool CanGetAgentInventoryItem(IClientAPI remoteClient, UUID itemID, UUID requestID) { InventoryItemBase assetRequestItem = GetItem(remoteClient.AgentId, itemID); if (assetRequestItem == null) diff --git a/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs b/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs index 305975e..da11e61 100644 --- a/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs @@ -59,7 +59,15 @@ namespace OpenSim.Region.Framework.Interfaces UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment); void TransferInventoryAssets(InventoryItemBase item, UUID sender, UUID receiver); - bool GetAgentInventoryItem(IClientAPI remoteClient, UUID itemID, UUID requestID); + + /// + /// Does the client have sufficient permissions to retrieve the inventory item? + /// + /// + /// + /// + /// + bool CanGetAgentInventoryItem(IClientAPI remoteClient, UUID itemID, UUID requestID); // Must be here because of textures in user's inventory bool IsForeignUser(UUID userID, out string assetServerURL); -- cgit v1.1 From 192bd1057e95e504955bebb4cd42a74b9101b6fa Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 8 Jul 2011 22:32:19 +0100 Subject: fix bug where opening a library script would fail --- .../CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index f7d187d..66fbcb9 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -1057,7 +1057,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess InventoryItemBase item = new InventoryItemBase(itemID, agentID); item = invService.GetItem(item); - if (item.CreatorData != null && item.CreatorData != string.Empty) + if (item != null && item.CreatorData != null && item.CreatorData != string.Empty) UserManagementModule.AddUser(item.CreatorIdAsUuid, item.CreatorData); return item; @@ -1065,4 +1065,4 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess #endregion } -} +} \ No newline at end of file -- cgit v1.1 From a048ec3f95ce261bad263bfc181d990498856d9b Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 8 Jul 2011 22:34:03 +0100 Subject: stop the local inventory services connector from logging an error when an item id isn't found. making this query is legitimate and so the log line can cause false positivies. It is up to callers to log an error if appropriate. --- .../Inventory/LocalInventoryServiceConnector.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs index 6dd871f..0c57618 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs @@ -284,9 +284,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory item = m_InventoryService.GetItem(item); - if (null == item) - m_log.ErrorFormat( - "[LOCAL INVENTORY SERVICES CONNECTOR]: Could not find item with id {0}", requestedItemId); +// if (null == item) +// m_log.ErrorFormat( +// "[LOCAL INVENTORY SERVICES CONNECTOR]: Could not find item with id {0}", requestedItemId); return item; } -- cgit v1.1 From c3d82bdcb1ac2ee0e0bdad75fbf8779252ef31c4 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 8 Jul 2011 22:53:19 +0100 Subject: When loading library asset set, only store an asset if it's different from an existing one with the same id. We compare existing and loaded asset by doing an SHA1 on both, so that a changed library asset will still update the store. This cuts asset library load time from 10 seconds to <1 sec. Note, a fix on the previous commit revealed a bug where a library script cannot be copied except on the first login after a cache clear. This is unrelated to this commit and needs to be fixed at some subsequent time. --- OpenSim/Framework/Util.cs | 16 +++++++++++++--- OpenSim/Services/AssetService/AssetService.cs | 15 ++++++++++++--- 2 files changed, 25 insertions(+), 6 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index 039b926..fce8999 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs @@ -440,20 +440,30 @@ namespace OpenSim.Framework } /// - /// Return an SHA1 hash of the given string + /// Return an SHA1 hash /// /// /// public static string SHA1Hash(string data) { + return SHA1Hash(Encoding.Default.GetBytes(data)); + } + + /// + /// Return an SHA1 hash + /// + /// + /// + public static string SHA1Hash(byte[] data) + { byte[] hash = ComputeSHA1Hash(data); return BitConverter.ToString(hash).Replace("-", String.Empty); } - private static byte[] ComputeSHA1Hash(string src) + private static byte[] ComputeSHA1Hash(byte[] src) { SHA1CryptoServiceProvider SHA1 = new SHA1CryptoServiceProvider(); - return SHA1.ComputeHash(Encoding.Default.GetBytes(src)); + return SHA1.ComputeHash(src); } public static int fast_distance2d(int x, int y) diff --git a/OpenSim/Services/AssetService/AssetService.cs b/OpenSim/Services/AssetService/AssetService.cs index 851b7b4..c7a259d 100644 --- a/OpenSim/Services/AssetService/AssetService.cs +++ b/OpenSim/Services/AssetService/AssetService.cs @@ -84,11 +84,20 @@ namespace OpenSim.Services.AssetService if (assetLoaderEnabled) { m_log.InfoFormat("[ASSET]: Loading default asset set from {0}", loaderArgs); - m_AssetLoader.ForEachDefaultXmlAsset(loaderArgs, - delegate(AssetBase a) + + m_AssetLoader.ForEachDefaultXmlAsset( + loaderArgs, + delegate(AssetBase a) + { + AssetBase existingAsset = Get(a.ID); +// AssetMetadata existingMetadata = GetMetadata(a.ID); + + if (existingAsset == null || Util.SHA1Hash(existingAsset.Data) != Util.SHA1Hash(a.Data)) { +// m_log.DebugFormat("[ASSET]: Storing {0} {1}", a.Name, a.ID); Store(a); - }); + } + }); } m_log.Info("[ASSET SERVICE]: Local asset service enabled"); -- cgit v1.1 From 5e8900dfd058bd103cb6dcf8a57dc94683efd878 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 9 Jul 2011 00:35:30 +0100 Subject: minor: code tidy and inserted log lines for future use. Unable to get to the bottom of why resizing a mesh fails to properly reset the physics proxy, when toggling phantom does After a mesh is generated, the existing sculptdata is set to zero in PrimitiveBaseShape to save memory When phantom is toggled, the sculptdata is regenerated before remeshing. But on resize, the sculptdata is not regenerated. So clearly, resetting sculptdata is possible, but haven't quite been able to pin down how this is being done when phantom is toggled. --- OpenSim/Framework/PrimitiveBaseShape.cs | 46 ++++++++++++------- .../Caps/ObjectCaps/UploadObjectAssetModule.cs | 4 +- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 1 - .../Scenes/Serialization/SceneObjectSerializer.cs | 2 + OpenSim/Region/Physics/Meshing/Meshmerizer.cs | 5 ++- OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | 52 ++++++++++++++-------- OpenSim/Region/Physics/OdePlugin/OdeScene.cs | 5 +-- 7 files changed, 72 insertions(+), 43 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Framework/PrimitiveBaseShape.cs b/OpenSim/Framework/PrimitiveBaseShape.cs index 7b5fb2e..8489ad8 100644 --- a/OpenSim/Framework/PrimitiveBaseShape.cs +++ b/OpenSim/Framework/PrimitiveBaseShape.cs @@ -213,6 +213,8 @@ namespace OpenSim.Framework /// public PrimitiveBaseShape(Primitive prim) { +// m_log.DebugFormat("[PRIMITIVE BASE SHAPE]: Creating from {0}", prim.ID); + PCode = (byte)prim.PrimData.PCode; ExtraParams = new byte[1]; @@ -613,29 +615,39 @@ namespace OpenSim.Framework } } - public byte SculptType { - get { + public byte SculptType + { + get + { return _sculptType; } - set { + set + { _sculptType = value; } } - public byte[] SculptData { - get { + public byte[] SculptData + { + get + { return _sculptData; } - set { + set + { +// m_log.DebugFormat("[PRIMITIVE BASE SHAPE]: Setting SculptData to data with length {0}", value.Length); _sculptData = value; } } - public int FlexiSoftness { - get { + public int FlexiSoftness + { + get + { return _flexiSoftness; } - set { + set + { _flexiSoftness = value; } } @@ -849,6 +861,8 @@ namespace OpenSim.Framework public byte[] ExtraParamsToBytes() { +// m_log.DebugFormat("[EXTRAPARAMS]: Called ExtraParamsToBytes()"); + ushort FlexiEP = 0x10; ushort LightEP = 0x20; ushort SculptEP = 0x30; @@ -864,18 +878,21 @@ namespace OpenSim.Framework TotalBytesLength += 16;// data TotalBytesLength += 2 + 4; // type } + if (_lightEntry) { ExtraParamsNum++; TotalBytesLength += 16;// data TotalBytesLength += 2 + 4; // type } + if (_sculptEntry) { ExtraParamsNum++; TotalBytesLength += 17;// data TotalBytesLength += 2 + 4; // type } + if (_projectionEntry) { ExtraParamsNum++; @@ -885,7 +902,6 @@ namespace OpenSim.Framework byte[] returnbytes = new byte[TotalBytesLength]; - // uint paramlength = ExtraParamsNum; // Stick in the number of parameters @@ -905,6 +921,7 @@ namespace OpenSim.Framework Array.Copy(FlexiData, 0, returnbytes, i, FlexiData.Length); i += FlexiData.Length; } + if (_lightEntry) { byte[] LightData = GetLightBytes(); @@ -919,6 +936,7 @@ namespace OpenSim.Framework Array.Copy(LightData, 0, returnbytes, i, LightData.Length); i += LightData.Length; } + if (_sculptEntry) { byte[] SculptData = GetSculptBytes(); @@ -933,6 +951,7 @@ namespace OpenSim.Framework Array.Copy(SculptData, 0, returnbytes, i, SculptData.Length); i += SculptData.Length; } + if (_projectionEntry) { byte[] ProjectionData = GetProjectionBytes(); @@ -946,6 +965,7 @@ namespace OpenSim.Framework Array.Copy(ProjectionData, 0, returnbytes, i, ProjectionData.Length); i += ProjectionData.Length; } + if (!_flexiEntry && !_lightEntry && !_sculptEntry && !_projectionEntry) { byte[] returnbyte = new byte[1]; @@ -953,10 +973,7 @@ namespace OpenSim.Framework return returnbyte; } - return returnbytes; - //m_log.Info("[EXTRAPARAMS]: Length = " + m_shape.ExtraParams.Length.ToString()); - } public void ReadInUpdateExtraParam(ushort type, bool inUse, byte[] data) @@ -1027,7 +1044,6 @@ namespace OpenSim.Framework extraParamCount = data[i++]; } - for (int k = 0; k < extraParamCount; k++) { ushort epType = Utils.BytesToUInt16(data, i); @@ -1071,7 +1087,6 @@ namespace OpenSim.Framework _sculptEntry = false; if (!lGotFilter) _projectionEntry = false; - } public void ReadSculptData(byte[] data, int pos) @@ -1100,6 +1115,7 @@ namespace OpenSim.Framework if (_sculptType != (byte)1 && _sculptType != (byte)2 && _sculptType != (byte)3 && _sculptType != (byte)4) _sculptType = 4; } + _sculptTexture = SculptUUID; _sculptType = SculptTypel; //m_log.Info("[SCULPT]:" + SculptUUID.ToString()); diff --git a/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs index 3809f84..15ed3b3 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs @@ -250,11 +250,9 @@ namespace OpenSim.Region.ClientStack.Linden case 0x40: pbs.ReadProjectionData(extraParam.ExtraParamData, 0); break; - } - - } + pbs.PathBegin = (ushort) obj.PathBegin; pbs.PathCurve = (byte) obj.PathCurve; pbs.PathEnd = (ushort) obj.PathEnd; diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index cd5046a..307c92a 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -2958,7 +2958,6 @@ namespace OpenSim.Region.Framework.Scenes } } - public void SculptTextureCallback(UUID textureID, AssetBase texture) { if (m_shape.SculptEntry) diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs index fcf7e0c..c18c93a 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs @@ -1001,6 +1001,8 @@ namespace OpenSim.Region.Framework.Scenes.Serialization private static void ProcessShpSculptData(PrimitiveBaseShape shp, XmlTextReader reader) { +// m_log.DebugFormat("[SCENE OBJECT SERIALIZER]: Setting sculpt data length {0}", shp.SculptData.Length); + shp.SculptData = Convert.FromBase64String(reader.ReadElementString("SculptData")); } diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index e92e97b..b79e1a1 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs @@ -540,7 +540,6 @@ namespace OpenSim.Region.Physics.Meshing profileBegin = 0.5f * profileBegin + 0.5f; profileEnd = 0.5f * profileEnd + 0.5f; - } int hollowSides = sides; @@ -660,7 +659,9 @@ namespace OpenSim.Region.Physics.Meshing public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical) { -// m_log.DebugFormat("[MESH]: Creating mesh for {0}", primName); +#if SPAM + m_log.DebugFormat("[MESH]: Creating mesh for {0}", primName); +#endif Mesh mesh = null; ulong key = 0; diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index bc839e0..b63168a 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs @@ -38,6 +38,9 @@ * switch between 'VEHICLE' parameter use and general dynamics * settings use. */ + +//#define SPAM + using System; using System.Collections.Generic; using System.Reflection; @@ -746,7 +749,6 @@ namespace OpenSim.Region.Physics.OdePlugin d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); } - d.BodyDestroy(Body); lock (childrenPrim) { @@ -775,7 +777,6 @@ namespace OpenSim.Region.Physics.OdePlugin d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); } - Body = IntPtr.Zero; } } @@ -858,7 +859,7 @@ namespace OpenSim.Region.Physics.OdePlugin public void ProcessTaints(float timestep) { -//Console.WriteLine("ProcessTaints for " + Name); +Console.WriteLine("ProcessTaints for " + Name); if (m_taintadd) { changeadd(timestep); @@ -867,7 +868,7 @@ namespace OpenSim.Region.Physics.OdePlugin if (prim_geom != IntPtr.Zero) { if (!_position.ApproxEquals(m_taintposition, 0f)) - changemove(timestep); + changemove(timestep); if (m_taintrot != _orientation) { @@ -885,19 +886,15 @@ namespace OpenSim.Region.Physics.OdePlugin rotate(timestep); } } - // if (m_taintPhysics != m_isphysical && !(m_taintparent != _parent)) changePhysicsStatus(timestep); - // - if (!_size.ApproxEquals(m_taintsize,0f)) + if (!_size.ApproxEquals(m_taintsize, 0f)) changesize(timestep); - // if (m_taintshape) changeshape(timestep); - // if (m_taintforce) changeAddForce(timestep); @@ -925,7 +922,6 @@ namespace OpenSim.Region.Physics.OdePlugin if (!m_angularlock.ApproxEquals(m_taintAngularLock,0f)) changeAngularLock(timestep); - } else { @@ -1424,10 +1420,11 @@ namespace OpenSim.Region.Physics.OdePlugin } } - lock (_parent_scene.OdeLock) { -//Console.WriteLine("changeadd 1"); +#if SPAM +Console.WriteLine("changeadd 1"); +#endif CreateGeom(m_targetSpace, _mesh); if (prim_geom != IntPtr.Zero) @@ -1890,6 +1887,10 @@ Console.WriteLine(" JointCreateFixed"); public void changesize(float timestamp) { +#if SPAM + m_log.DebugFormat("[ODE PRIM]: Called changesize"); +#endif + string oldname = _parent_scene.geom_name_map[prim_geom]; if (_size.X <= 0) _size.X = 0.01f; @@ -1899,8 +1900,9 @@ Console.WriteLine(" JointCreateFixed"); // Cleanup of old prim geometry if (_mesh != null) { - // Cleanup meshing here + // TODO: Cleanup meshing here } + //kill body to rebuild if (IsPhysical && Body != IntPtr.Zero) { @@ -1917,11 +1919,13 @@ Console.WriteLine(" JointCreateFixed"); disableBody(); } } + if (d.SpaceQuery(m_targetSpace, prim_geom)) { _parent_scene.waitForSpaceUnlock(m_targetSpace); d.SpaceRemove(m_targetSpace, prim_geom); } + d.GeomDestroy(prim_geom); prim_geom = IntPtr.Zero; // we don't need to do space calculation because the client sends a position update also. @@ -1941,13 +1945,19 @@ Console.WriteLine(" JointCreateFixed"); mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); //IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); -//Console.WriteLine("changesize 1"); +#if SPAM +Console.WriteLine("changesize 1"); +#endif CreateGeom(m_targetSpace, mesh); } else { _mesh = null; -//Console.WriteLine("changesize 2"); + +#if SPAM +Console.WriteLine("changesize 2"); +#endif + CreateGeom(m_targetSpace, _mesh); } @@ -2030,6 +2040,7 @@ Console.WriteLine(" JointCreateFixed"); prim_geom = IntPtr.Zero; m_log.ErrorFormat("[PHYSICS]: PrimGeom dead for {0}", Name); } + prim_geom = IntPtr.Zero; // we don't need to do space calculation because the client sends a position update also. if (_size.X <= 0) _size.X = 0.01f; @@ -2039,7 +2050,7 @@ Console.WriteLine(" JointCreateFixed"); if (_parent_scene.needsMeshing(_pbs)) { - // Don't need to re-enable body.. it's done in SetMesh + // Don't need to re-enable body.. it's done in CreateMesh float meshlod = _parent_scene.meshSculptLOD; if (IsPhysical) @@ -2047,13 +2058,18 @@ Console.WriteLine(" JointCreateFixed"); IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); // createmesh returns null when it doesn't mesh. -//Console.WriteLine("changeshape needed meshing"); +#if SPAM +Console.WriteLine("changeshape needed meshing"); +#endif CreateGeom(m_targetSpace, mesh); } else { _mesh = null; -//Console.WriteLine("changeshape not need meshing"); + +#if SPAM +Console.WriteLine("changeshape not need meshing"); +#endif CreateGeom(m_targetSpace, null); } diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs index 87d22af..f5172aa 100644 --- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs +++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs @@ -26,7 +26,7 @@ */ //#define USE_DRAWSTUFF -//#define SPAM +#define SPAM using System; using System.Collections.Generic; @@ -312,7 +312,6 @@ namespace OpenSim.Region.Physics.OdePlugin #endif } - _watermap = new float[258 * 258]; // Zero out the prim spaces array (we split our space into smaller spaces so @@ -2563,7 +2562,6 @@ namespace OpenSim.Region.Physics.OdePlugin if (pbs.SculptEntry && meshSculptedPrim) iPropertiesNotSupportedDefault++; - if (iPropertiesNotSupportedDefault == 0) { #if SPAM @@ -2703,7 +2701,6 @@ namespace OpenSim.Region.Physics.OdePlugin { foreach (OdeCharacter character in _taintedActors) { - character.ProcessTaints(timeStep); processedtaints = true; -- cgit v1.1 From d79c6c8820e7219afa3f01a0910a794bcdbb307d Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 9 Jul 2011 00:42:48 +0100 Subject: Rename SetSculptData() to SetSculptProperties(), since this is what it does (setting SculptData is done through the property) --- OpenSim/Framework/PrimitiveBaseShape.cs | 2 +- OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs | 2 +- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Framework/PrimitiveBaseShape.cs b/OpenSim/Framework/PrimitiveBaseShape.cs index 8489ad8..d873071 100644 --- a/OpenSim/Framework/PrimitiveBaseShape.cs +++ b/OpenSim/Framework/PrimitiveBaseShape.cs @@ -378,7 +378,7 @@ namespace OpenSim.Framework _pathEnd = Primitive.PackEndCut(end); } - public void SetSculptData(byte sculptType, UUID SculptTextureUUID) + public void SetSculptProperties(byte sculptType, UUID SculptTextureUUID) { _sculptType = sculptType; _sculptTexture = SculptTextureUUID; diff --git a/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs b/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs index faed522..aa23fee 100644 --- a/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs +++ b/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs @@ -801,7 +801,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule // retain pathcurve shapeBlock.PathCurve = part.Shape.PathCurve; - part.Shape.SetSculptData((byte)type, sculptId); + part.Shape.SetSculptProperties((byte)type, sculptId); part.Shape.SculptEntry = true; part.UpdateShape(shapeBlock); } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index ce7d97c..22f8ddb 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -6900,7 +6900,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // retain pathcurve shapeBlock.PathCurve = part.Shape.PathCurve; - part.Shape.SetSculptData((byte)type, sculptId); + part.Shape.SetSculptProperties((byte)type, sculptId); part.Shape.SculptEntry = true; part.UpdateShape(shapeBlock); } -- cgit v1.1 From e7abf834d1b51353ec90f424b87487bbeb391582 Mon Sep 17 00:00:00 2001 From: Makopoppo Date: Mon, 4 Jul 2011 22:45:21 +0900 Subject: Instance-types-in-list fix for LSL/OSSL functions. This will fix llListFindList() which always returns -1 when you compare with the list from those functions. *llCSV2List *llGetAnimationList *llGetLinkPrimitiveParams *llGetObjectDetails *llGetParcelDetails *llGetParcelPrimOwners *llGetPrimitiveParams *GetLinkPrimitiveParamsEx *osGetAgents *osMatchString *osGetLinkPrimitiveParams *osGetPrimitiveParams *osGetAvatarList --- .../Shared/Api/Implementation/LSL_Api.cs | 48 +++++++++++----------- .../Shared/Api/Implementation/OSSL_Api.cs | 13 +++--- 2 files changed, 31 insertions(+), 30 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 22f8ddb..fd6d64c 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -5050,7 +5050,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } - result.Add(src.Substring(start,length).Trim()); + result.Add(new LSL_String(src.Substring(start,length).Trim())); return result; } @@ -7391,7 +7391,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api UUID[] anims; anims = av.Animator.GetAnimationArray(); foreach (UUID foo in anims) - l.Add(foo.ToString()); + l.Add(new LSL_Key(foo.ToString())); return l; } @@ -7926,17 +7926,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_TEXT: Color4 textColor = part.GetTextColor(); - res.Add(part.Text); + res.Add(new LSL_String(part.Text)); res.Add(new LSL_Vector(textColor.R, textColor.G, textColor.B)); res.Add(new LSL_Float(textColor.A)); break; case (int)ScriptBaseClass.PRIM_NAME: - res.Add(part.Name); + res.Add(new LSL_String(part.Name)); break; case (int)ScriptBaseClass.PRIM_DESC: - res.Add(part.Description); + res.Add(new LSL_String(part.Description)); break; case (int)ScriptBaseClass.PRIM_ROT_LOCAL: res.Add(new LSL_Rotation(part.RotationOffset.X, part.RotationOffset.Y, part.RotationOffset.Z, part.RotationOffset.W)); @@ -9895,8 +9895,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { foreach (KeyValuePair detectedParams in land.GetLandObjectOwners()) { - ret.Add(detectedParams.Key.ToString()); - ret.Add(detectedParams.Value); + ret.Add(new LSL_String(detectedParams.Key.ToString())); + ret.Add(new LSL_Integer(detectedParams.Value)); } } ScriptSleep(2000); @@ -9946,25 +9946,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api switch (o.ToString()) { case "0": - ret = ret + new LSL_List(land.Name); + ret.Add(new LSL_String(land.Name)); break; case "1": - ret = ret + new LSL_List(land.Description); + ret.Add(new LSL_String(land.Description)); break; case "2": - ret = ret + new LSL_List(land.OwnerID.ToString()); + ret.Add(new LSL_Key(land.OwnerID.ToString())); break; case "3": - ret = ret + new LSL_List(land.GroupID.ToString()); + ret.Add(new LSL_Key(land.GroupID.ToString())); break; case "4": - ret = ret + new LSL_List(land.Area); + ret.Add(new LSL_Integer(land.Area)); break; case "5": - ret = ret + new LSL_List(land.GlobalID); + ret.Add(new LSL_Key(land.GlobalID.ToString())); break; default: - ret = ret + new LSL_List(0); + ret.Add(new LSL_Integer(0)); break; } } @@ -9996,10 +9996,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api switch (o.ToString()) { case "1": - ret.Add(av.Firstname + " " + av.Lastname); + ret.Add(new LSL_String(av.Firstname + " " + av.Lastname)); break; case "2": - ret.Add(""); + ret.Add(new LSL_String("")); break; case "3": ret.Add(new LSL_Vector((double)av.AbsolutePosition.X, (double)av.AbsolutePosition.Y, (double)av.AbsolutePosition.Z)); @@ -10011,13 +10011,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ret.Add(new LSL_Vector(av.Velocity.X, av.Velocity.Y, av.Velocity.Z)); break; case "6": - ret.Add(id); + ret.Add(new LSL_String(id)); break; case "7": - ret.Add(UUID.Zero.ToString()); + ret.Add(new LSL_String(UUID.Zero.ToString())); break; case "8": - ret.Add(UUID.Zero.ToString()); + ret.Add(new LSL_String(UUID.Zero.ToString())); break; } } @@ -10031,10 +10031,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api switch (o.ToString()) { case "1": - ret.Add(obj.Name); + ret.Add(new LSL_String(obj.Name)); break; case "2": - ret.Add(obj.Description); + ret.Add(new LSL_String(obj.Description)); break; case "3": ret.Add(new LSL_Vector(obj.AbsolutePosition.X, obj.AbsolutePosition.Y, obj.AbsolutePosition.Z)); @@ -10046,13 +10046,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ret.Add(new LSL_Vector(obj.Velocity.X, obj.Velocity.Y, obj.Velocity.Z)); break; case "6": - ret.Add(obj.OwnerID.ToString()); + ret.Add(new LSL_String(obj.OwnerID.ToString())); break; case "7": - ret.Add(obj.GroupID.ToString()); + ret.Add(new LSL_String(obj.GroupID.ToString())); break; case "8": - ret.Add(obj.CreatorID.ToString()); + ret.Add(new LSL_String(obj.CreatorID.ToString())); break; } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 1bc4534..b3f90e2 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -811,7 +811,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api World.ForEachScenePresence(delegate(ScenePresence sp) { if (!sp.IsChildAgent) - result.Add(sp.Name); + result.Add(new LSL_String(sp.Name)); }); return result; } @@ -2030,8 +2030,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { if (g.Success) { - result.Add(g.Value); - result.Add(g.Index); + result.Add(new LSL_String(g.Value)); + result.Add(new LSL_Integer(g.Index)); } } } @@ -2365,9 +2365,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { if (avatar.IsChildAgent == false) { - result.Add(avatar.UUID); - result.Add(avatar.AbsolutePosition); - result.Add(avatar.Name); + result.Add(new LSL_String(avatar.UUID.ToString())); + OpenMetaverse.Vector3 ap = avatar.AbsolutePosition; + result.Add(new LSL_Vector(ap.X, ap.Y, ap.Z)); + result.Add(new LSL_String(avatar.Name)); } } }); -- cgit v1.1 From 04f8d0e45dae6b773e49532e4cd31ee290f9a677 Mon Sep 17 00:00:00 2001 From: Makopoppo Date: Thu, 7 Jul 2011 23:36:41 +0900 Subject: Made some LSL_Constant or LS_Constant raw int values --- OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs index 461b473..0839ab4 100644 --- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs +++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs @@ -1741,8 +1741,13 @@ namespace OpenSim.Region.ScriptEngine.Shared public override bool Equals(Object o) { - if (!(o is LSLInteger)) - return false; + if (!(o is LSLInteger)) { + if(o is int) { + return value == (int)o; + } else { + return false; + } + } return value == ((LSLInteger)o).value; } -- cgit v1.1 From b983f38e2abc4ee28a572c680ba267138064ed5c Mon Sep 17 00:00:00 2001 From: Makopoppo Date: Thu, 7 Jul 2011 23:38:22 +0900 Subject: lsGetWindlightScene() returns raw int value, which makes unable to compare to another value with llListFindList() --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs index 645566e..80daf5b 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs @@ -130,7 +130,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api int idx = 0; while (idx < rules.Length) { - uint rule = (uint)rules.GetLSLIntegerItem(idx); + LSL_Integer ruleInt = rules.GetLSLIntegerItem(idx); + uint rule = (uint)ruleInt; LSL_List toadd = new LSL_List(); switch (rule) @@ -247,7 +248,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (toadd.Length > 0) { - values.Add(rule); + values.Add(ruleInt); values.Add(toadd.Data[0]); } idx++; -- cgit v1.1 From 52c3671aa07c5d4c91908a8e1b15b76e96cc49c0 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 9 Jul 2011 01:17:35 +0100 Subject: fix formatting issues from last patch --- OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs index 0839ab4..e0a4014 100644 --- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs +++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs @@ -1741,13 +1741,18 @@ namespace OpenSim.Region.ScriptEngine.Shared public override bool Equals(Object o) { - if (!(o is LSLInteger)) { - if(o is int) { + if (!(o is LSLInteger)) + { + if (o is int) + { return value == (int)o; - } else { + } + else + { return false; } } + return value == ((LSLInteger)o).value; } -- cgit v1.1 From f680c134955b3179265ec197c935ed86b397b6ad Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 9 Jul 2011 01:24:30 +0100 Subject: Fix osMatchString() so that it reports all instance of pattern matches, not just the first one. This is a slight adaptation of the patch in http://opensimulator.org/mantis/view.php?id=4568 which doesn't apply directly since the underlying code was changed by earlier makopoppo patches. Thanks makopoppo! --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index b3f90e2..b710229 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -1909,8 +1909,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api }; return NotecardCache.GetLines(assetID); - - } public string osAvatarName2Key(string firstname, string lastname) @@ -2024,7 +2022,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // Find matches beginning at start position Regex matcher = new Regex(pattern); Match match = matcher.Match(src, start); - if (match.Success) + while (match.Success) { foreach (System.Text.RegularExpressions.Group g in match.Groups) { @@ -2034,6 +2032,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api result.Add(new LSL_Integer(g.Index)); } } + + match = match.NextMatch(); } return result; -- cgit v1.1 From df586c9d2502523395b53d48ddd7dda8832c7a08 Mon Sep 17 00:00:00 2001 From: Makopoppo Date: Tue, 5 Jul 2011 22:19:26 +0900 Subject: Raw int numbers (ex.LSL Constants) are displayed like "1.000000" when type cast to string --- OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'OpenSim') diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs index e0a4014..bf66b12 100644 --- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs +++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs @@ -1396,6 +1396,12 @@ namespace OpenSim.Region.ScriptEngine.Shared string s = String.Format(Culture.FormatProvider, "{0:0.000000}", f.value); m_string=s; } + + public LSLString(int i) + { + string s = String.Format("{0}", i); + m_string = s; + } public LSLString(LSLInteger i) { @@ -1469,6 +1475,11 @@ namespace OpenSim.Region.ScriptEngine.Shared { return new LSLString(d); } + + static public explicit operator LSLString(int i) + { + return new LSLString(i); + } public static explicit operator LSLString(LSLFloat f) { -- cgit v1.1 From 6963b8b046f8a236d5a6e75a0fed81103d807c21 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 9 Jul 2011 01:28:27 +0100 Subject: refactor: Get LSLString(LSLInteger i) constructor to now call LSLString(int i) structure to remove code duplication. --- OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs index bf66b12..d848b2a 100644 --- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs +++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs @@ -1379,7 +1379,9 @@ namespace OpenSim.Region.ScriptEngine.Shared public struct LSLString { public string m_string; + #region Constructors + public LSLString(string s) { m_string = s; @@ -1387,14 +1389,14 @@ namespace OpenSim.Region.ScriptEngine.Shared public LSLString(double d) { - string s=String.Format(Culture.FormatProvider, "{0:0.000000}", d); - m_string=s; + string s = String.Format(Culture.FormatProvider, "{0:0.000000}", d); + m_string = s; } public LSLString(LSLFloat f) { string s = String.Format(Culture.FormatProvider, "{0:0.000000}", f.value); - m_string=s; + m_string = s; } public LSLString(int i) @@ -1403,12 +1405,8 @@ namespace OpenSim.Region.ScriptEngine.Shared m_string = s; } - public LSLString(LSLInteger i) - { - string s = String.Format("{0}", i); - m_string = s; - } - + public LSLString(LSLInteger i) : this(i.value) {} + #endregion #region Operators -- cgit v1.1 From f99b89990c9e4b136b77125c680c7a7c510a6ef2 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 9 Jul 2011 02:21:56 +0100 Subject: Add scratch AvatarFactoryModuleTests with one test to do a partial check on AvatarFactoryModule.SetAppearance() Baked texture set not yet checked, nor persistence of data in avatar service This is a foundation for later npc related tests. --- .../Avatar/AvatarFactory/AvatarFactoryModule.cs | 24 +++++--- .../Tests/AvatarFactoryModuleTests.cs | 72 ++++++++++++++++++++++ 2 files changed, 87 insertions(+), 9 deletions(-) create mode 100644 OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index d02a305..1955e5b 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs @@ -116,16 +116,20 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory #endregion /// - /// Check for the existence of the baked texture assets. Request a rebake - /// unless checkonly is true. + /// Check for the existence of the baked texture assets. /// /// - /// public bool ValidateBakedTextureCache(IClientAPI client) { return ValidateBakedTextureCache(client, true); } - + + /// + /// Check for the existence of the baked texture assets. Request a rebake + /// unless checkonly is true. + /// + /// + /// private bool ValidateBakedTextureCache(IClientAPI client, bool checkonly) { ScenePresence sp = m_scene.GetScenePresence(client.AgentId); @@ -156,13 +160,15 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory defonly = false; // found a non-default texture reference - if (! CheckBakedTextureAsset(client,face.TextureID,idx)) + if (!CheckBakedTextureAsset(client, face.TextureID, idx)) { // the asset didn't exist if we are only checking, then we found a bad // one and we're done otherwise, ask for a rebake - if (checkonly) return false; + if (checkonly) + return false; m_log.InfoFormat("[AVFACTORY]: missing baked texture {0}, requesting rebake", face.TextureID); + client.SendRebakeAvatarTextures(face.TextureID); } } @@ -183,7 +189,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory ScenePresence sp = m_scene.GetScenePresence(client.AgentId); if (sp == null) { - m_log.WarnFormat("[AVFACTORY]: SetAppearance unable to find presence for {0}",client.AgentId); + m_log.WarnFormat("[AVFACTORY]: SetAppearance unable to find presence for {0}", client.AgentId); return; } @@ -211,7 +217,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory changed = sp.Appearance.SetTextureEntries(textureEntry) || changed; m_log.InfoFormat("[AVFACTORY]: received texture update for {0}", client.AgentId); - Util.FireAndForget(delegate(object o) { ValidateBakedTextureCache(client,false); }); + Util.FireAndForget(delegate(object o) { ValidateBakedTextureCache(client, false); }); // This appears to be set only in the final stage of the appearance // update transaction. In theory, we should be able to do an immediate @@ -220,9 +226,9 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory // save only if there were changes, send no matter what (doesn't hurt to send twice) if (changed) QueueAppearanceSave(client.AgentId); + QueueAppearanceSend(client.AgentId); } - } // m_log.WarnFormat("[AVFACTORY]: complete SetAppearance for {0}:\n{1}",client.AgentId,sp.Appearance.ToString()); diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs new file mode 100644 index 0000000..cf4c331 --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs @@ -0,0 +1,72 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * 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 NUnit.Framework; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Tests.Common; +using OpenSim.Tests.Common.Mock; + +namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory +{ + [TestFixture] + public class AvatarFactoryModuleTests + { + /// + /// Only partial right now since we don't yet test that it's ended up in the avatar appearance service. + /// + [Test] + public void TestSetAppearance() + { + TestHelper.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + UUID userId = TestHelper.ParseTail(0x1); + + AvatarFactoryModule afm = new AvatarFactoryModule(); + TestScene scene = SceneSetupHelpers.SetupScene(); + SceneSetupHelpers.SetupSceneModules(scene, afm); + + AgentCircuitData acd = new AgentCircuitData(); + acd.AgentID = userId; + TestClient tc = SceneSetupHelpers.AddRootAgent(scene, acd); + + byte[] visualParams = new byte[AvatarAppearance.VISUALPARAM_COUNT]; + for (byte i = 0; i < visualParams.Length; i++) + visualParams[i] = i; + + afm.SetAppearance(tc, new Primitive.TextureEntry(TestHelper.ParseTail(0x10)), visualParams); + + ScenePresence sp = scene.GetScenePresence(userId); + + // TODO: Check baked texture + Assert.AreEqual(visualParams, sp.Appearance.VisualParams); + } + } +} \ No newline at end of file -- cgit v1.1 From 59aedbc94b345a964fc404c22247afd0487b6f54 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 9 Jul 2011 02:25:40 +0100 Subject: Rename SceneSetupHelpers.AddRootAgent to AddClient() to better represent its effects and return object --- .../Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs | 2 +- OpenSim/Region/Framework/Scenes/Tests/AttachmentTests.cs | 2 +- OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs | 2 +- OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs | 4 ++-- OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs | 2 +- OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs | 2 +- OpenSim/Region/Framework/Scenes/Tests/StandaloneTeleportTests.cs | 2 +- OpenSim/Tests/Common/Helpers/SceneSetupHelpers.cs | 6 +++--- 8 files changed, 11 insertions(+), 11 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs index cf4c331..736dd72 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs @@ -55,7 +55,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory AgentCircuitData acd = new AgentCircuitData(); acd.AgentID = userId; - TestClient tc = SceneSetupHelpers.AddRootAgent(scene, acd); + TestClient tc = SceneSetupHelpers.AddClient(scene, acd); byte[] visualParams = new byte[AvatarAppearance.VISUALPARAM_COUNT]; for (byte i = 0; i < visualParams.Length; i++) diff --git a/OpenSim/Region/Framework/Scenes/Tests/AttachmentTests.cs b/OpenSim/Region/Framework/Scenes/Tests/AttachmentTests.cs index cff649b..5586c65 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/AttachmentTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/AttachmentTests.cs @@ -83,7 +83,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests region1 = scene.RegionInfo.RegionHandle; region2 = scene2.RegionInfo.RegionHandle; - SceneSetupHelpers.AddRootAgent(scene, agent1); + SceneSetupHelpers.AddClient(scene, agent1); } [Test] diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs index 0a82c4f..260d1c0 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs @@ -139,7 +139,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests SceneObjectPart part = SceneSetupHelpers.AddSceneObject(scene); - IClientAPI client = SceneSetupHelpers.AddRootAgent(scene, agentId); + IClientAPI client = SceneSetupHelpers.AddClient(scene, agentId); scene.DeRezObjects(client, new System.Collections.Generic.List() { part.LocalId }, UUID.Zero, DeRezAction.Delete, UUID.Zero); SceneObjectPart retrievedPart = scene.GetSceneObjectPart(part.LocalId); diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs index 5357a06..1b8c100 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs @@ -66,7 +66,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests IConfig config = configSource.AddConfig("Startup"); config.Set("serverside_object_permissions", true); SceneSetupHelpers.SetupSceneModules(scene, configSource, new object[] { new PermissionsModule() }); - TestClient client = SceneSetupHelpers.AddRootAgent(scene, userId); + TestClient client = SceneSetupHelpers.AddClient(scene, userId); // Turn off the timer on the async sog deleter - we'll crank it by hand for this test. AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter; @@ -105,7 +105,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests IConfig config = configSource.AddConfig("Startup"); config.Set("serverside_object_permissions", true); SceneSetupHelpers.SetupSceneModules(scene, configSource, new object[] { new PermissionsModule() }); - TestClient client = SceneSetupHelpers.AddRootAgent(scene, userId); + TestClient client = SceneSetupHelpers.AddClient(scene, userId); // Turn off the timer on the async sog deleter - we'll crank it by hand for this test. AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter; diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs index 77bd4c2..8425d37 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs @@ -75,7 +75,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests new GroupsModule(), new MockGroupsServicesConnector() }); - TestClient client = SceneSetupHelpers.AddRootAgent(scene, userId); + TestClient client = SceneSetupHelpers.AddClient(scene, userId); IGroupsModule groupsModule = scene.RequestModuleInterface(); diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs index 03ac252..a37b338 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs @@ -212,7 +212,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests SceneSetupHelpers.SetupSceneModules(myScene1, configSource, etm); - SceneSetupHelpers.AddRootAgent(myScene1, agent1Id); + SceneSetupHelpers.AddClient(myScene1, agent1Id); ScenePresence childPresence = myScene2.GetScenePresence(agent1); // TODO: Need to do a fair amount of work to allow synchronous establishment of child agents diff --git a/OpenSim/Region/Framework/Scenes/Tests/StandaloneTeleportTests.cs b/OpenSim/Region/Framework/Scenes/Tests/StandaloneTeleportTests.cs index 1b5a54e..4074f5d 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/StandaloneTeleportTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/StandaloneTeleportTests.cs @@ -125,7 +125,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests sceneA.RegisterRegionWithGrid(); UUID agentId = UUID.Parse("00000000-0000-0000-0000-000000000041"); - TestClient client = SceneSetupHelpers.AddRootAgent(sceneA, agentId); + TestClient client = SceneSetupHelpers.AddClient(sceneA, agentId); ICapabilitiesModule sceneACapsModule = sceneA.RequestModuleInterface(); diff --git a/OpenSim/Tests/Common/Helpers/SceneSetupHelpers.cs b/OpenSim/Tests/Common/Helpers/SceneSetupHelpers.cs index bef0481..70621d5 100644 --- a/OpenSim/Tests/Common/Helpers/SceneSetupHelpers.cs +++ b/OpenSim/Tests/Common/Helpers/SceneSetupHelpers.cs @@ -341,9 +341,9 @@ namespace OpenSim.Tests.Common /// /// /// - public static TestClient AddRootAgent(Scene scene, UUID agentId) + public static TestClient AddClient(Scene scene, UUID agentId) { - return AddRootAgent(scene, GenerateAgentData(agentId)); + return AddClient(scene, GenerateAgentData(agentId)); } /// @@ -364,7 +364,7 @@ namespace OpenSim.Tests.Common /// /// /// - public static TestClient AddRootAgent(Scene scene, AgentCircuitData agentData) + public static TestClient AddClient(Scene scene, AgentCircuitData agentData) { string reason; -- cgit v1.1 From 457ba9d1a29daa203e326c6b9711c9e1ad99475d Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 9 Jul 2011 02:27:47 +0100 Subject: refactor: slightly simplify test --- .../Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs index 736dd72..07de908 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs @@ -52,10 +52,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory AvatarFactoryModule afm = new AvatarFactoryModule(); TestScene scene = SceneSetupHelpers.SetupScene(); SceneSetupHelpers.SetupSceneModules(scene, afm); - - AgentCircuitData acd = new AgentCircuitData(); - acd.AgentID = userId; - TestClient tc = SceneSetupHelpers.AddClient(scene, acd); + TestClient tc = SceneSetupHelpers.AddClient(scene, userId); byte[] visualParams = new byte[AvatarAppearance.VISUALPARAM_COUNT]; for (byte i = 0; i < visualParams.Length; i++) -- cgit v1.1 From c964114f7e1fd76970db4904a9bfd6a2cfad10b9 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 11 Jul 2011 02:09:11 +0100 Subject: refactor: make argument to SOP.UpdatePrimFlags() more readable --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 33 +++++++++++++--------- 1 file changed, 19 insertions(+), 14 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 307c92a..1a58952 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -1068,7 +1068,6 @@ namespace OpenSim.Region.Framework.Scenes } } - public bool CreateSelected { get { return m_createSelected; } @@ -1241,7 +1240,9 @@ namespace OpenSim.Region.Framework.Scenes /// /// Property flags. See OpenMetaverse.PrimFlags /// + /// /// Example properties are PrimFlags.Phantom and PrimFlags.DieAtEdge + /// public PrimFlags Flags { get { return _flags; } @@ -4324,14 +4325,21 @@ namespace OpenSim.Region.Framework.Scenes } } - public void UpdatePrimFlags(bool UsePhysics, bool IsTemporary, bool IsPhantom, bool IsVD) + /// + /// Update the flags on this prim. This covers properties such as phantom, physics and temporary. + /// + /// + /// + /// + /// + public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD) { bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0); bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0); bool wasPhantom = ((Flags & PrimFlags.Phantom) != 0); bool wasVD = VolumeDetectActive; - if ((UsePhysics == wasUsingPhysics) && (wasTemporary == IsTemporary) && (wasPhantom == IsPhantom) && (IsVD==wasVD)) + if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD== wasVD)) { return; } @@ -4341,32 +4349,31 @@ namespace OpenSim.Region.Framework.Scenes // that... // ... if VD is changed, all others are not. // ... if one of the others is changed, VD is not. - if (IsVD) // VD is active, special logic applies + if (SetVD) // VD is active, special logic applies { // State machine logic for VolumeDetect // More logic below - bool phanReset = (IsPhantom != wasPhantom) && !IsPhantom; + bool phanReset = (SetPhantom != wasPhantom) && !SetPhantom; if (phanReset) // Phantom changes from on to off switch VD off too { - IsVD = false; // Switch it of for the course of this routine + SetVD = false; // Switch it of for the course of this routine VolumeDetectActive = false; // and also permanently if (PhysActor != null) PhysActor.SetVolumeDetect(0); // Let physics know about it too } else { - IsPhantom = false; // If volumedetect is active we don't want phantom to be applied. // If this is a new call to VD out of the state "phantom" // this will also cause the prim to be visible to physics + SetPhantom = false; } - } if (UsePhysics && IsJoint()) { - IsPhantom = true; + SetPhantom = true; } if (UsePhysics) @@ -4396,8 +4403,7 @@ namespace OpenSim.Region.Framework.Scenes } } - - if (IsPhantom || IsAttachment || (Shape.PathCurve == (byte)Extrusion.Flexible)) // note: this may have been changed above in the case of joints + if (SetPhantom || IsAttachment || (Shape.PathCurve == (byte)Extrusion.Flexible)) // note: this may have been changed above in the case of joints { AddFlag(PrimFlags.Phantom); if (PhysActor != null) @@ -4471,7 +4477,7 @@ namespace OpenSim.Region.Framework.Scenes } } - if (IsVD) + if (SetVD) { // If the above logic worked (this is urgent candidate to unit tests!) // we now have a physicsactor. @@ -4496,8 +4502,7 @@ namespace OpenSim.Region.Framework.Scenes this.VolumeDetectActive = false; } - - if (IsTemporary) + if (SetTemporary) { AddFlag(PrimFlags.TemporaryOnRez); } -- cgit v1.1 From c6d4304a0442c606a1f87e440183ed0b7dbc384e Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 11 Jul 2011 02:11:16 +0100 Subject: refactor: very minor space insertion --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 1a58952..4fa3a68 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -4339,7 +4339,7 @@ namespace OpenSim.Region.Framework.Scenes bool wasPhantom = ((Flags & PrimFlags.Phantom) != 0); bool wasVD = VolumeDetectActive; - if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD== wasVD)) + if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD)) { return; } -- cgit v1.1 From e68ae44b6b28565f6867051e5e0ec5d8ecea72cb Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 11 Jul 2011 02:11:37 +0100 Subject: minor: remove mono compiler warning --- OpenSim/Region/Framework/Scenes/AsyncInventorySender.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Scenes/AsyncInventorySender.cs b/OpenSim/Region/Framework/Scenes/AsyncInventorySender.cs index 06cd14b..9cb5674 100644 --- a/OpenSim/Region/Framework/Scenes/AsyncInventorySender.cs +++ b/OpenSim/Region/Framework/Scenes/AsyncInventorySender.cs @@ -70,7 +70,7 @@ namespace OpenSim.Region.Framework.Scenes /// public class AsyncInventorySender { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); protected Scene m_scene; -- cgit v1.1 From 01b98c2e6267cb13cf18f8baeb2b38fd5b6a6cdf Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 11 Jul 2011 02:18:19 +0100 Subject: refactor: Make arguments for SceneObjectGroup.UpdatePrimFlags() more readable --- OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 42ac9aa..4b8e370 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -2513,14 +2513,15 @@ namespace OpenSim.Region.Framework.Scenes /// Update prim flags for this group. /// /// - /// - /// - /// - public void UpdatePrimFlags(uint localID, bool UsePhysics, bool IsTemporary, bool IsPhantom, bool IsVolumeDetect) + /// + /// + /// + /// + public void UpdatePrimFlags(uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVolumeDetect) { SceneObjectPart selectionPart = GetChildPart(localID); - if (IsTemporary) + if (SetTemporary) { DetachFromBackup(); // Remove from database and parcel prim count @@ -2545,7 +2546,7 @@ namespace OpenSim.Region.Framework.Scenes } for (int i = 0; i < parts.Length; i++) - parts[i].UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); + parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect); } } @@ -3292,6 +3293,7 @@ namespace OpenSim.Region.Framework.Scenes { if (IsDeleted) return; + if ((RootPart.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) != 0) return; -- cgit v1.1 From 6a15464b0ac731b678b224cb64c742957f36888f Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 11 Jul 2011 02:29:19 +0100 Subject: refactor: Make arguments to SceneGraph.UpdatePrimFlags() more readable --- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index a078291..7ec7ea3 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -1401,21 +1401,26 @@ namespace OpenSim.Region.Framework.Scenes } /// - /// + /// Update the flags on a scene object. This covers properties such as phantom, physics and temporary. /// + /// + /// This is currently handling the incoming call from the client stack (e.g. LLClientView). + /// /// - /// + /// + /// + /// /// - /// This routine seems to get called when a user changes object settings in the viewer. - /// If some one can confirm that, please change the comment according. - protected internal void UpdatePrimFlags(uint localID, bool UsePhysics, bool IsTemporary, bool IsPhantom, IClientAPI remoteClient) + protected internal void UpdatePrimFlags( + uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, IClientAPI remoteClient) { SceneObjectGroup group = GetGroupByPrim(localID); if (group != null) { if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) { - group.UpdatePrimFlags(localID, UsePhysics, IsTemporary, IsPhantom, false); // VolumeDetect can't be set via UI and will always be off when a change is made there + // VolumeDetect can't be set via UI and will always be off when a change is made there + group.UpdatePrimFlags(localID, UsePhysics, SetTemporary, SetPhantom, false); } } } -- cgit v1.1 From ce85675e705888f95fe00b6516da20118cbb24e0 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 11 Jul 2011 02:29:51 +0100 Subject: comment out accidential ProcessTaints physics debug line left in code --- OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index b63168a..0cf2f5d 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs @@ -859,7 +859,7 @@ namespace OpenSim.Region.Physics.OdePlugin public void ProcessTaints(float timestep) { -Console.WriteLine("ProcessTaints for " + Name); +//Console.WriteLine("ProcessTaints for " + Name); if (m_taintadd) { changeadd(timestep); -- cgit v1.1 From 2f3d0e209ff5c3028e3e29179b67504be9b2f887 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 11 Jul 2011 03:13:59 +0100 Subject: When a sculpt/mesh texture is received by a part on a callback request, don't do the unnecessary work of copying the base shape. Just setting the new base shape is enough to reinsert the sculpt data and set the taint. Also cleans up a few more left-in debugging messages. --- OpenSim/Region/Framework/Scenes/Scene.cs | 1 + .../Region/Framework/Scenes/SceneObjectGroup.cs | 3 +++ OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 28 +++++++++++++++------- OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | 3 ++- OpenSim/Region/Physics/OdePlugin/OdeScene.cs | 2 +- 5 files changed, 26 insertions(+), 11 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index ec6044b..8195a0d 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1726,6 +1726,7 @@ namespace OpenSim.Region.Framework.Scenes /// /// Loads the World's objects /// + /// public virtual void LoadPrimsFromStorage(UUID regionID) { LoadingPrims = true; diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 4b8e370..a184445 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -3297,7 +3297,10 @@ namespace OpenSim.Region.Framework.Scenes if ((RootPart.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) != 0) return; +// m_log.Debug("Processing CheckSculptAndLoad for {0} {1}", Name, LocalId); + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) { SceneObjectPart part = parts[i]; diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 4fa3a68..5b203e9 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -1810,7 +1810,6 @@ namespace OpenSim.Region.Framework.Scenes { ParentGroup.Scene.jointErrorMessage(joint, "warning: tracked body name not found! joint location will not be updated properly. joint: " + Name); } - } else { @@ -1872,7 +1871,6 @@ namespace OpenSim.Region.Framework.Scenes PhysActor.IsPhysical = UsePhysics; - // If we're not what we're supposed to be in the physics scene, recreate ourselves. //m_parentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); /// that's not wholesome. Had to make Scene public @@ -1896,6 +1894,7 @@ namespace OpenSim.Region.Framework.Scenes } } } + m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); } } @@ -2967,14 +2966,17 @@ namespace OpenSim.Region.Framework.Scenes //if (texture != null) { if (texture != null) + { +// m_log.DebugFormat( +// "[SCENE OBJECT PART]: Setting sculpt data for {0} on SculptTextureCallback()", Name); + m_shape.SculptData = texture.Data; + } if (PhysActor != null) { - // Tricks physics engine into thinking we've changed the part shape. - PrimitiveBaseShape m_newshape = m_shape.Copy(); - PhysActor.Shape = m_newshape; - m_shape = m_newshape; + // Update the physics actor with the new loaded sculpt data and set the taint signal. + PhysActor.Shape = m_shape; m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); } @@ -3270,11 +3272,14 @@ namespace OpenSim.Region.Framework.Scenes { m_parentGroup.SetAxisRotation(axis, rotate); } + //Cannot use ScriptBaseClass constants as no referance to it currently. if (axis == 2)//STATUS_ROTATE_X STATUS_ROTATE_X = rotate; + if (axis == 4)//STATUS_ROTATE_Y STATUS_ROTATE_Y = rotate; + if (axis == 8)//STATUS_ROTATE_Z STATUS_ROTATE_Z = rotate; } @@ -4418,6 +4423,7 @@ namespace OpenSim.Region.Framework.Scenes RemFlag(PrimFlags.Phantom); PhysicsActor pa = PhysActor; + if (pa == null) { // It's not phantom anymore. So make sure the physics engine get's knowledge of it @@ -4434,6 +4440,7 @@ namespace OpenSim.Region.Framework.Scenes if (pa != null) { DoPhysicsPropertyUpdate(UsePhysics, true); + if (m_parentGroup != null) { if (!m_parentGroup.IsDeleted) @@ -4444,6 +4451,7 @@ namespace OpenSim.Region.Framework.Scenes } } } + if ( ((AggregateScriptEvents & scriptEvents.collision) != 0) || ((AggregateScriptEvents & scriptEvents.collision_end) != 0) || @@ -4454,8 +4462,8 @@ namespace OpenSim.Region.Framework.Scenes (CollisionSound != UUID.Zero) ) { - PhysActor.OnCollisionUpdate += PhysicsCollision; - PhysActor.SubscribeEvents(1000); + PhysActor.OnCollisionUpdate += PhysicsCollision; + PhysActor.SubscribeEvents(1000); } } } @@ -4492,13 +4500,15 @@ namespace OpenSim.Region.Framework.Scenes } } else - { // Remove VolumeDetect in any case. Note, it's safe to call SetVolumeDetect as often as you like + { + // Remove VolumeDetect in any case. Note, it's safe to call SetVolumeDetect as often as you like // (mumbles, well, at least if you have infinte CPU powers :-)) PhysicsActor pa = this.PhysActor; if (pa != null) { PhysActor.SetVolumeDetect(0); } + this.VolumeDetectActive = false; } diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index 0cf2f5d..123c8ff 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs @@ -2104,6 +2104,7 @@ Console.WriteLine("changeshape not need meshing"); parent.ChildSetGeom(this); } } + resetCollisionAccounting(); m_taintshape = false; } @@ -2343,7 +2344,7 @@ Console.WriteLine("changeshape not need meshing"); { lock (_parent_scene.OdeLock) { - m_isVolumeDetect = (param!=0); + m_isVolumeDetect = (param != 0); } } diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs index f5172aa..99392cc 100644 --- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs +++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs @@ -26,7 +26,7 @@ */ //#define USE_DRAWSTUFF -#define SPAM +//#define SPAM using System; using System.Collections.Generic; -- cgit v1.1 From 0badf3718d98f579e0942e7c888986820d1250a7 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 11 Jul 2011 03:35:29 +0100 Subject: refactor: push the part of SceneObjectGroup.CheckSculptAndLoad() that actually deals with the part into a SceneObjectPart.CheckSculptAndLoad() method --- .../Region/Framework/Scenes/SceneObjectGroup.cs | 32 ++++++++++---------- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 34 ++++++++++++++++++++++ 2 files changed, 49 insertions(+), 17 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index a184445..fa23fcd 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -3288,7 +3288,14 @@ namespace OpenSim.Region.Framework.Scenes return retmass; } - + + /// + /// If the object is a sculpt/mesh, retrieve the mesh data for each part and reinsert it into each shape so that + /// the physics engine can use it. + /// + /// + /// When the physics engine has finished with it, the sculpt data is discarded to save memory. + /// public void CheckSculptAndLoad() { if (IsDeleted) @@ -3302,24 +3309,15 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectPart[] parts = m_parts.GetArray(); for (int i = 0; i < parts.Length; i++) - { - SceneObjectPart part = parts[i]; - if (part.Shape.SculptEntry && part.Shape.SculptTexture != UUID.Zero) - { - // check if a previously decoded sculpt map has been cached - if (File.Exists(System.IO.Path.Combine("j2kDecodeCache", "smap_" + part.Shape.SculptTexture.ToString()))) - { - part.SculptTextureCallback(part.Shape.SculptTexture, null); - } - else - { - m_scene.AssetService.Get( - part.Shape.SculptTexture.ToString(), part, AssetReceived); - } - } - } + parts[i].CheckSculptAndLoad(); } + /// + /// Handle an asset received asynchronously from the asset service. + /// + /// + /// + /// protected void AssetReceived(string id, Object sender, AssetBase asset) { SceneObjectPart sop = (SceneObjectPart)sender; diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 5b203e9..ce7c53a 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -28,6 +28,7 @@ using System; using System.Collections.Generic; using System.Drawing; +using System.IO; using System.Reflection; using System.Runtime.Serialization; using System.Security.Permissions; @@ -4563,6 +4564,7 @@ namespace OpenSim.Region.Framework.Scenes m_shape.PathTaperY = shapeBlock.PathTaperY; m_shape.PathTwist = shapeBlock.PathTwist; m_shape.PathTwistBegin = shapeBlock.PathTwistBegin; + if (PhysActor != null) { PhysActor.Shape = m_shape; @@ -4584,6 +4586,37 @@ namespace OpenSim.Region.Framework.Scenes } /// + /// If the part is a sculpt/mesh, retrieve the mesh data and reinsert it into the shape so that the physics + /// engine can use it. + /// + /// + /// When the physics engine has finished with it, the sculpt data is discarded to save memory. + /// + public void CheckSculptAndLoad() + { +// m_log.Debug("Processing CheckSculptAndLoad for {0} {1}", Name, LocalId); + + if (ParentGroup.IsDeleted) + return; + + if ((ParentGroup.RootPart.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) != 0) + return; + + if (Shape.SculptEntry && Shape.SculptTexture != UUID.Zero) + { + // check if a previously decoded sculpt map has been cached + if (File.Exists(System.IO.Path.Combine("j2kDecodeCache", "smap_" + Shape.SculptTexture.ToString()))) + { + SculptTextureCallback(Shape.SculptTexture, null); + } + else + { + ParentGroup.Scene.AssetService.Get(Shape.SculptTexture.ToString(), this, AssetReceived); + } + } + } + + /// /// Update the textures on the part. /// /// Added to handle bug in libsecondlife's TextureEntry.ToBytes() @@ -4819,6 +4852,7 @@ namespace OpenSim.Region.Framework.Scenes Inventory.ApplyNextOwnerPermissions(); } + public void UpdateLookAt() { try -- cgit v1.1 From 8e44a8e2b9a318143e8e5f8bb235356c6be5c5e5 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 11 Jul 2011 03:47:49 +0100 Subject: Properly regenerate physics proxy when a mesh is resized. This is done in SOP.Resize(). More common code from callers needs to be refactored into this method to reduce confusing copy/pasting --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index ce7c53a..2026c53 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -2831,6 +2831,12 @@ namespace OpenSim.Region.Framework.Scenes StoreUndoState(); m_shape.Scale = scale; + // If we're a mesh/sculpt, then we need to tell the physics engine about our new size. To do this, we + // need to reinsert the sculpt data into the shape, since the physics engine deletes it when done to + // save memory + if (PhysActor != null) + CheckSculptAndLoad(); + ParentGroup.HasGroupChanged = true; ScheduleFullUpdate(); } @@ -4619,9 +4625,11 @@ namespace OpenSim.Region.Framework.Scenes /// /// Update the textures on the part. /// + /// /// Added to handle bug in libsecondlife's TextureEntry.ToBytes() /// not handling RGBA properly. Cycles through, and "fixes" the color /// info + /// /// public void UpdateTexture(Primitive.TextureEntry tex) { -- cgit v1.1 From 24efb021ffe668154fa990f0d5d6f06e31221cb7 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 11 Jul 2011 04:23:30 +0100 Subject: minor Tack the prim name on the end of the "experimental mesh proxy generation" message. Can probably comment out this message soon, once a few other issues are tidied up. --- OpenSim/Region/Physics/Meshing/Meshmerizer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index b79e1a1..5ca5f20 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs @@ -319,7 +319,7 @@ namespace OpenSim.Region.Physics.Meshing if (!useMeshiesPhysicsMesh) return null; - m_log.Debug("[MESH]: experimental mesh proxy generation"); + m_log.DebugFormat("[MESH]: experimental mesh proxy generation for {0}", primName); OSD meshOsd = null; -- cgit v1.1