aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs394
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs133
2 files changed, 310 insertions, 217 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
index cb6f7a1..0fb6c99 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
@@ -87,6 +87,7 @@ namespace OpenSim.Region.ClientStack.Linden
87 87
88 private Scene m_Scene; 88 private Scene m_Scene;
89 private Caps m_HostCapsObj; 89 private Caps m_HostCapsObj;
90 private ModelCost m_ModelCost;
90 91
91 private static readonly string m_requestPath = "0000/"; 92 private static readonly string m_requestPath = "0000/";
92 // private static readonly string m_mapLayerPath = "0001/"; 93 // private static readonly string m_mapLayerPath = "0001/";
@@ -116,13 +117,22 @@ namespace OpenSim.Region.ClientStack.Linden
116 private bool m_dumpAssetsToFile = false; 117 private bool m_dumpAssetsToFile = false;
117 private string m_regionName; 118 private string m_regionName;
118 private int m_levelUpload = 0; 119 private int m_levelUpload = 0;
119 private bool m_addNewTextures = false; 120// private bool m_addNewTextures = false;
120 private bool m_addNewMeshes = false; 121// private bool m_addNewMeshes = false;
121 122
122 public BunchOfCaps(Scene scene, Caps caps) 123 public BunchOfCaps(Scene scene, Caps caps)
123 { 124 {
124 m_Scene = scene; 125 m_Scene = scene;
125 m_HostCapsObj = caps; 126 m_HostCapsObj = caps;
127
128 // create a model upload cost provider
129 m_ModelCost = new ModelCost();
130 // tell it about scene object limits
131 m_ModelCost.NonPhysicalPrimScaleMax = m_Scene.m_maxNonphys;
132 m_ModelCost.PhysicalPrimScaleMax = m_Scene.m_maxPhys;
133// m_ModelCost.PrimScaleMin = ??
134// m_ModelCost.ObjectLinkedPartsMax = ??
135
126 IConfigSource config = m_Scene.Config; 136 IConfigSource config = m_Scene.Config;
127 if (config != null) 137 if (config != null)
128 { 138 {
@@ -193,7 +203,6 @@ namespace OpenSim.Region.ClientStack.Linden
193 { 203 {
194 try 204 try
195 { 205 {
196 // I don't think this one works...
197 m_HostCapsObj.RegisterHandler( 206 m_HostCapsObj.RegisterHandler(
198 "NewFileAgentInventory", 207 "NewFileAgentInventory",
199 new LLSDStreamhandler<LLSDAssetUploadRequest, LLSDAssetUploadResponse>( 208 new LLSDStreamhandler<LLSDAssetUploadRequest, LLSDAssetUploadResponse>(
@@ -472,9 +481,8 @@ namespace OpenSim.Region.ClientStack.Linden
472 { 481 {
473 string error; 482 string error;
474 int modelcost; 483 int modelcost;
475 ModelCost mc = new ModelCost();
476 484
477 if (!mc.MeshModelCost(llsdRequest.asset_resources, baseCost, out modelcost, 485 if (!m_ModelCost.MeshModelCost(llsdRequest.asset_resources, baseCost, out modelcost,
478 meshcostdata, out error)) 486 meshcostdata, out error))
479 { 487 {
480 client.SendAgentAlertMessage(error, false); 488 client.SendAgentAlertMessage(error, false);
@@ -608,172 +616,181 @@ namespace OpenSim.Region.ClientStack.Linden
608 } 616 }
609 else if (inventoryType == "object") 617 else if (inventoryType == "object")
610 { 618 {
611 inType = (sbyte)InventoryType.Object; 619 if (assetType == "mesh") // this code for now is for mesh models uploads only
612 assType = (sbyte)AssetType.Object;
613
614 List<Vector3> positions = new List<Vector3>();
615 List<Quaternion> rotations = new List<Quaternion>();
616 OSDMap request = (OSDMap)OSDParser.DeserializeLLSDXml(data);
617 OSDArray instance_list = (OSDArray)request["instance_list"];
618 OSDArray mesh_list = (OSDArray)request["mesh_list"];
619 OSDArray texture_list = (OSDArray)request["texture_list"];
620 SceneObjectGroup grp = null;
621
622 // create and store texture assets
623 List<UUID> textures = new List<UUID>();
624 for (int i = 0; i < texture_list.Count; i++)
625 { 620 {
626 AssetBase textureAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Texture, ""); 621 inType = (sbyte)InventoryType.Object;
627 textureAsset.Data = texture_list[i].AsBinary(); 622 assType = (sbyte)AssetType.Object;
628 m_assetService.Store(textureAsset); 623
629 textures.Add(textureAsset.FullID); 624 List<Vector3> positions = new List<Vector3>();
630 625 List<Quaternion> rotations = new List<Quaternion>();
631 // save it to inventory 626 OSDMap request = (OSDMap)OSDParser.DeserializeLLSDXml(data);
632 if (m_addNewTextures && AddNewInventoryItem != null) 627 OSDArray instance_list = (OSDArray)request["instance_list"];
628 OSDArray mesh_list = (OSDArray)request["mesh_list"];
629 OSDArray texture_list = (OSDArray)request["texture_list"];
630 SceneObjectGroup grp = null;
631
632 // create and store texture assets
633 List<UUID> textures = new List<UUID>();
634 for (int i = 0; i < texture_list.Count; i++)
633 { 635 {
634 string name = assetName; 636 AssetBase textureAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Texture, "");
635 if (name.Length > 25) 637 textureAsset.Data = texture_list[i].AsBinary();
636 name = name.Substring(0, 24); 638 m_assetService.Store(textureAsset);
637 name += "_Texture#" + i.ToString(); 639 textures.Add(textureAsset.FullID);
638 InventoryItemBase texitem = new InventoryItemBase(); 640 /*
639 texitem.Owner = m_HostCapsObj.AgentID; 641 don't do this
640 texitem.CreatorId = m_HostCapsObj.AgentID.ToString(); 642 replace it by optionaly making model textures cost less than if individually uploaded
641 texitem.CreatorData = String.Empty; 643 since they can't be used for other purpuses
642 texitem.ID = UUID.Random(); 644
643 texitem.AssetID = textureAsset.FullID; 645 // save it to inventory
644 texitem.Description = "mesh model texture"; 646 if (m_addNewTextures && AddNewInventoryItem != null)
645 texitem.Name = name; 647 {
646 texitem.AssetType = (int)AssetType.Texture; 648 string name = assetName;
647 texitem.InvType = (int)InventoryType.Texture; 649 if (name.Length > 25)
648 texitem.Folder = UUID.Zero; // send to default 650 name = name.Substring(0, 24);
649 651 name += "_Texture#" + i.ToString();
650 // If we set PermissionMask.All then when we rez the item the next permissions will replace the current 652 InventoryItemBase texitem = new InventoryItemBase();
651 // (owner) permissions. This becomes a problem if next permissions are changed. 653 texitem.Owner = m_HostCapsObj.AgentID;
652 texitem.CurrentPermissions 654 texitem.CreatorId = m_HostCapsObj.AgentID.ToString();
653 = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer); 655 texitem.CreatorData = String.Empty;
654 656 texitem.ID = UUID.Random();
655 texitem.BasePermissions = (uint)PermissionMask.All; 657 texitem.AssetID = textureAsset.FullID;
656 texitem.EveryOnePermissions = 0; 658 texitem.Description = "mesh model texture";
657 texitem.NextPermissions = (uint)PermissionMask.All; 659 texitem.Name = name;
658 texitem.CreationDate = Util.UnixTimeSinceEpoch(); 660 texitem.AssetType = (int)AssetType.Texture;
659 661 texitem.InvType = (int)InventoryType.Texture;
660 AddNewInventoryItem(m_HostCapsObj.AgentID, texitem, 0); 662 texitem.Folder = UUID.Zero; // send to default
661 texitem = null; 663
664 // If we set PermissionMask.All then when we rez the item the next permissions will replace the current
665 // (owner) permissions. This becomes a problem if next permissions are changed.
666 texitem.CurrentPermissions
667 = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer);
668
669 texitem.BasePermissions = (uint)PermissionMask.All;
670 texitem.EveryOnePermissions = 0;
671 texitem.NextPermissions = (uint)PermissionMask.All;
672 texitem.CreationDate = Util.UnixTimeSinceEpoch();
673
674 AddNewInventoryItem(m_HostCapsObj.AgentID, texitem, 0);
675 texitem = null;
676 }
677 */
678 textureAsset = null;
662 } 679 }
663 680
664 textureAsset = null; 681 // create and store meshs assets
665 682 List<UUID> meshAssets = new List<UUID>();
666 } 683 for (int i = 0; i < mesh_list.Count; i++)
667
668 // create and store meshs assets
669 List<UUID> meshAssets = new List<UUID>();
670 for (int i = 0; i < mesh_list.Count; i++)
671 {
672 AssetBase meshAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Mesh, "");
673 meshAsset.Data = mesh_list[i].AsBinary();
674 m_assetService.Store(meshAsset);
675 meshAssets.Add(meshAsset.FullID);
676
677 // save it to inventory
678 if (m_addNewMeshes && AddNewInventoryItem != null)
679 { 684 {
680 string name = assetName; 685 AssetBase meshAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Mesh, "");
681 if (name.Length > 25) 686 meshAsset.Data = mesh_list[i].AsBinary();
682 name = name.Substring(0, 24); 687 m_assetService.Store(meshAsset);
683 name += "_Mesh#" + i.ToString(); 688 meshAssets.Add(meshAsset.FullID);
684 InventoryItemBase meshitem = new InventoryItemBase(); 689
685 meshitem.Owner = m_HostCapsObj.AgentID; 690 /* this was a test, funny and showed viewers deal with mesh inventory itens
686 meshitem.CreatorId = m_HostCapsObj.AgentID.ToString(); 691 * nut also same reason as for textures
687 meshitem.CreatorData = String.Empty; 692 * let integrated in a model cost eventually less than hipotetical independent meshs assets
688 meshitem.ID = UUID.Random(); 693 * that will be in inventory
689 meshitem.AssetID = meshAsset.FullID; 694 // save it to inventory
690 meshitem.Description = "mesh "; 695 if (m_addNewMeshes && AddNewInventoryItem != null)
691 meshitem.Name = name; 696 {
692 meshitem.AssetType = (int)AssetType.Mesh; 697 string name = assetName;
693 meshitem.InvType = (int)InventoryType.Mesh; 698 if (name.Length > 25)
694 meshitem.Folder = UUID.Zero; // send to default 699 name = name.Substring(0, 24);
695 700 name += "_Mesh#" + i.ToString();
696 // If we set PermissionMask.All then when we rez the item the next permissions will replace the current 701 InventoryItemBase meshitem = new InventoryItemBase();
697 // (owner) permissions. This becomes a problem if next permissions are changed. 702 meshitem.Owner = m_HostCapsObj.AgentID;
698 meshitem.CurrentPermissions 703 meshitem.CreatorId = m_HostCapsObj.AgentID.ToString();
699 = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer); 704 meshitem.CreatorData = String.Empty;
700 705 meshitem.ID = UUID.Random();
701 meshitem.BasePermissions = (uint)PermissionMask.All; 706 meshitem.AssetID = meshAsset.FullID;
702 meshitem.EveryOnePermissions = 0; 707 meshitem.Description = "mesh ";
703 meshitem.NextPermissions = (uint)PermissionMask.All; 708 meshitem.Name = name;
704 meshitem.CreationDate = Util.UnixTimeSinceEpoch(); 709 meshitem.AssetType = (int)AssetType.Mesh;
705 710 meshitem.InvType = (int)InventoryType.Mesh;
706 AddNewInventoryItem(m_HostCapsObj.AgentID, meshitem, 0); 711 meshitem.Folder = UUID.Zero; // send to default
707 meshitem = null; 712
713 // If we set PermissionMask.All then when we rez the item the next permissions will replace the current
714 // (owner) permissions. This becomes a problem if next permissions are changed.
715 meshitem.CurrentPermissions
716 = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer);
717
718 meshitem.BasePermissions = (uint)PermissionMask.All;
719 meshitem.EveryOnePermissions = 0;
720 meshitem.NextPermissions = (uint)PermissionMask.All;
721 meshitem.CreationDate = Util.UnixTimeSinceEpoch();
722
723 AddNewInventoryItem(m_HostCapsObj.AgentID, meshitem, 0);
724 meshitem = null;
725 }
726 */
727 meshAsset = null;
708 } 728 }
709 729
710 meshAsset = null; 730 // build prims from instances
711 } 731 for (int i = 0; i < instance_list.Count; i++)
712 732 {
713 // build prims from instances 733 PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateBox();
714 for (int i = 0; i < instance_list.Count; i++)
715 {
716 PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateBox();
717 734
718 Primitive.TextureEntry textureEntry 735 Primitive.TextureEntry textureEntry
719 = new Primitive.TextureEntry(Primitive.TextureEntry.WHITE_TEXTURE); 736 = new Primitive.TextureEntry(Primitive.TextureEntry.WHITE_TEXTURE);
720 737
721 OSDMap inner_instance_list = (OSDMap)instance_list[i]; 738 OSDMap inner_instance_list = (OSDMap)instance_list[i];
722 739
723 OSDArray face_list = (OSDArray)inner_instance_list["face_list"]; 740 OSDArray face_list = (OSDArray)inner_instance_list["face_list"];
724 for (uint face = 0; face < face_list.Count; face++) 741 for (uint face = 0; face < face_list.Count; face++)
725 { 742 {
726 OSDMap faceMap = (OSDMap)face_list[(int)face]; 743 OSDMap faceMap = (OSDMap)face_list[(int)face];
727 Primitive.TextureEntryFace f = pbs.Textures.CreateFace(face); 744 Primitive.TextureEntryFace f = pbs.Textures.CreateFace(face);
728 if(faceMap.ContainsKey("fullbright")) 745 if (faceMap.ContainsKey("fullbright"))
729 f.Fullbright = faceMap["fullbright"].AsBoolean(); 746 f.Fullbright = faceMap["fullbright"].AsBoolean();
730 if (faceMap.ContainsKey ("diffuse_color")) 747 if (faceMap.ContainsKey("diffuse_color"))
731 f.RGBA = faceMap["diffuse_color"].AsColor4(); 748 f.RGBA = faceMap["diffuse_color"].AsColor4();
732 749
733 int textureNum = faceMap["image"].AsInteger(); 750 int textureNum = faceMap["image"].AsInteger();
734 float imagerot = faceMap["imagerot"].AsInteger(); 751 float imagerot = faceMap["imagerot"].AsInteger();
735 float offsets = (float)faceMap["offsets"].AsReal(); 752 float offsets = (float)faceMap["offsets"].AsReal();
736 float offsett = (float)faceMap["offsett"].AsReal(); 753 float offsett = (float)faceMap["offsett"].AsReal();
737 float scales = (float)faceMap["scales"].AsReal(); 754 float scales = (float)faceMap["scales"].AsReal();
738 float scalet = (float)faceMap["scalet"].AsReal(); 755 float scalet = (float)faceMap["scalet"].AsReal();
739 756
740 if(imagerot != 0) 757 if (imagerot != 0)
741 f.Rotation = imagerot; 758 f.Rotation = imagerot;
742 759
743 if(offsets != 0) 760 if (offsets != 0)
744 f.OffsetU = offsets; 761 f.OffsetU = offsets;
745 762
746 if (offsett != 0) 763 if (offsett != 0)
747 f.OffsetV = offsett; 764 f.OffsetV = offsett;
748 765
749 if (scales != 0) 766 if (scales != 0)
750 f.RepeatU = scales; 767 f.RepeatU = scales;
751 768
752 if (scalet != 0) 769 if (scalet != 0)
753 f.RepeatV = scalet; 770 f.RepeatV = scalet;
754 771
755 if (textures.Count > textureNum) 772 if (textures.Count > textureNum)
756 f.TextureID = textures[textureNum]; 773 f.TextureID = textures[textureNum];
757 else 774 else
758 f.TextureID = Primitive.TextureEntry.WHITE_TEXTURE; 775 f.TextureID = Primitive.TextureEntry.WHITE_TEXTURE;
759 776
760 textureEntry.FaceTextures[face] = f; 777 textureEntry.FaceTextures[face] = f;
761 } 778 }
762 779
763 pbs.TextureEntry = textureEntry.GetBytes(); 780 pbs.TextureEntry = textureEntry.GetBytes();
764 781
765 int meshindx = inner_instance_list["mesh"].AsInteger(); 782 int meshindx = inner_instance_list["mesh"].AsInteger();
766 if (meshAssets.Count > meshindx) 783 if (meshAssets.Count > meshindx)
767 { 784 {
768 pbs.SculptEntry = true; 785 pbs.SculptEntry = true;
769 pbs.SculptType = (byte)SculptType.Mesh; 786 pbs.SculptType = (byte)SculptType.Mesh;
770 pbs.SculptTexture = meshAssets[meshindx]; // actual asset UUID after meshs suport introduction 787 pbs.SculptTexture = meshAssets[meshindx]; // actual asset UUID after meshs suport introduction
771 // data will be requested from asset on rez (i hope) 788 // data will be requested from asset on rez (i hope)
772 } 789 }
773 790
774 Vector3 position = inner_instance_list["position"].AsVector3(); 791 Vector3 position = inner_instance_list["position"].AsVector3();
775 Vector3 scale = inner_instance_list["scale"].AsVector3(); 792 Vector3 scale = inner_instance_list["scale"].AsVector3();
776 Quaternion rotation = inner_instance_list["rotation"].AsQuaternion(); 793 Quaternion rotation = inner_instance_list["rotation"].AsQuaternion();
777 794
778// no longer used - begin ------------------------ 795// no longer used - begin ------------------------
779// int physicsShapeType = inner_instance_list["physics_shape_type"].AsInteger(); 796// int physicsShapeType = inner_instance_list["physics_shape_type"].AsInteger();
@@ -793,23 +810,23 @@ namespace OpenSim.Region.ClientStack.Linden
793// int owner_mask = permissions["owner_mask"].AsInteger(); 810// int owner_mask = permissions["owner_mask"].AsInteger();
794// no longer used - end ------------------------ 811// no longer used - end ------------------------
795 812
796 UUID owner_id = m_HostCapsObj.AgentID; 813 UUID owner_id = m_HostCapsObj.AgentID;
797 814
798 SceneObjectPart prim 815 SceneObjectPart prim
799 = new SceneObjectPart(owner_id, pbs, position, Quaternion.Identity, Vector3.Zero); 816 = new SceneObjectPart(owner_id, pbs, position, Quaternion.Identity, Vector3.Zero);
800 817
801 prim.Scale = scale; 818 prim.Scale = scale;
802 prim.OffsetPosition = position; 819 prim.OffsetPosition = position;
803 rotations.Add(rotation); 820 rotations.Add(rotation);
804 positions.Add(position); 821 positions.Add(position);
805 prim.UUID = UUID.Random(); 822 prim.UUID = UUID.Random();
806 prim.CreatorID = owner_id; 823 prim.CreatorID = owner_id;
807 prim.OwnerID = owner_id; 824 prim.OwnerID = owner_id;
808 prim.GroupID = UUID.Zero; 825 prim.GroupID = UUID.Zero;
809 prim.LastOwnerID = prim.OwnerID; 826 prim.LastOwnerID = prim.OwnerID;
810 prim.CreationDate = Util.UnixTimeSinceEpoch(); 827 prim.CreationDate = Util.UnixTimeSinceEpoch();
811 prim.Name = assetName; 828 prim.Name = assetName;
812 prim.Description = ""; 829 prim.Description = "";
813 830
814// prim.BaseMask = (uint)base_mask; 831// prim.BaseMask = (uint)base_mask;
815// prim.EveryoneMask = (uint)everyone_mask; 832// prim.EveryoneMask = (uint)everyone_mask;
@@ -817,32 +834,39 @@ namespace OpenSim.Region.ClientStack.Linden
817// prim.NextOwnerMask = (uint)next_owner_mask; 834// prim.NextOwnerMask = (uint)next_owner_mask;
818// prim.OwnerMask = (uint)owner_mask; 835// prim.OwnerMask = (uint)owner_mask;
819 836
820 if (grp == null) 837 if (grp == null)
821 grp = new SceneObjectGroup(prim); 838 grp = new SceneObjectGroup(prim);
822 else 839 else
823 grp.AddPart(prim); 840 grp.AddPart(prim);
824 } 841 }
825 842
826 // Fix first link number 843 // Fix first link number
827 if (grp.Parts.Length > 1) 844 if (grp.Parts.Length > 1)
828 grp.RootPart.LinkNum++; 845 grp.RootPart.LinkNum++;
829 846
830 Vector3 rootPos = positions[0]; 847 Vector3 rootPos = positions[0];
831 grp.AbsolutePosition = rootPos; 848 grp.AbsolutePosition = rootPos;
832 for (int i = 0; i < positions.Count; i++) 849 for (int i = 0; i < positions.Count; i++)
833 { 850 {
834 Vector3 offset = positions[i] - rootPos; 851 Vector3 offset = positions[i] - rootPos;
835 grp.Parts[i].OffsetPosition = offset; 852 grp.Parts[i].OffsetPosition = offset;
853 }
854
855 for (int i = 0; i < rotations.Count; i++)
856 {
857 if (i != 0)
858 grp.Parts[i].RotationOffset = rotations[i];
859 }
860
861 grp.UpdateGroupRotationR(rotations[0]);
862 data = ASCIIEncoding.ASCII.GetBytes(SceneObjectSerializer.ToOriginalXmlFormat(grp));
836 } 863 }
837 864
838 for (int i = 0; i < rotations.Count; i++) 865 else // not a mesh model
839 { 866 {
840 if (i != 0) 867 m_log.ErrorFormat("[CAPS Asset Upload] got unsuported assetType for object upload");
841 grp.Parts[i].RotationOffset = rotations[i]; 868 return;
842 } 869 }
843
844 grp.UpdateGroupRotationR(rotations[0]);
845 data = ASCIIEncoding.ASCII.GetBytes(SceneObjectSerializer.ToOriginalXmlFormat(grp));
846 } 870 }
847 871
848 AssetBase asset; 872 AssetBase asset;
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs
index ba73a25..62f1d06 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs
@@ -23,42 +23,81 @@ using OSDMap = OpenMetaverse.StructuredData.OSDMap;
23 23
24namespace OpenSim.Region.ClientStack.Linden 24namespace OpenSim.Region.ClientStack.Linden
25{ 25{
26 public class ModelCost 26 public struct ModelPrimLimits
27 { 27 {
28 float ModelMinCost = 5.0f; // try to favor small meshs versus sculpts 28
29 29 }
30 const float primCreationCost = 0.01f; // 256 prims cost extra 2.56
31 30
32 // weigthed size to money convertion 31 public class ModelCost
33 const float bytecost = 1e-4f; 32 {
34 33
35 // for mesh upload fees based on compressed data sizes 34 // upload fee tunning paramenters
36 // not using streaming physics and server costs as SL apparently does ?? 35 // fees are normalized to 1.0
37 36 // this parameters scale them to basic cost ( so 1.0 translates to 10 )
37
38 public float ModelMeshCostFactor = 1.0f; // scale total cost relative to basic (excluding textures)
39 public float ModelTextureCostFactor = 0.25f; //(2.5c$) scale textures fee to basic.
40 // promote integration in a model
41 // since they will not show up in inventory
42 public float ModelMinCostFactor = 0.5f; // minimum total model free excluding textures
43
44 // itens costs in normalized values
45 // ie will be multiplied by basicCost and factors above
46 const float primCreationCost = 0.002f; // extra cost for each prim creation overhead
47 // weigthed size to normalized cost
48 const float bytecost = 1e-5f;
49
50 // mesh upload fees based on compressed data sizes
51 // several data sections are counted more that once
52 // to promote user optimization
53 // following parameters control how many extra times they are added
54 // to global size.
55 // LOD meshs
38 const float medSizeWth = 1f; // 2x 56 const float medSizeWth = 1f; // 2x
39 const float lowSizeWth = 1.5f; // 2.5x 57 const float lowSizeWth = 1.5f; // 2.5x
40 const float lowestSizeWth = 2f; // 3x 58 const float lowestSizeWth = 2f; // 3x
41 // favor potencial optimized meshs versus automatic decomposition 59 // favor potencially physical optimized meshs versus automatic decomposition
42 const float physMeshSizeWth = 6f; // counts 7x 60 const float physMeshSizeWth = 6f; // counts 7x
43 const float physHullSizeWth = 8f; // counts 9x 61 const float physHullSizeWth = 8f; // counts 9x
44 62
45 // stream cost area factors 63 // stream cost area factors
64 // more or less like SL
46 const float highLodFactor = 17.36f; 65 const float highLodFactor = 17.36f;
47 const float midLodFactor = 277.78f; 66 const float midLodFactor = 277.78f;
48 const float lowLodFactor = 1111.11f; 67 const float lowLodFactor = 1111.11f;
49 68
69 // physics cost is below, identical to SL, assuming shape type convex
70 // server cost is below identical to SL assuming non scripted non physical object
71
72 // internal
50 const int bytesPerCoord = 6; // 3 coords, 2 bytes per each 73 const int bytesPerCoord = 6; // 3 coords, 2 bytes per each
51 74
75 // control prims dimensions
76 public float PrimScaleMin = 0.01f;
77 public float NonPhysicalPrimScaleMax = 256f;
78 public float PhysicalPrimScaleMax = 10f;
79 public int ObjectLinkedPartsMax = 512;
80
81 // storage for a single mesh asset cost parameters
52 private class ameshCostParam 82 private class ameshCostParam
53 { 83 {
84 // LOD sizes for size dependent streaming cost
54 public int highLODSize; 85 public int highLODSize;
55 public int medLODSize; 86 public int medLODSize;
56 public int lowLODSize; 87 public int lowLODSize;
57 public int lowestLODSize; 88 public int lowestLODSize;
89 // normalized fee based on compressed data sizes
58 public float costFee; 90 public float costFee;
91 // physics cost
59 public float physicsCost; 92 public float physicsCost;
60 } 93 }
61 94
95 // calculates a mesh model costs
96 // returns false on error, with a reason on parameter error
97 // resources input LLSD request
98 // basicCost input region assets upload cost
99 // totalcost returns model total upload fee
100 // meshcostdata returns detailed costs for viewer
62 public bool MeshModelCost(LLSDAssetResource resources, int basicCost, out int totalcost, LLSDAssetUploadResponseData meshcostdata, out string error) 101 public bool MeshModelCost(LLSDAssetResource resources, int basicCost, out int totalcost, LLSDAssetUploadResponseData meshcostdata, out string error)
63 { 102 {
64 totalcost = 0; 103 totalcost = 0;
@@ -71,7 +110,15 @@ namespace OpenSim.Region.ClientStack.Linden
71 error = "Unable to upload mesh model. missing information."; 110 error = "Unable to upload mesh model. missing information.";
72 return false; 111 return false;
73 } 112 }
74 113
114 int numberInstances = resources.instance_list.Array.Count;
115
116 if( numberInstances > ObjectLinkedPartsMax )
117 {
118 error = "upload failed: Model whould have two many linked prims";
119 return false;
120 }
121
75 meshcostdata.model_streaming_cost = 0.0; 122 meshcostdata.model_streaming_cost = 0.0;
76 meshcostdata.simulation_cost = 0.0; 123 meshcostdata.simulation_cost = 0.0;
77 meshcostdata.physics_cost = 0.0; 124 meshcostdata.physics_cost = 0.0;
@@ -87,11 +134,12 @@ namespace OpenSim.Region.ClientStack.Linden
87 // textures cost 134 // textures cost
88 if (resources.texture_list != null && resources.texture_list.Array.Count > 0) 135 if (resources.texture_list != null && resources.texture_list.Array.Count > 0)
89 { 136 {
90 int textures_cost = resources.texture_list.Array.Count; 137 float textures_cost = (float)(resources.texture_list.Array.Count * basicCost);
91 textures_cost *= basicCost; 138 textures_cost *= ModelTextureCostFactor;
92 139
93 meshcostdata.upload_price_breakdown.texture = textures_cost; 140 itmp = (int)(textures_cost + 0.5f); // round
94 totalcost += textures_cost; 141 meshcostdata.upload_price_breakdown.texture = itmp;
142 totalcost += itmp;
95 } 143 }
96 144
97 // meshs assets cost 145 // meshs assets cost
@@ -120,12 +168,35 @@ namespace OpenSim.Region.ClientStack.Linden
120 } 168 }
121 169
122 // instances (prims) cost 170 // instances (prims) cost
123 int numberInstances = resources.instance_list.Array.Count; 171
172
124 int mesh; 173 int mesh;
125 for (int i = 0; i < numberInstances; i++) 174 for (int i = 0; i < numberInstances; i++)
126 { 175 {
127 Hashtable inst = (Hashtable)resources.instance_list.Array[i]; 176 Hashtable inst = (Hashtable)resources.instance_list.Array[i];
128 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 error = " upload fail: Model contains parts with a dimension lower than 0.01. Please adjust scaling";
191 return false;
192 }
193
194 if (scale.X > NonPhysicalPrimScaleMax || scale.Y > NonPhysicalPrimScaleMax || scale.Z > NonPhysicalPrimScaleMax)
195 {
196 error = "upload fail: Model contains parts larger than maximum allowed. Please adjust scaling";
197 return false;
198 }
199
129 if (haveMeshs && inst.ContainsKey("mesh")) 200 if (haveMeshs && inst.ContainsKey("mesh"))
130 { 201 {
131 mesh = (int)inst["mesh"]; 202 mesh = (int)inst["mesh"];
@@ -137,15 +208,6 @@ namespace OpenSim.Region.ClientStack.Linden
137 } 208 }
138 209
139 // streamming cost 210 // streamming cost
140 ArrayList ascale = (ArrayList)inst["scale"];
141 Vector3 scale;
142 double tmp;
143 tmp = (double)ascale[0];
144 scale.X = (float)tmp;
145 tmp = (double)ascale[1];
146 scale.Y = (float)tmp;
147 tmp = (double)ascale[2];
148 scale.Z = (float)tmp;
149 211
150 float sqdiam = scale.LengthSquared(); 212 float sqdiam = scale.LengthSquared();
151 213
@@ -176,12 +238,16 @@ namespace OpenSim.Region.ClientStack.Linden
176 if (meshcostdata.resource_cost < meshcostdata.simulation_cost) 238 if (meshcostdata.resource_cost < meshcostdata.simulation_cost)
177 meshcostdata.resource_cost = meshcostdata.simulation_cost; 239 meshcostdata.resource_cost = meshcostdata.simulation_cost;
178 240
241 // scale cost
242 // at this point a cost of 1.0 whould mean basic cost
243 meshsfee *= ModelMeshCostFactor;
179 244
180 if (meshsfee < ModelMinCost) 245 if (meshsfee < ModelMinCostFactor)
181 meshsfee = ModelMinCost; 246 meshsfee = ModelMinCostFactor;
247
248 // actually scale it to basic cost
249 meshsfee *= (float)basicCost;
182 250
183 // scale cost with basic cost changes relative to 10
184 meshsfee *= (float)basicCost / 10.0f;
185 meshsfee += 0.5f; // rounding 251 meshsfee += 0.5f; // rounding
186 252
187 totalcost += (int)meshsfee; 253 totalcost += (int)meshsfee;
@@ -192,6 +258,7 @@ namespace OpenSim.Region.ClientStack.Linden
192 return true; 258 return true;
193 } 259 }
194 260
261 // single mesh asset cost
195 private bool MeshCost(byte[] data, ameshCostParam cost, out string error) 262 private bool MeshCost(byte[] data, ameshCostParam cost, out string error)
196 { 263 {
197 cost.highLODSize = 0; 264 cost.highLODSize = 0;
@@ -377,6 +444,7 @@ namespace OpenSim.Region.ClientStack.Linden
377 return true; 444 return true;
378 } 445 }
379 446
447 // parses a LOD or physics mesh component
380 private bool submesh(byte[] data, int offset, int size, out int ntriangles) 448 private bool submesh(byte[] data, int offset, int size, out int ntriangles)
381 { 449 {
382 ntriangles = 0; 450 ntriangles = 0;
@@ -443,6 +511,7 @@ namespace OpenSim.Region.ClientStack.Linden
443 return true; 511 return true;
444 } 512 }
445 513
514 // parses convex hulls component
446 private bool hulls(byte[] data, int offset, int size, out int nvertices, out int nhulls) 515 private bool hulls(byte[] data, int offset, int size, out int nvertices, out int nhulls)
447 { 516 {
448 nvertices = 0; 517 nvertices = 0;
@@ -512,6 +581,7 @@ namespace OpenSim.Region.ClientStack.Linden
512 return true; 581 return true;
513 } 582 }
514 583
584 // returns streaming cost from on mesh LODs sizes in curCost and square of prim size length
515 private float streamingCost(ameshCostParam curCost, float sqdiam) 585 private float streamingCost(ameshCostParam curCost, float sqdiam)
516 { 586 {
517 // compute efective areas 587 // compute efective areas
@@ -571,7 +641,6 @@ namespace OpenSim.Region.ClientStack.Linden
571 h = 16; 641 h = 16;
572 642
573 // compute cost weighted by relative effective areas 643 // compute cost weighted by relative effective areas
574
575 float cost = (float)lst * mlst + (float)l * ml + (float)m * mm + (float)h * mh; 644 float cost = (float)lst * mlst + (float)l * ml + (float)m * mm + (float)h * mh;
576 cost /= ma; 645 cost /= ma;
577 646