diff options
-rw-r--r-- | OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs | 394 | ||||
-rw-r--r-- | OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs | 133 |
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 | ||
24 | namespace OpenSim.Region.ClientStack.Linden | 24 | namespace 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 | ||