aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps')
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs923
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs671
2 files changed, 1457 insertions, 137 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
index 185f9ce..c705f10 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Timers;
29using System.Collections; 30using System.Collections;
30using System.Collections.Generic; 31using System.Collections.Generic;
31using System.IO; 32using System.IO;
@@ -53,14 +54,16 @@ using OSDMap = OpenMetaverse.StructuredData.OSDMap;
53namespace OpenSim.Region.ClientStack.Linden 54namespace OpenSim.Region.ClientStack.Linden
54{ 55{
55 public delegate void UpLoadedAsset( 56 public delegate void UpLoadedAsset(
56 string assetName, string description, UUID assetID, UUID inventoryItem, UUID parentFolder, 57 string assetName, string description, UUID assetID, UUID inventoryItem, UUID parentFolder,
57 byte[] data, string inventoryType, string assetType); 58 byte[] data, string inventoryType, string assetType,
59 int cost, UUID texturesFolder, int nreqtextures, int nreqmeshs, int nreqinstances,
60 bool IsAtestUpload, ref string error);
58 61
59 public delegate UUID UpdateItem(UUID itemID, byte[] data); 62 public delegate UUID UpdateItem(UUID itemID, byte[] data);
60 63
61 public delegate void UpdateTaskScript(UUID itemID, UUID primID, bool isScriptRunning, byte[] data, ref ArrayList errors); 64 public delegate void UpdateTaskScript(UUID itemID, UUID primID, bool isScriptRunning, byte[] data, ref ArrayList errors);
62 65
63 public delegate void NewInventoryItem(UUID userID, InventoryItemBase item); 66 public delegate void NewInventoryItem(UUID userID, InventoryItemBase item, uint cost);
64 67
65 public delegate void NewAsset(AssetBase asset); 68 public delegate void NewAsset(AssetBase asset);
66 69
@@ -86,6 +89,7 @@ namespace OpenSim.Region.ClientStack.Linden
86 89
87 private Scene m_Scene; 90 private Scene m_Scene;
88 private Caps m_HostCapsObj; 91 private Caps m_HostCapsObj;
92 private ModelCost m_ModelCost;
89 93
90 private static readonly string m_requestPath = "0000/"; 94 private static readonly string m_requestPath = "0000/";
91 // private static readonly string m_mapLayerPath = "0001/"; 95 // private static readonly string m_mapLayerPath = "0001/";
@@ -96,7 +100,10 @@ namespace OpenSim.Region.ClientStack.Linden
96 // private static readonly string m_fetchInventoryPath = "0006/"; 100 // private static readonly string m_fetchInventoryPath = "0006/";
97 private static readonly string m_copyFromNotecardPath = "0007/"; 101 private static readonly string m_copyFromNotecardPath = "0007/";
98 // private static readonly string m_remoteParcelRequestPath = "0009/";// This is in the LandManagementModule. 102 // private static readonly string m_remoteParcelRequestPath = "0009/";// This is in the LandManagementModule.
99 103 private static readonly string m_getObjectPhysicsDataPath = "0101/";
104 private static readonly string m_getObjectCostPath = "0102/";
105 private static readonly string m_ResourceCostSelectedPath = "0103/";
106
100 107
101 // These are callbacks which will be setup by the scene so that we can update scene data when we 108 // These are callbacks which will be setup by the scene so that we can update scene data when we
102 // receive capability calls 109 // receive capability calls
@@ -111,12 +118,50 @@ namespace OpenSim.Region.ClientStack.Linden
111 private IAssetService m_assetService; 118 private IAssetService m_assetService;
112 private bool m_dumpAssetsToFile = false; 119 private bool m_dumpAssetsToFile = false;
113 private string m_regionName; 120 private string m_regionName;
121
114 private int m_levelUpload = 0; 122 private int m_levelUpload = 0;
115 123
124 private bool m_enableFreeTestUpload = false; // allows "TEST-" prefix hack
125 private bool m_ForceFreeTestUpload = false; // forces all uploads to be test
126
127 private bool m_enableModelUploadTextureToInventory = false; // place uploaded textures also in inventory
128 // may not be visible till relog
129
130 private bool m_RestrictFreeTestUploadPerms = false; // reduces also the permitions. Needs a creator defined!!
131 private UUID m_testAssetsCreatorID = UUID.Zero;
132
133 private float m_PrimScaleMin = 0.001f;
134
135 private enum FileAgentInventoryState : int
136 {
137 idle = 0,
138 processRequest = 1,
139 waitUpload = 2,
140 processUpload = 3
141 }
142 private FileAgentInventoryState m_FileAgentInventoryState = FileAgentInventoryState.idle;
143
116 public BunchOfCaps(Scene scene, Caps caps) 144 public BunchOfCaps(Scene scene, Caps caps)
117 { 145 {
118 m_Scene = scene; 146 m_Scene = scene;
119 m_HostCapsObj = caps; 147 m_HostCapsObj = caps;
148
149 // create a model upload cost provider
150 m_ModelCost = new ModelCost();
151 // tell it about scene object limits
152 m_ModelCost.NonPhysicalPrimScaleMax = m_Scene.m_maxNonphys;
153 m_ModelCost.PhysicalPrimScaleMax = m_Scene.m_maxPhys;
154
155// m_ModelCost.ObjectLinkedPartsMax = ??
156// m_ModelCost.PrimScaleMin = ??
157
158 m_PrimScaleMin = m_ModelCost.PrimScaleMin;
159 float modelTextureUploadFactor = m_ModelCost.ModelTextureCostFactor;
160 float modelUploadFactor = m_ModelCost.ModelMeshCostFactor;
161 float modelMinUploadCostFactor = m_ModelCost.ModelMinCostFactor;
162 float modelPrimCreationCost = m_ModelCost.primCreationCost;
163 float modelMeshByteCost = m_ModelCost.bytecost;
164
120 IConfigSource config = m_Scene.Config; 165 IConfigSource config = m_Scene.Config;
121 if (config != null) 166 if (config != null)
122 { 167 {
@@ -131,6 +176,37 @@ namespace OpenSim.Region.ClientStack.Linden
131 { 176 {
132 m_persistBakedTextures = appearanceConfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures); 177 m_persistBakedTextures = appearanceConfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures);
133 } 178 }
179 // economy for model upload
180 IConfig EconomyConfig = config.Configs["Economy"];
181 if (EconomyConfig != null)
182 {
183 modelUploadFactor = EconomyConfig.GetFloat("MeshModelUploadCostFactor", modelUploadFactor);
184 modelTextureUploadFactor = EconomyConfig.GetFloat("MeshModelUploadTextureCostFactor", modelTextureUploadFactor);
185 modelMinUploadCostFactor = EconomyConfig.GetFloat("MeshModelMinCostFactor", modelMinUploadCostFactor);
186 // next 2 are normalized so final cost is afected by modelUploadFactor above and normal cost
187 modelPrimCreationCost = EconomyConfig.GetFloat("ModelPrimCreationCost", modelPrimCreationCost);
188 modelMeshByteCost = EconomyConfig.GetFloat("ModelMeshByteCost", modelMeshByteCost);
189
190 m_enableModelUploadTextureToInventory = EconomyConfig.GetBoolean("MeshModelAllowTextureToInventory", m_enableModelUploadTextureToInventory);
191
192 m_RestrictFreeTestUploadPerms = EconomyConfig.GetBoolean("m_RestrictFreeTestUploadPerms", m_RestrictFreeTestUploadPerms);
193 m_enableFreeTestUpload = EconomyConfig.GetBoolean("AllowFreeTestUpload", m_enableFreeTestUpload);
194 m_ForceFreeTestUpload = EconomyConfig.GetBoolean("ForceFreeTestUpload", m_ForceFreeTestUpload);
195 string testcreator = EconomyConfig.GetString("TestAssetsCreatorID", "");
196 if (testcreator != "")
197 {
198 UUID id;
199 UUID.TryParse(testcreator, out id);
200 if (id != null)
201 m_testAssetsCreatorID = id;
202 }
203
204 m_ModelCost.ModelMeshCostFactor = modelUploadFactor;
205 m_ModelCost.ModelTextureCostFactor = modelTextureUploadFactor;
206 m_ModelCost.ModelMinCostFactor = modelMinUploadCostFactor;
207 m_ModelCost.primCreationCost = modelPrimCreationCost;
208 m_ModelCost.bytecost = modelMeshByteCost;
209 }
134 } 210 }
135 211
136 m_assetService = m_Scene.AssetService; 212 m_assetService = m_Scene.AssetService;
@@ -142,6 +218,8 @@ namespace OpenSim.Region.ClientStack.Linden
142 ItemUpdatedCall = m_Scene.CapsUpdateInventoryItemAsset; 218 ItemUpdatedCall = m_Scene.CapsUpdateInventoryItemAsset;
143 TaskScriptUpdatedCall = m_Scene.CapsUpdateTaskInventoryScriptAsset; 219 TaskScriptUpdatedCall = m_Scene.CapsUpdateTaskInventoryScriptAsset;
144 GetClient = m_Scene.SceneGraph.GetControllingClient; 220 GetClient = m_Scene.SceneGraph.GetControllingClient;
221
222 m_FileAgentInventoryState = FileAgentInventoryState.idle;
145 } 223 }
146 224
147 /// <summary> 225 /// <summary>
@@ -187,7 +265,6 @@ namespace OpenSim.Region.ClientStack.Linden
187 { 265 {
188 try 266 try
189 { 267 {
190 // I don't think this one works...
191 m_HostCapsObj.RegisterHandler( 268 m_HostCapsObj.RegisterHandler(
192 "NewFileAgentInventory", 269 "NewFileAgentInventory",
193 new LLSDStreamhandler<LLSDAssetUploadRequest, LLSDAssetUploadResponse>( 270 new LLSDStreamhandler<LLSDAssetUploadRequest, LLSDAssetUploadResponse>(
@@ -204,6 +281,12 @@ namespace OpenSim.Region.ClientStack.Linden
204 m_HostCapsObj.RegisterHandler("UpdateNotecardAgentInventory", req); 281 m_HostCapsObj.RegisterHandler("UpdateNotecardAgentInventory", req);
205 m_HostCapsObj.RegisterHandler("UpdateScriptAgentInventory", req); 282 m_HostCapsObj.RegisterHandler("UpdateScriptAgentInventory", req);
206 m_HostCapsObj.RegisterHandler("UpdateScriptAgent", req); 283 m_HostCapsObj.RegisterHandler("UpdateScriptAgent", req);
284 IRequestHandler getObjectPhysicsDataHandler = new RestStreamHandler("POST", capsBase + m_getObjectPhysicsDataPath, GetObjectPhysicsData);
285 m_HostCapsObj.RegisterHandler("GetObjectPhysicsData", getObjectPhysicsDataHandler);
286 IRequestHandler getObjectCostHandler = new RestStreamHandler("POST", capsBase + m_getObjectCostPath, GetObjectCost);
287 m_HostCapsObj.RegisterHandler("GetObjectCost", getObjectCostHandler);
288 IRequestHandler ResourceCostSelectedHandler = new RestStreamHandler("POST", capsBase + m_ResourceCostSelectedPath, ResourceCostSelected);
289 m_HostCapsObj.RegisterHandler("ResourceCostSelected", ResourceCostSelectedHandler);
207 290
208 m_HostCapsObj.RegisterHandler( 291 m_HostCapsObj.RegisterHandler(
209 "CopyInventoryFromNotecard", 292 "CopyInventoryFromNotecard",
@@ -385,62 +468,176 @@ namespace OpenSim.Region.ClientStack.Linden
385 //m_log.Debug("[CAPS]: NewAgentInventoryRequest Request is: " + llsdRequest.ToString()); 468 //m_log.Debug("[CAPS]: NewAgentInventoryRequest Request is: " + llsdRequest.ToString());
386 //m_log.Debug("asset upload request via CAPS" + llsdRequest.inventory_type + " , " + llsdRequest.asset_type); 469 //m_log.Debug("asset upload request via CAPS" + llsdRequest.inventory_type + " , " + llsdRequest.asset_type);
387 470
471 // start by getting the client
472 IClientAPI client = null;
473 m_Scene.TryGetClient(m_HostCapsObj.AgentID, out client);
474
475 // check current state so we only have one service at a time
476 lock (m_ModelCost)
477 {
478 switch (m_FileAgentInventoryState)
479 {
480 case FileAgentInventoryState.processRequest:
481 case FileAgentInventoryState.processUpload:
482 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
483 resperror.message = "Uploader busy processing previus request";
484 resperror.identifier = UUID.Zero;
485
486 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
487 errorResponse.uploader = "";
488 errorResponse.state = "error";
489 errorResponse.error = resperror;
490 return errorResponse;
491 break;
492 case FileAgentInventoryState.waitUpload:
493 // todo stop current uploader server
494 break;
495 case FileAgentInventoryState.idle:
496 default:
497 break;
498 }
499
500 m_FileAgentInventoryState = FileAgentInventoryState.processRequest;
501 }
502
503 int cost = 0;
504 int nreqtextures = 0;
505 int nreqmeshs= 0;
506 int nreqinstances = 0;
507 bool IsAtestUpload = false;
508
509 string assetName = llsdRequest.name;
510
511 LLSDAssetUploadResponseData meshcostdata = new LLSDAssetUploadResponseData();
512
388 if (llsdRequest.asset_type == "texture" || 513 if (llsdRequest.asset_type == "texture" ||
389 llsdRequest.asset_type == "animation" || 514 llsdRequest.asset_type == "animation" ||
515 llsdRequest.asset_type == "mesh" ||
390 llsdRequest.asset_type == "sound") 516 llsdRequest.asset_type == "sound")
391 { 517 {
392 ScenePresence avatar = null; 518 ScenePresence avatar = null;
393 IClientAPI client = null;
394 m_Scene.TryGetScenePresence(m_HostCapsObj.AgentID, out avatar); 519 m_Scene.TryGetScenePresence(m_HostCapsObj.AgentID, out avatar);
395 520
396 // check user level 521 // check user level
397 if (avatar != null) 522 if (avatar != null)
398 { 523 {
399 client = avatar.ControllingClient;
400
401 if (avatar.UserLevel < m_levelUpload) 524 if (avatar.UserLevel < m_levelUpload)
402 { 525 {
403 if (client != null) 526 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
404 client.SendAgentAlertMessage("Unable to upload asset. Insufficient permissions.", false); 527 resperror.message = "Insufficient permissions to upload";
528 resperror.identifier = UUID.Zero;
405 529
406 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse(); 530 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
407 errorResponse.uploader = ""; 531 errorResponse.uploader = "";
408 errorResponse.state = "error"; 532 errorResponse.state = "error";
533 errorResponse.error = resperror;
534 lock (m_ModelCost)
535 m_FileAgentInventoryState = FileAgentInventoryState.idle;
409 return errorResponse; 536 return errorResponse;
410 } 537 }
411 } 538 }
412 539
413 // check funds 540 // check test upload and funds
414 if (client != null) 541 if (client != null)
415 { 542 {
416 IMoneyModule mm = m_Scene.RequestModuleInterface<IMoneyModule>(); 543 IMoneyModule mm = m_Scene.RequestModuleInterface<IMoneyModule>();
417 544
545 int baseCost = 0;
418 if (mm != null) 546 if (mm != null)
547 baseCost = mm.UploadCharge;
548
549 string warning = String.Empty;
550
551 if (llsdRequest.asset_type == "mesh")
419 { 552 {
420 if (!mm.UploadCovered(client.AgentId, mm.UploadCharge)) 553 string error;
554 int modelcost;
555
556 if (!m_ModelCost.MeshModelCost(llsdRequest.asset_resources, baseCost, out modelcost,
557 meshcostdata, out error, ref warning))
421 { 558 {
422 client.SendAgentAlertMessage("Unable to upload asset. Insufficient funds.", false); 559 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
560 resperror.message = error;
561 resperror.identifier = UUID.Zero;
423 562
424 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse(); 563 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
425 errorResponse.uploader = ""; 564 errorResponse.uploader = "";
426 errorResponse.state = "error"; 565 errorResponse.state = "error";
566 errorResponse.error = resperror;
567
568 lock (m_ModelCost)
569 m_FileAgentInventoryState = FileAgentInventoryState.idle;
427 return errorResponse; 570 return errorResponse;
428 } 571 }
572 cost = modelcost;
429 } 573 }
574 else
575 {
576 cost = baseCost;
577 }
578
579 if (cost > 0 && mm != null)
580 {
581 // check for test upload
582
583 if (m_ForceFreeTestUpload) // all are test
584 {
585 if (!(assetName.Length > 5 && assetName.StartsWith("TEST-"))) // has normal name lets change it
586 assetName = "TEST-" + assetName;
587
588 IsAtestUpload = true;
589 }
590
591 else if (m_enableFreeTestUpload) // only if prefixed with "TEST-"
592 {
593
594 IsAtestUpload = (assetName.Length > 5 && assetName.StartsWith("TEST-"));
595 }
596
597
598 if(IsAtestUpload) // let user know, still showing cost estimation
599 warning += "Upload will have no cost, for testing purposes only. Other uses are prohibited. Items will not work after 48 hours or on other regions";
600
601 // check funds
602 else
603 {
604 if (!mm.UploadCovered(client.AgentId, (int)cost))
605 {
606 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
607 resperror.message = "Insuficient funds";
608 resperror.identifier = UUID.Zero;
609
610 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
611 errorResponse.uploader = "";
612 errorResponse.state = "error";
613 errorResponse.error = resperror;
614 lock (m_ModelCost)
615 m_FileAgentInventoryState = FileAgentInventoryState.idle;
616 return errorResponse;
617 }
618 }
619 }
620
621 if (client != null && warning != String.Empty)
622 client.SendAgentAlertMessage(warning, true);
430 } 623 }
431 } 624 }
432 625
433 string assetName = llsdRequest.name;
434 string assetDes = llsdRequest.description; 626 string assetDes = llsdRequest.description;
435 string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath; 627 string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath;
436 UUID newAsset = UUID.Random(); 628 UUID newAsset = UUID.Random();
437 UUID newInvItem = UUID.Random(); 629 UUID newInvItem = UUID.Random();
438 UUID parentFolder = llsdRequest.folder_id; 630 UUID parentFolder = llsdRequest.folder_id;
439 string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000"); 631 string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000");
632 UUID texturesFolder = UUID.Zero;
633
634 if(!IsAtestUpload && m_enableModelUploadTextureToInventory)
635 texturesFolder = llsdRequest.texture_folder_id;
440 636
441 AssetUploader uploader = 637 AssetUploader uploader =
442 new AssetUploader(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type, 638 new AssetUploader(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type,
443 llsdRequest.asset_type, capsBase + uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile); 639 llsdRequest.asset_type, capsBase + uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile, cost,
640 texturesFolder, nreqtextures, nreqmeshs, nreqinstances, IsAtestUpload);
444 641
445 m_HostCapsObj.HttpListener.AddStreamHandler( 642 m_HostCapsObj.HttpListener.AddStreamHandler(
446 new BinaryStreamHandler( 643 new BinaryStreamHandler(
@@ -458,10 +655,22 @@ namespace OpenSim.Region.ClientStack.Linden
458 string uploaderURL = protocol + m_HostCapsObj.HostName + ":" + m_HostCapsObj.Port.ToString() + capsBase + 655 string uploaderURL = protocol + m_HostCapsObj.HostName + ":" + m_HostCapsObj.Port.ToString() + capsBase +
459 uploaderPath; 656 uploaderPath;
460 657
658
461 LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse(); 659 LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse();
462 uploadResponse.uploader = uploaderURL; 660 uploadResponse.uploader = uploaderURL;
463 uploadResponse.state = "upload"; 661 uploadResponse.state = "upload";
662 uploadResponse.upload_price = (int)cost;
663
664 if (llsdRequest.asset_type == "mesh")
665 {
666 uploadResponse.data = meshcostdata;
667 }
668
464 uploader.OnUpLoad += UploadCompleteHandler; 669 uploader.OnUpLoad += UploadCompleteHandler;
670
671 lock (m_ModelCost)
672 m_FileAgentInventoryState = FileAgentInventoryState.waitUpload;
673
465 return uploadResponse; 674 return uploadResponse;
466 } 675 }
467 676
@@ -473,8 +682,14 @@ namespace OpenSim.Region.ClientStack.Linden
473 /// <param name="data"></param> 682 /// <param name="data"></param>
474 public void UploadCompleteHandler(string assetName, string assetDescription, UUID assetID, 683 public void UploadCompleteHandler(string assetName, string assetDescription, UUID assetID,
475 UUID inventoryItem, UUID parentFolder, byte[] data, string inventoryType, 684 UUID inventoryItem, UUID parentFolder, byte[] data, string inventoryType,
476 string assetType) 685 string assetType, int cost,
686 UUID texturesFolder, int nreqtextures, int nreqmeshs, int nreqinstances,
687 bool IsAtestUpload, ref string error)
477 { 688 {
689
690 lock (m_ModelCost)
691 m_FileAgentInventoryState = FileAgentInventoryState.processUpload;
692
478 m_log.DebugFormat( 693 m_log.DebugFormat(
479 "[BUNCH OF CAPS]: Uploaded asset {0} for inventory item {1}, inv type {2}, asset type {3}", 694 "[BUNCH OF CAPS]: Uploaded asset {0} for inventory item {1}, inv type {2}, asset type {3}",
480 assetID, inventoryItem, inventoryType, assetType); 695 assetID, inventoryItem, inventoryType, assetType);
@@ -482,117 +697,247 @@ namespace OpenSim.Region.ClientStack.Linden
482 sbyte assType = 0; 697 sbyte assType = 0;
483 sbyte inType = 0; 698 sbyte inType = 0;
484 699
700 IClientAPI client = null;
701
702 UUID owner_id = m_HostCapsObj.AgentID;
703 UUID creatorID;
704
705 bool istest = IsAtestUpload && m_enableFreeTestUpload && (cost > 0);
706
707 bool restrictPerms = m_RestrictFreeTestUploadPerms && istest;
708
709 if (istest && m_testAssetsCreatorID != UUID.Zero)
710 creatorID = m_testAssetsCreatorID;
711 else
712 creatorID = owner_id;
713
714 string creatorIDstr = creatorID.ToString();
715
716 IMoneyModule mm = m_Scene.RequestModuleInterface<IMoneyModule>();
717 if (mm != null)
718 {
719 // make sure client still has enougth credit
720 if (!mm.UploadCovered(m_HostCapsObj.AgentID, (int)cost))
721 {
722 error = "Insufficient funds.";
723 return;
724 }
725 }
726
727 // strings to types
485 if (inventoryType == "sound") 728 if (inventoryType == "sound")
486 { 729 {
487 inType = 1; 730 inType = (sbyte)InventoryType.Sound;
488 assType = 1; 731 assType = (sbyte)AssetType.Sound;
489 } 732 }
490 else if (inventoryType == "animation") 733 else if (inventoryType == "animation")
491 { 734 {
492 inType = 19; 735 inType = (sbyte)InventoryType.Animation;
493 assType = 20; 736 assType = (sbyte)AssetType.Animation;
494 } 737 }
495 else if (inventoryType == "wearable") 738 else if (inventoryType == "wearable")
496 { 739 {
497 inType = 18; 740 inType = (sbyte)InventoryType.Wearable;
498 switch (assetType) 741 switch (assetType)
499 { 742 {
500 case "bodypart": 743 case "bodypart":
501 assType = 13; 744 assType = (sbyte)AssetType.Bodypart;
502 break; 745 break;
503 case "clothing": 746 case "clothing":
504 assType = 5; 747 assType = (sbyte)AssetType.Clothing;
505 break; 748 break;
506 } 749 }
507 } 750 }
508 else if (inventoryType == "object") 751 else if (inventoryType == "object")
509 { 752 {
510 inType = (sbyte)InventoryType.Object; 753 if (assetType == "mesh") // this code for now is for mesh models uploads only
511 assType = (sbyte)AssetType.Object;
512
513 List<Vector3> positions = new List<Vector3>();
514 List<Quaternion> rotations = new List<Quaternion>();
515 OSDMap request = (OSDMap)OSDParser.DeserializeLLSDXml(data);
516 OSDArray instance_list = (OSDArray)request["instance_list"];
517 OSDArray mesh_list = (OSDArray)request["mesh_list"];
518 OSDArray texture_list = (OSDArray)request["texture_list"];
519 SceneObjectGroup grp = null;
520
521 List<UUID> textures = new List<UUID>();
522 for (int i = 0; i < texture_list.Count; i++)
523 { 754 {
524 AssetBase textureAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Texture, ""); 755 inType = (sbyte)InventoryType.Object;
525 textureAsset.Data = texture_list[i].AsBinary(); 756 assType = (sbyte)AssetType.Object;
526 m_assetService.Store(textureAsset);
527 textures.Add(textureAsset.FullID);
528 }
529 757
530 for (int i = 0; i < mesh_list.Count; i++) 758 List<Vector3> positions = new List<Vector3>();
531 { 759 List<Quaternion> rotations = new List<Quaternion>();
532 PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateBox(); 760 OSDMap request = (OSDMap)OSDParser.DeserializeLLSDXml(data);
761
762 // compare and get updated information
533 763
534 Primitive.TextureEntry textureEntry 764 bool mismatchError = true;
535 = new Primitive.TextureEntry(Primitive.TextureEntry.WHITE_TEXTURE);
536 OSDMap inner_instance_list = (OSDMap)instance_list[i];
537 765
538 OSDArray face_list = (OSDArray)inner_instance_list["face_list"]; 766 while (mismatchError)
539 for (uint face = 0; face < face_list.Count; face++)
540 { 767 {
541 OSDMap faceMap = (OSDMap)face_list[(int)face]; 768 mismatchError = false;
542 Primitive.TextureEntryFace f = pbs.Textures.CreateFace(face); 769 }
543 if(faceMap.ContainsKey("fullbright"))
544 f.Fullbright = faceMap["fullbright"].AsBoolean();
545 if (faceMap.ContainsKey ("diffuse_color"))
546 f.RGBA = faceMap["diffuse_color"].AsColor4();
547 770
548 int textureNum = faceMap["image"].AsInteger(); 771 if (mismatchError)
549 float imagerot = faceMap["imagerot"].AsInteger(); 772 {
550 float offsets = (float)faceMap["offsets"].AsReal(); 773 error = "Upload and fee estimation information don't match";
551 float offsett = (float)faceMap["offsett"].AsReal(); 774 lock (m_ModelCost)
552 float scales = (float)faceMap["scales"].AsReal(); 775 m_FileAgentInventoryState = FileAgentInventoryState.idle;
553 float scalet = (float)faceMap["scalet"].AsReal();
554 776
555 if(imagerot != 0) 777 return;
556 f.Rotation = imagerot; 778 }
557 779
558 if(offsets != 0) 780 OSDArray instance_list = (OSDArray)request["instance_list"];
559 f.OffsetU = offsets; 781 OSDArray mesh_list = (OSDArray)request["mesh_list"];
782 OSDArray texture_list = (OSDArray)request["texture_list"];
783 SceneObjectGroup grp = null;
560 784
561 if (offsett != 0) 785 // create and store texture assets
562 f.OffsetV = offsett; 786 bool doTextInv = (!istest && m_enableModelUploadTextureToInventory &&
787 texturesFolder != UUID.Zero);
563 788
564 if (scales != 0)
565 f.RepeatU = scales;
566 789
567 if (scalet != 0) 790 List<UUID> textures = new List<UUID>();
568 f.RepeatV = scalet;
569 791
570 if (textures.Count > textureNum) 792
571 f.TextureID = textures[textureNum]; 793 if (doTextInv)
572 else 794 m_Scene.TryGetClient(m_HostCapsObj.AgentID, out client);
573 f.TextureID = Primitive.TextureEntry.WHITE_TEXTURE;
574 795
575 textureEntry.FaceTextures[face] = f; 796 if(client == null) // don't put textures in inventory if there is no client
797 doTextInv = false;
798
799 for (int i = 0; i < texture_list.Count; i++)
800 {
801 AssetBase textureAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Texture, creatorIDstr);
802 textureAsset.Data = texture_list[i].AsBinary();
803 if (istest)
804 textureAsset.Local = true;
805 m_assetService.Store(textureAsset);
806 textures.Add(textureAsset.FullID);
807
808 if (doTextInv)
809 {
810 string name = assetName;
811 if (name.Length > 25)
812 name = name.Substring(0, 24);
813 name += "_Texture#" + i.ToString();
814 InventoryItemBase texitem = new InventoryItemBase();
815 texitem.Owner = m_HostCapsObj.AgentID;
816 texitem.CreatorId = creatorIDstr;
817 texitem.CreatorData = String.Empty;
818 texitem.ID = UUID.Random();
819 texitem.AssetID = textureAsset.FullID;
820 texitem.Description = "mesh model texture";
821 texitem.Name = name;
822 texitem.AssetType = (int)AssetType.Texture;
823 texitem.InvType = (int)InventoryType.Texture;
824 texitem.Folder = texturesFolder;
825
826 texitem.CurrentPermissions
827 = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer);
828
829 texitem.BasePermissions = (uint)PermissionMask.All;
830 texitem.EveryOnePermissions = 0;
831 texitem.NextPermissions = (uint)PermissionMask.All;
832 texitem.CreationDate = Util.UnixTimeSinceEpoch();
833
834 m_Scene.AddInventoryItem(client, texitem);
835 texitem = null;
836 }
837 }
838
839 // create and store meshs assets
840 List<UUID> meshAssets = new List<UUID>();
841 for (int i = 0; i < mesh_list.Count; i++)
842 {
843 AssetBase meshAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Mesh, creatorIDstr);
844 meshAsset.Data = mesh_list[i].AsBinary();
845 if (istest)
846 meshAsset.Local = true;
847 m_assetService.Store(meshAsset);
848 meshAssets.Add(meshAsset.FullID);
576 } 849 }
577 850
578 pbs.TextureEntry = textureEntry.GetBytes(); 851 int skipedMeshs = 0;
852 // build prims from instances
853 for (int i = 0; i < instance_list.Count; i++)
854 {
855 OSDMap inner_instance_list = (OSDMap)instance_list[i];
856
857 // skip prims that are 2 small
858 Vector3 scale = inner_instance_list["scale"].AsVector3();
859
860 if (scale.X < m_PrimScaleMin || scale.Y < m_PrimScaleMin || scale.Z < m_PrimScaleMin)
861 {
862 skipedMeshs++;
863 continue;
864 }
865
866 PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateBox();
867
868 Primitive.TextureEntry textureEntry
869 = new Primitive.TextureEntry(Primitive.TextureEntry.WHITE_TEXTURE);
870
871
872 OSDArray face_list = (OSDArray)inner_instance_list["face_list"];
873 for (uint face = 0; face < face_list.Count; face++)
874 {
875 OSDMap faceMap = (OSDMap)face_list[(int)face];
876 Primitive.TextureEntryFace f = pbs.Textures.CreateFace(face);
877 if (faceMap.ContainsKey("fullbright"))
878 f.Fullbright = faceMap["fullbright"].AsBoolean();
879 if (faceMap.ContainsKey("diffuse_color"))
880 f.RGBA = faceMap["diffuse_color"].AsColor4();
881
882 int textureNum = faceMap["image"].AsInteger();
883 float imagerot = faceMap["imagerot"].AsInteger();
884 float offsets = (float)faceMap["offsets"].AsReal();
885 float offsett = (float)faceMap["offsett"].AsReal();
886 float scales = (float)faceMap["scales"].AsReal();
887 float scalet = (float)faceMap["scalet"].AsReal();
579 888
580 AssetBase meshAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Mesh, ""); 889 if (imagerot != 0)
581 meshAsset.Data = mesh_list[i].AsBinary(); 890 f.Rotation = imagerot;
582 m_assetService.Store(meshAsset);
583 891
584 pbs.SculptEntry = true; 892 if (offsets != 0)
585 pbs.SculptTexture = meshAsset.FullID; 893 f.OffsetU = offsets;
586 pbs.SculptType = (byte)SculptType.Mesh;
587 pbs.SculptData = meshAsset.Data;
588 894
589 Vector3 position = inner_instance_list["position"].AsVector3(); 895 if (offsett != 0)
590 Vector3 scale = inner_instance_list["scale"].AsVector3(); 896 f.OffsetV = offsett;
591 Quaternion rotation = inner_instance_list["rotation"].AsQuaternion(); 897
898 if (scales != 0)
899 f.RepeatU = scales;
900
901 if (scalet != 0)
902 f.RepeatV = scalet;
903
904 if (textures.Count > textureNum)
905 f.TextureID = textures[textureNum];
906 else
907 f.TextureID = Primitive.TextureEntry.WHITE_TEXTURE;
908
909 textureEntry.FaceTextures[face] = f;
910 }
911
912 pbs.TextureEntry = textureEntry.GetBytes();
913
914 bool hasmesh = false;
915 if (inner_instance_list.ContainsKey("mesh")) // seems to happen always but ...
916 {
917 int meshindx = inner_instance_list["mesh"].AsInteger();
918 if (meshAssets.Count > meshindx)
919 {
920 pbs.SculptEntry = true;
921 pbs.SculptType = (byte)SculptType.Mesh;
922 pbs.SculptTexture = meshAssets[meshindx]; // actual asset UUID after meshs suport introduction
923 // data will be requested from asset on rez (i hope)
924 hasmesh = true;
925 }
926 }
927
928 Vector3 position = inner_instance_list["position"].AsVector3();
929 Quaternion rotation = inner_instance_list["rotation"].AsQuaternion();
930
931 // for now viwers do send fixed defaults
932 // but this may change
933// int physicsShapeType = inner_instance_list["physics_shape_type"].AsInteger();
934 byte physicsShapeType = (byte)PhysShapeType.prim; // default for mesh is simple convex
935 if(hasmesh)
936 physicsShapeType = (byte) PhysShapeType.convex; // default for mesh is simple convex
937// int material = inner_instance_list["material"].AsInteger();
938 byte material = (byte)Material.Wood;
592 939
593// no longer used - begin ------------------------ 940// no longer used - begin ------------------------
594// int physicsShapeType = inner_instance_list["physics_shape_type"].AsInteger();
595// int material = inner_instance_list["material"].AsInteger();
596// int mesh = inner_instance_list["mesh"].AsInteger(); 941// int mesh = inner_instance_list["mesh"].AsInteger();
597 942
598// OSDMap permissions = (OSDMap)inner_instance_list["permissions"]; 943// OSDMap permissions = (OSDMap)inner_instance_list["permissions"];
@@ -607,24 +952,42 @@ namespace OpenSim.Region.ClientStack.Linden
607// UUID owner_id = permissions["owner_id"].AsUUID(); 952// UUID owner_id = permissions["owner_id"].AsUUID();
608// int owner_mask = permissions["owner_mask"].AsInteger(); 953// int owner_mask = permissions["owner_mask"].AsInteger();
609// no longer used - end ------------------------ 954// no longer used - end ------------------------
955
956
957 SceneObjectPart prim
958 = new SceneObjectPart(owner_id, pbs, position, Quaternion.Identity, Vector3.Zero);
959
960 prim.Scale = scale;
961 rotations.Add(rotation);
962 positions.Add(position);
963 prim.UUID = UUID.Random();
964 prim.CreatorID = creatorID;
965 prim.OwnerID = owner_id;
966 prim.GroupID = UUID.Zero;
967 prim.LastOwnerID = creatorID;
968 prim.CreationDate = Util.UnixTimeSinceEpoch();
969
970 if (grp == null)
971 prim.Name = assetName;
972 else
973 prim.Name = assetName + "#" + i.ToString();
610 974
611 UUID owner_id = m_HostCapsObj.AgentID; 975 if (restrictPerms)
976 {
977 prim.BaseMask = (uint)(PermissionMask.Move | PermissionMask.Modify);
978 prim.EveryoneMask = 0;
979 prim.GroupMask = 0;
980 prim.NextOwnerMask = 0;
981 prim.OwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify);
982 }
612 983
613 SceneObjectPart prim 984 if(istest)
614 = new SceneObjectPart(owner_id, pbs, position, Quaternion.Identity, Vector3.Zero); 985 prim.Description = "For testing only. Other uses are prohibited";
986 else
987 prim.Description = "";
615 988
616 prim.Scale = scale; 989 prim.Material = material;
617 prim.OffsetPosition = position; 990 prim.PhysicsShapeType = physicsShapeType;
618 rotations.Add(rotation);
619 positions.Add(position);
620 prim.UUID = UUID.Random();
621 prim.CreatorID = owner_id;
622 prim.OwnerID = owner_id;
623 prim.GroupID = UUID.Zero;
624 prim.LastOwnerID = prim.OwnerID;
625 prim.CreationDate = Util.UnixTimeSinceEpoch();
626 prim.Name = assetName;
627 prim.Description = "";
628 991
629// prim.BaseMask = (uint)base_mask; 992// prim.BaseMask = (uint)base_mask;
630// prim.EveryoneMask = (uint)everyone_mask; 993// prim.EveryoneMask = (uint)everyone_mask;
@@ -632,37 +995,64 @@ namespace OpenSim.Region.ClientStack.Linden
632// prim.NextOwnerMask = (uint)next_owner_mask; 995// prim.NextOwnerMask = (uint)next_owner_mask;
633// prim.OwnerMask = (uint)owner_mask; 996// prim.OwnerMask = (uint)owner_mask;
634 997
635 if (grp == null) 998 if (grp == null)
636 grp = new SceneObjectGroup(prim); 999 {
637 else 1000 grp = new SceneObjectGroup(prim);
638 grp.AddPart(prim); 1001 grp.LastOwnerID = creatorID;
639 } 1002 }
1003 else
1004 grp.AddPart(prim);
1005 }
640 1006
641 // Fix first link number 1007 Vector3 rootPos = positions[0];
642 if (grp.Parts.Length > 1)
643 grp.RootPart.LinkNum++;
644 1008
645 Vector3 rootPos = positions[0]; 1009 if (grp.Parts.Length > 1)
646 grp.AbsolutePosition = rootPos; 1010 {
647 for (int i = 0; i < positions.Count; i++) 1011 // Fix first link number
648 { 1012 grp.RootPart.LinkNum++;
649 Vector3 offset = positions[i] - rootPos; 1013
650 grp.Parts[i].OffsetPosition = offset; 1014 Quaternion rootRotConj = Quaternion.Conjugate(rotations[0]);
1015 Quaternion tmprot;
1016 Vector3 offset;
1017
1018 // fix children rotations and positions
1019 for (int i = 1; i < rotations.Count; i++)
1020 {
1021 tmprot = rotations[i];
1022 tmprot = rootRotConj * tmprot;
1023
1024 grp.Parts[i].RotationOffset = tmprot;
1025
1026 offset = positions[i] - rootPos;
1027
1028 offset *= rootRotConj;
1029 grp.Parts[i].OffsetPosition = offset;
1030 }
1031
1032 grp.AbsolutePosition = rootPos;
1033 grp.UpdateGroupRotationR(rotations[0]);
1034 }
1035 else
1036 {
1037 grp.AbsolutePosition = rootPos;
1038 grp.UpdateGroupRotationR(rotations[0]);
1039 }
1040
1041 data = ASCIIEncoding.ASCII.GetBytes(SceneObjectSerializer.ToOriginalXmlFormat(grp));
651 } 1042 }
652 1043
653 for (int i = 0; i < rotations.Count; i++) 1044 else // not a mesh model
654 { 1045 {
655 if (i != 0) 1046 m_log.ErrorFormat("[CAPS Asset Upload] got unsuported assetType for object upload");
656 grp.Parts[i].RotationOffset = rotations[i]; 1047 return;
657 } 1048 }
658
659 grp.UpdateGroupRotationR(rotations[0]);
660 data = ASCIIEncoding.ASCII.GetBytes(SceneObjectSerializer.ToOriginalXmlFormat(grp));
661 } 1049 }
662 1050
663 AssetBase asset; 1051 AssetBase asset;
664 asset = new AssetBase(assetID, assetName, assType, m_HostCapsObj.AgentID.ToString()); 1052 asset = new AssetBase(assetID, assetName, assType, creatorIDstr);
665 asset.Data = data; 1053 asset.Data = data;
1054 if (istest)
1055 asset.Local = true;
666 if (AddNewAsset != null) 1056 if (AddNewAsset != null)
667 AddNewAsset(asset); 1057 AddNewAsset(asset);
668 else if (m_assetService != null) 1058 else if (m_assetService != null)
@@ -670,11 +1060,17 @@ namespace OpenSim.Region.ClientStack.Linden
670 1060
671 InventoryItemBase item = new InventoryItemBase(); 1061 InventoryItemBase item = new InventoryItemBase();
672 item.Owner = m_HostCapsObj.AgentID; 1062 item.Owner = m_HostCapsObj.AgentID;
673 item.CreatorId = m_HostCapsObj.AgentID.ToString(); 1063 item.CreatorId = creatorIDstr;
674 item.CreatorData = String.Empty; 1064 item.CreatorData = String.Empty;
675 item.ID = inventoryItem; 1065 item.ID = inventoryItem;
676 item.AssetID = asset.FullID; 1066 item.AssetID = asset.FullID;
677 item.Description = assetDescription; 1067 if (istest)
1068 {
1069 item.Description = "For testing only. Other uses are prohibited";
1070 item.Flags = (uint) (InventoryItemFlags.SharedSingleReference);
1071 }
1072 else
1073 item.Description = assetDescription;
678 item.Name = assetName; 1074 item.Name = assetName;
679 item.AssetType = assType; 1075 item.AssetType = assType;
680 item.InvType = inType; 1076 item.InvType = inType;
@@ -682,18 +1078,60 @@ namespace OpenSim.Region.ClientStack.Linden
682 1078
683 // If we set PermissionMask.All then when we rez the item the next permissions will replace the current 1079 // If we set PermissionMask.All then when we rez the item the next permissions will replace the current
684 // (owner) permissions. This becomes a problem if next permissions are changed. 1080 // (owner) permissions. This becomes a problem if next permissions are changed.
685 item.CurrentPermissions
686 = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer);
687 1081
688 item.BasePermissions = (uint)PermissionMask.All; 1082 if (restrictPerms)
689 item.EveryOnePermissions = 0; 1083 {
690 item.NextPermissions = (uint)PermissionMask.All; 1084 item.CurrentPermissions
1085 = (uint)(PermissionMask.Move | PermissionMask.Modify);
1086
1087 item.BasePermissions = (uint)(PermissionMask.Move | PermissionMask.Modify);
1088 item.EveryOnePermissions = 0;
1089 item.NextPermissions = 0;
1090 }
1091 else
1092 {
1093 item.CurrentPermissions
1094 = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer);
1095
1096 item.BasePermissions = (uint)PermissionMask.All;
1097 item.EveryOnePermissions = 0;
1098 item.NextPermissions = (uint)PermissionMask.All;
1099 }
1100
691 item.CreationDate = Util.UnixTimeSinceEpoch(); 1101 item.CreationDate = Util.UnixTimeSinceEpoch();
692 1102
1103 m_Scene.TryGetClient(m_HostCapsObj.AgentID, out client);
1104
693 if (AddNewInventoryItem != null) 1105 if (AddNewInventoryItem != null)
694 { 1106 {
695 AddNewInventoryItem(m_HostCapsObj.AgentID, item); 1107 if (istest)
1108 {
1109 m_Scene.AddInventoryItem(client, item);
1110/*
1111 AddNewInventoryItem(m_HostCapsObj.AgentID, item, 0);
1112 if (client != null)
1113 client.SendAgentAlertMessage("Upload will have no cost, for personal test purposes only. Other uses are forbiden. Items may not work on a another region" , true);
1114 */
1115 }
1116 else
1117 {
1118 AddNewInventoryItem(m_HostCapsObj.AgentID, item, (uint)cost);
1119 if (client != null)
1120 {
1121 // let users see anything.. i don't so far
1122 string str;
1123 if (cost > 0)
1124 // dont remember where is money unit name to put here
1125 str = "Upload complete. charged " + cost.ToString() + "$";
1126 else
1127 str = "Upload complete";
1128 client.SendAgentAlertMessage(str, true);
1129 }
1130 }
696 } 1131 }
1132
1133 lock (m_ModelCost)
1134 m_FileAgentInventoryState = FileAgentInventoryState.idle;
697 } 1135 }
698 1136
699 /// <summary> 1137 /// <summary>
@@ -854,10 +1292,159 @@ namespace OpenSim.Region.ClientStack.Linden
854 response["int_response_code"] = 200; 1292 response["int_response_code"] = 200;
855 return LLSDHelpers.SerialiseLLSDReply(response); 1293 return LLSDHelpers.SerialiseLLSDReply(response);
856 } 1294 }
1295
1296 public string GetObjectPhysicsData(string request, string path,
1297 string param, IOSHttpRequest httpRequest,
1298 IOSHttpResponse httpResponse)
1299 {
1300 OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
1301 OSDMap resp = new OSDMap();
1302 OSDArray object_ids = (OSDArray)req["object_ids"];
1303
1304 for (int i = 0 ; i < object_ids.Count ; i++)
1305 {
1306 UUID uuid = object_ids[i].AsUUID();
1307
1308 SceneObjectPart obj = m_Scene.GetSceneObjectPart(uuid);
1309 if (obj != null)
1310 {
1311 OSDMap object_data = new OSDMap();
1312
1313 object_data["PhysicsShapeType"] = obj.PhysicsShapeType;
1314 object_data["Density"] = obj.Density;
1315 object_data["Friction"] = obj.Friction;
1316 object_data["Restitution"] = obj.Bounciness;
1317 object_data["GravityMultiplier"] = obj.GravityModifier;
1318
1319 resp[uuid.ToString()] = object_data;
1320 }
1321 }
1322
1323 string response = OSDParser.SerializeLLSDXmlString(resp);
1324 return response;
1325 }
1326
1327 public string GetObjectCost(string request, string path,
1328 string param, IOSHttpRequest httpRequest,
1329 IOSHttpResponse httpResponse)
1330 {
1331 OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
1332 OSDMap resp = new OSDMap();
1333
1334 OSDArray object_ids = (OSDArray)req["object_ids"];
1335
1336 for (int i = 0; i < object_ids.Count; i++)
1337 {
1338 UUID uuid = object_ids[i].AsUUID();
1339
1340 SceneObjectPart part = m_Scene.GetSceneObjectPart(uuid);
1341
1342 if (part != null)
1343 {
1344 SceneObjectGroup grp = part.ParentGroup;
1345 if (grp != null)
1346 {
1347 float linksetCost;
1348 float linksetPhysCost;
1349 float partCost;
1350 float partPhysCost;
1351
1352 grp.GetResourcesCosts(part, out linksetCost, out linksetPhysCost, out partCost, out partPhysCost);
1353
1354 OSDMap object_data = new OSDMap();
1355 object_data["linked_set_resource_cost"] = linksetCost;
1356 object_data["resource_cost"] = partCost;
1357 object_data["physics_cost"] = partPhysCost;
1358 object_data["linked_set_physics_cost"] = linksetPhysCost;
1359
1360 resp[uuid.ToString()] = object_data;
1361 }
1362 }
1363 }
1364
1365 string response = OSDParser.SerializeLLSDXmlString(resp);
1366 return response;
1367 }
1368
1369 public string ResourceCostSelected(string request, string path,
1370 string param, IOSHttpRequest httpRequest,
1371 IOSHttpResponse httpResponse)
1372 {
1373 OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
1374 OSDMap resp = new OSDMap();
1375
1376
1377 float phys=0;
1378 float stream=0;
1379 float simul=0;
1380
1381 if (req.ContainsKey("selected_roots"))
1382 {
1383 OSDArray object_ids = (OSDArray)req["selected_roots"];
1384
1385 // should go by SOG suming costs for all parts
1386 // ll v3 works ok with several objects select we get the list and adds ok
1387 // FS calls per object so results are wrong guess fs bug
1388 for (int i = 0; i < object_ids.Count; i++)
1389 {
1390 UUID uuid = object_ids[i].AsUUID();
1391 float Physc;
1392 float simulc;
1393 float streamc;
1394
1395 SceneObjectGroup grp = m_Scene.GetGroupByPrim(uuid);
1396 if (grp != null)
1397 {
1398 grp.GetSelectedCosts(out Physc, out streamc, out simulc);
1399 phys += Physc;
1400 stream += streamc;
1401 simul += simulc;
1402 }
1403 }
1404 }
1405 else if (req.ContainsKey("selected_prims"))
1406 {
1407 OSDArray object_ids = (OSDArray)req["selected_prims"];
1408
1409 // don't see in use in any of the 2 viewers
1410 // guess it should be for edit linked but... nothing
1411 // should go to SOP per part
1412 for (int i = 0; i < object_ids.Count; i++)
1413 {
1414 UUID uuid = object_ids[i].AsUUID();
1415
1416 SceneObjectPart part = m_Scene.GetSceneObjectPart(uuid);
1417 if (part != null)
1418 {
1419 phys += part.PhysicsCost;
1420 stream += part.StreamingCost;
1421 simul += part.SimulationCost;
1422 }
1423 }
1424 }
1425
1426 if (simul != 0)
1427 {
1428 OSDMap object_data = new OSDMap();
1429
1430 object_data["physics"] = phys;
1431 object_data["streaming"] = stream;
1432 object_data["simulation"] = simul;
1433
1434 resp["selected"] = object_data;
1435 }
1436
1437 string response = OSDParser.SerializeLLSDXmlString(resp);
1438 return response;
1439 }
857 } 1440 }
858 1441
859 public class AssetUploader 1442 public class AssetUploader
860 { 1443 {
1444 private static readonly ILog m_log =
1445 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
1446
1447
861 public event UpLoadedAsset OnUpLoad; 1448 public event UpLoadedAsset OnUpLoad;
862 private UpLoadedAsset handlerUpLoad = null; 1449 private UpLoadedAsset handlerUpLoad = null;
863 1450
@@ -872,10 +1459,21 @@ namespace OpenSim.Region.ClientStack.Linden
872 1459
873 private string m_invType = String.Empty; 1460 private string m_invType = String.Empty;
874 private string m_assetType = String.Empty; 1461 private string m_assetType = String.Empty;
1462 private int m_cost;
1463 private string m_error = String.Empty;
1464
1465 private Timer m_timeoutTimer = new Timer();
1466 private UUID m_texturesFolder;
1467 private int m_nreqtextures;
1468 private int m_nreqmeshs;
1469 private int m_nreqinstances;
1470 private bool m_IsAtestUpload;
875 1471
876 public AssetUploader(string assetName, string description, UUID assetID, UUID inventoryItem, 1472 public AssetUploader(string assetName, string description, UUID assetID, UUID inventoryItem,
877 UUID parentFolderID, string invType, string assetType, string path, 1473 UUID parentFolderID, string invType, string assetType, string path,
878 IHttpServer httpServer, bool dumpAssetsToFile) 1474 IHttpServer httpServer, bool dumpAssetsToFile,
1475 int totalCost, UUID texturesFolder, int nreqtextures, int nreqmeshs, int nreqinstances,
1476 bool IsAtestUpload)
879 { 1477 {
880 m_assetName = assetName; 1478 m_assetName = assetName;
881 m_assetDes = description; 1479 m_assetDes = description;
@@ -887,6 +1485,18 @@ namespace OpenSim.Region.ClientStack.Linden
887 m_assetType = assetType; 1485 m_assetType = assetType;
888 m_invType = invType; 1486 m_invType = invType;
889 m_dumpAssetsToFile = dumpAssetsToFile; 1487 m_dumpAssetsToFile = dumpAssetsToFile;
1488 m_cost = totalCost;
1489
1490 m_texturesFolder = texturesFolder;
1491 m_nreqtextures = nreqtextures;
1492 m_nreqmeshs = nreqmeshs;
1493 m_nreqinstances = nreqinstances;
1494 m_IsAtestUpload = IsAtestUpload;
1495
1496 m_timeoutTimer.Elapsed += TimedOut;
1497 m_timeoutTimer.Interval = 120000;
1498 m_timeoutTimer.AutoReset = false;
1499 m_timeoutTimer.Start();
890 } 1500 }
891 1501
892 /// <summary> 1502 /// <summary>
@@ -901,12 +1511,14 @@ namespace OpenSim.Region.ClientStack.Linden
901 UUID inv = inventoryItemID; 1511 UUID inv = inventoryItemID;
902 string res = String.Empty; 1512 string res = String.Empty;
903 LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete(); 1513 LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete();
1514/*
904 uploadComplete.new_asset = newAssetID.ToString(); 1515 uploadComplete.new_asset = newAssetID.ToString();
905 uploadComplete.new_inventory_item = inv; 1516 uploadComplete.new_inventory_item = inv;
906 uploadComplete.state = "complete"; 1517 uploadComplete.state = "complete";
907 1518
908 res = LLSDHelpers.SerialiseLLSDReply(uploadComplete); 1519 res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
909 1520*/
1521 m_timeoutTimer.Stop();
910 httpListener.RemoveStreamHandler("POST", uploaderPath); 1522 httpListener.RemoveStreamHandler("POST", uploaderPath);
911 1523
912 // TODO: probably make this a better set of extensions here 1524 // TODO: probably make this a better set of extensions here
@@ -923,12 +1535,49 @@ namespace OpenSim.Region.ClientStack.Linden
923 handlerUpLoad = OnUpLoad; 1535 handlerUpLoad = OnUpLoad;
924 if (handlerUpLoad != null) 1536 if (handlerUpLoad != null)
925 { 1537 {
926 handlerUpLoad(m_assetName, m_assetDes, newAssetID, inv, parentFolder, data, m_invType, m_assetType); 1538 handlerUpLoad(m_assetName, m_assetDes, newAssetID, inv, parentFolder, data, m_invType, m_assetType,
1539 m_cost, m_texturesFolder, m_nreqtextures, m_nreqmeshs, m_nreqinstances, m_IsAtestUpload, ref m_error);
1540 }
1541 if (m_IsAtestUpload)
1542 {
1543 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
1544 resperror.message = "Upload SUCESSEFULL for testing purposes only. Other uses are prohibited. Item will not work after 48 hours or on other regions";
1545 resperror.identifier = inv;
1546
1547 uploadComplete.error = resperror;
1548 uploadComplete.state = "Upload4Testing";
927 } 1549 }
1550 else
1551 {
1552 if (m_error == String.Empty)
1553 {
1554 uploadComplete.new_asset = newAssetID.ToString();
1555 uploadComplete.new_inventory_item = inv;
1556 // if (m_texturesFolder != UUID.Zero)
1557 // uploadComplete.new_texture_folder_id = m_texturesFolder;
1558 uploadComplete.state = "complete";
1559 }
1560 else
1561 {
1562 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
1563 resperror.message = m_error;
1564 resperror.identifier = inv;
928 1565
1566 uploadComplete.error = resperror;
1567 uploadComplete.state = "failed";
1568 }
1569 }
1570
1571 res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
929 return res; 1572 return res;
930 } 1573 }
931 1574
1575 private void TimedOut(object sender, ElapsedEventArgs args)
1576 {
1577 m_log.InfoFormat("[CAPS]: Removing URL and handler for timed out mesh upload");
1578 httpListener.RemoveStreamHandler("POST", uploaderPath);
1579 }
1580
932 ///Left this in and commented in case there are unforseen issues 1581 ///Left this in and commented in case there are unforseen issues
933 //private void SaveAssetToFile(string filename, byte[] data) 1582 //private void SaveAssetToFile(string filename, byte[] data)
934 //{ 1583 //{
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs
new file mode 100644
index 0000000..4a3fae6
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs
@@ -0,0 +1,671 @@
1// Proprietary code of Avination Virtual Limited
2// (c) 2012 Melanie Thielker, Leal Duarte
3//
4
5using System;
6using System.IO;
7using System.Collections;
8using System.Collections.Generic;
9using System.Text;
10
11using OpenMetaverse;
12using OpenMetaverse.StructuredData;
13
14using OpenSim.Framework;
15using OpenSim.Region.Framework;
16using OpenSim.Region.Framework.Scenes;
17using OpenSim.Framework.Capabilities;
18
19using ComponentAce.Compression.Libs.zlib;
20
21using OSDArray = OpenMetaverse.StructuredData.OSDArray;
22using OSDMap = OpenMetaverse.StructuredData.OSDMap;
23
24namespace OpenSim.Region.ClientStack.Linden
25{
26 public struct ModelPrimLimits
27 {
28
29 }
30
31 public class ModelCost
32 {
33
34 // upload fee defaults
35 // fees are normalized to 1.0
36 // this parameters scale them to basic cost ( so 1.0 translates to 10 )
37
38 public float ModelMeshCostFactor = 0.0f; // scale total cost relative to basic (excluding textures)
39 public float ModelTextureCostFactor = 1.0f; // scale textures fee to basic.
40 public float ModelMinCostFactor = 0.0f; // 0.5f; // minimum total model free excluding textures
41
42 // itens costs in normalized values
43 // ie will be multiplied by basicCost and factors above
44 public float primCreationCost = 0.002f; // extra cost for each prim creation overhead
45 // weigthed size to normalized cost
46 public float bytecost = 1e-5f;
47
48 // mesh upload fees based on compressed data sizes
49 // several data sections are counted more that once
50 // to promote user optimization
51 // following parameters control how many extra times they are added
52 // to global size.
53 // LOD meshs
54 const float medSizeWth = 1f; // 2x
55 const float lowSizeWth = 1.5f; // 2.5x
56 const float lowestSizeWth = 2f; // 3x
57 // favor potencially physical optimized meshs versus automatic decomposition
58 const float physMeshSizeWth = 6f; // counts 7x
59 const float physHullSizeWth = 8f; // counts 9x
60
61 // stream cost area factors
62 // more or less like SL
63 const float highLodFactor = 17.36f;
64 const float midLodFactor = 277.78f;
65 const float lowLodFactor = 1111.11f;
66
67 // physics cost is below, identical to SL, assuming shape type convex
68 // server cost is below identical to SL assuming non scripted non physical object
69
70 // internal
71 const int bytesPerCoord = 6; // 3 coords, 2 bytes per each
72
73 // control prims dimensions
74 public float PrimScaleMin = 0.001f;
75 public float NonPhysicalPrimScaleMax = 256f;
76 public float PhysicalPrimScaleMax = 10f;
77 public int ObjectLinkedPartsMax = 512;
78
79 // storage for a single mesh asset cost parameters
80 private class ameshCostParam
81 {
82 // LOD sizes for size dependent streaming cost
83 public int highLODSize;
84 public int medLODSize;
85 public int lowLODSize;
86 public int lowestLODSize;
87 // normalized fee based on compressed data sizes
88 public float costFee;
89 // physics cost
90 public float physicsCost;
91 }
92
93 // calculates a mesh model costs
94 // returns false on error, with a reason on parameter error
95 // resources input LLSD request
96 // basicCost input region assets upload cost
97 // totalcost returns model total upload fee
98 // meshcostdata returns detailed costs for viewer
99 public bool MeshModelCost(LLSDAssetResource resources, int basicCost, out int totalcost,
100 LLSDAssetUploadResponseData meshcostdata, out string error, ref string warning)
101 {
102 totalcost = 0;
103 error = string.Empty;
104
105 if (resources == null ||
106 resources.instance_list == null ||
107 resources.instance_list.Array.Count == 0)
108 {
109 error = "missing model information.";
110 return false;
111 }
112
113 int numberInstances = resources.instance_list.Array.Count;
114
115 if( numberInstances > ObjectLinkedPartsMax )
116 {
117 error = "Model whould have more than " + ObjectLinkedPartsMax.ToString() + " linked prims";
118 return false;
119 }
120
121 meshcostdata.model_streaming_cost = 0.0;
122 meshcostdata.simulation_cost = 0.0;
123 meshcostdata.physics_cost = 0.0;
124 meshcostdata.resource_cost = 0.0;
125
126 meshcostdata.upload_price_breakdown.mesh_instance = 0;
127 meshcostdata.upload_price_breakdown.mesh_physics = 0;
128 meshcostdata.upload_price_breakdown.mesh_streaming = 0;
129 meshcostdata.upload_price_breakdown.model = 0;
130
131 int itmp;
132
133 // textures cost
134 if (resources.texture_list != null && resources.texture_list.Array.Count > 0)
135 {
136 float textures_cost = (float)(resources.texture_list.Array.Count * basicCost);
137 textures_cost *= ModelTextureCostFactor;
138
139 itmp = (int)(textures_cost + 0.5f); // round
140 meshcostdata.upload_price_breakdown.texture = itmp;
141 totalcost += itmp;
142 }
143
144 // meshs assets cost
145 float meshsfee = 0;
146 int numberMeshs = 0;
147 bool haveMeshs = false;
148 List<ameshCostParam> meshsCosts = new List<ameshCostParam>();
149
150 if (resources.mesh_list != null && resources.mesh_list.Array.Count > 0)
151 {
152 numberMeshs = resources.mesh_list.Array.Count;
153
154 for (int i = 0; i < numberMeshs; i++)
155 {
156 ameshCostParam curCost = new ameshCostParam();
157 byte[] data = (byte[])resources.mesh_list.Array[i];
158
159 if (!MeshCost(data, curCost, out error))
160 {
161 return false;
162 }
163 meshsCosts.Add(curCost);
164 meshsfee += curCost.costFee;
165 }
166 haveMeshs = true;
167 }
168
169 // instances (prims) cost
170
171
172 int mesh;
173 int skipedSmall = 0;
174 for (int i = 0; i < numberInstances; i++)
175 {
176 Hashtable inst = (Hashtable)resources.instance_list.Array[i];
177
178 ArrayList ascale = (ArrayList)inst["scale"];
179 Vector3 scale;
180 double tmp;
181 tmp = (double)ascale[0];
182 scale.X = (float)tmp;
183 tmp = (double)ascale[1];
184 scale.Y = (float)tmp;
185 tmp = (double)ascale[2];
186 scale.Z = (float)tmp;
187
188 if (scale.X < PrimScaleMin || scale.Y < PrimScaleMin || scale.Z < PrimScaleMin)
189 {
190 skipedSmall++;
191 continue;
192 }
193
194 if (scale.X > NonPhysicalPrimScaleMax || scale.Y > NonPhysicalPrimScaleMax || scale.Z > NonPhysicalPrimScaleMax)
195 {
196 error = "Model contains parts with sides larger than " + NonPhysicalPrimScaleMax.ToString() + "m. Please ajust scale";
197 return false;
198 }
199
200 if (haveMeshs && inst.ContainsKey("mesh"))
201 {
202 mesh = (int)inst["mesh"];
203
204 if (mesh >= numberMeshs)
205 {
206 error = "Incoerent model information.";
207 return false;
208 }
209
210 // streamming cost
211
212 float sqdiam = scale.LengthSquared();
213
214 ameshCostParam curCost = meshsCosts[mesh];
215 float mesh_streaming = streamingCost(curCost, sqdiam);
216
217 meshcostdata.model_streaming_cost += mesh_streaming;
218 meshcostdata.physics_cost += curCost.physicsCost;
219 }
220 else // instance as no mesh ??
221 {
222 // to do later if needed
223 meshcostdata.model_streaming_cost += 0.5f;
224 meshcostdata.physics_cost += 1.0f;
225 }
226
227 // assume unscripted and static prim server cost
228 meshcostdata.simulation_cost += 0.5f;
229 // charge for prims creation
230 meshsfee += primCreationCost;
231 }
232
233 if (skipedSmall > 0)
234 {
235 if (skipedSmall > numberInstances / 2)
236 {
237 error = "Model contains too many prims smaller than " + PrimScaleMin.ToString() +
238 "m minimum allowed size. Please check scalling";
239 return false;
240 }
241 else
242 warning += skipedSmall.ToString() + " of the requested " +numberInstances.ToString() +
243 " model prims will not upload because they are smaller than " + PrimScaleMin.ToString() +
244 "m minimum allowed size. Please check scalling ";
245 }
246
247 if (meshcostdata.physics_cost <= meshcostdata.model_streaming_cost)
248 meshcostdata.resource_cost = meshcostdata.model_streaming_cost;
249 else
250 meshcostdata.resource_cost = meshcostdata.physics_cost;
251
252 if (meshcostdata.resource_cost < meshcostdata.simulation_cost)
253 meshcostdata.resource_cost = meshcostdata.simulation_cost;
254
255 // scale cost
256 // at this point a cost of 1.0 whould mean basic cost
257 meshsfee *= ModelMeshCostFactor;
258
259 if (meshsfee < ModelMinCostFactor)
260 meshsfee = ModelMinCostFactor;
261
262 // actually scale it to basic cost
263 meshsfee *= (float)basicCost;
264
265 meshsfee += 0.5f; // rounding
266
267 totalcost += (int)meshsfee;
268
269 // breakdown prices
270 // don't seem to be in use so removed code for now
271
272 return true;
273 }
274
275 // single mesh asset cost
276 private bool MeshCost(byte[] data, ameshCostParam cost, out string error)
277 {
278 cost.highLODSize = 0;
279 cost.medLODSize = 0;
280 cost.lowLODSize = 0;
281 cost.lowestLODSize = 0;
282 cost.physicsCost = 0.0f;
283 cost.costFee = 0.0f;
284
285 error = string.Empty;
286
287 if (data == null || data.Length == 0)
288 {
289 error = "Missing model information.";
290 return false;
291 }
292
293 OSD meshOsd = null;
294 int start = 0;
295
296 error = "Invalid model data";
297
298 using (MemoryStream ms = new MemoryStream(data))
299 {
300 try
301 {
302 OSD osd = OSDParser.DeserializeLLSDBinary(ms);
303 if (osd is OSDMap)
304 meshOsd = (OSDMap)osd;
305 else
306 return false;
307 }
308 catch (Exception e)
309 {
310 return false;
311 }
312 start = (int)ms.Position;
313 }
314
315 OSDMap map = (OSDMap)meshOsd;
316 OSDMap tmpmap;
317
318 int highlod_size = 0;
319 int medlod_size = 0;
320 int lowlod_size = 0;
321 int lowestlod_size = 0;
322 int skin_size = 0;
323
324 int hulls_size = 0;
325 int phys_nhulls;
326 int phys_hullsvertices = 0;
327
328 int physmesh_size = 0;
329 int phys_ntriangles = 0;
330
331 int submesh_offset = -1;
332
333 if (map.ContainsKey("physics_convex"))
334 {
335 tmpmap = (OSDMap)map["physics_convex"];
336 if (tmpmap.ContainsKey("offset"))
337 submesh_offset = tmpmap["offset"].AsInteger() + start;
338 if (tmpmap.ContainsKey("size"))
339 hulls_size = tmpmap["size"].AsInteger();
340 }
341
342 if (submesh_offset < 0 || hulls_size == 0)
343 {
344 error = "Missing physics_convex block";
345 return false;
346 }
347
348 if (!hulls(data, submesh_offset, hulls_size, out phys_hullsvertices, out phys_nhulls))
349 {
350 error = "Bad physics_convex block";
351 return false;
352 }
353
354 submesh_offset = -1;
355
356 // only look for LOD meshs sizes
357
358 if (map.ContainsKey("high_lod"))
359 {
360 tmpmap = (OSDMap)map["high_lod"];
361 // see at least if there is a offset for this one
362 if (tmpmap.ContainsKey("offset"))
363 submesh_offset = tmpmap["offset"].AsInteger() + start;
364 if (tmpmap.ContainsKey("size"))
365 highlod_size = tmpmap["size"].AsInteger();
366 }
367
368 if (submesh_offset < 0 || highlod_size <= 0)
369 {
370 error = "Missing high_lod block";
371 return false;
372 }
373
374 bool haveprev = true;
375
376 if (map.ContainsKey("medium_lod"))
377 {
378 tmpmap = (OSDMap)map["medium_lod"];
379 if (tmpmap.ContainsKey("size"))
380 medlod_size = tmpmap["size"].AsInteger();
381 else
382 haveprev = false;
383 }
384
385 if (haveprev && map.ContainsKey("low_lod"))
386 {
387 tmpmap = (OSDMap)map["low_lod"];
388 if (tmpmap.ContainsKey("size"))
389 lowlod_size = tmpmap["size"].AsInteger();
390 else
391 haveprev = false;
392 }
393
394 if (haveprev && map.ContainsKey("lowest_lod"))
395 {
396 tmpmap = (OSDMap)map["lowest_lod"];
397 if (tmpmap.ContainsKey("size"))
398 lowestlod_size = tmpmap["size"].AsInteger();
399 }
400
401 if (map.ContainsKey("skin"))
402 {
403 tmpmap = (OSDMap)map["skin"];
404 if (tmpmap.ContainsKey("size"))
405 skin_size = tmpmap["size"].AsInteger();
406 }
407
408 cost.highLODSize = highlod_size;
409 cost.medLODSize = medlod_size;
410 cost.lowLODSize = lowlod_size;
411 cost.lowestLODSize = lowestlod_size;
412
413 submesh_offset = -1;
414
415 tmpmap = null;
416 if(map.ContainsKey("physics_mesh"))
417 tmpmap = (OSDMap)map["physics_mesh"];
418 else if (map.ContainsKey("physics_shape")) // old naming
419 tmpmap = (OSDMap)map["physics_shape"];
420
421 if(tmpmap != null)
422 {
423 if (tmpmap.ContainsKey("offset"))
424 submesh_offset = tmpmap["offset"].AsInteger() + start;
425 if (tmpmap.ContainsKey("size"))
426 physmesh_size = tmpmap["size"].AsInteger();
427
428 if (submesh_offset >= 0 || physmesh_size > 0)
429 {
430
431 if (!submesh(data, submesh_offset, physmesh_size, out phys_ntriangles))
432 {
433 error = "Model data parsing error";
434 return false;
435 }
436 }
437 }
438
439 // upload is done in convex shape type so only one hull
440 phys_hullsvertices++;
441 cost.physicsCost = 0.04f * phys_hullsvertices;
442
443 float sfee;
444
445 sfee = data.Length; // start with total compressed data size
446
447 // penalize lod meshs that should be more builder optimized
448 sfee += medSizeWth * medlod_size;
449 sfee += lowSizeWth * lowlod_size;
450 sfee += lowestSizeWth * lowlod_size;
451
452 // physics
453 // favor potencial optimized meshs versus automatic decomposition
454 if (physmesh_size != 0)
455 sfee += physMeshSizeWth * (physmesh_size + hulls_size / 4); // reduce cost of mandatory convex hull
456 else
457 sfee += physHullSizeWth * hulls_size;
458
459 // bytes to money
460 sfee *= bytecost;
461
462 cost.costFee = sfee;
463 return true;
464 }
465
466 // parses a LOD or physics mesh component
467 private bool submesh(byte[] data, int offset, int size, out int ntriangles)
468 {
469 ntriangles = 0;
470
471 OSD decodedMeshOsd = new OSD();
472 byte[] meshBytes = new byte[size];
473 System.Buffer.BlockCopy(data, offset, meshBytes, 0, size);
474 try
475 {
476 using (MemoryStream inMs = new MemoryStream(meshBytes))
477 {
478 using (MemoryStream outMs = new MemoryStream())
479 {
480 using (ZOutputStream zOut = new ZOutputStream(outMs))
481 {
482 byte[] readBuffer = new byte[4096];
483 int readLen = 0;
484 while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0)
485 {
486 zOut.Write(readBuffer, 0, readLen);
487 }
488 zOut.Flush();
489 outMs.Seek(0, SeekOrigin.Begin);
490
491 byte[] decompressedBuf = outMs.GetBuffer();
492 decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf);
493 }
494 }
495 }
496 }
497 catch (Exception e)
498 {
499 return false;
500 }
501
502 OSDArray decodedMeshOsdArray = null;
503 if ((!decodedMeshOsd is OSDArray))
504 return false;
505
506 byte[] dummy;
507
508 decodedMeshOsdArray = (OSDArray)decodedMeshOsd;
509 foreach (OSD subMeshOsd in decodedMeshOsdArray)
510 {
511 if (subMeshOsd is OSDMap)
512 {
513 OSDMap subtmpmap = (OSDMap)subMeshOsd;
514 if (subtmpmap.ContainsKey("NoGeometry") && ((OSDBoolean)subtmpmap["NoGeometry"]))
515 continue;
516
517 if (!subtmpmap.ContainsKey("Position"))
518 return false;
519
520 if (subtmpmap.ContainsKey("TriangleList"))
521 {
522 dummy = subtmpmap["TriangleList"].AsBinary();
523 ntriangles += dummy.Length / bytesPerCoord;
524 }
525 else
526 return false;
527 }
528 }
529
530 return true;
531 }
532
533 // parses convex hulls component
534 private bool hulls(byte[] data, int offset, int size, out int nvertices, out int nhulls)
535 {
536 nvertices = 0;
537 nhulls = 1;
538
539 OSD decodedMeshOsd = new OSD();
540 byte[] meshBytes = new byte[size];
541 System.Buffer.BlockCopy(data, offset, meshBytes, 0, size);
542 try
543 {
544 using (MemoryStream inMs = new MemoryStream(meshBytes))
545 {
546 using (MemoryStream outMs = new MemoryStream())
547 {
548 using (ZOutputStream zOut = new ZOutputStream(outMs))
549 {
550 byte[] readBuffer = new byte[4096];
551 int readLen = 0;
552 while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0)
553 {
554 zOut.Write(readBuffer, 0, readLen);
555 }
556 zOut.Flush();
557 outMs.Seek(0, SeekOrigin.Begin);
558
559 byte[] decompressedBuf = outMs.GetBuffer();
560 decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf);
561 }
562 }
563 }
564 }
565 catch (Exception e)
566 {
567 return false;
568 }
569
570 OSDMap cmap = (OSDMap)decodedMeshOsd;
571 if (cmap == null)
572 return false;
573
574 byte[] dummy;
575
576 // must have one of this
577 if (cmap.ContainsKey("BoundingVerts"))
578 {
579 dummy = cmap["BoundingVerts"].AsBinary();
580 nvertices = dummy.Length / bytesPerCoord;
581 }
582 else
583 return false;
584
585/* upload is done with convex shape type
586 if (cmap.ContainsKey("HullList"))
587 {
588 dummy = cmap["HullList"].AsBinary();
589 nhulls += dummy.Length;
590 }
591
592
593 if (cmap.ContainsKey("Positions"))
594 {
595 dummy = cmap["Positions"].AsBinary();
596 nvertices = dummy.Length / bytesPerCoord;
597 }
598 */
599
600 return true;
601 }
602
603 // returns streaming cost from on mesh LODs sizes in curCost and square of prim size length
604 private float streamingCost(ameshCostParam curCost, float sqdiam)
605 {
606 // compute efective areas
607 float ma = 262144f;
608
609 float mh = sqdiam * highLodFactor;
610 if (mh > ma)
611 mh = ma;
612 float mm = sqdiam * midLodFactor;
613 if (mm > ma)
614 mm = ma;
615
616 float ml = sqdiam * lowLodFactor;
617 if (ml > ma)
618 ml = ma;
619
620 float mlst = ma;
621
622 mlst -= ml;
623 ml -= mm;
624 mm -= mh;
625
626 if (mlst < 1.0f)
627 mlst = 1.0f;
628 if (ml < 1.0f)
629 ml = 1.0f;
630 if (mm < 1.0f)
631 mm = 1.0f;
632 if (mh < 1.0f)
633 mh = 1.0f;
634
635 ma = mlst + ml + mm + mh;
636
637 // get LODs compressed sizes
638 // giving 384 bytes bonus
639 int lst = curCost.lowestLODSize - 384;
640 int l = curCost.lowLODSize - 384;
641 int m = curCost.medLODSize - 384;
642 int h = curCost.highLODSize - 384;
643
644 // use previus higher LOD size on missing ones
645 if (m <= 0)
646 m = h;
647 if (l <= 0)
648 l = m;
649 if (lst <= 0)
650 lst = l;
651
652 // force minumum sizes
653 if (lst < 16)
654 lst = 16;
655 if (l < 16)
656 l = 16;
657 if (m < 16)
658 m = 16;
659 if (h < 16)
660 h = 16;
661
662 // compute cost weighted by relative effective areas
663 float cost = (float)lst * mlst + (float)l * ml + (float)m * mm + (float)h * mh;
664 cost /= ma;
665
666 cost *= 0.004f; // overall tunning parameter
667
668 return cost;
669 }
670 }
671}