protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { bool result = false; string[] p = SplitParams(path); if (p.Length > 0) { if (m_allowedTypes != AllowedRemoteDeleteTypes.None) { string assetID = p[0]; AssetBase asset = m_AssetService.Get(assetID); if (asset != null) { if (m_allowedTypes == AllowedRemoteDeleteTypes.All || (int)(asset.Flags & AssetFlags.Maptile) != 0) { result = m_AssetService.Delete(assetID); } else { m_log.DebugFormat( "[ASSET SERVER DELETE HANDLER]: Request to delete asset {0}, but type is {1} and allowed remote delete types are {2}", assetID, (AssetFlags)asset.Flags, m_allowedTypes); } } } } XmlSerializer xs = new XmlSerializer(typeof(bool)); return(ServerUtils.SerializeResult(xs, result)); }
protected internal void Execute() { m_requestState = RequestState.Running; m_log.DebugFormat("[ARCHIVER]: AssetsRequest executed looking for {0} possible assets", m_repliesRequired); // We can stop here if there are no assets to fetch if (m_repliesRequired == 0) { m_requestState = RequestState.Completed; PerformAssetsRequestCallback(false); return; } m_requestCallbackTimer.Enabled = true; foreach (KeyValuePair <UUID, sbyte> kvp in m_uuids) { // m_log.DebugFormat("[ARCHIVER]: Requesting asset {0}", kvp.Key); // m_assetService.Get(kvp.Key.ToString(), kvp.Value, PreAssetRequestCallback); AssetBase asset = m_assetService.Get(kvp.Key.ToString()); PreAssetRequestCallback(kvp.Key.ToString(), kvp.Value, asset); } }
/// <summary> /// Iterates through all Scenes, doing a deep scan through assets /// to cache all assets present in the scene or referenced by assets /// in the scene /// </summary> /// <returns></returns> private int CacheScenes() { UuidGatherer gatherer = new UuidGatherer(m_AssetService); Dictionary <UUID, AssetType> assets = new Dictionary <UUID, AssetType>(); foreach (Scene s in m_Scenes) { StampRegionStatusFile(s.RegionInfo.RegionID); s.ForEachSOG(delegate(SceneObjectGroup e) { gatherer.GatherAssetUuids(e, assets); } ); } foreach (UUID assetID in assets.Keys) { string filename = GetFileName(assetID.ToString()); if (File.Exists(filename)) { File.SetLastAccessTime(filename, DateTime.Now); } else { m_AssetService.Get(assetID.ToString()); } } return(assets.Keys.Count); }
/// <summary> /// Iterates through all Scenes, doing a deep scan through assets /// to cache all assets present in the scene or referenced by assets /// in the scene /// </summary> /// <returns></returns> private int CacheScenes() { //Make sure this is not null if (m_AssetService == null) { return(0); } Dictionary <UUID, AssetType> assets = new Dictionary <UUID, AssetType>(); ISceneManager manager = m_simulationBase.ApplicationRegistry.RequestModuleInterface <ISceneManager>(); if (manager != null) { UuidGatherer gatherer = new UuidGatherer(m_AssetService); StampRegionStatusFile(manager.Scene.RegionInfo.RegionID); manager.Scene.ForEachSceneEntity(e => gatherer.GatherAssetUuids(e, assets, manager.Scene)); foreach (UUID assetID in assets.Keys) { string filename = GetFileName(assetID.ToString()); if (File.Exists(filename)) { File.SetLastAccessTime(filename, DateTime.Now); } else { m_AssetService.Get(assetID.ToString()); } } } return(assets.Keys.Count); }
public static void AssetMustBeValidAndSupported <T>( this IRuleBuilderInitial <T, string> ruleBuilder, IAssetService assetService) { ruleBuilder .Must((rootObject, assetId, context) => { if (string.IsNullOrWhiteSpace(assetId)) { context.MessageFormatter.AppendArgument("Reason", "Must be specified."); return(false); } if (assetService.Get().Id != assetId) { context.MessageFormatter.AppendArgument("Reason", "Must be supported."); return(false); } return(true); }) .WithMessage("{Reason}"); }
// /// <summary> // /// The callback made when we request the asset for an object from the asset service. // /// </summary> // private void AssetReceived(string id, Object sender, AssetBase asset) // { // lock (this) // { // m_requestedObjectAsset = asset; // m_waitingForObjectAsset = false; // Monitor.Pulse(this); // } // } /// <summary> /// Get an asset synchronously, potentially using an asynchronous callback. If the /// asynchronous callback is used, we will wait for it to complete. /// </summary> /// <param name="uuid"></param> /// <returns></returns> protected virtual AssetBase GetAsset(UUID uuid) { return(m_assetService.Get(uuid.ToString())); // XXX: Switching to do this synchronously where the call was async before but we always waited for it // to complete anyway! // m_waitingForObjectAsset = true; // m_assetCache.Get(uuid.ToString(), this, AssetReceived); // // // The asset cache callback can either // // // // 1. Complete on the same thread (if the asset is already in the cache) or // // 2. Come in via a different thread (if we need to go fetch it). // // // // The code below handles both these alternatives. // lock (this) // { // if (m_waitingForObjectAsset) // { // Monitor.Wait(this); // m_waitingForObjectAsset = false; // } // } // // return m_requestedObjectAsset; }
/// <summary> /// Iterates through all Scenes, doing a deep scan through assets /// to cache all assets present in the scene or referenced by assets /// in the scene /// </summary> /// <returns></returns> int CacheScenes() { // Make sure this is not null if (m_AssetService == null) { return(0); } HashSet <UUID> uniqueUuids = new HashSet <UUID> (); Dictionary <UUID, AssetType> assets = new Dictionary <UUID, AssetType> (); ISceneManager manager = m_simulationBase.ApplicationRegistry.RequestModuleInterface <ISceneManager> (); if (manager != null) { UuidGatherer gatherer = new UuidGatherer(m_AssetService); foreach (IScene scene in manager.Scenes) { StampRegionStatusFile(scene.RegionInfo.RegionID); scene.ForEachSceneEntity(e => gatherer.GatherAssetUuids(e, assets)); } foreach (UUID assetID in assets.Keys) { string filename = GetFileName(assetID.ToString()); if (File.Exists(filename)) { if (!uniqueUuids.Contains(assetID)) { File.SetLastAccessTime(filename, DateTime.Now); } } else { AssetBase cachedAsset = null; if (!uniqueUuids.Contains(assetID)) { // getting the asset will save it in cache if reqy=uired cachedAsset = m_AssetService.Get(assetID.ToString()); if (cachedAsset == null && assets [assetID] != AssetType.Unknown) { MainConsole.Instance.DebugFormat("[Flotsam asset cache]: Could not find asset {0}, type {1} when pre-caching all scene assets", assetID, assets [assetID]); } // we don't actually need what we retrieved if (cachedAsset != null) { cachedAsset.Dispose(); } } } uniqueUuids.Add(assetID); } assets.Clear(); } return(assets.Keys.Count); }
public AssetBase Get(string id) { //m_log.DebugFormat("[HG ASSET CONNECTOR]: Get {0}", id); AssetBase asset = null; if (m_Cache != null) { if (!m_Cache.Get(id, out asset)) { return(null); } if (asset != null) { return(asset); } } if (IsHG(id)) { asset = m_HGService.Get(id); if (asset != null) { // Now store it locally, if allowed if (m_AssetPerms.AllowedImport(asset.Type)) { m_GridService.Store(asset); } else { return(null); } } } else { asset = m_GridService.Get(id); } if (m_Cache != null) { m_Cache.Cache(asset); } return(asset); }
private AssetBase GetFromForeign(string id, string ForeignAssetService) { if (m_HGConnector == null || string.IsNullOrEmpty(ForeignAssetService)) { return(null); } return(m_HGConnector.Get(id, ForeignAssetService, true)); }
public AssetBase Get(string id) { //m_log.DebugFormat("[HG ASSET CONNECTOR]: Get {0}", id); AssetBase asset = null; if (m_Cache != null) { asset = m_Cache.Get(id); if (asset != null) { return(asset); } } if (IsHG(id)) { asset = m_HGService.Get(id); if (asset != null) { // Now store it locally // For now, let me just do it for textures and scripts if (((AssetType)asset.Type == AssetType.Texture) || ((AssetType)asset.Type == AssetType.LSLBytecode) || ((AssetType)asset.Type == AssetType.LSLText)) { m_GridService.Store(asset); } } } else { asset = m_GridService.Get(id); } if (asset != null) { if (m_Cache != null) { m_Cache.Cache(asset); } } return(asset); }
private void SaveAsset(UUID AssetID, OSDMap assetMap) { AssetBase asset = AssetService.Get(AssetID.ToString()); if (asset != null) { OSDMap assetData = new OSDMap(); m_log.Info("[AvatarArchive]: Saving asset " + asset.ID); CreateMetaDataMap(asset.Metadata, assetData); assetData.Add("AssetData", OSD.FromBinary(asset.Data)); assetMap.Add(asset.ID, assetData); } else { m_log.Warn("[AvatarArchive]: Could not find asset to save: " + AssetID.ToString()); return; } }
public AssetBase Get(string id) { if (checkForError()) { return(null); } try { AssetBase result = m_assetService.Get(id); if (result == null || result.Data.Length == 0) { foreach (AssetServerProxy service in m_extraAssetServers) { if (result == null) { result = service.Get(id); if (result != null && result.Data.Length != 0) { m_log.Info("[AssetServerProxy]: Get asset data for '" + id + "' from external asset storage at " + service.AssetServiceName); Store(result); if (m_backupService != null) { m_backupService.Store(result); } } } } } return(result); } catch { m_errorCount++; m_lastError = Tools.getUnixTime(); m_log.Error("[AssetServerProxy]: Add remote asset server to temporary blacklist: " + m_assetServiceURL); } return(null); }
public AssetBase Get(string id) { AssetBase asset = null; if (m_Cache != null) { asset = m_Cache.Get(id); } if (asset == null) { asset = m_AssetService.Get(id); if ((m_Cache != null) && (asset != null)) { m_Cache.Cache(asset); } } return(asset); }
private byte[] GetBakedTexture(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse) { string[] req = path.Split('/'); UUID avID = UUID.Parse(req[2]); UUID textureID = UUID.Parse(req[4]); AssetBase texture = m_assetService.Get(textureID.ToString()); if (texture == null) { MainConsole.Instance.WarnFormat("[AgentAppearanceService]: Could not find baked texture {0} for {1}", textureID, avID); return(new byte[0]); } MainConsole.Instance.InfoFormat("[AgentAppearanceService]: Found baked texture {0} for {1}", textureID, avID); // Full content request httpResponse.StatusCode = (int)System.Net.HttpStatusCode.OK; httpResponse.ContentType = texture.TypeString; return(texture.Data); }
protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { // Try to parse the texture ID from the request URL NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query); string meshStr = query.GetOne("mesh_id"); // m_log.DebugFormat("Fetching mesh {0}", meshStr); UUID meshID = UUID.Zero; if (!String.IsNullOrEmpty(meshStr) && UUID.TryParse(meshStr, out meshID)) { if (m_assetService == null) { httpResponse.StatusCode = 404; httpResponse.ContentType = "text/plain"; byte[] data = Encoding.UTF8.GetBytes("The asset service is unavailable. So is your mesh."); httpResponse.Body.Write(data, 0, data.Length); return(null); } AssetBase mesh = m_assetService.Get(meshID.ToString()); if (mesh != null) { if (mesh.Type == (SByte)AssetType.Mesh) { byte[] data = mesh.Data; httpResponse.Body.Write(data, 0, data.Length); httpResponse.ContentType = "application/vnd.ll.mesh"; httpResponse.StatusCode = 200; } // Optionally add additional mesh types here else { httpResponse.StatusCode = 404; httpResponse.ContentType = "text/plain"; byte[] data = Encoding.UTF8.GetBytes("Unfortunately, this asset isn't a mesh."); httpResponse.Body.Write(data, 0, data.Length); httpResponse.KeepAlive = false; } } else { httpResponse.StatusCode = 404; httpResponse.ContentType = "text/plain"; byte[] data = Encoding.UTF8.GetBytes("Your Mesh wasn't found. Sorry!"); httpResponse.Body.Write(data, 0, data.Length); httpResponse.KeepAlive = false; } } return(null); }
void SaveAsset(UUID AssetID, ref AvatarArchive archive, bool isPortable) { IDictionary <UUID, AssetType> assetUuids = new Dictionary <UUID, AssetType> (); AssetBase assetBase = assetService.Get(AssetID.ToString()); if (assetBase == null) { return; } if (isPortable) { assetGatherer.GatherAssetUuids(assetBase.ID, assetBase.TypeAsset, assetUuids); } else { // we need this one at least assetUuids [assetBase.ID] = assetBase.TypeAsset; } assetBase.Dispose(); // was //assetBase = null; // save the required assets foreach (KeyValuePair <UUID, AssetType> kvp in assetUuids) { var asset = assetService.Get(kvp.Key.ToString()); if (asset != null) { MainConsole.Instance.Debug("[Avatar Archiver]: Saving asset " + asset.ID); archive.AssetsMap [asset.ID.ToString()] = asset.ToOSD(); } else { MainConsole.Instance.Debug("[Avatar Archiver]: Could not find asset to save: " + kvp.Key); return; } asset.Dispose(); //was//asset = null; } }
private void SaveAsset(UUID AssetID, ref AvatarArchive archive) { try { AssetBase asset = AssetService.Get(AssetID.ToString()); if (asset != null) { MainConsole.Instance.Info("[AvatarArchive]: Saving asset " + asset.ID); archive.AssetsMap[asset.ID.ToString()] = asset.ToOSD(); } else { MainConsole.Instance.Warn("[AvatarArchive]: Could not find asset to save: " + AssetID.ToString()); return; } } catch (Exception ex) { MainConsole.Instance.Warn("[AvatarArchive]: Could not save asset: " + AssetID.ToString() + ", " + ex); } }
public AssetBase Get(string id) { string url = string.Empty; string assetID = string.Empty; if (Util.ParseForeignAssetID(id, out url, out assetID) > 0) { IAssetService connector = GetConnector(url); return(connector.Get(assetID)); } return(null); }
public async Task <ActionResult <Space> > Create(SpaceViewModel spaceIn) { if (ModelState.IsValid) { var space = new Space { Capacity = spaceIn.Capacity, Name = spaceIn.Name, SpaceTypeId = spaceIn.SpaceTypeId, Tags = spaceIn.Tags }; try { if (spaceIn.assets.Any()) { var assets = await _assetService.Get(spaceIn.assets); space.assests = assets; } var result = await _spaceService.Create(space); } catch (RessourceTypeRepositoryException ex) { ModelState.AddModelError(ex.Field, ex.Message); return(BadRequest(new ValidationProblemDetails(ModelState))); } catch (SpaceRepositoryException ex) { ModelState.AddModelError(ex.Field, ex.Message); return(BadRequest(new ValidationProblemDetails(ModelState))); } catch (AssetRepositoryException ex) { ModelState.AddModelError(ex.Field, ex.Message); return(BadRequest(new ValidationProblemDetails(ModelState))); } return(CreatedAtRoute("GetSpace", new { id = space.Id.ToString() }, space)); } return(BadRequest(new ValidationProblemDetails(ModelState))); }
/// <summary> /// Iterates through all Scenes, doing a deep scan through assets /// to update the access time of all assets present in the scene or referenced by assets /// in the scene. /// </summary> /// <param name="storeUncached"> /// If true, then assets scanned which are not found in cache are added to the cache. /// </param> /// <returns>Number of distinct asset references found in the scene.</returns> private int TouchAllSceneAssets(bool storeUncached) { UuidGatherer gatherer = new UuidGatherer(m_AssetService); Dictionary <UUID, bool> assetsFound = new Dictionary <UUID, bool>(); foreach (Scene s in m_Scenes) { StampRegionStatusFile(s.RegionInfo.RegionID); s.ForEachSOG(delegate(SceneObjectGroup e) { gatherer.AddForInspection(e); gatherer.GatherAll(); foreach (UUID assetID in gatherer.GatheredUuids.Keys) { if (!assetsFound.ContainsKey(assetID)) { string filename = GetFileName(assetID.ToString()); if (File.Exists(filename)) { UpdateFileLastAccessTime(filename); } else if (storeUncached) { AssetBase cachedAsset = m_AssetService.Get(assetID.ToString()); if (cachedAsset == null && gatherer.GatheredUuids[assetID] != (sbyte)AssetType.Unknown) { assetsFound[assetID] = false; } else { assetsFound[assetID] = true; } } } else if (!assetsFound[assetID]) { m_log.DebugFormat( "[FLOTSAM ASSET CACHE]: Could not find asset {0}, type {1} referenced by object {2} at {3} in scene {4} when pre-caching all scene assets", assetID, gatherer.GatheredUuids[assetID], e.Name, e.AbsolutePosition, s.Name); } } gatherer.GatheredUuids.Clear(); }); } return(assetsFound.Count); }
/// <summary> /// Iterates through all Scenes, doing a deep scan through assets /// to update the access time of all assets present in the scene or referenced by assets /// in the scene. /// </summary> /// <param name="storeUncached"> /// If true, then assets scanned which are not found in cache are added to the cache. /// </param> /// <returns>Number of distinct asset references found in the scene.</returns> private int TouchAllSceneAssets(bool storeUncached) { UuidGatherer gatherer = new UuidGatherer(m_AssetService); HashSet <UUID> uniqueUuids = new HashSet <UUID>(); m_Scenes.ForEach(delegate(Scene s) { StampRegionStatusFile(s.RegionInfo.RegionID); s.ForEachSOG(delegate(SceneObjectGroup e) { gatherer.AddForInspection(e); gatherer.GatherAll(); IDictionary <UUID, sbyte> assets = gatherer.GatheredUuids; foreach (UUID assetID in assets.Keys) { string filename = GetFileName(assetID.ToString()); if (File.Exists(filename)) { if (!uniqueUuids.Contains(assetID)) { File.SetLastAccessTime(filename, DateTime.Now); } } else if (storeUncached) { AssetBase cachedAsset = null; if (!uniqueUuids.Contains(assetID)) { cachedAsset = m_AssetService.Get(assetID.ToString()); } if (cachedAsset == null && assets[assetID] != (sbyte)AssetType.Unknown) { m_log.DebugFormat( "[FLOTSAM ASSET CACHE]: Could not find asset {0}, type {1} referenced by object {2} at {3} in scene {4} when pre-caching all scene assets", assetID, assets[assetID], e.Name, e.AbsolutePosition, s.Name); } } uniqueUuids.Add(assetID); } assets.Clear(); }); }); return(uniqueUuids.Count); }
public override byte[] Handle(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse) { byte[] result = new byte[0]; string[] p = SplitParams(path); if (p.Length == 0) { return(result); } if (p.Length > 1 && p[1] == "data") { result = m_AssetService.GetData(p[0]); if (result == null) { result = new byte[0]; } httpResponse.StatusCode = (int)HttpStatusCode.OK; httpResponse.ContentType = "application/octet-stream"; } else if (p.Length > 1 && p[1] == "metadata") { AssetMetadata metadata = m_AssetService.GetMetadata(p[0]); if (metadata != null) { XmlSerializer xs = new XmlSerializer(typeof(AssetMetadata)); result = ServerUtils.SerializeResult(xs, metadata); httpResponse.StatusCode = (int)HttpStatusCode.OK; httpResponse.ContentType = ServerUtils.SLAssetTypeToContentType(metadata.Type); } } else { AssetBase asset = m_AssetService.Get(p[0]); if (asset != null) { XmlSerializer xs = new XmlSerializer(typeof(AssetBase)); result = ServerUtils.SerializeResult(xs, asset); httpResponse.StatusCode = (int)HttpStatusCode.OK; httpResponse.ContentType = ServerUtils.SLAssetTypeToContentType(asset.Type); } } return(result); }
public bool Get(string id, object sender, AssetRetrieved handler) { string url = string.Empty; string assetID = string.Empty; if (Util.ParseForeignAssetID(id, out url, out assetID) > 0) { IAssetService connector = GetConnector(url); return(connector.Get(assetID, sender, handler)); } return(false); }
public bool Get(string id, Object sender, AssetRetrieved handler) { string url = string.Empty; string assetID = string.Empty; if (StringToUrlAndAssetID(id, out url, out assetID)) { IAssetService connector = GetConnector(url); return(connector.Get(assetID, sender, handler)); } return(false); }
private byte[] GetBakedTexture(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse) { string[] req = path.Split('/'); UUID avID = UUID.Parse(req[2]); string type = req[3]; UUID textureID = UUID.Parse(req[4]); //IAvatarService avService = m_registry.RequestModuleInterface<IAvatarService>(); //Aurora.Framework.ClientInterfaces.AvatarAppearance appearance = avService.GetAppearance(avID); //AvatarTextureIndex textureIndex = AppearanceManager.BakeTypeToAgentTextureIndex((BakeType)Enum.Parse(typeof(BakeType), type, true)); //AssetBase texture = m_assetService.Get(appearance.Texture.FaceTextures[(int)textureIndex].TextureID.ToString()); AssetBase texture = m_assetService.Get(textureID.ToString()); if (texture == null) { return(new byte[0]); } // Full content request httpResponse.StatusCode = (int)System.Net.HttpStatusCode.OK; httpResponse.ContentType = texture.TypeString; return(texture.Data); }
public AssetBase Get(string id) { string url = string.Empty; string assetID = string.Empty; if (StringToUrlAndAssetID(id, out url, out assetID)) { IAssetService connector = GetConnector(url); return(connector.Get(assetID)); } return(null); }
private async Task <HistoricalTransactionContract> ConvertToHistoricalTransactionContractAsync( TransactionReceipt transactionReceipt) { return(new HistoricalTransactionContract { Amount = transactionReceipt.Amount.ToString(), AssetId = _assetService.Get().Id, FromAddress = await _addressService.AddChecksumAsync(transactionReceipt.From), Hash = transactionReceipt.Hash, Timestamp = DateTimeOffset.FromUnixTimeSeconds((long)transactionReceipt.Timestamp).UtcDateTime, ToAddress = await _addressService.AddChecksumAsync(transactionReceipt.To) }); }
AssetBase FetchAsset(UUID assetID, bool isTexture) { // Remote call to the Asset server if (m_assetProvider == null) { return(m_AssetClient.SyncGetAsset(assetID, isTexture)); } // local call else { return(m_assetProvider.Get(assetID.ToString())); } }
public AssetBase Get(string id) { AssetBase asset = m_assetConnector.Get(id); if (asset == null) { return(null); } if (!m_AssetPerms.AllowedExport(asset.Type)) { return(null); } if (asset.Metadata.Type == (sbyte)AssetType.Object) { asset.Data = AdjustIdentifiers(asset.Data); } AdjustIdentifiers(asset.Metadata); return(asset); }
//Constructor public LLImageManager(LLClientView client, IAssetService pAssetCache, IJ2KDecoder pJ2kDecodeModule) { m_imagestore = new Dictionary<UUID,J2KImage>(); m_priorities = new SortedList<double,UUID>(); m_priorityresolver = new Dictionary<int, int>(); m_client = client; m_assetCache = pAssetCache; if (pAssetCache != null) m_missingsubstitute = pAssetCache.Get("5748decc-f629-461c-9a36-a35a221fe21f"); else m_log.Error("[ClientView] - couldn't set missing image, all manner of things will probably break"); m_j2kDecodeModule = pJ2kDecodeModule; }
public LLImageManager(LLClientView client, IAssetService pAssetCache, IJ2KDecoder pJ2kDecodeModule) { m_client = client; m_assetCache = pAssetCache; if (pAssetCache != null && m_missingImage == null) m_missingImage = pAssetCache.Get("5748decc-f629-461c-9a36-a35a221fe21f"); if (m_missingImage == null) MainConsole.Instance.Error( "[ClientView] - Couldn't set missing image asset, falling back to missing image packet. This is known to crash the client"); m_j2kDecodeModule = pJ2kDecodeModule; }
/// <summary> /// Builds a composited terrain texture given the region texture /// and heightmap settings /// </summary> /// <param name="heightmap">Terrain heightmap</param> /// <param name="regionInfo">Region information including terrain texture parameters</param> /// <returns>A composited 256x256 RGB texture ready for rendering</returns> /// <remarks>Based on the algorithm described at http://opensimulator.org/wiki/Terrain_Splatting /// </remarks> public static Bitmap Splat(float[] heightmap, UUID[] textureIDs, float[] startHeights, float[] heightRanges, Vector3d regionPosition, IAssetService assetService, bool textureTerrain) { Debug.Assert(heightmap.Length == 256 * 256); Debug.Assert(textureIDs.Length == 4); Debug.Assert(startHeights.Length == 4); Debug.Assert(heightRanges.Length == 4); Bitmap[] detailTexture = new Bitmap[4]; if (textureTerrain) { // Swap empty terrain textureIDs with default IDs for (int i = 0; i < textureIDs.Length; i++) { if (textureIDs[i] == UUID.Zero) textureIDs[i] = DEFAULT_TERRAIN_DETAIL[i]; } #region Texture Fetching if (assetService != null) { for (int i = 0; i < 4; i++) { AssetBase asset; UUID cacheID = UUID.Combine(TERRAIN_CACHE_MAGIC, textureIDs[i]); // Try to fetch a cached copy of the decoded/resized version of this texture asset = assetService.GetCached(cacheID.ToString()); if (asset != null) { try { using (System.IO.MemoryStream stream = new System.IO.MemoryStream(asset.Data)) detailTexture[i] = (Bitmap)Image.FromStream(stream); } catch (Exception ex) { m_log.Warn("Failed to decode cached terrain texture " + cacheID + " (textureID: " + textureIDs[i] + "): " + ex.Message); } } if (detailTexture[i] == null) { // Try to fetch the original JPEG2000 texture, resize if needed, and cache as PNG asset = assetService.Get(textureIDs[i].ToString()); if (asset != null) { try { detailTexture[i] = (Bitmap)CSJ2K.J2kImage.FromBytes(asset.Data); } catch (Exception ex) { m_log.Warn("Failed to decode terrain texture " + asset.ID + ": " + ex.Message); } } if (detailTexture[i] != null) { Bitmap bitmap = detailTexture[i]; // Make sure this texture is the correct size, otherwise resize if (bitmap.Width != 256 || bitmap.Height != 256) bitmap = ImageUtils.ResizeImage(bitmap, 256, 256); // Save the decoded and resized texture to the cache byte[] data; using (System.IO.MemoryStream stream = new System.IO.MemoryStream()) { bitmap.Save(stream, ImageFormat.Png); data = stream.ToArray(); } // Cache a PNG copy of this terrain texture AssetBase newAsset = new AssetBase { Data = data, Description = "PNG", Flags = AssetFlags.Collectable, FullID = cacheID, ID = cacheID.ToString(), Local = true, Name = String.Empty, Temporary = true, Type = (sbyte)AssetType.Simstate // Make something up to get around OpenSim's myopic treatment of assets }; newAsset.Metadata.ContentType = "image/png"; assetService.Store(newAsset); } } } } #endregion Texture Fetching } // Fill in any missing textures with a solid color for (int i = 0; i < 4; i++) { if (detailTexture[i] == null) { // Create a solid color texture for this layer detailTexture[i] = new Bitmap(256, 256, PixelFormat.Format24bppRgb); using (Graphics gfx = Graphics.FromImage(detailTexture[i])) { using (SolidBrush brush = new SolidBrush(DEFAULT_TERRAIN_COLOR[i])) gfx.FillRectangle(brush, 0, 0, 256, 256); } } } #region Layer Map float[] layermap = new float[256 * 256]; for (int y = 0; y < 256; y++) { for (int x = 0; x < 256; x++) { float height = heightmap[y * 256 + x]; float pctX = (float)x / 255f; float pctY = (float)y / 255f; // Use bilinear interpolation between the four corners of start height and // height range to select the current values at this position float startHeight = ImageUtils.Bilinear( startHeights[0], startHeights[2], startHeights[1], startHeights[3], pctX, pctY); startHeight = Utils.Clamp(startHeight, 0f, 255f); float heightRange = ImageUtils.Bilinear( heightRanges[0], heightRanges[2], heightRanges[1], heightRanges[3], pctX, pctY); heightRange = Utils.Clamp(heightRange, 0f, 255f); // Generate two frequencies of perlin noise based on our global position // The magic values were taken from http://opensimulator.org/wiki/Terrain_Splatting Vector3 vec = new Vector3 ( ((float)regionPosition.X + x) * 0.20319f, ((float)regionPosition.Y + y) * 0.20319f, height * 0.25f ); float lowFreq = Perlin.noise2(vec.X * 0.222222f, vec.Y * 0.222222f) * 6.5f; float highFreq = Perlin.turbulence2(vec.X, vec.Y, 2f) * 2.25f; float noise = (lowFreq + highFreq) * 2f; // Combine the current height, generated noise, start height, and height range parameters, then scale all of it float layer = ((height + noise - startHeight) / heightRange) * 4f; if (Single.IsNaN(layer)) layer = 0f; layermap[y * 256 + x] = Utils.Clamp(layer, 0f, 3f); } } #endregion Layer Map #region Texture Compositing Bitmap output = new Bitmap(256, 256, PixelFormat.Format24bppRgb); BitmapData outputData = output.LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb); unsafe { // Get handles to all of the texture data arrays BitmapData[] datas = new BitmapData[] { detailTexture[0].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[0].PixelFormat), detailTexture[1].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[1].PixelFormat), detailTexture[2].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[2].PixelFormat), detailTexture[3].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[3].PixelFormat) }; int[] comps = new int[] { (datas[0].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3, (datas[1].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3, (datas[2].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3, (datas[3].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3 }; for (int y = 0; y < 256; y++) { for (int x = 0; x < 256; x++) { float layer = layermap[y * 256 + x]; // Select two textures int l0 = (int)Math.Floor(layer); int l1 = Math.Min(l0 + 1, 3); byte* ptrA = (byte*)datas[l0].Scan0 + y * datas[l0].Stride + x * comps[l0]; byte* ptrB = (byte*)datas[l1].Scan0 + y * datas[l1].Stride + x * comps[l1]; byte* ptrO = (byte*)outputData.Scan0 + y * outputData.Stride + x * 3; float aB = *(ptrA + 0); float aG = *(ptrA + 1); float aR = *(ptrA + 2); float bB = *(ptrB + 0); float bG = *(ptrB + 1); float bR = *(ptrB + 2); float layerDiff = layer - l0; // Interpolate between the two selected textures *(ptrO + 0) = (byte)Math.Floor(aB + layerDiff * (bB - aB)); *(ptrO + 1) = (byte)Math.Floor(aG + layerDiff * (bG - aG)); *(ptrO + 2) = (byte)Math.Floor(aR + layerDiff * (bR - aR)); } } for (int i = 0; i < 4; i++) detailTexture[i].UnlockBits(datas[i]); } output.UnlockBits(outputData); // We generated the texture upside down, so flip it output.RotateFlip(RotateFlipType.RotateNoneFlipY); #endregion Texture Compositing return output; }
/// <summary> /// Builds a composited terrain texture given the region texture /// and heightmap settings /// </summary> /// <param name="heightmap">Terrain heightmap</param> /// <param name="textureIDs"></param> /// <param name="startHeights"></param> /// <param name="heightRanges"></param> /// <param name="regionPosition"></param> /// <param name="assetService"></param> /// <param name="textureTerrain"></param> /// <returns>A composited 256x256 RGB texture ready for rendering</returns> /// <remarks> /// Based on the algorithm described at http://opensimulator.org/wiki/Terrain_Splatting /// </remarks> public static Bitmap Splat(ITerrainChannel heightmap, UUID[] textureIDs, float[] startHeights, float[] heightRanges, Vector3d regionPosition, IAssetService assetService, bool textureTerrain) { Debug.Assert(textureIDs.Length == 4); Debug.Assert(startHeights.Length == 4); Debug.Assert(heightRanges.Length == 4); Bitmap[] detailTexture = new Bitmap[4]; int outWidth = heightmap.Width; int outHeight = heightmap.Height; IJ2KDecoder m_imgDecoder; if (textureTerrain) { // Swap empty terrain textureIDs with default IDs for (int i = 0; i < textureIDs.Length; i++) { if (textureIDs[i] == UUID.Zero) textureIDs[i] = DEFAULT_TERRAIN_DETAIL[i]; } #region Texture Fetching if (assetService != null) { m_imgDecoder = heightmap.Scene.RequestModuleInterface<IJ2KDecoder>(); for (int i = 0; i < 4; i++) { UUID cacheID = UUID.Combine(TERRAIN_CACHE_MAGIC, textureIDs[i]); AssetBase asset = assetService.Get(cacheID.ToString(),false); // ignore warnings here as the cached texture may not exist if ((asset != null) && (asset.Data != null) && (asset.Data.Length != 0)) { try { using (MemoryStream stream = new MemoryStream(asset.Data)) detailTexture[i] = (Bitmap) Image.FromStream(stream); } catch (Exception ex) { MainConsole.Instance.Warn("Failed to decode cached terrain texture " + cacheID + " (textureID: " + textureIDs[i] + "): " + ex.Message); } } if (detailTexture[i] == null) { // Try to fetch the original JPEG2000 texture, resize if needed, and cache as PNG byte[] assetData = assetService.GetData(textureIDs[i].ToString()); if (assetData != null) { try { detailTexture[i] = (Bitmap)m_imgDecoder.DecodeToImage(assetData); } catch (Exception ex) { MainConsole.Instance.Warn("Failed to decode terrain texture " + textureIDs[i] + ": " + ex.Message); } } if (detailTexture[i] != null) { Bitmap bitmap = detailTexture[i]; // Make sure this texture is the correct size, otherwise resize if (bitmap.Width != outWidth || bitmap.Height != outHeight) bitmap = ImageUtils.ResizeImage(bitmap, outWidth, outHeight); // Save the decoded and resized texture to the cache byte[] data; using (MemoryStream stream = new MemoryStream()) { bitmap.Save(stream, ImageFormat.Png); data = stream.ToArray(); } // Cache a PNG copy of this terrain texture AssetBase newAsset = new AssetBase { Data = data, Description = "PNG", Flags = AssetFlags.Collectable | AssetFlags.Temporary | AssetFlags.Local, ID = cacheID, Name = String.Empty, TypeString = "image/png" }; newAsset.ID = assetService.Store(newAsset); } } } } #endregion Texture Fetching } // Fill in any missing textures with a solid color for (int i = 0; i < 4; i++) { if (detailTexture[i] == null) { // Create a solid color texture for this layer detailTexture[i] = new Bitmap(outWidth, outHeight, PixelFormat.Format24bppRgb); using (Graphics gfx = Graphics.FromImage(detailTexture[i])) { using (SolidBrush brush = new SolidBrush(DEFAULT_TERRAIN_COLOR[i])) gfx.FillRectangle(brush, 0, 0, outWidth, outHeight); } } else if (detailTexture[i].Width != outWidth || detailTexture[i].Height != outHeight) { detailTexture[i] = ResizeBitmap(detailTexture[i], outWidth, outHeight); } } #region Layer Map float diffX = 1.0f; float diffY = 1.0f; int newRsX = heightmap.Width / (int)diffX; int newRsY = heightmap.Height / (int)diffY; float[] layermap = new float[newRsX*newRsY]; for (float y = 0; y < heightmap.Height; y += diffY) { for (float x = 0; x < heightmap.Width; x += diffX) { float newX = x/diffX; float newY = y/diffY; float height = heightmap[(int) x, (int) y]; float pctX = newX/255f; float pctY = newY/255f; // Use bilinear interpolation between the four corners of start height and // height range to select the current values at this position float startHeight = ImageUtils.Bilinear( startHeights[0], startHeights[2], startHeights[1], startHeights[3], pctX, pctY); startHeight = Utils.Clamp(startHeight, 0f, 255f); float heightRange = ImageUtils.Bilinear( heightRanges[0], heightRanges[2], heightRanges[1], heightRanges[3], pctX, pctY); heightRange = Utils.Clamp(heightRange, 0f, 255f); // Generate two frequencies of perlin noise based on our global position // The magic values were taken from http://opensimulator.org/wiki/Terrain_Splatting Vector3 vec = new Vector3 ( ((float) regionPosition.X + newX)*0.20319f, ((float) regionPosition.Y + newY)*0.20319f, height*0.25f ); float lowFreq = Perlin.noise2(vec.X*0.222222f, vec.Y*0.222222f)*6.5f; float highFreq = Perlin.turbulence2(vec.X, vec.Y, 2f)*2.25f; float noise = (lowFreq + highFreq)*2f; // Combine the current height, generated noise, start height, and height range parameters, then scale all of it float layer = ((height + noise - startHeight)/heightRange)*4f; if (Single.IsNaN(layer)) layer = 0f; layermap[(int) (newY*newRsX + newX)] = Utils.Clamp(layer, 0f, 3f); } } #endregion Layer Map #region Texture Compositing Bitmap output = new Bitmap(outWidth, outHeight, PixelFormat.Format24bppRgb); BitmapData outputData = output.LockBits(new Rectangle(0, 0, outWidth, outHeight), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb); unsafe { // Get handles to all of the texture data arrays BitmapData[] datas = new[] { detailTexture[0].LockBits(new Rectangle(0, 0, outWidth, outHeight), ImageLockMode.ReadOnly, detailTexture[0].PixelFormat), detailTexture[1].LockBits(new Rectangle(0, 0, outWidth, outHeight), ImageLockMode.ReadOnly, detailTexture[1].PixelFormat), detailTexture[2].LockBits(new Rectangle(0, 0, outWidth, outHeight), ImageLockMode.ReadOnly, detailTexture[2].PixelFormat), detailTexture[3].LockBits(new Rectangle(0, 0, outWidth, outHeight), ImageLockMode.ReadOnly, detailTexture[3].PixelFormat) }; int[] comps = new[] { (datas[0].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3, (datas[1].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3, (datas[2].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3, (datas[3].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3 }; for (int y = 0; y < newRsY; y++) { for (int x = 0; x < newRsX; x++) { float layer = layermap[y*newRsX + x]; // Select two textures int l0 = (int) Math.Floor(layer); int l1 = Math.Min(l0 + 1, 3); byte* ptrA = (byte*) datas[l0].Scan0 + y*datas[l0].Stride + x*comps[l0]; byte* ptrB = (byte*) datas[l1].Scan0 + y*datas[l1].Stride + x*comps[l1]; byte* ptrO = (byte*) outputData.Scan0 + y*outputData.Stride + x*3; float aB = *(ptrA + 0); float aG = *(ptrA + 1); float aR = *(ptrA + 2); float bB = *(ptrB + 0); float bG = *(ptrB + 1); float bR = *(ptrB + 2); float layerDiff = layer - l0; // Interpolate between the two selected textures *(ptrO + 0) = (byte) Math.Floor(aB + layerDiff*(bB - aB)); *(ptrO + 1) = (byte) Math.Floor(aG + layerDiff*(bG - aG)); *(ptrO + 2) = (byte) Math.Floor(aR + layerDiff*(bR - aR)); } } for (int i = 0; i < 4; i++) { detailTexture[i].UnlockBits(datas[i]); detailTexture[i].Dispose(); } } layermap = null; output.UnlockBits(outputData); // We generated the texture upside down, so flip it output.RotateFlip(RotateFlipType.RotateNoneFlipY); #endregion Texture Compositing return output; }