31 using System.Collections;
 
   32 using System.Collections.Generic;
 
   36 using OpenMetaverse.StructuredData;
 
   38 using OpenSim.Framework;
 
   39 using OpenSim.Region.Framework;
 
   40 using OpenSim.Region.Framework.Scenes;
 
   41 using OpenSim.Framework.Capabilities;
 
   43 using ComponentAce.Compression.Libs.zlib;
 
   48 namespace OpenSim.
Region.ClientStack.Linden
 
   62         public float ModelMeshCostFactor = 0.0f; 
 
   63         public float ModelTextureCostFactor = 1.0f; 
 
   64         public float ModelMinCostFactor = 0.0f; 
 
   68         public float primCreationCost = 0.002f;  
 
   70         public float bytecost = 1e-5f;
 
   78         const float medSizeWth = 1f; 
 
   79         const float lowSizeWth = 1.5f; 
 
   80         const float lowestSizeWth = 2f; 
 
   82         const float physMeshSizeWth = 6f; 
 
   83         const float physHullSizeWth = 8f; 
 
   87         const float highLodFactor = 17.36f;
 
   88         const float midLodFactor = 277.78f;
 
   89         const float lowLodFactor = 1111.11f;
 
   95         const int bytesPerCoord = 6; 
 
   98         public float PrimScaleMin = 0.001f;
 
   99         public float NonPhysicalPrimScaleMax = 256f;
 
  100         public float PhysicalPrimScaleMax = 10f;
 
  101         public int ObjectLinkedPartsMax = 512;
 
  104         private class ameshCostParam
 
  107             public int highLODSize;
 
  108             public int medLODSize;
 
  109             public int lowLODSize;
 
  110             public int lowestLODSize;
 
  112             public float costFee;
 
  114             public float physicsCost;
 
  129             error = string.Empty;
 
  131             bool avatarSkeleton = 
false;
 
  133             if (resources == null ||
 
  137                 error = 
"missing model information.";
 
  141             int numberInstances = resources.instance_list.Array.Count;
 
  143             if (ObjectLinkedPartsMax != 0 && numberInstances > ObjectLinkedPartsMax)
 
  145                 error = 
"Model would have more than " + ObjectLinkedPartsMax.ToString() + 
" linked prims";
 
  149             meshcostdata.model_streaming_cost = 0.0;
 
  150             meshcostdata.simulation_cost = 0.0;
 
  151             meshcostdata.physics_cost = 0.0;
 
  152             meshcostdata.resource_cost = 0.0;
 
  154             meshcostdata.upload_price_breakdown.mesh_instance = 0;
 
  155             meshcostdata.upload_price_breakdown.mesh_physics = 0;
 
  156             meshcostdata.upload_price_breakdown.mesh_streaming = 0;
 
  157             meshcostdata.upload_price_breakdown.model = 0;
 
  165                 textures_cost *= ModelTextureCostFactor;
 
  167                 itmp = (int)(textures_cost + 0.5f); 
 
  168                 meshcostdata.upload_price_breakdown.texture = itmp;
 
  175             bool haveMeshs = 
false;
 
  180             List<ameshCostParam> meshsCosts = 
new List<ameshCostParam>();
 
  184                 numberMeshs = resources.mesh_list.Array.Count;
 
  186                 for (
int i = 0; i < numberMeshs; i++)
 
  188                     ameshCostParam curCost = 
new ameshCostParam();
 
  191                     if (!MeshCost(data, curCost,out curskeleton, out curAvatarPhys, out error))
 
  200                             error = 
"model can only contain a avatar skeleton";
 
  203                         avatarSkeleton = 
true;
 
  205                     meshsCosts.Add(curCost);
 
  206                     meshsfee += curCost.costFee;
 
  216             for (
int i = 0; i < numberInstances; i++)
 
  220                 ArrayList ascale = (ArrayList)inst[
"scale"];
 
  223                 tmp = (double)ascale[0];
 
  224                 scale.X = (float)tmp;
 
  225                 tmp = (double)ascale[1];
 
  226                 scale.Y = (float)tmp;
 
  227                 tmp = (double)ascale[2];
 
  228                 scale.Z = (float)tmp;
 
  230                 if (scale.X < PrimScaleMin || scale.Y < PrimScaleMin || scale.Z < PrimScaleMin)
 
  236                 if (scale.X > NonPhysicalPrimScaleMax || scale.Y > NonPhysicalPrimScaleMax || scale.Z > NonPhysicalPrimScaleMax)
 
  238                     error = 
"Model contains parts with sides larger than " + NonPhysicalPrimScaleMax.ToString() + 
"m. Please ajust scale";
 
  242                 if (haveMeshs && inst.ContainsKey(
"mesh"))
 
  244                     mesh = (int)inst[
"mesh"];
 
  246                     if (mesh >= numberMeshs)
 
  248                         error = 
"Incoerent model information.";
 
  254                     float sqdiam = scale.LengthSquared();
 
  256                     ameshCostParam curCost = meshsCosts[mesh];
 
  257                     float mesh_streaming = streamingCost(curCost, sqdiam);
 
  259                     meshcostdata.model_streaming_cost += mesh_streaming;
 
  260                     meshcostdata.physics_cost += curCost.physicsCost;
 
  265                     meshcostdata.model_streaming_cost += 0.5f;
 
  266                     meshcostdata.physics_cost += 1.0f;
 
  270                 meshcostdata.simulation_cost += 0.5f;
 
  272                 meshsfee += primCreationCost;
 
  277                 if (skipedSmall > numberInstances / 2)
 
  279                     error = 
"Model contains too many prims smaller than " + PrimScaleMin.ToString() +
 
  280                         "m minimum allowed size. Please check scalling";
 
  284                     warning += skipedSmall.ToString() + 
" of the requested " +numberInstances.ToString() +
 
  285                         " model prims will not upload because they are smaller than " + PrimScaleMin.ToString() +
 
  286                         "m minimum allowed size. Please check scalling ";
 
  290                 meshcostdata.resource_cost = meshcostdata.model_streaming_cost;
 
  292                 meshcostdata.resource_cost = meshcostdata.physics_cost;
 
  295                 meshcostdata.resource_cost = meshcostdata.simulation_cost;
 
  299             meshsfee *= ModelMeshCostFactor;
 
  301             if (meshsfee < ModelMinCostFactor)
 
  302                 meshsfee = ModelMinCostFactor;
 
  305             meshsfee *= (float)basicCost;
 
  309             totalcost += (int)meshsfee;
 
  318         private bool MeshCost(byte[] data, ameshCostParam cost,out 
bool skeleton, out 
bool avatarPhys, out 
string error)
 
  320             cost.highLODSize = 0;
 
  323             cost.lowestLODSize = 0;
 
  324             cost.physicsCost = 0.0f;
 
  327             error = string.Empty;
 
  332             if (data == null || data.Length == 0)
 
  334                 error = 
"Missing model information.";
 
  341             error = 
"Invalid model data";
 
  343             using (MemoryStream ms = 
new MemoryStream(data))
 
  347                     OSD osd = OSDParser.DeserializeLLSDBinary(ms);
 
  357                 start = (int)ms.Position;
 
  363             int highlod_size = 0;
 
  366             int lowestlod_size = 0;
 
  371             int phys_hullsvertices = 0;
 
  373             int physmesh_size = 0;
 
  374             int phys_ntriangles = 0;
 
  376             int submesh_offset = -1;
 
  378             if (map.ContainsKey(
"skeleton"))
 
  380                 tmpmap = (
OSDMap)map[
"skeleton"];
 
  381                 if (tmpmap.ContainsKey(
"offset") && tmpmap.ContainsKey(
"size"))
 
  383                     int sksize = tmpmap[
"size"].AsInteger();
 
  389             if (map.ContainsKey(
"physics_convex"))
 
  391                 tmpmap = (
OSDMap)map[
"physics_convex"];
 
  392                 if (tmpmap.ContainsKey(
"offset"))
 
  393                     submesh_offset = tmpmap[
"offset"].AsInteger() + start;
 
  394                 if (tmpmap.ContainsKey(
"size"))
 
  395                     hulls_size = tmpmap[
"size"].AsInteger();
 
  398             if (submesh_offset < 0 || hulls_size == 0)
 
  400                 error = 
"Missing physics_convex block";
 
  404             if (!hulls(data, submesh_offset, hulls_size, out phys_hullsvertices, out phys_nhulls))
 
  406                 error = 
"Bad physics_convex block";
 
  414             if (map.ContainsKey(
"high_lod"))
 
  416                 tmpmap = (
OSDMap)map[
"high_lod"];
 
  418                 if (tmpmap.ContainsKey(
"offset"))
 
  419                     submesh_offset = tmpmap[
"offset"].AsInteger() + start;
 
  420                 if (tmpmap.ContainsKey(
"size"))
 
  421                     highlod_size = tmpmap[
"size"].AsInteger();
 
  424             if (submesh_offset < 0 || highlod_size <= 0)
 
  426                 error = 
"Missing high_lod block";
 
  430             bool haveprev = 
true;
 
  432             if (map.ContainsKey(
"medium_lod"))
 
  434                 tmpmap = (
OSDMap)map[
"medium_lod"];
 
  435                 if (tmpmap.ContainsKey(
"size"))
 
  436                     medlod_size = tmpmap[
"size"].AsInteger();
 
  441             if (haveprev && map.ContainsKey(
"low_lod"))
 
  443                 tmpmap = (
OSDMap)map[
"low_lod"];
 
  444                 if (tmpmap.ContainsKey(
"size"))
 
  445                     lowlod_size = tmpmap[
"size"].AsInteger();
 
  450             if (haveprev && map.ContainsKey(
"lowest_lod"))
 
  452                 tmpmap = (
OSDMap)map[
"lowest_lod"];
 
  453                 if (tmpmap.ContainsKey(
"size"))
 
  454                     lowestlod_size = tmpmap[
"size"].AsInteger();
 
  457             if (map.ContainsKey(
"skin"))
 
  459                 tmpmap = (
OSDMap)map[
"skin"];
 
  460                 if (tmpmap.ContainsKey(
"size"))
 
  461                     skin_size = tmpmap[
"size"].AsInteger();
 
  464             cost.highLODSize = highlod_size;
 
  465             cost.medLODSize = medlod_size;
 
  466             cost.lowLODSize = lowlod_size;
 
  467             cost.lowestLODSize = lowestlod_size;
 
  472             if(map.ContainsKey(
"physics_mesh"))
 
  473                 tmpmap = (
OSDMap)map[
"physics_mesh"];
 
  474             else if (map.ContainsKey(
"physics_shape")) 
 
  475                 tmpmap = (
OSDMap)map[
"physics_shape"];
 
  479                 if (tmpmap.ContainsKey(
"offset"))
 
  480                     submesh_offset = tmpmap[
"offset"].AsInteger() + start;
 
  481                 if (tmpmap.ContainsKey(
"size"))
 
  482                     physmesh_size = tmpmap[
"size"].AsInteger();
 
  484                 if (submesh_offset >= 0 || physmesh_size > 0)
 
  487                     if (!submesh(data, submesh_offset, physmesh_size, out phys_ntriangles))
 
  489                         error = 
"Model data parsing error";
 
  496             phys_hullsvertices++;
 
  497             cost.physicsCost = 0.04f * phys_hullsvertices;
 
  504             sfee += medSizeWth * medlod_size;
 
  505             sfee += lowSizeWth * lowlod_size;
 
  506             sfee += lowestSizeWth * lowlod_size;
 
  510             if (physmesh_size != 0)
 
  511                 sfee += physMeshSizeWth * (physmesh_size + hulls_size / 4); 
 
  513                 sfee += physHullSizeWth * hulls_size;
 
  523         private bool submesh(byte[] data, 
int offset, 
int size, out 
int ntriangles)
 
  527             OSD decodedMeshOsd = 
new OSD();
 
  528             byte[] meshBytes = 
new byte[size];
 
  529             System.Buffer.BlockCopy(data, offset, meshBytes, 0, size);
 
  532                 using (MemoryStream inMs = 
new MemoryStream(meshBytes))
 
  534                     using (MemoryStream outMs = 
new MemoryStream())
 
  536                         using (ZOutputStream zOut = 
new ZOutputStream(outMs))
 
  538                             byte[] readBuffer = 
new byte[4096];
 
  540                             while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0)
 
  542                                 zOut.Write(readBuffer, 0, readLen);
 
  545                             outMs.Seek(0, SeekOrigin.Begin);
 
  547                             byte[] decompressedBuf = outMs.GetBuffer();
 
  548                             decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf);
 
  558             OSDArray decodedMeshOsdArray = null;
 
  562             decodedMeshOsdArray = (
OSDArray)decodedMeshOsd;
 
  563             foreach (
OSD subMeshOsd 
in decodedMeshOsdArray)
 
  567                     OSDMap subtmpmap = (
OSDMap)subMeshOsd;
 
  568                     if (subtmpmap.ContainsKey(
"NoGeometry") && ((OSDBoolean)subtmpmap[
"NoGeometry"]))
 
  571                     if (!subtmpmap.ContainsKey(
"Position"))
 
  574                     if (subtmpmap.ContainsKey(
"TriangleList"))
 
  576                         dummy = subtmpmap[
"TriangleList"].AsBinary();
 
  577                         ntriangles += dummy.Length / bytesPerCoord;
 
  588         private bool hulls(byte[] data, 
int offset, 
int size, out 
int nvertices, out 
int nhulls)
 
  593             OSD decodedMeshOsd = 
new OSD();
 
  594             byte[] meshBytes = 
new byte[size];
 
  595             System.Buffer.BlockCopy(data, offset, meshBytes, 0, size);
 
  598                 using (MemoryStream inMs = 
new MemoryStream(meshBytes))
 
  600                     using (MemoryStream outMs = 
new MemoryStream())
 
  602                         using (ZOutputStream zOut = 
new ZOutputStream(outMs))
 
  604                             byte[] readBuffer = 
new byte[4096];
 
  606                             while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0)
 
  608                                 zOut.Write(readBuffer, 0, readLen);
 
  611                             outMs.Seek(0, SeekOrigin.Begin);
 
  613                             byte[] decompressedBuf = outMs.GetBuffer();
 
  614                             decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf);
 
  624             OSDMap cmap = (
OSDMap)decodedMeshOsd;
 
  631             if (cmap.ContainsKey(
"BoundingVerts"))
 
  633                 dummy = cmap[
"BoundingVerts"].AsBinary();
 
  634                 nvertices = dummy.Length / bytesPerCoord;
 
  658         private float streamingCost(ameshCostParam curCost, 
float sqdiam)
 
  663             float mh = sqdiam * highLodFactor;
 
  666             float mm = sqdiam * midLodFactor;
 
  670             float ml = sqdiam * lowLodFactor;
 
  689             ma = mlst + ml + mm + mh;
 
  693             int lst = curCost.lowestLODSize - 384;
 
  694             int l = curCost.lowLODSize - 384;
 
  695             int m = curCost.medLODSize - 384;
 
  696             int h = curCost.highLODSize - 384;
 
  717             float cost = (float)lst * mlst + (
float)l * ml + (float)m * mm + (
float)h * mh;
 
OpenMetaverse.StructuredData.OSDMap OSDMap
 
bool MeshModelCost(LLSDAssetResource resources, int basicCost, out int totalcost, LLSDAssetUploadResponseData meshcostdata, out string error, ref string warning)
 
OpenMetaverse.StructuredData.OSD OSD
 
OpenMetaverse.StructuredData.OSDArray OSDArray
 
double model_streaming_cost