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 cc69645..f6146a9 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",
@@ -386,62 +469,176 @@ namespace OpenSim.Region.ClientStack.Linden
386 //m_log.Debug("[CAPS]: NewAgentInventoryRequest Request is: " + llsdRequest.ToString()); 469 //m_log.Debug("[CAPS]: NewAgentInventoryRequest Request is: " + llsdRequest.ToString());
387 //m_log.Debug("asset upload request via CAPS" + llsdRequest.inventory_type + " , " + llsdRequest.asset_type); 470 //m_log.Debug("asset upload request via CAPS" + llsdRequest.inventory_type + " , " + llsdRequest.asset_type);
388 471
472 // start by getting the client
473 IClientAPI client = null;
474 m_Scene.TryGetClient(m_HostCapsObj.AgentID, out client);
475
476 // check current state so we only have one service at a time
477 lock (m_ModelCost)
478 {
479 switch (m_FileAgentInventoryState)
480 {
481 case FileAgentInventoryState.processRequest:
482 case FileAgentInventoryState.processUpload:
483 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
484 resperror.message = "Uploader busy processing previus request";
485 resperror.identifier = UUID.Zero;
486
487 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
488 errorResponse.uploader = "";
489 errorResponse.state = "error";
490 errorResponse.error = resperror;
491 return errorResponse;
492 break;
493 case FileAgentInventoryState.waitUpload:
494 // todo stop current uploader server
495 break;
496 case FileAgentInventoryState.idle:
497 default:
498 break;
499 }
500
501 m_FileAgentInventoryState = FileAgentInventoryState.processRequest;
502 }
503
504 int cost = 0;
505 int nreqtextures = 0;
506 int nreqmeshs= 0;
507 int nreqinstances = 0;
508 bool IsAtestUpload = false;
509
510 string assetName = llsdRequest.name;
511
512 LLSDAssetUploadResponseData meshcostdata = new LLSDAssetUploadResponseData();
513
389 if (llsdRequest.asset_type == "texture" || 514 if (llsdRequest.asset_type == "texture" ||
390 llsdRequest.asset_type == "animation" || 515 llsdRequest.asset_type == "animation" ||
516 llsdRequest.asset_type == "mesh" ||
391 llsdRequest.asset_type == "sound") 517 llsdRequest.asset_type == "sound")
392 { 518 {
393 ScenePresence avatar = null; 519 ScenePresence avatar = null;
394 IClientAPI client = null;
395 m_Scene.TryGetScenePresence(m_HostCapsObj.AgentID, out avatar); 520 m_Scene.TryGetScenePresence(m_HostCapsObj.AgentID, out avatar);
396 521
397 // check user level 522 // check user level
398 if (avatar != null) 523 if (avatar != null)
399 { 524 {
400 client = avatar.ControllingClient;
401
402 if (avatar.UserLevel < m_levelUpload) 525 if (avatar.UserLevel < m_levelUpload)
403 { 526 {
404 if (client != null) 527 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
405 client.SendAgentAlertMessage("Unable to upload asset. Insufficient permissions.", false); 528 resperror.message = "Insufficient permissions to upload";
529 resperror.identifier = UUID.Zero;
406 530
407 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse(); 531 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
408 errorResponse.uploader = ""; 532 errorResponse.uploader = "";
409 errorResponse.state = "error"; 533 errorResponse.state = "error";
534 errorResponse.error = resperror;
535 lock (m_ModelCost)
536 m_FileAgentInventoryState = FileAgentInventoryState.idle;
410 return errorResponse; 537 return errorResponse;
411 } 538 }
412 } 539 }
413 540
414 // check funds 541 // check test upload and funds
415 if (client != null) 542 if (client != null)
416 { 543 {
417 IMoneyModule mm = m_Scene.RequestModuleInterface<IMoneyModule>(); 544 IMoneyModule mm = m_Scene.RequestModuleInterface<IMoneyModule>();
418 545
546 int baseCost = 0;
419 if (mm != null) 547 if (mm != null)
548 baseCost = mm.UploadCharge;
549
550 string warning = String.Empty;
551
552 if (llsdRequest.asset_type == "mesh")
420 { 553 {
421 if (!mm.UploadCovered(client.AgentId, mm.UploadCharge)) 554 string error;
555 int modelcost;
556
557 if (!m_ModelCost.MeshModelCost(llsdRequest.asset_resources, baseCost, out modelcost,
558 meshcostdata, out error, ref warning))
422 { 559 {
423 client.SendAgentAlertMessage("Unable to upload asset. Insufficient funds.", false); 560 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
561 resperror.message = error;
562 resperror.identifier = UUID.Zero;
424 563
425 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse(); 564 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
426 errorResponse.uploader = ""; 565 errorResponse.uploader = "";
427 errorResponse.state = "error"; 566 errorResponse.state = "error";
567 errorResponse.error = resperror;
568
569 lock (m_ModelCost)
570 m_FileAgentInventoryState = FileAgentInventoryState.idle;
428 return errorResponse; 571 return errorResponse;
429 } 572 }
573 cost = modelcost;
574 }
575 else
576 {
577 cost = baseCost;
578 }
579
580 if (cost > 0 && mm != null)
581 {
582 // check for test upload
583
584 if (m_ForceFreeTestUpload) // all are test
585 {
586 if (!(assetName.Length > 5 && assetName.StartsWith("TEST-"))) // has normal name lets change it
587 assetName = "TEST-" + assetName;
588
589 IsAtestUpload = true;
590 }
591
592 else if (m_enableFreeTestUpload) // only if prefixed with "TEST-"
593 {
594
595 IsAtestUpload = (assetName.Length > 5 && assetName.StartsWith("TEST-"));
596 }
597
598
599 if(IsAtestUpload) // let user know, still showing cost estimation
600 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";
601
602 // check funds
603 else
604 {
605 if (!mm.UploadCovered(client.AgentId, (int)cost))
606 {
607 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
608 resperror.message = "Insuficient funds";
609 resperror.identifier = UUID.Zero;
610
611 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
612 errorResponse.uploader = "";
613 errorResponse.state = "error";
614 errorResponse.error = resperror;
615 lock (m_ModelCost)
616 m_FileAgentInventoryState = FileAgentInventoryState.idle;
617 return errorResponse;
618 }
619 }
430 } 620 }
621
622 if (client != null && warning != String.Empty)
623 client.SendAgentAlertMessage(warning, true);
431 } 624 }
432 } 625 }
433 626
434 string assetName = llsdRequest.name;
435 string assetDes = llsdRequest.description; 627 string assetDes = llsdRequest.description;
436 string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath; 628 string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath;
437 UUID newAsset = UUID.Random(); 629 UUID newAsset = UUID.Random();
438 UUID newInvItem = UUID.Random(); 630 UUID newInvItem = UUID.Random();
439 UUID parentFolder = llsdRequest.folder_id; 631 UUID parentFolder = llsdRequest.folder_id;
440 string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000"); 632 string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000");
633 UUID texturesFolder = UUID.Zero;
634
635 if(!IsAtestUpload && m_enableModelUploadTextureToInventory)
636 texturesFolder = llsdRequest.texture_folder_id;
441 637
442 AssetUploader uploader = 638 AssetUploader uploader =
443 new AssetUploader(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type, 639 new AssetUploader(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type,
444 llsdRequest.asset_type, capsBase + uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile); 640 llsdRequest.asset_type, capsBase + uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile, cost,
641 texturesFolder, nreqtextures, nreqmeshs, nreqinstances, IsAtestUpload);
445 642
446 m_HostCapsObj.HttpListener.AddStreamHandler( 643 m_HostCapsObj.HttpListener.AddStreamHandler(
447 new BinaryStreamHandler( 644 new BinaryStreamHandler(
@@ -459,10 +656,22 @@ namespace OpenSim.Region.ClientStack.Linden
459 string uploaderURL = protocol + m_HostCapsObj.HostName + ":" + m_HostCapsObj.Port.ToString() + capsBase + 656 string uploaderURL = protocol + m_HostCapsObj.HostName + ":" + m_HostCapsObj.Port.ToString() + capsBase +
460 uploaderPath; 657 uploaderPath;
461 658
659
462 LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse(); 660 LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse();
463 uploadResponse.uploader = uploaderURL; 661 uploadResponse.uploader = uploaderURL;
464 uploadResponse.state = "upload"; 662 uploadResponse.state = "upload";
663 uploadResponse.upload_price = (int)cost;
664
665 if (llsdRequest.asset_type == "mesh")
666 {
667 uploadResponse.data = meshcostdata;
668 }
669
465 uploader.OnUpLoad += UploadCompleteHandler; 670 uploader.OnUpLoad += UploadCompleteHandler;
671
672 lock (m_ModelCost)
673 m_FileAgentInventoryState = FileAgentInventoryState.waitUpload;
674
466 return uploadResponse; 675 return uploadResponse;
467 } 676 }
468 677
@@ -474,8 +683,14 @@ namespace OpenSim.Region.ClientStack.Linden
474 /// <param name="data"></param> 683 /// <param name="data"></param>
475 public void UploadCompleteHandler(string assetName, string assetDescription, UUID assetID, 684 public void UploadCompleteHandler(string assetName, string assetDescription, UUID assetID,
476 UUID inventoryItem, UUID parentFolder, byte[] data, string inventoryType, 685 UUID inventoryItem, UUID parentFolder, byte[] data, string inventoryType,
477 string assetType) 686 string assetType, int cost,
687 UUID texturesFolder, int nreqtextures, int nreqmeshs, int nreqinstances,
688 bool IsAtestUpload, ref string error)
478 { 689 {
690
691 lock (m_ModelCost)
692 m_FileAgentInventoryState = FileAgentInventoryState.processUpload;
693
479 m_log.DebugFormat( 694 m_log.DebugFormat(
480 "[BUNCH OF CAPS]: Uploaded asset {0} for inventory item {1}, inv type {2}, asset type {3}", 695 "[BUNCH OF CAPS]: Uploaded asset {0} for inventory item {1}, inv type {2}, asset type {3}",
481 assetID, inventoryItem, inventoryType, assetType); 696 assetID, inventoryItem, inventoryType, assetType);
@@ -483,117 +698,247 @@ namespace OpenSim.Region.ClientStack.Linden
483 sbyte assType = 0; 698 sbyte assType = 0;
484 sbyte inType = 0; 699 sbyte inType = 0;
485 700
701 IClientAPI client = null;
702
703 UUID owner_id = m_HostCapsObj.AgentID;
704 UUID creatorID;
705
706 bool istest = IsAtestUpload && m_enableFreeTestUpload && (cost > 0);
707
708 bool restrictPerms = m_RestrictFreeTestUploadPerms && istest;
709
710 if (istest && m_testAssetsCreatorID != UUID.Zero)
711 creatorID = m_testAssetsCreatorID;
712 else
713 creatorID = owner_id;
714
715 string creatorIDstr = creatorID.ToString();
716
717 IMoneyModule mm = m_Scene.RequestModuleInterface<IMoneyModule>();
718 if (mm != null)
719 {
720 // make sure client still has enougth credit
721 if (!mm.UploadCovered(m_HostCapsObj.AgentID, (int)cost))
722 {
723 error = "Insufficient funds.";
724 return;
725 }
726 }
727
728 // strings to types
486 if (inventoryType == "sound") 729 if (inventoryType == "sound")
487 { 730 {
488 inType = 1; 731 inType = (sbyte)InventoryType.Sound;
489 assType = 1; 732 assType = (sbyte)AssetType.Sound;
490 } 733 }
491 else if (inventoryType == "animation") 734 else if (inventoryType == "animation")
492 { 735 {
493 inType = 19; 736 inType = (sbyte)InventoryType.Animation;
494 assType = 20; 737 assType = (sbyte)AssetType.Animation;
495 } 738 }
496 else if (inventoryType == "wearable") 739 else if (inventoryType == "wearable")
497 { 740 {
498 inType = 18; 741 inType = (sbyte)InventoryType.Wearable;
499 switch (assetType) 742 switch (assetType)
500 { 743 {
501 case "bodypart": 744 case "bodypart":
502 assType = 13; 745 assType = (sbyte)AssetType.Bodypart;
503 break; 746 break;
504 case "clothing": 747 case "clothing":
505 assType = 5; 748 assType = (sbyte)AssetType.Clothing;
506 break; 749 break;
507 } 750 }
508 } 751 }
509 else if (inventoryType == "object") 752 else if (inventoryType == "object")
510 { 753 {
511 inType = (sbyte)InventoryType.Object; 754 if (assetType == "mesh") // this code for now is for mesh models uploads only
512 assType = (sbyte)AssetType.Object;
513
514 List<Vector3> positions = new List<Vector3>();
515 List<Quaternion> rotations = new List<Quaternion>();
516 OSDMap request = (OSDMap)OSDParser.DeserializeLLSDXml(data);
517 OSDArray instance_list = (OSDArray)request["instance_list"];
518 OSDArray mesh_list = (OSDArray)request["mesh_list"];
519 OSDArray texture_list = (OSDArray)request["texture_list"];
520 SceneObjectGroup grp = null;
521
522 List<UUID> textures = new List<UUID>();
523 for (int i = 0; i < texture_list.Count; i++)
524 { 755 {
525 AssetBase textureAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Texture, ""); 756 inType = (sbyte)InventoryType.Object;
526 textureAsset.Data = texture_list[i].AsBinary(); 757 assType = (sbyte)AssetType.Object;
527 m_assetService.Store(textureAsset);
528 textures.Add(textureAsset.FullID);
529 }
530 758
531 for (int i = 0; i < mesh_list.Count; i++) 759 List<Vector3> positions = new List<Vector3>();
532 { 760 List<Quaternion> rotations = new List<Quaternion>();
533 PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateBox(); 761 OSDMap request = (OSDMap)OSDParser.DeserializeLLSDXml(data);
762
763 // compare and get updated information
534 764
535 Primitive.TextureEntry textureEntry 765 bool mismatchError = true;
536 = new Primitive.TextureEntry(Primitive.TextureEntry.WHITE_TEXTURE);
537 OSDMap inner_instance_list = (OSDMap)instance_list[i];
538 766
539 OSDArray face_list = (OSDArray)inner_instance_list["face_list"]; 767 while (mismatchError)
540 for (uint face = 0; face < face_list.Count; face++)
541 { 768 {
542 OSDMap faceMap = (OSDMap)face_list[(int)face]; 769 mismatchError = false;
543 Primitive.TextureEntryFace f = pbs.Textures.CreateFace(face); 770 }
544 if(faceMap.ContainsKey("fullbright"))
545 f.Fullbright = faceMap["fullbright"].AsBoolean();
546 if (faceMap.ContainsKey ("diffuse_color"))
547 f.RGBA = faceMap["diffuse_color"].AsColor4();
548 771
549 int textureNum = faceMap["image"].AsInteger(); 772 if (mismatchError)
550 float imagerot = faceMap["imagerot"].AsInteger(); 773 {
551 float offsets = (float)faceMap["offsets"].AsReal(); 774 error = "Upload and fee estimation information don't match";
552 float offsett = (float)faceMap["offsett"].AsReal(); 775 lock (m_ModelCost)
553 float scales = (float)faceMap["scales"].AsReal(); 776 m_FileAgentInventoryState = FileAgentInventoryState.idle;
554 float scalet = (float)faceMap["scalet"].AsReal();
555 777
556 if(imagerot != 0) 778 return;
557 f.Rotation = imagerot; 779 }
558 780
559 if(offsets != 0) 781 OSDArray instance_list = (OSDArray)request["instance_list"];
560 f.OffsetU = offsets; 782 OSDArray mesh_list = (OSDArray)request["mesh_list"];
783 OSDArray texture_list = (OSDArray)request["texture_list"];
784 SceneObjectGroup grp = null;
561 785
562 if (offsett != 0) 786 // create and store texture assets
563 f.OffsetV = offsett; 787 bool doTextInv = (!istest && m_enableModelUploadTextureToInventory &&
788 texturesFolder != UUID.Zero);
564 789
565 if (scales != 0)
566 f.RepeatU = scales;
567 790
568 if (scalet != 0) 791 List<UUID> textures = new List<UUID>();
569 f.RepeatV = scalet;
570 792
571 if (textures.Count > textureNum) 793
572 f.TextureID = textures[textureNum]; 794 if (doTextInv)
573 else 795 m_Scene.TryGetClient(m_HostCapsObj.AgentID, out client);
574 f.TextureID = Primitive.TextureEntry.WHITE_TEXTURE; 796
797 if(client == null) // don't put textures in inventory if there is no client
798 doTextInv = false;
575 799
576 textureEntry.FaceTextures[face] = f; 800 for (int i = 0; i < texture_list.Count; i++)
801 {
802 AssetBase textureAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Texture, creatorIDstr);
803 textureAsset.Data = texture_list[i].AsBinary();
804 if (istest)
805 textureAsset.Local = true;
806 m_assetService.Store(textureAsset);
807 textures.Add(textureAsset.FullID);
808
809 if (doTextInv)
810 {
811 string name = assetName;
812 if (name.Length > 25)
813 name = name.Substring(0, 24);
814 name += "_Texture#" + i.ToString();
815 InventoryItemBase texitem = new InventoryItemBase();
816 texitem.Owner = m_HostCapsObj.AgentID;
817 texitem.CreatorId = creatorIDstr;
818 texitem.CreatorData = String.Empty;
819 texitem.ID = UUID.Random();
820 texitem.AssetID = textureAsset.FullID;
821 texitem.Description = "mesh model texture";
822 texitem.Name = name;
823 texitem.AssetType = (int)AssetType.Texture;
824 texitem.InvType = (int)InventoryType.Texture;
825 texitem.Folder = texturesFolder;
826
827 texitem.CurrentPermissions
828 = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer);
829
830 texitem.BasePermissions = (uint)PermissionMask.All;
831 texitem.EveryOnePermissions = 0;
832 texitem.NextPermissions = (uint)PermissionMask.All;
833 texitem.CreationDate = Util.UnixTimeSinceEpoch();
834
835 m_Scene.AddInventoryItem(client, texitem);
836 texitem = null;
837 }
838 }
839
840 // create and store meshs assets
841 List<UUID> meshAssets = new List<UUID>();
842 for (int i = 0; i < mesh_list.Count; i++)
843 {
844 AssetBase meshAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Mesh, creatorIDstr);
845 meshAsset.Data = mesh_list[i].AsBinary();
846 if (istest)
847 meshAsset.Local = true;
848 m_assetService.Store(meshAsset);
849 meshAssets.Add(meshAsset.FullID);
577 } 850 }
578 851
579 pbs.TextureEntry = textureEntry.GetBytes(); 852 int skipedMeshs = 0;
853 // build prims from instances
854 for (int i = 0; i < instance_list.Count; i++)
855 {
856 OSDMap inner_instance_list = (OSDMap)instance_list[i];
857
858 // skip prims that are 2 small
859 Vector3 scale = inner_instance_list["scale"].AsVector3();
860
861 if (scale.X < m_PrimScaleMin || scale.Y < m_PrimScaleMin || scale.Z < m_PrimScaleMin)
862 {
863 skipedMeshs++;
864 continue;
865 }
866
867 PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateBox();
868
869 Primitive.TextureEntry textureEntry
870 = new Primitive.TextureEntry(Primitive.TextureEntry.WHITE_TEXTURE);
871
872
873 OSDArray face_list = (OSDArray)inner_instance_list["face_list"];
874 for (uint face = 0; face < face_list.Count; face++)
875 {
876 OSDMap faceMap = (OSDMap)face_list[(int)face];
877 Primitive.TextureEntryFace f = pbs.Textures.CreateFace(face);
878 if (faceMap.ContainsKey("fullbright"))
879 f.Fullbright = faceMap["fullbright"].AsBoolean();
880 if (faceMap.ContainsKey("diffuse_color"))
881 f.RGBA = faceMap["diffuse_color"].AsColor4();
882
883 int textureNum = faceMap["image"].AsInteger();
884 float imagerot = faceMap["imagerot"].AsInteger();
885 float offsets = (float)faceMap["offsets"].AsReal();
886 float offsett = (float)faceMap["offsett"].AsReal();
887 float scales = (float)faceMap["scales"].AsReal();
888 float scalet = (float)faceMap["scalet"].AsReal();
889
890 if (imagerot != 0)
891 f.Rotation = imagerot;
892
893 if (offsets != 0)
894 f.OffsetU = offsets;
580 895
581 AssetBase meshAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Mesh, ""); 896 if (offsett != 0)
582 meshAsset.Data = mesh_list[i].AsBinary(); 897 f.OffsetV = offsett;
583 m_assetService.Store(meshAsset);
584 898
585 pbs.SculptEntry = true; 899 if (scales != 0)
586 pbs.SculptTexture = meshAsset.FullID; 900 f.RepeatU = scales;
587 pbs.SculptType = (byte)SculptType.Mesh; 901
588 pbs.SculptData = meshAsset.Data; 902 if (scalet != 0)
903 f.RepeatV = scalet;
904
905 if (textures.Count > textureNum)
906 f.TextureID = textures[textureNum];
907 else
908 f.TextureID = Primitive.TextureEntry.WHITE_TEXTURE;
909
910 textureEntry.FaceTextures[face] = f;
911 }
589 912
590 Vector3 position = inner_instance_list["position"].AsVector3(); 913 pbs.TextureEntry = textureEntry.GetBytes();
591 Vector3 scale = inner_instance_list["scale"].AsVector3(); 914
592 Quaternion rotation = inner_instance_list["rotation"].AsQuaternion(); 915 bool hasmesh = false;
916 if (inner_instance_list.ContainsKey("mesh")) // seems to happen always but ...
917 {
918 int meshindx = inner_instance_list["mesh"].AsInteger();
919 if (meshAssets.Count > meshindx)
920 {
921 pbs.SculptEntry = true;
922 pbs.SculptType = (byte)SculptType.Mesh;
923 pbs.SculptTexture = meshAssets[meshindx]; // actual asset UUID after meshs suport introduction
924 // data will be requested from asset on rez (i hope)
925 hasmesh = true;
926 }
927 }
928
929 Vector3 position = inner_instance_list["position"].AsVector3();
930 Quaternion rotation = inner_instance_list["rotation"].AsQuaternion();
931
932 // for now viwers do send fixed defaults
933 // but this may change
934// int physicsShapeType = inner_instance_list["physics_shape_type"].AsInteger();
935 byte physicsShapeType = (byte)PhysShapeType.prim; // default for mesh is simple convex
936 if(hasmesh)
937 physicsShapeType = (byte) PhysShapeType.convex; // default for mesh is simple convex
938// int material = inner_instance_list["material"].AsInteger();
939 byte material = (byte)Material.Wood;
593 940
594// no longer used - begin ------------------------ 941// no longer used - begin ------------------------
595// int physicsShapeType = inner_instance_list["physics_shape_type"].AsInteger();
596// int material = inner_instance_list["material"].AsInteger();
597// int mesh = inner_instance_list["mesh"].AsInteger(); 942// int mesh = inner_instance_list["mesh"].AsInteger();
598 943
599// OSDMap permissions = (OSDMap)inner_instance_list["permissions"]; 944// OSDMap permissions = (OSDMap)inner_instance_list["permissions"];
@@ -608,24 +953,42 @@ namespace OpenSim.Region.ClientStack.Linden
608// UUID owner_id = permissions["owner_id"].AsUUID(); 953// UUID owner_id = permissions["owner_id"].AsUUID();
609// int owner_mask = permissions["owner_mask"].AsInteger(); 954// int owner_mask = permissions["owner_mask"].AsInteger();
610// no longer used - end ------------------------ 955// no longer used - end ------------------------
956
957
958 SceneObjectPart prim
959 = new SceneObjectPart(owner_id, pbs, position, Quaternion.Identity, Vector3.Zero);
960
961 prim.Scale = scale;
962 rotations.Add(rotation);
963 positions.Add(position);
964 prim.UUID = UUID.Random();
965 prim.CreatorID = creatorID;
966 prim.OwnerID = owner_id;
967 prim.GroupID = UUID.Zero;
968 prim.LastOwnerID = creatorID;
969 prim.CreationDate = Util.UnixTimeSinceEpoch();
970
971 if (grp == null)
972 prim.Name = assetName;
973 else
974 prim.Name = assetName + "#" + i.ToString();
611 975
612 UUID owner_id = m_HostCapsObj.AgentID; 976 if (restrictPerms)
977 {
978 prim.BaseMask = (uint)(PermissionMask.Move | PermissionMask.Modify);
979 prim.EveryoneMask = 0;
980 prim.GroupMask = 0;
981 prim.NextOwnerMask = 0;
982 prim.OwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify);
983 }
613 984
614 SceneObjectPart prim 985 if(istest)
615 = new SceneObjectPart(owner_id, pbs, position, Quaternion.Identity, Vector3.Zero); 986 prim.Description = "For testing only. Other uses are prohibited";
987 else
988 prim.Description = "";
616 989
617 prim.Scale = scale; 990 prim.Material = material;
618 prim.OffsetPosition = position; 991 prim.PhysicsShapeType = physicsShapeType;
619 rotations.Add(rotation);
620 positions.Add(position);
621 prim.UUID = UUID.Random();
622 prim.CreatorID = owner_id;
623 prim.OwnerID = owner_id;
624 prim.GroupID = UUID.Zero;
625 prim.LastOwnerID = prim.OwnerID;
626 prim.CreationDate = Util.UnixTimeSinceEpoch();
627 prim.Name = assetName;
628 prim.Description = "";
629 992
630// prim.BaseMask = (uint)base_mask; 993// prim.BaseMask = (uint)base_mask;
631// prim.EveryoneMask = (uint)everyone_mask; 994// prim.EveryoneMask = (uint)everyone_mask;
@@ -633,37 +996,64 @@ namespace OpenSim.Region.ClientStack.Linden
633// prim.NextOwnerMask = (uint)next_owner_mask; 996// prim.NextOwnerMask = (uint)next_owner_mask;
634// prim.OwnerMask = (uint)owner_mask; 997// prim.OwnerMask = (uint)owner_mask;
635 998
636 if (grp == null) 999 if (grp == null)
637 grp = new SceneObjectGroup(prim); 1000 {
638 else 1001 grp = new SceneObjectGroup(prim);
639 grp.AddPart(prim); 1002 grp.LastOwnerID = creatorID;
640 } 1003 }
1004 else
1005 grp.AddPart(prim);
1006 }
641 1007
642 // Fix first link number 1008 Vector3 rootPos = positions[0];
643 if (grp.Parts.Length > 1)
644 grp.RootPart.LinkNum++;
645 1009
646 Vector3 rootPos = positions[0]; 1010 if (grp.Parts.Length > 1)
647 grp.AbsolutePosition = rootPos; 1011 {
648 for (int i = 0; i < positions.Count; i++) 1012 // Fix first link number
649 { 1013 grp.RootPart.LinkNum++;
650 Vector3 offset = positions[i] - rootPos; 1014
651 grp.Parts[i].OffsetPosition = offset; 1015 Quaternion rootRotConj = Quaternion.Conjugate(rotations[0]);
1016 Quaternion tmprot;
1017 Vector3 offset;
1018
1019 // fix children rotations and positions
1020 for (int i = 1; i < rotations.Count; i++)
1021 {
1022 tmprot = rotations[i];
1023 tmprot = rootRotConj * tmprot;
1024
1025 grp.Parts[i].RotationOffset = tmprot;
1026
1027 offset = positions[i] - rootPos;
1028
1029 offset *= rootRotConj;
1030 grp.Parts[i].OffsetPosition = offset;
1031 }
1032
1033 grp.AbsolutePosition = rootPos;
1034 grp.UpdateGroupRotationR(rotations[0]);
1035 }
1036 else
1037 {
1038 grp.AbsolutePosition = rootPos;
1039 grp.UpdateGroupRotationR(rotations[0]);
1040 }
1041
1042 data = ASCIIEncoding.ASCII.GetBytes(SceneObjectSerializer.ToOriginalXmlFormat(grp));
652 } 1043 }
653 1044
654 for (int i = 0; i < rotations.Count; i++) 1045 else // not a mesh model
655 { 1046 {
656 if (i != 0) 1047 m_log.ErrorFormat("[CAPS Asset Upload] got unsuported assetType for object upload");
657 grp.Parts[i].RotationOffset = rotations[i]; 1048 return;
658 } 1049 }
659
660 grp.UpdateGroupRotationR(rotations[0]);
661 data = ASCIIEncoding.ASCII.GetBytes(SceneObjectSerializer.ToOriginalXmlFormat(grp));
662 } 1050 }
663 1051
664 AssetBase asset; 1052 AssetBase asset;
665 asset = new AssetBase(assetID, assetName, assType, m_HostCapsObj.AgentID.ToString()); 1053 asset = new AssetBase(assetID, assetName, assType, creatorIDstr);
666 asset.Data = data; 1054 asset.Data = data;
1055 if (istest)
1056 asset.Local = true;
667 if (AddNewAsset != null) 1057 if (AddNewAsset != null)
668 AddNewAsset(asset); 1058 AddNewAsset(asset);
669 else if (m_assetService != null) 1059 else if (m_assetService != null)
@@ -671,11 +1061,17 @@ namespace OpenSim.Region.ClientStack.Linden
671 1061
672 InventoryItemBase item = new InventoryItemBase(); 1062 InventoryItemBase item = new InventoryItemBase();
673 item.Owner = m_HostCapsObj.AgentID; 1063 item.Owner = m_HostCapsObj.AgentID;
674 item.CreatorId = m_HostCapsObj.AgentID.ToString(); 1064 item.CreatorId = creatorIDstr;
675 item.CreatorData = String.Empty; 1065 item.CreatorData = String.Empty;
676 item.ID = inventoryItem; 1066 item.ID = inventoryItem;
677 item.AssetID = asset.FullID; 1067 item.AssetID = asset.FullID;
678 item.Description = assetDescription; 1068 if (istest)
1069 {
1070 item.Description = "For testing only. Other uses are prohibited";
1071 item.Flags = (uint) (InventoryItemFlags.SharedSingleReference);
1072 }
1073 else
1074 item.Description = assetDescription;
679 item.Name = assetName; 1075 item.Name = assetName;
680 item.AssetType = assType; 1076 item.AssetType = assType;
681 item.InvType = inType; 1077 item.InvType = inType;
@@ -683,18 +1079,60 @@ namespace OpenSim.Region.ClientStack.Linden
683 1079
684 // If we set PermissionMask.All then when we rez the item the next permissions will replace the current 1080 // If we set PermissionMask.All then when we rez the item the next permissions will replace the current
685 // (owner) permissions. This becomes a problem if next permissions are changed. 1081 // (owner) permissions. This becomes a problem if next permissions are changed.
686 item.CurrentPermissions
687 = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer);
688 1082
689 item.BasePermissions = (uint)PermissionMask.All; 1083 if (restrictPerms)
690 item.EveryOnePermissions = 0; 1084 {
691 item.NextPermissions = (uint)PermissionMask.All; 1085 item.CurrentPermissions
1086 = (uint)(PermissionMask.Move | PermissionMask.Modify);
1087
1088 item.BasePermissions = (uint)(PermissionMask.Move | PermissionMask.Modify);
1089 item.EveryOnePermissions = 0;
1090 item.NextPermissions = 0;
1091 }
1092 else
1093 {
1094 item.CurrentPermissions
1095 = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer);
1096
1097 item.BasePermissions = (uint)PermissionMask.All;
1098 item.EveryOnePermissions = 0;
1099 item.NextPermissions = (uint)PermissionMask.All;
1100 }
1101
692 item.CreationDate = Util.UnixTimeSinceEpoch(); 1102 item.CreationDate = Util.UnixTimeSinceEpoch();
693 1103
1104 m_Scene.TryGetClient(m_HostCapsObj.AgentID, out client);
1105
694 if (AddNewInventoryItem != null) 1106 if (AddNewInventoryItem != null)
695 { 1107 {
696 AddNewInventoryItem(m_HostCapsObj.AgentID, item); 1108 if (istest)
1109 {
1110 m_Scene.AddInventoryItem(client, item);
1111/*
1112 AddNewInventoryItem(m_HostCapsObj.AgentID, item, 0);
1113 if (client != null)
1114 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);
1115 */
1116 }
1117 else
1118 {
1119 AddNewInventoryItem(m_HostCapsObj.AgentID, item, (uint)cost);
1120// if (client != null)
1121// {
1122// // let users see anything.. i don't so far
1123// string str;
1124// if (cost > 0)
1125// // dont remember where is money unit name to put here
1126// str = "Upload complete. charged " + cost.ToString() + "$";
1127// else
1128// str = "Upload complete";
1129// client.SendAgentAlertMessage(str, true);
1130// }
1131 }
697 } 1132 }
1133
1134 lock (m_ModelCost)
1135 m_FileAgentInventoryState = FileAgentInventoryState.idle;
698 } 1136 }
699 1137
700 /// <summary> 1138 /// <summary>
@@ -855,10 +1293,159 @@ namespace OpenSim.Region.ClientStack.Linden
855 response["int_response_code"] = 200; 1293 response["int_response_code"] = 200;
856 return LLSDHelpers.SerialiseLLSDReply(response); 1294 return LLSDHelpers.SerialiseLLSDReply(response);
857 } 1295 }
1296
1297 public string GetObjectPhysicsData(string request, string path,
1298 string param, IOSHttpRequest httpRequest,
1299 IOSHttpResponse httpResponse)
1300 {
1301 OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
1302 OSDMap resp = new OSDMap();
1303 OSDArray object_ids = (OSDArray)req["object_ids"];
1304
1305 for (int i = 0 ; i < object_ids.Count ; i++)
1306 {
1307 UUID uuid = object_ids[i].AsUUID();
1308
1309 SceneObjectPart obj = m_Scene.GetSceneObjectPart(uuid);
1310 if (obj != null)
1311 {
1312 OSDMap object_data = new OSDMap();
1313
1314 object_data["PhysicsShapeType"] = obj.PhysicsShapeType;
1315 object_data["Density"] = obj.Density;
1316 object_data["Friction"] = obj.Friction;
1317 object_data["Restitution"] = obj.Bounciness;
1318 object_data["GravityMultiplier"] = obj.GravityModifier;
1319
1320 resp[uuid.ToString()] = object_data;
1321 }
1322 }
1323
1324 string response = OSDParser.SerializeLLSDXmlString(resp);
1325 return response;
1326 }
1327
1328 public string GetObjectCost(string request, string path,
1329 string param, IOSHttpRequest httpRequest,
1330 IOSHttpResponse httpResponse)
1331 {
1332 OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
1333 OSDMap resp = new OSDMap();
1334
1335 OSDArray object_ids = (OSDArray)req["object_ids"];
1336
1337 for (int i = 0; i < object_ids.Count; i++)
1338 {
1339 UUID uuid = object_ids[i].AsUUID();
1340
1341 SceneObjectPart part = m_Scene.GetSceneObjectPart(uuid);
1342
1343 if (part != null)
1344 {
1345 SceneObjectGroup grp = part.ParentGroup;
1346 if (grp != null)
1347 {
1348 float linksetCost;
1349 float linksetPhysCost;
1350 float partCost;
1351 float partPhysCost;
1352
1353 grp.GetResourcesCosts(part, out linksetCost, out linksetPhysCost, out partCost, out partPhysCost);
1354
1355 OSDMap object_data = new OSDMap();
1356 object_data["linked_set_resource_cost"] = linksetCost;
1357 object_data["resource_cost"] = partCost;
1358 object_data["physics_cost"] = partPhysCost;
1359 object_data["linked_set_physics_cost"] = linksetPhysCost;
1360
1361 resp[uuid.ToString()] = object_data;
1362 }
1363 }
1364 }
1365
1366 string response = OSDParser.SerializeLLSDXmlString(resp);
1367 return response;
1368 }
1369
1370 public string ResourceCostSelected(string request, string path,
1371 string param, IOSHttpRequest httpRequest,
1372 IOSHttpResponse httpResponse)
1373 {
1374 OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
1375 OSDMap resp = new OSDMap();
1376
1377
1378 float phys=0;
1379 float stream=0;
1380 float simul=0;
1381
1382 if (req.ContainsKey("selected_roots"))
1383 {
1384 OSDArray object_ids = (OSDArray)req["selected_roots"];
1385
1386 // should go by SOG suming costs for all parts
1387 // ll v3 works ok with several objects select we get the list and adds ok
1388 // FS calls per object so results are wrong guess fs bug
1389 for (int i = 0; i < object_ids.Count; i++)
1390 {
1391 UUID uuid = object_ids[i].AsUUID();
1392 float Physc;
1393 float simulc;
1394 float streamc;
1395
1396 SceneObjectGroup grp = m_Scene.GetGroupByPrim(uuid);
1397 if (grp != null)
1398 {
1399 grp.GetSelectedCosts(out Physc, out streamc, out simulc);
1400 phys += Physc;
1401 stream += streamc;
1402 simul += simulc;
1403 }
1404 }
1405 }
1406 else if (req.ContainsKey("selected_prims"))
1407 {
1408 OSDArray object_ids = (OSDArray)req["selected_prims"];
1409
1410 // don't see in use in any of the 2 viewers
1411 // guess it should be for edit linked but... nothing
1412 // should go to SOP per part
1413 for (int i = 0; i < object_ids.Count; i++)
1414 {
1415 UUID uuid = object_ids[i].AsUUID();
1416
1417 SceneObjectPart part = m_Scene.GetSceneObjectPart(uuid);
1418 if (part != null)
1419 {
1420 phys += part.PhysicsCost;
1421 stream += part.StreamingCost;
1422 simul += part.SimulationCost;
1423 }
1424 }
1425 }
1426
1427 if (simul != 0)
1428 {
1429 OSDMap object_data = new OSDMap();
1430
1431 object_data["physics"] = phys;
1432 object_data["streaming"] = stream;
1433 object_data["simulation"] = simul;
1434
1435 resp["selected"] = object_data;
1436 }
1437
1438 string response = OSDParser.SerializeLLSDXmlString(resp);
1439 return response;
1440 }
858 } 1441 }
859 1442
860 public class AssetUploader 1443 public class AssetUploader
861 { 1444 {
1445 private static readonly ILog m_log =
1446 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
1447
1448
862 public event UpLoadedAsset OnUpLoad; 1449 public event UpLoadedAsset OnUpLoad;
863 private UpLoadedAsset handlerUpLoad = null; 1450 private UpLoadedAsset handlerUpLoad = null;
864 1451
@@ -873,10 +1460,21 @@ namespace OpenSim.Region.ClientStack.Linden
873 1460
874 private string m_invType = String.Empty; 1461 private string m_invType = String.Empty;
875 private string m_assetType = String.Empty; 1462 private string m_assetType = String.Empty;
1463 private int m_cost;
1464 private string m_error = String.Empty;
1465
1466 private Timer m_timeoutTimer = new Timer();
1467 private UUID m_texturesFolder;
1468 private int m_nreqtextures;
1469 private int m_nreqmeshs;
1470 private int m_nreqinstances;
1471 private bool m_IsAtestUpload;
876 1472
877 public AssetUploader(string assetName, string description, UUID assetID, UUID inventoryItem, 1473 public AssetUploader(string assetName, string description, UUID assetID, UUID inventoryItem,
878 UUID parentFolderID, string invType, string assetType, string path, 1474 UUID parentFolderID, string invType, string assetType, string path,
879 IHttpServer httpServer, bool dumpAssetsToFile) 1475 IHttpServer httpServer, bool dumpAssetsToFile,
1476 int totalCost, UUID texturesFolder, int nreqtextures, int nreqmeshs, int nreqinstances,
1477 bool IsAtestUpload)
880 { 1478 {
881 m_assetName = assetName; 1479 m_assetName = assetName;
882 m_assetDes = description; 1480 m_assetDes = description;
@@ -888,6 +1486,18 @@ namespace OpenSim.Region.ClientStack.Linden
888 m_assetType = assetType; 1486 m_assetType = assetType;
889 m_invType = invType; 1487 m_invType = invType;
890 m_dumpAssetsToFile = dumpAssetsToFile; 1488 m_dumpAssetsToFile = dumpAssetsToFile;
1489 m_cost = totalCost;
1490
1491 m_texturesFolder = texturesFolder;
1492 m_nreqtextures = nreqtextures;
1493 m_nreqmeshs = nreqmeshs;
1494 m_nreqinstances = nreqinstances;
1495 m_IsAtestUpload = IsAtestUpload;
1496
1497 m_timeoutTimer.Elapsed += TimedOut;
1498 m_timeoutTimer.Interval = 120000;
1499 m_timeoutTimer.AutoReset = false;
1500 m_timeoutTimer.Start();
891 } 1501 }
892 1502
893 /// <summary> 1503 /// <summary>
@@ -902,12 +1512,14 @@ namespace OpenSim.Region.ClientStack.Linden
902 UUID inv = inventoryItemID; 1512 UUID inv = inventoryItemID;
903 string res = String.Empty; 1513 string res = String.Empty;
904 LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete(); 1514 LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete();
1515/*
905 uploadComplete.new_asset = newAssetID.ToString(); 1516 uploadComplete.new_asset = newAssetID.ToString();
906 uploadComplete.new_inventory_item = inv; 1517 uploadComplete.new_inventory_item = inv;
907 uploadComplete.state = "complete"; 1518 uploadComplete.state = "complete";
908 1519
909 res = LLSDHelpers.SerialiseLLSDReply(uploadComplete); 1520 res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
910 1521*/
1522 m_timeoutTimer.Stop();
911 httpListener.RemoveStreamHandler("POST", uploaderPath); 1523 httpListener.RemoveStreamHandler("POST", uploaderPath);
912 1524
913 // TODO: probably make this a better set of extensions here 1525 // TODO: probably make this a better set of extensions here
@@ -924,12 +1536,49 @@ namespace OpenSim.Region.ClientStack.Linden
924 handlerUpLoad = OnUpLoad; 1536 handlerUpLoad = OnUpLoad;
925 if (handlerUpLoad != null) 1537 if (handlerUpLoad != null)
926 { 1538 {
927 handlerUpLoad(m_assetName, m_assetDes, newAssetID, inv, parentFolder, data, m_invType, m_assetType); 1539 handlerUpLoad(m_assetName, m_assetDes, newAssetID, inv, parentFolder, data, m_invType, m_assetType,
1540 m_cost, m_texturesFolder, m_nreqtextures, m_nreqmeshs, m_nreqinstances, m_IsAtestUpload, ref m_error);
1541 }
1542 if (m_IsAtestUpload)
1543 {
1544 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
1545 resperror.message = "Upload SUCESSEFULL for testing purposes only. Other uses are prohibited. Item will not work after 48 hours or on other regions";
1546 resperror.identifier = inv;
1547
1548 uploadComplete.error = resperror;
1549 uploadComplete.state = "Upload4Testing";
928 } 1550 }
1551 else
1552 {
1553 if (m_error == String.Empty)
1554 {
1555 uploadComplete.new_asset = newAssetID.ToString();
1556 uploadComplete.new_inventory_item = inv;
1557 // if (m_texturesFolder != UUID.Zero)
1558 // uploadComplete.new_texture_folder_id = m_texturesFolder;
1559 uploadComplete.state = "complete";
1560 }
1561 else
1562 {
1563 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
1564 resperror.message = m_error;
1565 resperror.identifier = inv;
929 1566
1567 uploadComplete.error = resperror;
1568 uploadComplete.state = "failed";
1569 }
1570 }
1571
1572 res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
930 return res; 1573 return res;
931 } 1574 }
932 1575
1576 private void TimedOut(object sender, ElapsedEventArgs args)
1577 {
1578 m_log.InfoFormat("[CAPS]: Removing URL and handler for timed out mesh upload");
1579 httpListener.RemoveStreamHandler("POST", uploaderPath);
1580 }
1581
933 ///Left this in and commented in case there are unforseen issues 1582 ///Left this in and commented in case there are unforseen issues
934 //private void SaveAssetToFile(string filename, byte[] data) 1583 //private void SaveAssetToFile(string filename, byte[] data)
935 //{ 1584 //{
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}