aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs')
-rw-r--r--OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs664
1 files changed, 664 insertions, 0 deletions
diff --git a/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs b/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs
new file mode 100644
index 0000000..e707154
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs
@@ -0,0 +1,664 @@
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("MaterialsDemoModule", "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 // THIS MODULE IS FOR EXPERIMENTAL USE ONLY AND MAY CAUSE REGION OR ASSET CORRUPTION!
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 /// Materials are persisted via SceneObjectPart.dynattrs. This is a relatively new feature
73 /// of OpenSimulator and is not field proven at the time this module was written. Persistence
74 /// may fail or become corrupt and this could cause viewer crashes due to erroneous materials
75 /// data being sent to viewers. Materials descriptions might survive IAR, OAR, or other means
76 /// of archiving however the texture resources used by these materials probably will not as they
77 /// may not be adequately referenced to ensure proper archiving.
78 ///
79 ///
80 ///
81 /// To enable this module, add this string at the bottom of OpenSim.ini:
82 /// [MaterialsDemoModule]
83 ///
84 /// </summary>
85 ///
86
87 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MaterialsDemoModule")]
88 public class MaterialsDemoModule : INonSharedRegionModule
89 {
90 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
91
92 public string Name { get { return "MaterialsDemoModule"; } }
93
94 public Type ReplaceableInterface { get { return null; } }
95
96 private Scene m_scene = null;
97 private bool m_enabled = false;
98
99 public Dictionary<UUID, OSDMap> m_knownMaterials = new Dictionary<UUID, OSDMap>();
100
101 public void Initialise(IConfigSource source)
102 {
103 m_enabled = (source.Configs["MaterialsDemoModule"] != null);
104 if (!m_enabled)
105 return;
106
107 m_log.DebugFormat("[MaterialsDemoModule]: Initialized");
108 }
109
110 public void Close()
111 {
112 if (!m_enabled)
113 return;
114
115 //m_log.DebugFormat("[MaterialsDemoModule]: CLOSED MODULE");
116 }
117
118 public void AddRegion(Scene scene)
119 {
120 if (!m_enabled)
121 return;
122
123 //m_log.DebugFormat("[MaterialsDemoModule]: REGION {0} ADDED", scene.RegionInfo.RegionName);
124
125 m_scene = scene;
126 m_scene.EventManager.OnRegisterCaps += OnRegisterCaps;
127 m_scene.EventManager.OnObjectAddedToScene += EventManager_OnObjectAddedToScene;
128// m_scene.EventManager.OnGatherUuids += GatherMaterialsUuids;
129 }
130
131 void EventManager_OnObjectAddedToScene(SceneObjectGroup obj)
132 {
133 foreach (var part in obj.Parts)
134 if (part != null)
135 GetStoredMaterialsForPart(part);
136 }
137
138 void OnRegisterCaps(OpenMetaverse.UUID agentID, OpenSim.Framework.Capabilities.Caps caps)
139 {
140 string capsBase = "/CAPS/" + caps.CapsObjectPath;
141
142 IRequestHandler renderMaterialsPostHandler
143 = new RestStreamHandler("POST", capsBase + "/", RenderMaterialsPostCap, "RenderMaterials", null);
144 caps.RegisterHandler("RenderMaterials", renderMaterialsPostHandler);
145
146 // OpenSimulator CAPs infrastructure seems to be somewhat hostile towards any CAP that requires both GET
147 // and POST handlers, (at least at the time this was originally written), so we first set up a POST
148 // handler normally and then add a GET handler via MainServer
149
150 IRequestHandler renderMaterialsGetHandler
151 = new RestStreamHandler("GET", capsBase + "/", RenderMaterialsGetCap, "RenderMaterials", null);
152 MainServer.Instance.AddStreamHandler(renderMaterialsGetHandler);
153
154 // materials viewer seems to use either POST or PUT, so assign POST handler for PUT as well
155 IRequestHandler renderMaterialsPutHandler
156 = new RestStreamHandler("PUT", capsBase + "/", RenderMaterialsPostCap, "RenderMaterials", null);
157 MainServer.Instance.AddStreamHandler(renderMaterialsPutHandler);
158 }
159
160 public void RemoveRegion(Scene scene)
161 {
162 if (!m_enabled)
163 return;
164
165 m_scene.EventManager.OnRegisterCaps -= OnRegisterCaps;
166 m_scene.EventManager.OnObjectAddedToScene -= EventManager_OnObjectAddedToScene;
167// m_scene.EventManager.OnGatherUuids -= GatherMaterialsUuids;
168
169 //m_log.DebugFormat("[MaterialsDemoModule]: REGION {0} REMOVED", scene.RegionInfo.RegionName);
170 }
171
172 public void RegionLoaded(Scene scene)
173 {
174 }
175
176 OSDMap GetMaterial(UUID id)
177 {
178 OSDMap map = null;
179 lock (m_knownMaterials)
180 {
181 if (m_knownMaterials.ContainsKey(id))
182 {
183 map = new OSDMap();
184 map["ID"] = OSD.FromBinary(id.GetBytes());
185 map["Material"] = m_knownMaterials[id];
186 }
187 }
188 return map;
189 }
190
191 void GetStoredMaterialsForPart(SceneObjectPart part)
192 {
193 OSD OSMaterials = null;
194 OSDArray matsArr = null;
195
196 if (part.DynAttrs == null)
197 {
198 //m_log.Warn("[MaterialsDemoModule]: NULL DYNATTRS :( ");
199 return;
200 }
201
202 lock (part.DynAttrs)
203 {
204 if (part.DynAttrs.ContainsStore("OpenSim", "Materials"))
205 {
206 OSDMap materialsStore = part.DynAttrs.GetStore("OpenSim", "Materials");
207
208 if (materialsStore == null)
209 return;
210
211 materialsStore.TryGetValue("Materials", out OSMaterials);
212 }
213
214 if (OSMaterials != null && OSMaterials is OSDArray)
215 matsArr = OSMaterials as OSDArray;
216 else
217 return;
218 }
219
220 //m_log.Info("[MaterialsDemoModule]: OSMaterials: " + OSDParser.SerializeJsonString(OSMaterials));
221
222 if (matsArr == null)
223 {
224 //m_log.Info("[MaterialsDemoModule]: matsArr is null :( ");
225 return;
226 }
227
228 foreach (OSD elemOsd in matsArr)
229 {
230 if (elemOsd != null && elemOsd is OSDMap)
231 {
232 OSDMap matMap = elemOsd as OSDMap;
233 if (matMap.ContainsKey("ID") && matMap.ContainsKey("Material"))
234 {
235 try
236 {
237 lock (m_knownMaterials)
238 m_knownMaterials[matMap["ID"].AsUUID()] = (OSDMap)matMap["Material"];
239 }
240 catch (Exception e)
241 {
242 m_log.Warn("[MaterialsDemoModule]: exception decoding persisted material ", e);
243 }
244 }
245 }
246 }
247 }
248
249 void StoreMaterialsForPart(SceneObjectPart part)
250 {
251 try
252 {
253 if (part == null || part.Shape == null)
254 return;
255
256 Dictionary<UUID, OSDMap> mats = new Dictionary<UUID, OSDMap>();
257
258 Primitive.TextureEntry te = part.Shape.Textures;
259
260 if (te.DefaultTexture != null)
261 {
262 lock (m_knownMaterials)
263 {
264 if (m_knownMaterials.ContainsKey(te.DefaultTexture.MaterialID))
265 mats[te.DefaultTexture.MaterialID] = m_knownMaterials[te.DefaultTexture.MaterialID];
266 }
267 }
268
269 if (te.FaceTextures != null)
270 {
271 foreach (var face in te.FaceTextures)
272 {
273 if (face != null)
274 {
275 lock (m_knownMaterials)
276 {
277 if (m_knownMaterials.ContainsKey(face.MaterialID))
278 mats[face.MaterialID] = m_knownMaterials[face.MaterialID];
279 }
280 }
281 }
282 }
283 if (mats.Count == 0)
284 return;
285
286 OSDArray matsArr = new OSDArray();
287 foreach (KeyValuePair<UUID, OSDMap> kvp in mats)
288 {
289 OSDMap matOsd = new OSDMap();
290 matOsd["ID"] = OSD.FromUUID(kvp.Key);
291 matOsd["Material"] = kvp.Value;
292 matsArr.Add(matOsd);
293 }
294
295 OSDMap OSMaterials = new OSDMap();
296 OSMaterials["Materials"] = matsArr;
297
298 lock (part.DynAttrs)
299 part.DynAttrs.SetStore("OpenSim", "Materials", OSMaterials);
300 }
301 catch (Exception e)
302 {
303 m_log.Warn("[MaterialsDemoModule]: exception in StoreMaterialsForPart() ", e);
304 }
305 }
306
307 public string RenderMaterialsPostCap(string request, string path,
308 string param, IOSHttpRequest httpRequest,
309 IOSHttpResponse httpResponse)
310 {
311 //m_log.Debug("[MaterialsDemoModule]: POST cap handler");
312
313 OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
314 OSDMap resp = new OSDMap();
315
316 OSDMap materialsFromViewer = null;
317
318 OSDArray respArr = new OSDArray();
319
320 if (req.ContainsKey("Zipped"))
321 {
322 OSD osd = null;
323
324 byte[] inBytes = req["Zipped"].AsBinary();
325
326 try
327 {
328 osd = ZDecompressBytesToOsd(inBytes);
329
330 if (osd != null)
331 {
332 if (osd is OSDArray) // assume array of MaterialIDs designating requested material entries
333 {
334 foreach (OSD elem in (OSDArray)osd)
335 {
336
337 try
338 {
339 UUID id = new UUID(elem.AsBinary(), 0);
340
341 lock (m_knownMaterials)
342 {
343 if (m_knownMaterials.ContainsKey(id))
344 {
345 //m_log.Info("[MaterialsDemoModule]: request for known material ID: " + id.ToString());
346 OSDMap matMap = new OSDMap();
347 matMap["ID"] = OSD.FromBinary(id.GetBytes());
348
349 matMap["Material"] = m_knownMaterials[id];
350 respArr.Add(matMap);
351 }
352 else
353 m_log.Info("[MaterialsDemoModule]: request for UNKNOWN material ID: " + id.ToString());
354 }
355 }
356 catch (Exception e)
357 {
358 // report something here?
359 continue;
360 }
361 }
362 }
363 else if (osd is OSDMap) // reqest to assign a material
364 {
365 materialsFromViewer = osd as OSDMap;
366
367 if (materialsFromViewer.ContainsKey("FullMaterialsPerFace"))
368 {
369 OSD matsOsd = materialsFromViewer["FullMaterialsPerFace"];
370 if (matsOsd is OSDArray)
371 {
372 OSDArray matsArr = matsOsd as OSDArray;
373
374 try
375 {
376 foreach (OSDMap matsMap in matsArr)
377 {
378 //m_log.Debug("[MaterialsDemoModule]: processing matsMap: " + OSDParser.SerializeJsonString(matsMap));
379
380 uint primLocalID = 0;
381 try { primLocalID = matsMap["ID"].AsUInteger(); }
382 catch (Exception e) { m_log.Warn("[MaterialsDemoModule]: cannot decode \"ID\" from matsMap: " + e.Message); }
383 //m_log.Debug("[MaterialsDemoModule]: primLocalID: " + primLocalID.ToString());
384
385 OSDMap mat = null;
386 try { mat = matsMap["Material"] as OSDMap; }
387 catch (Exception e) { m_log.Warn("[MaterialsDemoModule]: cannot decode \"Material\" from matsMap: " + e.Message); }
388 //m_log.Debug("[MaterialsDemoModule]: mat: " + OSDParser.SerializeJsonString(mat));
389
390 UUID id;
391 if (mat == null)
392 {
393 id = UUID.Zero;
394 }
395 else
396 {
397 id = HashOsd(mat);
398 lock (m_knownMaterials)
399 m_knownMaterials[id] = mat;
400 }
401
402 var sop = m_scene.GetSceneObjectPart(primLocalID);
403 if (sop == null)
404 m_log.Debug("[MaterialsDemoModule]: null SOP for localId: " + primLocalID.ToString());
405 else
406 {
407 var te = new Primitive.TextureEntry(sop.Shape.TextureEntry, 0, sop.Shape.TextureEntry.Length);
408
409 if (te == null)
410 {
411 m_log.Debug("[MaterialsDemoModule]: null TextureEntry for localId: " + primLocalID.ToString());
412 }
413 else
414 {
415 int face = -1;
416
417 if (matsMap.ContainsKey("Face"))
418 {
419 face = matsMap["Face"].AsInteger();
420 if (te.FaceTextures == null) // && face == 0)
421 {
422 if (te.DefaultTexture == null)
423 m_log.Debug("[MaterialsDemoModule]: te.DefaultTexture is null");
424 else
425 te.DefaultTexture.MaterialID = id;
426 }
427 else
428 {
429 if (te.FaceTextures.Length >= face - 1)
430 {
431 if (te.FaceTextures[face] == null)
432 te.DefaultTexture.MaterialID = id;
433 else
434 te.FaceTextures[face].MaterialID = id;
435 }
436 }
437 }
438 else
439 {
440 if (te.DefaultTexture != null)
441 te.DefaultTexture.MaterialID = id;
442 }
443
444 //m_log.DebugFormat("[MaterialsDemoModule]: in \"{0}\", setting material ID for face {1} to {2}", sop.Name, face, id);
445
446 //we cant use sop.UpdateTextureEntry(te); because it filters so do it manually
447
448 if (sop.ParentGroup != null)
449 {
450 sop.Shape.TextureEntry = te.GetBytes();
451 sop.TriggerScriptChangedEvent(Changed.TEXTURE);
452 sop.UpdateFlag = UpdateRequired.FULL;
453 sop.ParentGroup.HasGroupChanged = true;
454
455 sop.ScheduleFullUpdate();
456
457 StoreMaterialsForPart(sop);
458 }
459 }
460 }
461 }
462 }
463 catch (Exception e)
464 {
465 m_log.Warn("[MaterialsDemoModule]: exception processing received material ", e);
466 }
467 }
468 }
469 }
470 }
471
472 }
473 catch (Exception e)
474 {
475 m_log.Warn("[MaterialsDemoModule]: exception decoding zipped CAP payload ", e);
476 //return "";
477 }
478 //m_log.Debug("[MaterialsDemoModule]: knownMaterials.Count: " + m_knownMaterials.Count.ToString());
479 }
480
481
482 resp["Zipped"] = ZCompressOSD(respArr, false);
483 string response = OSDParser.SerializeLLSDXmlString(resp);
484
485 //m_log.Debug("[MaterialsDemoModule]: cap request: " + request);
486 //m_log.Debug("[MaterialsDemoModule]: cap request (zipped portion): " + ZippedOsdBytesToString(req["Zipped"].AsBinary()));
487 //m_log.Debug("[MaterialsDemoModule]: cap response: " + response);
488 return response;
489 }
490
491
492 public string RenderMaterialsGetCap(string request, string path,
493 string param, IOSHttpRequest httpRequest,
494 IOSHttpResponse httpResponse)
495 {
496 //m_log.Debug("[MaterialsDemoModule]: GET cap handler");
497
498 OSDMap resp = new OSDMap();
499 int matsCount = 0;
500 OSDArray allOsd = new OSDArray();
501
502 lock (m_knownMaterials)
503 {
504 foreach (KeyValuePair<UUID, OSDMap> kvp in m_knownMaterials)
505 {
506 OSDMap matMap = new OSDMap();
507
508 matMap["ID"] = OSD.FromBinary(kvp.Key.GetBytes());
509 matMap["Material"] = kvp.Value;
510 allOsd.Add(matMap);
511 matsCount++;
512 }
513 }
514
515 resp["Zipped"] = ZCompressOSD(allOsd, false);
516 //m_log.Debug("[MaterialsDemoModule]: matsCount: " + matsCount.ToString());
517
518 return OSDParser.SerializeLLSDXmlString(resp);
519 }
520
521 static string ZippedOsdBytesToString(byte[] bytes)
522 {
523 try
524 {
525 return OSDParser.SerializeJsonString(ZDecompressBytesToOsd(bytes));
526 }
527 catch (Exception e)
528 {
529 return "ZippedOsdBytesToString caught an exception: " + e.ToString();
530 }
531 }
532
533 /// <summary>
534 /// computes a UUID by hashing a OSD object
535 /// </summary>
536 /// <param name="osd"></param>
537 /// <returns></returns>
538 private static UUID HashOsd(OSD osd)
539 {
540 using (var md5 = MD5.Create())
541 using (MemoryStream ms = new MemoryStream(OSDParser.SerializeLLSDBinary(osd, false)))
542 return new UUID(md5.ComputeHash(ms), 0);
543 }
544
545 public static OSD ZCompressOSD(OSD inOsd, bool useHeader)
546 {
547 OSD osd = null;
548
549 using (MemoryStream msSinkCompressed = new MemoryStream())
550 {
551 using (Ionic.Zlib.ZlibStream zOut = new Ionic.Zlib.ZlibStream(msSinkCompressed,
552 Ionic.Zlib.CompressionMode.Compress, CompressionLevel.BestCompression, true))
553 {
554 CopyStream(new MemoryStream(OSDParser.SerializeLLSDBinary(inOsd, useHeader)), zOut);
555 zOut.Close();
556 }
557
558 msSinkCompressed.Seek(0L, SeekOrigin.Begin);
559 osd = OSD.FromBinary( msSinkCompressed.ToArray());
560 }
561
562 return osd;
563 }
564
565
566 public static OSD ZDecompressBytesToOsd(byte[] input)
567 {
568 OSD osd = null;
569
570 using (MemoryStream msSinkUnCompressed = new MemoryStream())
571 {
572 using (Ionic.Zlib.ZlibStream zOut = new Ionic.Zlib.ZlibStream(msSinkUnCompressed, CompressionMode.Decompress, true))
573 {
574 CopyStream(new MemoryStream(input), zOut);
575 zOut.Close();
576 }
577 msSinkUnCompressed.Seek(0L, SeekOrigin.Begin);
578 osd = OSDParser.DeserializeLLSDBinary(msSinkUnCompressed.ToArray());
579 }
580
581 return osd;
582 }
583
584 static void CopyStream(System.IO.Stream input, System.IO.Stream output)
585 {
586 byte[] buffer = new byte[2048];
587 int len;
588 while ((len = input.Read(buffer, 0, 2048)) > 0)
589 {
590 output.Write(buffer, 0, len);
591 }
592
593 output.Flush();
594 }
595
596 // FIXME: This code is currently still in UuidGatherer since we cannot use Scene.EventManager as some
597 // calls to the gatherer are done for objects with no scene.
598// /// <summary>
599// /// Gather all of the texture asset UUIDs used to reference "Materials" such as normal and specular maps
600// /// </summary>
601// /// <param name="part"></param>
602// /// <param name="assetUuids"></param>
603// private void GatherMaterialsUuids(SceneObjectPart part, IDictionary<UUID, AssetType> assetUuids)
604// {
605// // scan thru the dynAttrs map of this part for any textures used as materials
606// OSD osdMaterials = null;
607//
608// lock (part.DynAttrs)
609// {
610// if (part.DynAttrs.ContainsStore("OpenSim", "Materials"))
611// {
612// OSDMap materialsStore = part.DynAttrs.GetStore("OpenSim", "Materials");
613// if (materialsStore == null)
614// return;
615//
616// materialsStore.TryGetValue("Materials", out osdMaterials);
617// }
618//
619// if (osdMaterials != null)
620// {
621// //m_log.Info("[UUID Gatherer]: found Materials: " + OSDParser.SerializeJsonString(osd));
622//
623// if (osdMaterials is OSDArray)
624// {
625// OSDArray matsArr = osdMaterials as OSDArray;
626// foreach (OSDMap matMap in matsArr)
627// {
628// try
629// {
630// if (matMap.ContainsKey("Material"))
631// {
632// OSDMap mat = matMap["Material"] as OSDMap;
633// if (mat.ContainsKey("NormMap"))
634// {
635// UUID normalMapId = mat["NormMap"].AsUUID();
636// if (normalMapId != UUID.Zero)
637// {
638// assetUuids[normalMapId] = AssetType.Texture;
639// //m_log.Info("[UUID Gatherer]: found normal map ID: " + normalMapId.ToString());
640// }
641// }
642// if (mat.ContainsKey("SpecMap"))
643// {
644// UUID specularMapId = mat["SpecMap"].AsUUID();
645// if (specularMapId != UUID.Zero)
646// {
647// assetUuids[specularMapId] = AssetType.Texture;
648// //m_log.Info("[UUID Gatherer]: found specular map ID: " + specularMapId.ToString());
649// }
650// }
651// }
652//
653// }
654// catch (Exception e)
655// {
656// m_log.Warn("[MaterialsDemoModule]: exception getting materials: " + e.Message);
657// }
658// }
659// }
660// }
661// }
662// }
663 }
664}