coment out mesh model upload code to add textures and individual meshs

assets to inventory, since it may actually be a bad ideia since good
 model textures are deply related to it and there is no current use for
 independent mesh assets. Added the option to have a reduced free for textures (2.5 C$ as is, total textures cost rounded to nearest int) compensating for the fact that they can't be used outside the model or its parts.
avinationmerge
UbitUmarov 2012-09-19 00:29:16 +01:00
parent ac2380bbfa
commit 51ca84afdf
2 changed files with 249 additions and 198 deletions

View File

@ -116,8 +116,8 @@ namespace OpenSim.Region.ClientStack.Linden
private bool m_dumpAssetsToFile = false; private bool m_dumpAssetsToFile = false;
private string m_regionName; private string m_regionName;
private int m_levelUpload = 0; private int m_levelUpload = 0;
private bool m_addNewTextures = false; // private bool m_addNewTextures = false;
private bool m_addNewMeshes = false; // private bool m_addNewMeshes = false;
public BunchOfCaps(Scene scene, Caps caps) public BunchOfCaps(Scene scene, Caps caps)
{ {
@ -608,172 +608,181 @@ namespace OpenSim.Region.ClientStack.Linden
} }
else if (inventoryType == "object") else if (inventoryType == "object")
{ {
inType = (sbyte)InventoryType.Object; if (assetType == "mesh") // this code for now is for mesh models uploads only
assType = (sbyte)AssetType.Object;
List<Vector3> positions = new List<Vector3>();
List<Quaternion> rotations = new List<Quaternion>();
OSDMap request = (OSDMap)OSDParser.DeserializeLLSDXml(data);
OSDArray instance_list = (OSDArray)request["instance_list"];
OSDArray mesh_list = (OSDArray)request["mesh_list"];
OSDArray texture_list = (OSDArray)request["texture_list"];
SceneObjectGroup grp = null;
// create and store texture assets
List<UUID> textures = new List<UUID>();
for (int i = 0; i < texture_list.Count; i++)
{ {
AssetBase textureAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Texture, ""); inType = (sbyte)InventoryType.Object;
textureAsset.Data = texture_list[i].AsBinary(); assType = (sbyte)AssetType.Object;
m_assetService.Store(textureAsset);
textures.Add(textureAsset.FullID);
// save it to inventory List<Vector3> positions = new List<Vector3>();
if (m_addNewTextures && AddNewInventoryItem != null) List<Quaternion> rotations = new List<Quaternion>();
OSDMap request = (OSDMap)OSDParser.DeserializeLLSDXml(data);
OSDArray instance_list = (OSDArray)request["instance_list"];
OSDArray mesh_list = (OSDArray)request["mesh_list"];
OSDArray texture_list = (OSDArray)request["texture_list"];
SceneObjectGroup grp = null;
// create and store texture assets
List<UUID> textures = new List<UUID>();
for (int i = 0; i < texture_list.Count; i++)
{ {
string name = assetName; AssetBase textureAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Texture, "");
if (name.Length > 25) textureAsset.Data = texture_list[i].AsBinary();
name = name.Substring(0, 24); m_assetService.Store(textureAsset);
name += "_Texture#" + i.ToString(); textures.Add(textureAsset.FullID);
InventoryItemBase texitem = new InventoryItemBase(); /*
texitem.Owner = m_HostCapsObj.AgentID; don't do this
texitem.CreatorId = m_HostCapsObj.AgentID.ToString(); replace it by optionaly making model textures cost less than if individually uploaded
texitem.CreatorData = String.Empty; since they can't be used for other purpuses
texitem.ID = UUID.Random();
texitem.AssetID = textureAsset.FullID;
texitem.Description = "mesh model texture";
texitem.Name = name;
texitem.AssetType = (int)AssetType.Texture;
texitem.InvType = (int)InventoryType.Texture;
texitem.Folder = UUID.Zero; // send to default
// If we set PermissionMask.All then when we rez the item the next permissions will replace the current // save it to inventory
// (owner) permissions. This becomes a problem if next permissions are changed. if (m_addNewTextures && AddNewInventoryItem != null)
texitem.CurrentPermissions {
= (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer); string name = assetName;
if (name.Length > 25)
name = name.Substring(0, 24);
name += "_Texture#" + i.ToString();
InventoryItemBase texitem = new InventoryItemBase();
texitem.Owner = m_HostCapsObj.AgentID;
texitem.CreatorId = m_HostCapsObj.AgentID.ToString();
texitem.CreatorData = String.Empty;
texitem.ID = UUID.Random();
texitem.AssetID = textureAsset.FullID;
texitem.Description = "mesh model texture";
texitem.Name = name;
texitem.AssetType = (int)AssetType.Texture;
texitem.InvType = (int)InventoryType.Texture;
texitem.Folder = UUID.Zero; // send to default
texitem.BasePermissions = (uint)PermissionMask.All; // If we set PermissionMask.All then when we rez the item the next permissions will replace the current
texitem.EveryOnePermissions = 0; // (owner) permissions. This becomes a problem if next permissions are changed.
texitem.NextPermissions = (uint)PermissionMask.All; texitem.CurrentPermissions
texitem.CreationDate = Util.UnixTimeSinceEpoch(); = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer);
AddNewInventoryItem(m_HostCapsObj.AgentID, texitem, 0); texitem.BasePermissions = (uint)PermissionMask.All;
texitem = null; texitem.EveryOnePermissions = 0;
texitem.NextPermissions = (uint)PermissionMask.All;
texitem.CreationDate = Util.UnixTimeSinceEpoch();
AddNewInventoryItem(m_HostCapsObj.AgentID, texitem, 0);
texitem = null;
}
*/
textureAsset = null;
} }
textureAsset = null; // create and store meshs assets
List<UUID> meshAssets = new List<UUID>();
} for (int i = 0; i < mesh_list.Count; i++)
// create and store meshs assets
List<UUID> meshAssets = new List<UUID>();
for (int i = 0; i < mesh_list.Count; i++)
{
AssetBase meshAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Mesh, "");
meshAsset.Data = mesh_list[i].AsBinary();
m_assetService.Store(meshAsset);
meshAssets.Add(meshAsset.FullID);
// save it to inventory
if (m_addNewMeshes && AddNewInventoryItem != null)
{ {
string name = assetName; AssetBase meshAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Mesh, "");
if (name.Length > 25) meshAsset.Data = mesh_list[i].AsBinary();
name = name.Substring(0, 24); m_assetService.Store(meshAsset);
name += "_Mesh#" + i.ToString(); meshAssets.Add(meshAsset.FullID);
InventoryItemBase meshitem = new InventoryItemBase();
meshitem.Owner = m_HostCapsObj.AgentID;
meshitem.CreatorId = m_HostCapsObj.AgentID.ToString();
meshitem.CreatorData = String.Empty;
meshitem.ID = UUID.Random();
meshitem.AssetID = meshAsset.FullID;
meshitem.Description = "mesh ";
meshitem.Name = name;
meshitem.AssetType = (int)AssetType.Mesh;
meshitem.InvType = (int)InventoryType.Mesh;
meshitem.Folder = UUID.Zero; // send to default
// If we set PermissionMask.All then when we rez the item the next permissions will replace the current /* this was a test, funny and showed viewers deal with mesh inventory itens
// (owner) permissions. This becomes a problem if next permissions are changed. * nut also same reason as for textures
meshitem.CurrentPermissions * let integrated in a model cost eventually less than hipotetical independent meshs assets
= (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer); * that will be in inventory
// save it to inventory
if (m_addNewMeshes && AddNewInventoryItem != null)
{
string name = assetName;
if (name.Length > 25)
name = name.Substring(0, 24);
name += "_Mesh#" + i.ToString();
InventoryItemBase meshitem = new InventoryItemBase();
meshitem.Owner = m_HostCapsObj.AgentID;
meshitem.CreatorId = m_HostCapsObj.AgentID.ToString();
meshitem.CreatorData = String.Empty;
meshitem.ID = UUID.Random();
meshitem.AssetID = meshAsset.FullID;
meshitem.Description = "mesh ";
meshitem.Name = name;
meshitem.AssetType = (int)AssetType.Mesh;
meshitem.InvType = (int)InventoryType.Mesh;
meshitem.Folder = UUID.Zero; // send to default
meshitem.BasePermissions = (uint)PermissionMask.All; // If we set PermissionMask.All then when we rez the item the next permissions will replace the current
meshitem.EveryOnePermissions = 0; // (owner) permissions. This becomes a problem if next permissions are changed.
meshitem.NextPermissions = (uint)PermissionMask.All; meshitem.CurrentPermissions
meshitem.CreationDate = Util.UnixTimeSinceEpoch(); = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer);
AddNewInventoryItem(m_HostCapsObj.AgentID, meshitem, 0); meshitem.BasePermissions = (uint)PermissionMask.All;
meshitem = null; meshitem.EveryOnePermissions = 0;
meshitem.NextPermissions = (uint)PermissionMask.All;
meshitem.CreationDate = Util.UnixTimeSinceEpoch();
AddNewInventoryItem(m_HostCapsObj.AgentID, meshitem, 0);
meshitem = null;
}
*/
meshAsset = null;
} }
meshAsset = null; // build prims from instances
} for (int i = 0; i < instance_list.Count; i++)
// build prims from instances
for (int i = 0; i < instance_list.Count; i++)
{
PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateBox();
Primitive.TextureEntry textureEntry
= new Primitive.TextureEntry(Primitive.TextureEntry.WHITE_TEXTURE);
OSDMap inner_instance_list = (OSDMap)instance_list[i];
OSDArray face_list = (OSDArray)inner_instance_list["face_list"];
for (uint face = 0; face < face_list.Count; face++)
{ {
OSDMap faceMap = (OSDMap)face_list[(int)face]; PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateBox();
Primitive.TextureEntryFace f = pbs.Textures.CreateFace(face);
if(faceMap.ContainsKey("fullbright"))
f.Fullbright = faceMap["fullbright"].AsBoolean();
if (faceMap.ContainsKey ("diffuse_color"))
f.RGBA = faceMap["diffuse_color"].AsColor4();
int textureNum = faceMap["image"].AsInteger(); Primitive.TextureEntry textureEntry
float imagerot = faceMap["imagerot"].AsInteger(); = new Primitive.TextureEntry(Primitive.TextureEntry.WHITE_TEXTURE);
float offsets = (float)faceMap["offsets"].AsReal();
float offsett = (float)faceMap["offsett"].AsReal();
float scales = (float)faceMap["scales"].AsReal();
float scalet = (float)faceMap["scalet"].AsReal();
if(imagerot != 0) OSDMap inner_instance_list = (OSDMap)instance_list[i];
f.Rotation = imagerot;
if(offsets != 0) OSDArray face_list = (OSDArray)inner_instance_list["face_list"];
f.OffsetU = offsets; for (uint face = 0; face < face_list.Count; face++)
{
OSDMap faceMap = (OSDMap)face_list[(int)face];
Primitive.TextureEntryFace f = pbs.Textures.CreateFace(face);
if (faceMap.ContainsKey("fullbright"))
f.Fullbright = faceMap["fullbright"].AsBoolean();
if (faceMap.ContainsKey("diffuse_color"))
f.RGBA = faceMap["diffuse_color"].AsColor4();
if (offsett != 0) int textureNum = faceMap["image"].AsInteger();
f.OffsetV = offsett; float imagerot = faceMap["imagerot"].AsInteger();
float offsets = (float)faceMap["offsets"].AsReal();
float offsett = (float)faceMap["offsett"].AsReal();
float scales = (float)faceMap["scales"].AsReal();
float scalet = (float)faceMap["scalet"].AsReal();
if (scales != 0) if (imagerot != 0)
f.RepeatU = scales; f.Rotation = imagerot;
if (scalet != 0) if (offsets != 0)
f.RepeatV = scalet; f.OffsetU = offsets;
if (textures.Count > textureNum) if (offsett != 0)
f.TextureID = textures[textureNum]; f.OffsetV = offsett;
else
f.TextureID = Primitive.TextureEntry.WHITE_TEXTURE;
textureEntry.FaceTextures[face] = f; if (scales != 0)
} f.RepeatU = scales;
pbs.TextureEntry = textureEntry.GetBytes(); if (scalet != 0)
f.RepeatV = scalet;
int meshindx = inner_instance_list["mesh"].AsInteger(); if (textures.Count > textureNum)
if (meshAssets.Count > meshindx) f.TextureID = textures[textureNum];
{ else
pbs.SculptEntry = true; f.TextureID = Primitive.TextureEntry.WHITE_TEXTURE;
pbs.SculptType = (byte)SculptType.Mesh;
pbs.SculptTexture = meshAssets[meshindx]; // actual asset UUID after meshs suport introduction
// data will be requested from asset on rez (i hope)
}
Vector3 position = inner_instance_list["position"].AsVector3(); textureEntry.FaceTextures[face] = f;
Vector3 scale = inner_instance_list["scale"].AsVector3(); }
Quaternion rotation = inner_instance_list["rotation"].AsQuaternion();
pbs.TextureEntry = textureEntry.GetBytes();
int meshindx = inner_instance_list["mesh"].AsInteger();
if (meshAssets.Count > meshindx)
{
pbs.SculptEntry = true;
pbs.SculptType = (byte)SculptType.Mesh;
pbs.SculptTexture = meshAssets[meshindx]; // actual asset UUID after meshs suport introduction
// data will be requested from asset on rez (i hope)
}
Vector3 position = inner_instance_list["position"].AsVector3();
Vector3 scale = inner_instance_list["scale"].AsVector3();
Quaternion rotation = inner_instance_list["rotation"].AsQuaternion();
// no longer used - begin ------------------------ // no longer used - begin ------------------------
// int physicsShapeType = inner_instance_list["physics_shape_type"].AsInteger(); // int physicsShapeType = inner_instance_list["physics_shape_type"].AsInteger();
@ -793,23 +802,23 @@ namespace OpenSim.Region.ClientStack.Linden
// int owner_mask = permissions["owner_mask"].AsInteger(); // int owner_mask = permissions["owner_mask"].AsInteger();
// no longer used - end ------------------------ // no longer used - end ------------------------
UUID owner_id = m_HostCapsObj.AgentID; UUID owner_id = m_HostCapsObj.AgentID;
SceneObjectPart prim SceneObjectPart prim
= new SceneObjectPart(owner_id, pbs, position, Quaternion.Identity, Vector3.Zero); = new SceneObjectPart(owner_id, pbs, position, Quaternion.Identity, Vector3.Zero);
prim.Scale = scale; prim.Scale = scale;
prim.OffsetPosition = position; prim.OffsetPosition = position;
rotations.Add(rotation); rotations.Add(rotation);
positions.Add(position); positions.Add(position);
prim.UUID = UUID.Random(); prim.UUID = UUID.Random();
prim.CreatorID = owner_id; prim.CreatorID = owner_id;
prim.OwnerID = owner_id; prim.OwnerID = owner_id;
prim.GroupID = UUID.Zero; prim.GroupID = UUID.Zero;
prim.LastOwnerID = prim.OwnerID; prim.LastOwnerID = prim.OwnerID;
prim.CreationDate = Util.UnixTimeSinceEpoch(); prim.CreationDate = Util.UnixTimeSinceEpoch();
prim.Name = assetName; prim.Name = assetName;
prim.Description = ""; prim.Description = "";
// prim.BaseMask = (uint)base_mask; // prim.BaseMask = (uint)base_mask;
// prim.EveryoneMask = (uint)everyone_mask; // prim.EveryoneMask = (uint)everyone_mask;
@ -817,32 +826,39 @@ namespace OpenSim.Region.ClientStack.Linden
// prim.NextOwnerMask = (uint)next_owner_mask; // prim.NextOwnerMask = (uint)next_owner_mask;
// prim.OwnerMask = (uint)owner_mask; // prim.OwnerMask = (uint)owner_mask;
if (grp == null) if (grp == null)
grp = new SceneObjectGroup(prim); grp = new SceneObjectGroup(prim);
else else
grp.AddPart(prim); grp.AddPart(prim);
}
// Fix first link number
if (grp.Parts.Length > 1)
grp.RootPart.LinkNum++;
Vector3 rootPos = positions[0];
grp.AbsolutePosition = rootPos;
for (int i = 0; i < positions.Count; i++)
{
Vector3 offset = positions[i] - rootPos;
grp.Parts[i].OffsetPosition = offset;
}
for (int i = 0; i < rotations.Count; i++)
{
if (i != 0)
grp.Parts[i].RotationOffset = rotations[i];
}
grp.UpdateGroupRotationR(rotations[0]);
data = ASCIIEncoding.ASCII.GetBytes(SceneObjectSerializer.ToOriginalXmlFormat(grp));
} }
// Fix first link number else // not a mesh model
if (grp.Parts.Length > 1)
grp.RootPart.LinkNum++;
Vector3 rootPos = positions[0];
grp.AbsolutePosition = rootPos;
for (int i = 0; i < positions.Count; i++)
{ {
Vector3 offset = positions[i] - rootPos; m_log.ErrorFormat("[CAPS Asset Upload] got unsuported assetType for object upload");
grp.Parts[i].OffsetPosition = offset; return;
} }
for (int i = 0; i < rotations.Count; i++)
{
if (i != 0)
grp.Parts[i].RotationOffset = rotations[i];
}
grp.UpdateGroupRotationR(rotations[0]);
data = ASCIIEncoding.ASCII.GetBytes(SceneObjectSerializer.ToOriginalXmlFormat(grp));
} }
AssetBase asset; AssetBase asset;

View File

@ -25,40 +25,67 @@ namespace OpenSim.Region.ClientStack.Linden
{ {
public class ModelCost public class ModelCost
{ {
float ModelMinCost = 5.0f; // try to favor small meshs versus sculpts // upload fee tunning paramenters
// fees are normalized to 1.0
// this parameters scale them to basic cost ( so 1.0 translates to 10 )
const float primCreationCost = 0.01f; // 256 prims cost extra 2.56 public float ModelMeshCostFactor = 1.0f; // scale total cost relative to basic (excluding textures)
public float ModelTextureCostFactor = 0.25f; //(2.5c$) scale textures fee to basic.
// promote integration in a model
// since they will not show up in inventory
public float ModelMinCostFactor = 0.5f; // minimum total model free excluding textures
// weigthed size to money convertion // itens costs in normalized values
const float bytecost = 1e-4f; // ie will be multiplied by basicCost and factors above
const float primCreationCost = 0.002f; // extra cost for each prim creation overhead
// for mesh upload fees based on compressed data sizes // weigthed size to normalized cost
// not using streaming physics and server costs as SL apparently does ?? const float bytecost = 1e-5f;
// mesh upload fees based on compressed data sizes
// several data sections are counted more that once
// to promote user optimization
// following parameters control how many extra times they are added
// to global size.
// LOD meshs
const float medSizeWth = 1f; // 2x const float medSizeWth = 1f; // 2x
const float lowSizeWth = 1.5f; // 2.5x const float lowSizeWth = 1.5f; // 2.5x
const float lowestSizeWth = 2f; // 3x const float lowestSizeWth = 2f; // 3x
// favor potencial optimized meshs versus automatic decomposition // favor potencially physical optimized meshs versus automatic decomposition
const float physMeshSizeWth = 6f; // counts 7x const float physMeshSizeWth = 6f; // counts 7x
const float physHullSizeWth = 8f; // counts 9x const float physHullSizeWth = 8f; // counts 9x
// stream cost area factors // stream cost area factors
// more or less like SL
const float highLodFactor = 17.36f; const float highLodFactor = 17.36f;
const float midLodFactor = 277.78f; const float midLodFactor = 277.78f;
const float lowLodFactor = 1111.11f; const float lowLodFactor = 1111.11f;
// physics cost is below, identical to SL, assuming shape type convex
// server cost is below identical to SL assuming non scripted non physical object
// internal
const int bytesPerCoord = 6; // 3 coords, 2 bytes per each const int bytesPerCoord = 6; // 3 coords, 2 bytes per each
// storage for a single mesh asset cost parameters
private class ameshCostParam private class ameshCostParam
{ {
// LOD sizes for size dependent streaming cost
public int highLODSize; public int highLODSize;
public int medLODSize; public int medLODSize;
public int lowLODSize; public int lowLODSize;
public int lowestLODSize; public int lowestLODSize;
// normalized fee based on compressed data sizes
public float costFee; public float costFee;
// physics cost
public float physicsCost; public float physicsCost;
} }
// calculates a mesh model costs
// returns false on error, with a reason on parameter error
// resources input LLSD request
// basicCost input region assets upload cost
// totalcost returns model total upload fee
// meshcostdata returns detailed costs for viewer
public bool MeshModelCost(LLSDAssetResource resources, int basicCost, out int totalcost, LLSDAssetUploadResponseData meshcostdata, out string error) public bool MeshModelCost(LLSDAssetResource resources, int basicCost, out int totalcost, LLSDAssetUploadResponseData meshcostdata, out string error)
{ {
totalcost = 0; totalcost = 0;
@ -87,11 +114,12 @@ namespace OpenSim.Region.ClientStack.Linden
// textures cost // textures cost
if (resources.texture_list != null && resources.texture_list.Array.Count > 0) if (resources.texture_list != null && resources.texture_list.Array.Count > 0)
{ {
int textures_cost = resources.texture_list.Array.Count; float textures_cost = (float)(resources.texture_list.Array.Count * basicCost);
textures_cost *= basicCost; textures_cost *= ModelTextureCostFactor;
meshcostdata.upload_price_breakdown.texture = textures_cost; itmp = (int)(textures_cost + 0.5f); // round
totalcost += textures_cost; meshcostdata.upload_price_breakdown.texture = itmp;
totalcost += itmp;
} }
// meshs assets cost // meshs assets cost
@ -176,12 +204,16 @@ namespace OpenSim.Region.ClientStack.Linden
if (meshcostdata.resource_cost < meshcostdata.simulation_cost) if (meshcostdata.resource_cost < meshcostdata.simulation_cost)
meshcostdata.resource_cost = meshcostdata.simulation_cost; meshcostdata.resource_cost = meshcostdata.simulation_cost;
// scale cost
// at this point a cost of 1.0 whould mean basic cost
meshsfee *= ModelMeshCostFactor;
if (meshsfee < ModelMinCost) if (meshsfee < ModelMinCostFactor)
meshsfee = ModelMinCost; meshsfee = ModelMinCostFactor;
// actually scale it to basic cost
meshsfee *= (float)basicCost;
// scale cost with basic cost changes relative to 10
meshsfee *= (float)basicCost / 10.0f;
meshsfee += 0.5f; // rounding meshsfee += 0.5f; // rounding
totalcost += (int)meshsfee; totalcost += (int)meshsfee;
@ -192,6 +224,7 @@ namespace OpenSim.Region.ClientStack.Linden
return true; return true;
} }
// single mesh asset cost
private bool MeshCost(byte[] data, ameshCostParam cost, out string error) private bool MeshCost(byte[] data, ameshCostParam cost, out string error)
{ {
cost.highLODSize = 0; cost.highLODSize = 0;
@ -377,6 +410,7 @@ namespace OpenSim.Region.ClientStack.Linden
return true; return true;
} }
// parses a LOD or physics mesh component
private bool submesh(byte[] data, int offset, int size, out int ntriangles) private bool submesh(byte[] data, int offset, int size, out int ntriangles)
{ {
ntriangles = 0; ntriangles = 0;
@ -443,6 +477,7 @@ namespace OpenSim.Region.ClientStack.Linden
return true; return true;
} }
// parses convex hulls component
private bool hulls(byte[] data, int offset, int size, out int nvertices, out int nhulls) private bool hulls(byte[] data, int offset, int size, out int nvertices, out int nhulls)
{ {
nvertices = 0; nvertices = 0;
@ -512,6 +547,7 @@ namespace OpenSim.Region.ClientStack.Linden
return true; return true;
} }
// returns streaming cost from on mesh LODs sizes in curCost and square of prim size length
private float streamingCost(ameshCostParam curCost, float sqdiam) private float streamingCost(ameshCostParam curCost, float sqdiam)
{ {
// compute efective areas // compute efective areas
@ -571,7 +607,6 @@ namespace OpenSim.Region.ClientStack.Linden
h = 16; h = 16;
// compute cost weighted by relative effective areas // compute cost weighted by relative effective areas
float cost = (float)lst * mlst + (float)l * ml + (float)m * mm + (float)h * mh; float cost = (float)lst * mlst + (float)l * ml + (float)m * mm + (float)h * mh;
cost /= ma; cost /= ma;