aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/OptionalModules/Materials/MaterialsDemoModule.cs382
1 files changed, 382 insertions, 0 deletions
diff --git a/OpenSim/Region/OptionalModules/Materials/MaterialsDemoModule.cs b/OpenSim/Region/OptionalModules/Materials/MaterialsDemoModule.cs
new file mode 100644
index 0000000..de2c3fc
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/Materials/MaterialsDemoModule.cs
@@ -0,0 +1,382 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.Reflection;
32using System.Security.Cryptography; // for computing md5 hash
33using log4net;
34using Mono.Addins;
35using Nini.Config;
36
37using OpenMetaverse;
38using OpenMetaverse.StructuredData;
39
40using OpenSim.Framework;
41using OpenSim.Framework.Servers;
42using OpenSim.Framework.Servers.HttpServer;
43using OpenSim.Region.Framework.Interfaces;
44using OpenSim.Region.Framework.Scenes;
45
46using Ionic.Zlib;
47
48// You will need to uncomment these lines if you are adding a region module to some other assembly which does not already
49// specify its assembly. Otherwise, the region modules in the assembly will not be picked up when OpenSimulator scans
50// the available DLLs
51//[assembly: Addin("MyModule", "1.0")]
52//[assembly: AddinDependency("OpenSim", "0.5")]
53
54namespace OpenSim.Region.OptionalModules.MaterialsDemoModule
55{
56 /// <summary>
57 ///
58 // # # ## ##### # # # # # ####
59 // # # # # # # ## # # ## # # #
60 // # # # # # # # # # # # # # #
61 // # ## # ###### ##### # # # # # # # # ###
62 // ## ## # # # # # ## # # ## # #
63 // # # # # # # # # # # # ####
64 //
65 //
66 //
67 ////////////// WARNING //////////////////////////////////////////////////////////////////
68 /// This is an *Experimental* module for developing support for materials-capable viewers
69 /// This module should NOT be used in a production environment! It may cause data corruption and
70 /// viewer crashes. It should be only used to evaluate implementations of materials.
71 ///
72 /// CURRENTLY NO MATERIALS ARE PERSISTED ACROSS SIMULATOR RESTARTS OR ARE STORED IN ANY INVENTORY OR ASSETS
73 /// This may change in future implementations.
74 ///
75 /// To enable this module, add this string at the bottom of OpenSim.ini:
76 /// [MaterialsDemoModule]
77 ///
78 /// </summary>
79 ///
80
81 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MaterialsDemoModule")]
82 public class MaterialsDemoModule : INonSharedRegionModule
83 {
84 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
85
86 public string Name { get { return "MaterialsDemoModule"; } }
87
88 public Type ReplaceableInterface { get { return null; } }
89
90 private Scene m_scene = null;
91 private bool m_enabled = false;
92
93 public void Initialise(IConfigSource source)
94 {
95 m_enabled = (source.Configs["MaterialsDemoModule"] != null);
96 if (!m_enabled)
97 return;
98
99 m_log.DebugFormat("[MaterialsDemoModule]: INITIALIZED MODULE");
100
101 }
102
103 public void Close()
104 {
105 if (!m_enabled)
106 return;
107
108 m_log.DebugFormat("[MaterialsDemoModule]: CLOSED MODULE");
109 }
110
111 public void AddRegion(Scene scene)
112 {
113 if (!m_enabled)
114 return;
115
116 m_log.DebugFormat("[MaterialsDemoModule]: REGION {0} ADDED", scene.RegionInfo.RegionName);
117 m_scene = scene;
118 m_scene.EventManager.OnRegisterCaps += new EventManager.RegisterCapsEvent(OnRegisterCaps);
119 }
120
121 void OnRegisterCaps(OpenMetaverse.UUID agentID, OpenSim.Framework.Capabilities.Caps caps)
122 {
123 string capsBase = "/CAPS/" + caps.CapsObjectPath;
124
125 IRequestHandler renderMaterialsPostHandler = new RestStreamHandler("POST", capsBase + "/", RenderMaterialsPostCap);
126 caps.RegisterHandler("RenderMaterials", renderMaterialsPostHandler);
127
128 // OpenSimulator CAPs infrastructure seems to be somewhat hostile towards any CAP that requires both GET
129 // and POST handlers, (at least at the time this was originally written), so we first set up a POST
130 // handler normally and then add a GET handler via MainServer
131
132 IRequestHandler renderMaterialsGetHandler = new RestStreamHandler("GET", capsBase + "/", RenderMaterialsGetCap);
133 MainServer.Instance.AddStreamHandler(renderMaterialsGetHandler);
134 }
135
136 public void RemoveRegion(Scene scene)
137 {
138 if (!m_enabled)
139 return;
140
141 m_log.DebugFormat("[MaterialsDemoModule]: REGION {0} REMOVED", scene.RegionInfo.RegionName);
142 }
143
144 public void RegionLoaded(Scene scene)
145 {
146 if (!m_enabled)
147 return;
148 m_log.DebugFormat("[MaterialsDemoModule]: REGION {0} LOADED", scene.RegionInfo.RegionName);
149 }
150
151 public string RenderMaterialsPostCap(string request, string path,
152 string param, IOSHttpRequest httpRequest,
153 IOSHttpResponse httpResponse)
154 {
155 m_log.Debug("[MaterialsDemoModule]: POST cap handler");
156
157 OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
158 OSDMap resp = new OSDMap();
159
160 OSDMap materialsFromViewer = null;
161
162 if (req.ContainsKey("Zipped"))
163 {
164 OSD osd = null;
165
166 byte[] inBytes = req["Zipped"].AsBinary();
167
168 try
169 {
170 osd = ZDecompressBytesToOsd(inBytes);
171
172 if (osd != null && osd is OSDMap)
173 {
174 materialsFromViewer = osd as OSDMap;
175
176 if (materialsFromViewer.ContainsKey("FullMaterialsPerFace"))
177 {
178 OSD matsOsd = materialsFromViewer["FullMaterialsPerFace"];
179 if (matsOsd is OSDArray)
180 {
181 OSDArray matsArr = matsOsd as OSDArray;
182
183 try
184 {
185 foreach (OSDMap matsMap in matsArr)
186 {
187 m_log.Debug("[MaterialsDemoModule]: processing matsMap: " + OSDParser.SerializeJsonString(matsMap));
188
189 uint matLocalID = 0;
190 try { matLocalID = matsMap["ID"].AsUInteger(); }
191 catch (Exception e) { m_log.Warn("[MaterialsDemoModule]: cannot decode \"ID\" from matsMap: " + e.Message); }
192 m_log.Debug("[MaterialsDemoModule]: matLocalId: " + matLocalID.ToString());
193
194
195 OSDMap mat = null;
196 try { mat = matsMap["Material"] as OSDMap; }
197 catch (Exception e) { m_log.Warn("[MaterialsDemoModule]: cannot decode \"Material\" from matsMap: " + e.Message); }
198 m_log.Debug("[MaterialsDemoModule]: mat: " + OSDParser.SerializeJsonString(mat));
199
200 UUID id = HashOsd(mat);
201 m_knownMaterials[id] = mat;
202
203
204 var sop = m_scene.GetSceneObjectPart(matLocalID);
205 if (sop == null)
206 m_log.Debug("[MaterialsDemoModule]: null SOP for localId: " + matLocalID.ToString());
207 else
208 {
209 var te = sop.Shape.Textures;
210
211 if (te == null)
212 {
213 m_log.Debug("[MaterialsDemoModule]: null TextureEntry for localId: " + matLocalID.ToString());
214 }
215 else
216 {
217 int face = -1;
218
219 if (matsMap.ContainsKey("Face"))
220 {
221 face = matsMap["Face"].AsInteger();
222 if (te.FaceTextures == null) // && face == 0)
223 {
224 if (te.DefaultTexture == null)
225 m_log.Debug("[MaterialsDemoModule]: te.DefaultTexture is null");
226 else
227 {
228 if (te.DefaultTexture.MaterialID == null)
229 m_log.Debug("[MaterialsDemoModule]: te.DefaultTexture.MaterialID is null");
230 else
231 {
232 te.DefaultTexture.MaterialID = id;
233 }
234 }
235 }
236 else
237 {
238 if (te.FaceTextures.Length >= face - 1)
239 {
240 if (te.FaceTextures[face] == null)
241 te.DefaultTexture.MaterialID = id;
242 else
243 te.FaceTextures[face].MaterialID = id;
244 }
245 }
246 }
247 else
248 {
249 if (te.DefaultTexture != null)
250 te.DefaultTexture.MaterialID = id;
251 }
252
253 m_log.Debug("[MaterialsDemoModule]: setting material ID for face " + face.ToString() + " to " + id.ToString());
254
255 sop.UpdateTextureEntry(te);
256 }
257 }
258 }
259 }
260 catch (Exception e)
261 {
262 m_log.Warn("[MaterialsDemoModule]: exception processing received material: " + e.Message);
263 }
264 }
265 }
266 }
267 }
268 catch (Exception e)
269 {
270 m_log.Warn("[MaterialsDemoModule]: exception decoding zipped CAP payload: " + e.Message);
271 //return "";
272 }
273 m_log.Debug("[MaterialsDemoModule]: knownMaterials.Count: " + m_knownMaterials.Count.ToString());
274 }
275
276
277 string response = OSDParser.SerializeLLSDXmlString(resp);
278
279 m_log.Debug("[MaterialsDemoModule]: cap request: " + request);
280 m_log.Debug("[MaterialsDemoModule]: cap response: " + response);
281 return response;
282 }
283
284
285 public string RenderMaterialsGetCap(string request, string path,
286 string param, IOSHttpRequest httpRequest,
287 IOSHttpResponse httpResponse)
288 {
289 m_log.Debug("[MaterialsDemoModule]: GET cap handler");
290
291 OSDMap resp = new OSDMap();
292
293
294 int matsCount = 0;
295
296 OSDArray allOsd = new OSDArray();
297
298 foreach (KeyValuePair<UUID, OSDMap> kvp in m_knownMaterials)
299 {
300 OSDMap matMap = new OSDMap();
301
302 matMap["ID"] = OSD.FromBinary(kvp.Key.GetBytes());
303
304 matMap["Material"] = kvp.Value;
305 allOsd.Add(matMap);
306 matsCount++;
307 }
308
309
310 resp["Zipped"] = ZCompressOSD(allOsd, false);
311 m_log.Debug("[MaterialsDemoModule]: matsCount: " + matsCount.ToString());
312
313 return OSDParser.SerializeLLSDXmlString(resp);
314 }
315
316 public Dictionary<UUID, OSDMap> m_knownMaterials = new Dictionary<UUID, OSDMap>();
317
318 /// <summary>
319 /// computes a UUID by hashing a OSD object
320 /// </summary>
321 /// <param name="osd"></param>
322 /// <returns></returns>
323 private static UUID HashOsd(OSD osd)
324 {
325 using (var md5 = MD5.Create())
326 using (MemoryStream ms = new MemoryStream(OSDParser.SerializeLLSDBinary(osd, false)))
327 return new UUID(md5.ComputeHash(ms), 0);
328 }
329
330 public static OSD ZCompressOSD(OSD inOsd, bool useHeader = true)
331 {
332 OSD osd = null;
333
334 using (MemoryStream msSinkCompressed = new MemoryStream())
335 {
336 using (Ionic.Zlib.ZlibStream zOut = new Ionic.Zlib.ZlibStream(msSinkCompressed,
337 Ionic.Zlib.CompressionMode.Compress, CompressionLevel.BestCompression, true))
338 {
339 CopyStream(new MemoryStream(OSDParser.SerializeLLSDBinary(inOsd, useHeader)), zOut);
340 zOut.Close();
341 }
342
343 msSinkCompressed.Seek(0L, SeekOrigin.Begin);
344 osd = OSD.FromBinary( msSinkCompressed.ToArray());
345 }
346
347 return osd;
348 }
349
350
351 public static OSD ZDecompressBytesToOsd(byte[] input)
352 {
353 OSD osd = null;
354
355 using (MemoryStream msSinkUnCompressed = new MemoryStream())
356 {
357 using (Ionic.Zlib.ZlibStream zOut = new Ionic.Zlib.ZlibStream(msSinkUnCompressed, CompressionMode.Decompress, true))
358 {
359 CopyStream(new MemoryStream(input), zOut);
360 zOut.Close();
361 }
362 msSinkUnCompressed.Seek(0L, SeekOrigin.Begin);
363 osd = OSDParser.DeserializeLLSDBinary(msSinkUnCompressed.ToArray());
364 }
365
366 return osd;
367 }
368
369 static void CopyStream(System.IO.Stream input, System.IO.Stream output)
370 {
371 byte[] buffer = new byte[2048];
372 int len;
373 while ((len = input.Read(buffer, 0, 2048)) > 0)
374 {
375 output.Write(buffer, 0, len);
376 }
377
378 output.Flush();
379 }
380
381 }
382} \ No newline at end of file