123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692 |
- /*
- * Copyright (c) Contributors, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the OpenSimulator Project nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Reflection;
- using System.Xml;
- using System.Xml.Schema;
- using System.Xml.Serialization;
- using System.Runtime.CompilerServices;
- using log4net;
- using OpenMetaverse;
- using OpenMetaverse.StructuredData;
- namespace OpenSim.Framework
- {
- public enum ProfileShape : byte
- {
- Circle = 0,
- Square = 1,
- IsometricTriangle = 2,
- EquilateralTriangle = 3,
- RightTriangle = 4,
- HalfCircle = 5
- }
- public enum HollowShape : byte
- {
- Same = 0,
- Circle = 16,
- Square = 32,
- Triangle = 48
- }
- public enum PCodeEnum : byte
- {
- Primitive = 9,
- Avatar = 47,
- Grass = 95,
- NewTree = 111,
- ParticleSystem = 143,
- Tree = 255
- }
- public enum Extrusion : byte
- {
- Straight = 16,
- Curve1 = 32,
- Curve2 = 48,
- Flexible = 128
- }
- [Serializable]
- public class PrimitiveBaseShape
- {
- private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
- private static readonly byte[] DEFAULT_TEXTURE = new Primitive.TextureEntry(new UUID("89556747-24cb-43ed-920b-47caed15465f")).GetBytes();
- private byte[] m_textureEntry;
- private ushort _pathBegin;
- private byte _pathCurve;
- private ushort _pathEnd;
- private sbyte _pathRadiusOffset;
- private byte _pathRevolutions;
- private byte _pathScaleX;
- private byte _pathScaleY;
- private byte _pathShearX;
- private byte _pathShearY;
- private sbyte _pathSkew;
- private sbyte _pathTaperX;
- private sbyte _pathTaperY;
- private sbyte _pathTwist;
- private sbyte _pathTwistBegin;
- private byte _pCode;
- private ushort _profileBegin;
- private ushort _profileEnd;
- private ushort _profileHollow;
- private Vector3 _scale;
- private byte _state;
- private byte _lastattach;
- private ProfileShape _profileShape;
- private HollowShape _hollowShape;
- //extra parameters Sculpted
- [XmlIgnore] private UUID _sculptTexture;
- [XmlIgnore] private byte _sculptType;
- [XmlIgnore] private byte[] _sculptData = Utils.EmptyBytes;
- //extra parameters Flexi
- [XmlIgnore] private int _flexiSoftness;
- [XmlIgnore] private float _flexiTension;
- [XmlIgnore] private float _flexiDrag;
- [XmlIgnore] private float _flexiGravity;
- [XmlIgnore] private float _flexiWind;
- [XmlIgnore] private float _flexiForceX;
- [XmlIgnore] private float _flexiForceY;
- [XmlIgnore] private float _flexiForceZ;
- //extra parameters light
- [XmlIgnore] private float _lightColorR;
- [XmlIgnore] private float _lightColorG;
- [XmlIgnore] private float _lightColorB;
- [XmlIgnore] private float _lightColorA = 1.0f;
- [XmlIgnore] private float _lightRadius;
- [XmlIgnore] private float _lightCutoff;
- [XmlIgnore] private float _lightFalloff;
- [XmlIgnore] private float _lightIntensity = 1.0f;
- //extra parameters Projection
- [XmlIgnore] private UUID _projectionTextureID;
- [XmlIgnore] private float _projectionFOV;
- [XmlIgnore] private float _projectionFocus;
- [XmlIgnore] private float _projectionAmb;
- //extra parameters extramesh/flag
- [XmlIgnore] private uint _meshFlags;
- [XmlIgnore] private bool _flexiEntry;
- [XmlIgnore] private bool _lightEntry;
- [XmlIgnore] private bool _sculptEntry;
- [XmlIgnore] private bool _projectionEntry;
- [XmlIgnore] private bool _meshFlagsEntry;
- [XmlIgnore]
- public Primitive.ReflectionProbe ReflectionProbe = null;
- [XmlIgnore]
- public Primitive.RenderMaterials RenderMaterials = null;
- public bool MeshFlagEntry
- {
- get { return _meshFlagsEntry; }
- }
- public bool AnimeshEnabled
- {
- get
- {
- return(_meshFlagsEntry &&
- (_meshFlags & 0x01) != 0 &&
- (_sculptType & 0x07) == (int)OpenMetaverse.SculptType.Mesh);
- }
- set
- {
- if((_sculptType & 0x07) != (int)OpenMetaverse.SculptType.Mesh)
- {
- _meshFlagsEntry = false;
- _meshFlags = 0;
- return;
- }
- if (value)
- {
- _meshFlagsEntry = true;
- _meshFlags |= 1;
- }
- else
- _meshFlags &= 0xfe;
- }
- }
- public byte ProfileCurve
- {
- get { return (byte)((byte)HollowShape | (byte)ProfileShape); }
- set
- {
- // Handle hollow shape component
- byte hollowShapeByte = (byte)(value & 0xf0);
- if (!Enum.IsDefined(typeof(HollowShape), hollowShapeByte))
- {
- m_log.WarnFormat(
- "[SHAPE]: Attempt to set a ProfileCurve with a hollow shape value of {0}, which isn't a valid enum. Replacing with default shape.",
- hollowShapeByte);
- _hollowShape = HollowShape.Same;
- }
- else
- {
- _hollowShape = (HollowShape)hollowShapeByte;
- }
- // Handle profile shape component
- byte profileShapeByte = (byte)(value & 0xf);
- if (!Enum.IsDefined(typeof(ProfileShape), profileShapeByte))
- {
- m_log.WarnFormat(
- "[SHAPE]: Attempt to set a ProfileCurve with a profile shape value of {0}, which isn't a valid enum. Replacing with square.",
- profileShapeByte);
- _profileShape = ProfileShape.Square;
- }
- else
- {
- _profileShape = (ProfileShape)profileShapeByte;
- }
- }
- }
- /// <summary>
- /// Entries to store media textures on each face
- /// </summary>
- /// Do not change this value directly - always do it through an IMoapModule.
- /// Lock before manipulating.
- public MediaList Media { get; set; }
- public PrimitiveBaseShape()
- {
- PCode = (byte)PCodeEnum.Primitive;
- m_textureEntry = DEFAULT_TEXTURE;
- }
- /// <summary>
- /// Construct a PrimitiveBaseShape object from a OpenMetaverse.Primitive object
- /// </summary>
- /// <param name="prim"></param>
- public PrimitiveBaseShape(Primitive prim)
- {
- //m_log.DebugFormat("[PRIMITIVE BASE SHAPE]: Creating from {0}", prim.ID);
- PCode = (byte)prim.PrimData.PCode;
- State = prim.PrimData.State;
- LastAttachPoint = prim.PrimData.State;
- PathBegin = Primitive.PackBeginCut(prim.PrimData.PathBegin);
- PathEnd = Primitive.PackEndCut(prim.PrimData.PathEnd);
- PathScaleX = Primitive.PackPathScale(prim.PrimData.PathScaleX);
- PathScaleY = Primitive.PackPathScale(prim.PrimData.PathScaleY);
- PathShearX = (byte)Primitive.PackPathShear(prim.PrimData.PathShearX);
- PathShearY = (byte)Primitive.PackPathShear(prim.PrimData.PathShearY);
- PathSkew = Primitive.PackPathTwist(prim.PrimData.PathSkew);
- ProfileBegin = Primitive.PackBeginCut(prim.PrimData.ProfileBegin);
- ProfileEnd = Primitive.PackEndCut(prim.PrimData.ProfileEnd);
- Scale = prim.Scale;
- PathCurve = (byte)prim.PrimData.PathCurve;
- ProfileCurve = (byte)prim.PrimData.ProfileCurve;
- ProfileHollow = Primitive.PackProfileHollow(prim.PrimData.ProfileHollow);
- PathRadiusOffset = Primitive.PackPathTwist(prim.PrimData.PathRadiusOffset);
- PathRevolutions = Primitive.PackPathRevolutions(prim.PrimData.PathRevolutions);
- PathTaperX = Primitive.PackPathTaper(prim.PrimData.PathTaperX);
- PathTaperY = Primitive.PackPathTaper(prim.PrimData.PathTaperY);
- PathTwist = Primitive.PackPathTwist(prim.PrimData.PathTwist);
- PathTwistBegin = Primitive.PackPathTwist(prim.PrimData.PathTwistBegin);
- m_textureEntry = prim.Textures.GetBytes();
- if (prim.Sculpt != null)
- {
- SculptEntry = (prim.Sculpt.Type != OpenMetaverse.SculptType.None);
- SculptData = prim.Sculpt.GetBytes();
- SculptTexture = prim.Sculpt.SculptTexture;
- SculptType = (byte)prim.Sculpt.Type;
- }
- else
- {
- SculptType = (byte)OpenMetaverse.SculptType.None;
- }
- }
- [XmlIgnore]
- public Primitive.TextureEntry Textures
- {
- get
- {
- //m_log.DebugFormat("[SHAPE]: get m_textureEntry length {0}", m_textureEntry.Length);
- try { return new Primitive.TextureEntry(m_textureEntry, 0, m_textureEntry.Length); }
- catch { }
- m_log.Warn("[SHAPE]: Failed to decode texture, length=" + ((m_textureEntry != null) ? m_textureEntry.Length : 0));
- return new Primitive.TextureEntry(UUID.Zero);
- }
- set { m_textureEntry = value.GetBytes(); }
- }
- public byte[] TextureEntry
- {
- get { return m_textureEntry; }
- set
- {
- if (value == null)
- m_textureEntry = new byte[1];
- else
- m_textureEntry = value;
- }
- }
- public static PrimitiveBaseShape Default
- {
- get
- {
- PrimitiveBaseShape boxShape = CreateBox();
- boxShape.SetScale(0.5f);
- return boxShape;
- }
- }
- public static PrimitiveBaseShape Create()
- {
- return new PrimitiveBaseShape();
- }
- public static PrimitiveBaseShape CreateBox()
- {
- PrimitiveBaseShape shape = new()
- {
- _pathCurve = (byte)Extrusion.Straight,
- _profileShape = ProfileShape.Square,
- _pathScaleX = 100,
- _pathScaleY = 100
- };
- return shape;
- }
- public static PrimitiveBaseShape CreateSphere()
- {
- PrimitiveBaseShape shape = new()
- {
- _pathCurve = (byte)Extrusion.Curve1,
- _profileShape = ProfileShape.HalfCircle,
- _pathScaleX = 100,
- _pathScaleY = 100
- };
- return shape;
- }
- public static PrimitiveBaseShape CreateCylinder()
- {
- PrimitiveBaseShape shape = new()
- {
- _pathCurve = (byte)Extrusion.Curve1,
- _profileShape = ProfileShape.Square,
- _pathScaleX = 100,
- _pathScaleY = 100
- };
- return shape;
- }
- public static PrimitiveBaseShape CreateMesh(int numberOfFaces, UUID meshAssetID)
- {
- PrimitiveBaseShape shape = new()
- {
- _pathScaleX = 100,
- _pathScaleY = 100
- };
- if (numberOfFaces <= 0) // oops ?
- numberOfFaces = 1;
- switch(numberOfFaces)
- {
- case 1: // torus
- shape.ProfileCurve = (byte)ProfileShape.Circle | (byte)HollowShape.Triangle;
- shape.PathCurve = (byte)Extrusion.Curve1;
- shape._pathScaleY = 150;
- break;
- case 2: // torus with hollow (a sl viewer whould see 4 faces on a hollow sphere)
- shape.ProfileCurve = (byte)ProfileShape.Circle | (byte)HollowShape.Triangle;
- shape.PathCurve = (byte)Extrusion.Curve1;
- shape.ProfileHollow = 27500;
- shape._pathScaleY = 150;
- break;
- case 3: // cylinder
- shape.ProfileCurve = (byte)ProfileShape.Circle | (byte)HollowShape.Triangle;
- shape.PathCurve = (byte)Extrusion.Straight;
- break;
- case 4: // cylinder with hollow
- shape.ProfileCurve = (byte)ProfileShape.Circle | (byte)HollowShape.Triangle;
- shape.PathCurve = (byte)Extrusion.Straight;
- shape.ProfileHollow = 27500;
- break;
- case 5: // prism
- shape.ProfileCurve = (byte)ProfileShape.EquilateralTriangle | (byte)HollowShape.Triangle;
- shape.PathCurve = (byte)Extrusion.Straight;
- break;
- case 6: // box
- shape.ProfileCurve = (byte)ProfileShape.Square | (byte)HollowShape.Triangle;
- shape.PathCurve = (byte)Extrusion.Straight;
- break;
- case 7: // box with hollow
- shape.ProfileCurve = (byte)ProfileShape.Square | (byte)HollowShape.Triangle;
- shape.PathCurve = (byte)Extrusion.Straight;
- shape.ProfileHollow = 27500;
- break;
- default: // 8 faces box with cut
- shape.ProfileCurve = (byte)ProfileShape.Square | (byte)HollowShape.Triangle;
- shape.PathCurve = (byte)Extrusion.Straight;
- shape.ProfileBegin = 9375;
- break;
- }
- shape.SculptEntry = true;
- shape.SculptType = (byte)OpenMetaverse.SculptType.Mesh;
- shape.SculptTexture = meshAssetID;
- return shape;
- }
- public void SetScale(float side)
- {
- _scale = new Vector3(side, side, side);
- }
- public void SetHeigth(float height)
- {
- _scale.Z = height;
- }
- public void SetRadius(float radius)
- {
- _scale.X = _scale.Y = radius * 2f;
- }
- // TODO: void returns need to change of course
- public virtual void GetMesh()
- {
- }
- public PrimitiveBaseShape Copy()
- {
- return (PrimitiveBaseShape) MemberwiseClone();
- }
- public static PrimitiveBaseShape CreateCylinder(float radius, float heigth)
- {
- PrimitiveBaseShape shape = CreateCylinder();
- shape.SetHeigth(heigth);
- shape.SetRadius(radius);
- return shape;
- }
- public void SetPathRange(Vector3 pathRange)
- {
- _pathBegin = Primitive.PackBeginCut(pathRange.X);
- _pathEnd = Primitive.PackEndCut(pathRange.Y);
- }
- public void SetPathRange(float begin, float end)
- {
- _pathBegin = Primitive.PackBeginCut(begin);
- _pathEnd = Primitive.PackEndCut(end);
- }
- public void SetSculptProperties(byte sculptType, UUID SculptTextureUUID)
- {
- _sculptType = sculptType;
- _sculptTexture = SculptTextureUUID;
- }
- public void SetProfileRange(Vector3 profileRange)
- {
- _profileBegin = Primitive.PackBeginCut(profileRange.X);
- _profileEnd = Primitive.PackEndCut(profileRange.Y);
- }
- public void SetProfileRange(float begin, float end)
- {
- _profileBegin = Primitive.PackBeginCut(begin);
- _profileEnd = Primitive.PackEndCut(end);
- }
- public byte[] ExtraParams
- {
- get
- {
- return ExtraParamsToBytes();
- }
- set
- {
- ReadInExtraParamsBytes(value);
- }
- }
- public ushort PathBegin
- {
- get { return _pathBegin; }
- set { _pathBegin = value; }
- }
- public byte PathCurve
- {
- get { return _pathCurve; }
- set { _pathCurve = value; }
- }
- public ushort PathEnd
- {
- get { return _pathEnd; }
- set { _pathEnd = value; }
- }
- public sbyte PathRadiusOffset
- {
- get { return _pathRadiusOffset; }
- set { _pathRadiusOffset = value; }
- }
- public byte PathRevolutions
- {
- get { return _pathRevolutions; }
- set { _pathRevolutions = value; }
- }
- public byte PathScaleX
- {
- get { return _pathScaleX; }
- set { _pathScaleX = value; }
- }
- public byte PathScaleY
- {
- get { return _pathScaleY; }
- set { _pathScaleY = value; }
- }
- public byte PathShearX
- {
- get { return _pathShearX; }
- set { _pathShearX = value; }
- }
- public byte PathShearY
- {
- get { return _pathShearY; }
- set { _pathShearY = value; }
- }
- public sbyte PathSkew
- {
- get { return _pathSkew; }
- set { _pathSkew = value; }
- }
- public sbyte PathTaperX
- {
- get { return _pathTaperX; }
- set { _pathTaperX = value; }
- }
- public sbyte PathTaperY
- {
- get { return _pathTaperY; }
- set { _pathTaperY = value; }
- }
- public sbyte PathTwist
- {
- get { return _pathTwist; }
- set { _pathTwist = value; }
- }
- public sbyte PathTwistBegin
- {
- get { return _pathTwistBegin; }
- set { _pathTwistBegin = value; }
- }
- public byte PCode
- {
- get { return _pCode; }
- set { _pCode = value; }
- }
- public ushort ProfileBegin
- {
- get { return _profileBegin; }
- set { _profileBegin = value; }
- }
- public ushort ProfileEnd
- {
- get { return _profileEnd; }
- set { _profileEnd = value; }
- }
- public ushort ProfileHollow
- {
- get { return _profileHollow; }
- set { _profileHollow = value; }
- }
- public Vector3 Scale
- {
- get { return _scale; }
- set { _scale = value; }
- }
- public byte State
- {
- get { return _state; }
- set { _state = value; }
- }
- public byte LastAttachPoint
- {
- get { return _lastattach; }
- set { _lastattach = value; }
- }
- public ProfileShape ProfileShape
- {
- get { return _profileShape; }
- set { _profileShape = value; }
- }
- public HollowShape HollowShape
- {
- get { return _hollowShape; }
- set { _hollowShape = value; }
- }
- public UUID SculptTexture
- {
- get { return _sculptTexture; }
- set { _sculptTexture = value; }
- }
- public byte SculptType
- {
- get { return _sculptType; }
- set { _sculptType = value; }
- }
- // This is only used at runtime. For sculpties this holds the texture data, and for meshes
- // the mesh data.
- public byte[] SculptData
- {
- get { return _sculptData; }
- set { _sculptData = value; }
- }
- public int FlexiSoftness
- {
- get { return _flexiSoftness; }
- set { _flexiSoftness = value; }
- }
- public float FlexiTension
- {
- get { return _flexiTension; }
- set { _flexiTension = value; }
- }
- public float FlexiDrag
- {
- get { return _flexiDrag; }
- set { _flexiDrag = value; }
- }
- public float FlexiGravity
- {
- get { return _flexiGravity; }
- set { _flexiGravity = value; }
- }
- public float FlexiWind
- {
- get { return _flexiWind; }
- set { _flexiWind = value; }
- }
- public float FlexiForceX
- {
- get { return _flexiForceX; }
- set { _flexiForceX = value; }
- }
- public float FlexiForceY
- {
- get { return _flexiForceY; }
- set { _flexiForceY = value; }
- }
- public float FlexiForceZ
- {
- get { return _flexiForceZ; }
- set { _flexiForceZ = value; }
- }
- public float LightColorR
- {
- get { return _lightColorR; }
- set
- {
- if (value < 0)
- _lightColorR = 0;
- else if (value > 1.0f)
- _lightColorR = 1.0f;
- else
- _lightColorR = value;
- }
- }
- public float LightColorG
- {
- get { return _lightColorG; }
- set
- {
- if (value < 0)
- _lightColorG = 0;
- else if (value > 1.0f)
- _lightColorG = 1.0f;
- else
- _lightColorG = value;
- }
- }
- public float LightColorB
- {
- get { return _lightColorB; }
- set
- {
- if (value < 0)
- _lightColorB = 0;
- else if (value > 1.0f)
- _lightColorB = 1.0f;
- else
- _lightColorB = value;
- }
- }
- public float LightColorA
- {
- get { return _lightColorA; }
- set
- {
- if (value < 0)
- _lightColorA = 0;
- else if (value > 1.0f)
- _lightColorA = 1.0f;
- else
- _lightColorA = value;
- }
- }
- public float LightRadius
- {
- get { return _lightRadius; }
- set { _lightRadius = value; }
- }
- public float LightCutoff
- {
- get { return _lightCutoff; }
- set { _lightCutoff = value; }
- }
- public float LightFalloff
- {
- get { return _lightFalloff; }
- set { _lightFalloff = value; }
- }
- public float LightIntensity
- {
- get { return _lightIntensity; }
- set { _lightIntensity = value; }
- }
- // only means we do have flexi data
- public bool FlexiEntry
- {
- get { return _flexiEntry; }
- set { _flexiEntry = value; }
- }
- public bool LightEntry
- {
- get { return _lightEntry; }
- set { _lightEntry = value; }
- }
- public bool SculptEntry
- {
- get { return _sculptEntry; }
- set { _sculptEntry = value; }
- }
- public bool ProjectionEntry
- {
- get { return _projectionEntry; }
- set { _projectionEntry = value; }
- }
- public UUID ProjectionTextureUUID
- {
- get { return _projectionTextureID; }
- set { _projectionTextureID = value; }
- }
- public float ProjectionFOV
- {
- get { return _projectionFOV; }
- set { _projectionFOV = value; }
- }
- public float ProjectionFocus
- {
- get { return _projectionFocus; }
- set { _projectionFocus = value; }
- }
- public float ProjectionAmbiance
- {
- get { return _projectionAmb; }
- set { _projectionAmb = value; }
- }
- public ulong GetMeshKey(Vector3 size, float lod)
- {
- return GetMeshKey(size, lod, false);
- }
- public ulong GetMeshKey(Vector3 size, float lod, bool convex)
- {
- ulong hash = 5381;
- hash = djb2(hash, PathCurve);
- hash = djb2(hash, (byte)((byte)HollowShape | (byte)ProfileShape));
- hash = djb2(hash, PathBegin);
- hash = djb2(hash, PathEnd);
- hash = djb2(hash, PathScaleX);
- hash = djb2(hash, PathScaleY);
- hash = djb2(hash, PathShearX);
- hash = djb2(hash, PathShearY);
- hash = djb2(hash, (byte)PathTwist);
- hash = djb2(hash, (byte)PathTwistBegin);
- hash = djb2(hash, (byte)PathRadiusOffset);
- hash = djb2(hash, (byte)PathTaperX);
- hash = djb2(hash, (byte)PathTaperY);
- hash = djb2(hash, PathRevolutions);
- hash = djb2(hash, (byte)PathSkew);
- hash = djb2(hash, ProfileBegin);
- hash = djb2(hash, ProfileEnd);
- hash = djb2(hash, ProfileHollow);
- // TODO: Separate scale out from the primitive shape data (after
- // scaling is supported at the physics engine level)
- hash = djb2(hash, size.X);
- hash = djb2(hash, size.Y);
- hash = djb2(hash, size.Z);
-
- hash = djb2(hash, lod);
- // include sculpt UUID
- if (SculptEntry)
- {
- byte[] scaleBytes = this.SculptTexture.GetBytes();
- for (int i = 0; i < scaleBytes.Length; i++)
- hash = djb2(hash, scaleBytes[i]);
- }
- if(convex)
- hash = djb2(hash, 0xa5);
- return hash;
- }
- private static ulong djb2(ulong hash, byte c)
- {
- //return ((hash << 5) + hash) + (ulong)c;
- return 33 * hash + (ulong)c;
- }
- private static ulong djb2(ulong hash, ushort c)
- {
- //hash = ((hash << 5) + hash) + (ulong)((byte)c);
- //return ((hash << 5) + hash) + (ulong)(c >> 8);
- return 33 * hash + c;
- }
- private static ulong djb2(ulong hash, float c)
- {
- //hash = ((hash << 5) + hash) + (ulong)((byte)c);
- //return ((hash << 5) + hash) + (ulong)(c >> 8);
- return 33 * hash + (ulong)c.GetHashCode();
- }
- public unsafe byte[] ExtraParamsToBytes()
- {
- //m_log.DebugFormat("[EXTRAPARAMS]: Called ExtraParamsToBytes()");
- const byte FlexiEP = 0x10;
- const byte LightEP = 0x20;
- const byte SculptEP = 0x30;
- const byte ProjectionEP = 0x40;
- //const byte MeshEP = 0x60;
- const byte MeshFlagsEP = 0x70;
- const byte MaterialsEP = 0x80;
- const byte ReflectionProbeEP = 0x90;
- int TotalBytesLength = 1; // ExtraParamsNum
- uint ExtraParamsNum = 0;
- if (_flexiEntry)
- {
- ExtraParamsNum++;
- TotalBytesLength += 16 + 2 + 4;// data
- }
- if (_lightEntry)
- {
- ExtraParamsNum++;
- TotalBytesLength += 16 + 2 + 4; // data
- }
- if (_sculptEntry)
- {
- ExtraParamsNum++;
- TotalBytesLength += 17 + 2 + 4;// data
- }
- if (_projectionEntry)
- {
- ExtraParamsNum++;
- TotalBytesLength += 28 + 2 + 4; // data
- }
- if (_meshFlagsEntry)
- {
- ExtraParamsNum++;
- TotalBytesLength += 4 + 2 + 4; // data
- }
- if (ReflectionProbe != null)
- {
- ExtraParamsNum++;
- TotalBytesLength += 9 + 2 + 4; // data
- }
- bool hasRenderMaterials = RenderMaterials is not null && RenderMaterials.entries is not null && RenderMaterials.entries.Length > 0;
- if (hasRenderMaterials)
- {
- ExtraParamsNum++;
- TotalBytesLength += 1 + 17 * RenderMaterials.entries.Length + 2 + 4; // data
- }
- byte[] safeReturnBytes = new byte[TotalBytesLength];
- if(TotalBytesLength == 1)
- {
- safeReturnBytes[0] = 0;
- return safeReturnBytes;
- }
- fixed(byte* breturnBytes = &safeReturnBytes[0])
- {
- byte* returnBytes = breturnBytes;
- *returnBytes++ = (byte)ExtraParamsNum;
- if (_flexiEntry)
- {
- *returnBytes = FlexiEP; returnBytes += 2;// 2 bytes id code
- *returnBytes = 16; returnBytes += 4;// 4 bytes size
- // Softness is packed in the upper bits of tension and drag
- *returnBytes++ = (byte)(((_flexiSoftness & 2) << 6) | ((byte)(_flexiTension * 10.01f) & 0x7F));
- *returnBytes++ = (byte)(((_flexiSoftness & 1) << 7) | ((byte)(_flexiDrag * 10.01f) & 0x7F));
- *returnBytes++ = (byte)((_flexiGravity + 10.0f) * 10.01f);
- *returnBytes++ = (byte)(_flexiWind * 10.01f);
- Utils.FloatToBytes(_flexiForceX, returnBytes); returnBytes += 4;
- Utils.FloatToBytes(_flexiForceY, returnBytes); returnBytes += 4;
- Utils.FloatToBytes(_flexiForceZ, returnBytes); returnBytes += 4;
- }
- if (_lightEntry)
- {
- *returnBytes = LightEP; returnBytes += 2;
- *returnBytes = 16; returnBytes += 4;
- // Alpha channel in color is intensity
- *returnBytes++ = Utils.FloatZeroOneToByte(_lightColorR);
- *returnBytes++ = Utils.FloatZeroOneToByte(_lightColorG);
- *returnBytes++ = Utils.FloatZeroOneToByte(_lightColorB);
- *returnBytes++ = Utils.FloatZeroOneToByte(_lightIntensity);
- Utils.FloatToBytes(_lightRadius, returnBytes); returnBytes += 4;
- Utils.FloatToBytes(_lightCutoff, returnBytes); returnBytes += 4;
- Utils.FloatToBytes(_lightFalloff, returnBytes); returnBytes += 4;
- }
- if (_sculptEntry)
- {
- //if(_sculptType == 5)
- // *returnBytes = MeshEP; returnBytes += 2;
- //else
- *returnBytes = SculptEP; returnBytes += 2;
- *returnBytes = 17; returnBytes += 4;
- _sculptTexture.ToBytes(returnBytes); returnBytes += 16;
- *returnBytes++ = _sculptType;
- }
- if (_projectionEntry)
- {
- *returnBytes = ProjectionEP; returnBytes += 2;
- *returnBytes = 28; returnBytes += 4;
- _projectionTextureID.ToBytes(returnBytes); returnBytes += 16;
- Utils.FloatToBytes(_projectionFOV, returnBytes); returnBytes += 4;
- Utils.FloatToBytes(_projectionFocus, returnBytes); returnBytes += 4;
- Utils.FloatToBytes(_projectionAmb, returnBytes); returnBytes += 4;
- }
- if (_meshFlagsEntry)
- {
- *returnBytes = MeshFlagsEP; returnBytes += 2;
- *returnBytes = 4; returnBytes += 4;
- Utils.UIntToBytes(_meshFlags, returnBytes); returnBytes += 4;
- }
- if (ReflectionProbe != null)
- {
- *returnBytes = ReflectionProbeEP; returnBytes += 2;
- *returnBytes = 9; returnBytes += 4;
- Utils.FloatToBytes(ReflectionProbe.Ambiance, returnBytes); returnBytes += 4;
- Utils.FloatToBytes(ReflectionProbe.ClipDistance, returnBytes); returnBytes += 4;
- *returnBytes++ = ReflectionProbe.Flags;
- }
- if (hasRenderMaterials)
- {
- *returnBytes = MaterialsEP; returnBytes += 2;
- int len = 1 + 17 * RenderMaterials.entries.Length;
- *returnBytes++ = (byte)len;
- *returnBytes++ = (byte)(len >> 8);
- *returnBytes++ = (byte)(len >> 16);
- *returnBytes++ = (byte)(len >> 24);
- *returnBytes++ = (byte)RenderMaterials.entries.Length;
- for (int j = 0; j < RenderMaterials.entries.Length; ++j)
- {
- *returnBytes++ = RenderMaterials.entries[j].te_index;
- RenderMaterials.entries[j].id.ToBytes(returnBytes); returnBytes += 16;
- }
- }
- }
- return safeReturnBytes;
- }
- public void ReadInUpdateExtraParam(ushort type, bool inUse, byte[] data)
- {
- const ushort FlexiEP = 0x10;
- const ushort LightEP = 0x20;
- const ushort SculptEP = 0x30;
- const ushort ProjectionEP = 0x40;
- const ushort MeshEP = 0x60;
- const ushort MeshFlagsEP = 0x70;
- const ushort MaterialsEP = 0x80;
- const ushort ReflectionProbeEP = 0x90;
- switch (type)
- {
- case FlexiEP:
- if (!inUse)
- {
- _flexiEntry = false;
- return;
- }
- ReadFlexiData(data, 0);
- break;
- case LightEP:
- if (!inUse)
- {
- _lightEntry = false;
- return;
- }
- ReadLightData(data, 0);
- break;
- case MeshEP:
- case SculptEP:
- if (!inUse)
- {
- _sculptEntry = false;
- return;
- }
- ReadSculptData(data, 0);
- break;
- case ProjectionEP:
- if (!inUse)
- {
- _projectionEntry = false;
- return;
- }
- ReadProjectionData(data, 0);
- break;
- case MeshFlagsEP:
- if (!inUse)
- {
- _meshFlagsEntry = false;
- _meshFlags = 0;
- return;
- }
- ReadMeshFlagsData(data, 0);
- break;
- case ReflectionProbeEP:
- if (!inUse)
- {
- ReflectionProbe = null;
- return;
- }
- ReadReflectionProbe(data, 0);
- break;
- case MaterialsEP:
- if (!inUse)
- {
- RenderMaterials = null;
- return;
- }
- ReadRenderMaterials(data, 0, data.Length);
- break;
- }
- }
- public void ReadInExtraParamsBytes(byte[] data)
- {
- if (data == null)
- return;
- _flexiEntry = false;
- _lightEntry = false;
- _sculptEntry = false;
- _projectionEntry = false;
- _meshFlagsEntry = false;
- RenderMaterials = null;
- ReflectionProbe = null;
- if (data.Length == 1)
- return;
- const byte FlexiEP = 0x10;
- const byte LightEP = 0x20;
- const byte SculptEP = 0x30;
- const byte ProjectionEP = 0x40;
- const byte MeshEP = 0x60;
- const byte MeshFlagsEP = 0x70;
- const byte MaterialsEP = 0x80;
- const byte ReflectionProbeEP = 0x90;
- byte extraParamCount = data[0];
- int i = 1;
- for (int k = 0; k < extraParamCount; ++k)
- {
- byte epType = data[i];
- switch (epType)
- {
- case FlexiEP:
- i += 6;
- ReadFlexiData(data, i);
- i += 16;
- break;
- case LightEP:
- i += 6;
- ReadLightData(data, i);
- i += 16;
- break;
- case MeshEP:
- case SculptEP:
- i += 6;
- ReadSculptData(data, i);
- i += 17;
- break;
- case ProjectionEP:
- i += 6;
- ReadProjectionData(data, i);
- i += 28;
- break;
- case MeshFlagsEP:
- i += 6;
- ReadMeshFlagsData(data, i);
- i += 4;
- break;
- case ReflectionProbeEP:
- i += 6;
- ReadReflectionProbe(data, i);
- i += 9;
- break;
- case MaterialsEP:
- i += 2;
- if (data.Length - i >= 4)
- {
- int size = Utils.BytesToInt(data, i);
- i += 4;
- i += ReadRenderMaterials(data, i, size);
- }
- break;
- }
- }
- }
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ReadSculptData(byte[] data, int pos)
- {
- if (data.Length-pos >= 17)
- {
- _sculptTexture = new UUID(data, pos);
- _sculptType = data[pos + 16];
- _sculptEntry = true;
- }
- else
- {
- _sculptEntry = false;
- _sculptTexture = UUID.Zero;
- _sculptType = 0x00;
- }
- }
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ReadFlexiData(byte[] data, int pos)
- {
- if (data.Length-pos >= 16)
- {
- _flexiEntry = true;
- _flexiSoftness = ((data[pos] & 0x80) >> 6) | ((data[pos + 1] & 0x80) >> 7);
- _flexiTension = (float)(data[pos++] & 0x7F) / 10.0f;
- _flexiDrag = (float)(data[pos++] & 0x7F) / 10.0f;
- _flexiGravity = (float)(data[pos++] / 10.0f) - 10.0f;
- _flexiWind = (float)data[pos++] / 10.0f;
- _flexiForceX = Utils.BytesToFloat(data, pos);
- _flexiForceY = Utils.BytesToFloat(data, pos + 4);
- _flexiForceZ = Utils.BytesToFloat(data, pos + 8);
- }
- else
- {
- _flexiEntry = false;
- _flexiSoftness = 0;
- _flexiTension = 0.0f;
- _flexiDrag = 0.0f;
- _flexiGravity = 0.0f;
- _flexiWind = 0.0f;
- _flexiForceX = 0f;
- _flexiForceY = 0f;
- _flexiForceZ = 0f;
- }
- }
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ReadLightData(byte[] data, int pos)
- {
- if (data.Length - pos >= 16)
- {
- _lightEntry = true;
- Color4 lColor = new(data, pos, false);
- _lightIntensity = lColor.A;
- _lightColorA = 1f;
- _lightColorR = lColor.R;
- _lightColorG = lColor.G;
- _lightColorB = lColor.B;
- _lightRadius = Utils.BytesToFloat(data, pos + 4);
- _lightCutoff = Utils.BytesToFloat(data, pos + 8);
- _lightFalloff = Utils.BytesToFloat(data, pos + 12);
- }
- else
- {
- _lightEntry = false;
- _lightColorA = 1f;
- _lightColorR = 0f;
- _lightColorG = 0f;
- _lightColorB = 0f;
- _lightRadius = 0f;
- _lightCutoff = 0f;
- _lightFalloff = 0f;
- _lightIntensity = 0f;
- }
- }
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ReadProjectionData(byte[] data, int pos)
- {
- if (data.Length - pos >= 28)
- {
- _projectionEntry = true;
- _projectionTextureID = new UUID(data, pos);
- _projectionFOV = Utils.BytesToFloat(data, pos + 16);
- _projectionFocus = Utils.BytesToFloat(data, pos + 20);
- _projectionAmb = Utils.BytesToFloat(data, pos + 24);
- }
- else
- {
- _projectionEntry = false;
- _projectionTextureID = UUID.Zero;
- _projectionFOV = 0f;
- _projectionFocus = 0f;
- _projectionAmb = 0f;
- }
- }
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ReadMeshFlagsData(byte[] data, int pos)
- {
- _meshFlagsEntry = true;
- _meshFlags = data.Length - pos >= 4 ? Utils.BytesToUInt(data, pos) : 0;
- }
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ReadReflectionProbe(byte[] data, int pos)
- {
- if (data.Length - pos >= 9)
- {
- ReflectionProbe = new Primitive.ReflectionProbe
- {
- Ambiance = Utils.Clamp(Utils.BytesToFloat(data, pos), 0, 1.0f),
- ClipDistance = Utils.Clamp(Utils.BytesToFloat(data, pos + 4), 0, 1024f),
- Flags = data[pos + 8]
- };
- }
- }
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public int ReadRenderMaterials(byte[] data, int pos, int size)
- {
- if (size > 17)
- {
- int count = data[pos];
- ++pos;
- if (size >= 1 + 17 * count)
- {
- var entries = new Primitive.RenderMaterials.RenderMaterialEntry[count];
- for (int i = 0; i < count; ++i)
- {
- entries[i].te_index = data[pos++];
- entries[i].id = new UUID(data, pos);
- pos += 16;
- }
- RenderMaterials ??= new Primitive.RenderMaterials();
- RenderMaterials.entries = entries;
- }
- }
- return size + 4;
- }
- /// <summary>
- /// Creates a OpenMetaverse.Primitive and populates it with converted PrimitiveBaseShape values
- /// </summary>
- /// <returns></returns>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Primitive ToOmvPrimitive()
- {
- // position and rotation defaults here since they are not available in PrimitiveBaseShape
- return ToOmvPrimitive(new Vector3(0.0f, 0.0f, 0.0f),
- new Quaternion(0.0f, 0.0f, 0.0f, 1.0f));
- }
- /// <summary>
- /// Creates a OpenMetaverse.Primitive and populates it with converted PrimitiveBaseShape values
- /// </summary>
- /// <param name="position"></param>
- /// <param name="rotation"></param>
- /// <returns></returns>
- public Primitive ToOmvPrimitive(Vector3 position, Quaternion rotation)
- {
- OpenMetaverse.Primitive prim = new()
- {
- Scale = this.Scale,
- Position = position,
- Rotation = rotation
- };
- if (SculptEntry)
- {
- prim.Sculpt = new Primitive.SculptData
- {
- Type = (SculptType)SculptType,
- SculptTexture = SculptTexture
- };
- }
- prim.PrimData.PathShearX = PathShearX < 128 ? (float)PathShearX * 0.01f : (float)(PathShearX - 256) * 0.01f;
- prim.PrimData.PathShearY = PathShearY < 128 ? (float)PathShearY * 0.01f : (float)(PathShearY - 256) * 0.01f;
- prim.PrimData.PathBegin = (float)PathBegin * 2.0e-5f;
- prim.PrimData.PathEnd = 1.0f - (float)PathEnd * 2.0e-5f;
- prim.PrimData.PathScaleX = (200 - PathScaleX) * 0.01f;
- prim.PrimData.PathScaleY = (200 - PathScaleY) * 0.01f;
- prim.PrimData.PathTaperX = PathTaperX * 0.01f;
- prim.PrimData.PathTaperY = PathTaperY * 0.01f;
- prim.PrimData.PathTwistBegin = PathTwistBegin * 0.01f;
- prim.PrimData.PathTwist = PathTwist * 0.01f;
- prim.PrimData.ProfileBegin = (float)ProfileBegin * 2.0e-5f;
- prim.PrimData.ProfileEnd = 1.0f - (float)ProfileEnd * 2.0e-5f;
- prim.PrimData.ProfileHollow = (float)ProfileHollow * 2.0e-5f;
- prim.PrimData.profileCurve = ProfileCurve;
- prim.PrimData.ProfileHole = (HoleType)HollowShape;
- prim.PrimData.PathCurve = (PathCurve)PathCurve;
- prim.PrimData.PathRadiusOffset = 0.01f * PathRadiusOffset;
- prim.PrimData.PathRevolutions = 1.0f + 0.015f * PathRevolutions;
- prim.PrimData.PathSkew = 0.01f * PathSkew;
- prim.PrimData.PCode = OpenMetaverse.PCode.Prim;
- prim.PrimData.State = 0;
- if (FlexiEntry)
- {
- prim.Flexible = new Primitive.FlexibleData
- {
- Drag = FlexiDrag,
- Force = new Vector3(FlexiForceX, FlexiForceY, FlexiForceZ),
- Gravity = FlexiGravity,
- Softness = FlexiSoftness,
- Tension = FlexiTension,
- Wind = FlexiWind
- };
- }
- if (LightEntry)
- {
- prim.Light = new Primitive.LightData
- {
- Color = new Color4(LightColorR, LightColorG, LightColorB, LightColorA),
- Cutoff = LightCutoff,
- Falloff = LightFalloff,
- Intensity = LightIntensity,
- Radius = LightRadius
- };
- }
- prim.Textures = Textures;
- prim.Properties = new Primitive.ObjectProperties
- {
- Name = "Object",
- Description = "",
- CreatorID = UUID.Zero,
- GroupID = UUID.Zero,
- OwnerID = UUID.Zero,
- Permissions = new Permissions(),
- SalePrice = 10,
- SaleType = new SaleType()
- };
- return prim;
- }
- public byte[] RenderMaterialsOvrToRawBin()
- {
- // byte: number of entries
- // repeat:
- // byte; entry face index
- // byte; low entry override utf8 length
- // byte: high entry override utf8 length
- // utf8 bytes: override
- if (RenderMaterials is null)
- return null;
- if (RenderMaterials.overrides is null || RenderMaterials.overrides.Length == 0)
- return new byte[] { 0 }; // store so outdated viewer caches can be updated
- int nentries = 0;
- for (int i = 0; i < RenderMaterials.overrides.Length; i++)
- {
- if (!string.IsNullOrEmpty(RenderMaterials.overrides[i].data))
- nentries++;
- }
- if(nentries == 0)
- return new byte[] { 0 };
- osUTF8 sb = OSUTF8Cached.Acquire();
- sb.Append((byte)nentries);
- for (int i = 0; i < RenderMaterials.overrides.Length; i++)
- {
- if (string.IsNullOrEmpty(RenderMaterials.overrides[i].data))
- continue;
- sb.Append(RenderMaterials.overrides[i].te_index);
- int len = RenderMaterials.overrides[i].data.Length;
- sb.Append((byte)(len & 0xff));
- sb.Append((byte)((len >> 8) & 0xff));
- sb.Append(RenderMaterials.overrides[i].data);
- }
- return OSUTF8Cached.GetArrayAndRelease(sb);
- }
- public void RenderMaterialsOvrFromRawBin(byte[] data)
- {
- if (RenderMaterials is not null && RenderMaterials.overrides is not null)
- RenderMaterials.overrides = null;
- if (data is null || data.Length < 1)
- return;
- int nentries = data[0];
- if (nentries > 128)
- return;
- if (nentries == 0) // for outdated viewer caches
- {
- RenderMaterials ??= new Primitive.RenderMaterials();
- return;
- }
- int indx = 1;
- Primitive.RenderMaterials.RenderMaterialOverrideEntry[] overrides = new Primitive.RenderMaterials.RenderMaterialOverrideEntry[nentries];
- try
- {
- for(int i = 0; i < overrides.Length; i++)
- {
- overrides[i].te_index = data[indx++];
- int ovrlen = data[indx++];
- ovrlen += data[indx++] << 8;
- overrides[i].data = Utils.BytesToString(data,indx, ovrlen);
- if(overrides[i].data.StartsWith("{\"asset")) // ignore old test data
- return;
- indx += ovrlen;
- }
- }
- catch
- {
- return;
- }
- RenderMaterials ??= new Primitive.RenderMaterials();
- RenderMaterials.overrides = overrides;
- }
- /// <summary>
- /// Encapsulates a list of media entries.
- /// </summary>
- /// This class is necessary because we want to replace auto-serialization of MediaEntry with something more
- /// OSD like and less vulnerable to change.
- public class MediaList : List<MediaEntry>, IXmlSerializable
- {
- public const string MEDIA_TEXTURE_TYPE = "sl";
- public MediaList() : base() {}
- public MediaList(IEnumerable<MediaEntry> collection) : base(collection) {}
- public MediaList(int capacity) : base(capacity) {}
- public XmlSchema GetSchema()
- {
- return null;
- }
- public string ToXml()
- {
- lock (this)
- {
- using (StringWriter sw = new())
- {
- using (XmlTextWriter xtw = new(sw))
- {
- xtw.WriteStartElement("OSMedia");
- xtw.WriteAttributeString("type", MEDIA_TEXTURE_TYPE);
- xtw.WriteAttributeString("version", "0.1");
- OSDArray meArray = new();
- foreach (MediaEntry me in this)
- {
- OSD osd = (null == me ? new OSD() : me.GetOSD());
- meArray.Add(osd);
- }
- xtw.WriteStartElement("OSData");
- xtw.WriteRaw(OSDParser.SerializeLLSDXmlString(meArray));
- xtw.WriteEndElement();
- xtw.WriteEndElement();
- xtw.Flush();
- return sw.ToString();
- }
- }
- }
- }
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void WriteXml(XmlWriter writer)
- {
- writer.WriteRaw(ToXml());
- }
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static MediaList FromXml(string rawXml)
- {
- MediaList ml = new();
- ml.ReadXml(rawXml);
- if(ml.Count == 0)
- return null;
- return ml;
- }
- public void ReadXml(string rawXml)
- {
- try
- {
- using (StringReader sr = new(rawXml))
- {
- using (XmlTextReader xtr = new(sr))
- {
- xtr.DtdProcessing = DtdProcessing.Ignore;
- xtr.MoveToContent();
- string type = xtr.GetAttribute("type");
- //m_log.DebugFormat("[MOAP]: Loaded media texture entry with type {0}", type);
- if (type != MEDIA_TEXTURE_TYPE)
- return;
- xtr.ReadStartElement("OSMedia");
- OSD osdp = OSDParser.DeserializeLLSDXml(xtr.ReadInnerXml());
- if(osdp is not OSDArray osdMeArray)
- return;
- if(osdMeArray.Count == 0)
- return;
- foreach (OSD osdMe in osdMeArray)
- {
- MediaEntry me = (osdMe is OSDMap ? MediaEntry.FromOSD(osdMe) : new MediaEntry());
- Add(me);
- }
- }
- }
- }
- catch
- {
- m_log.Debug("PrimitiveBaseShape] error decoding MOAP xml" );
- }
- }
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ReadXml(XmlReader reader)
- {
- if (reader.IsEmptyElement)
- return;
- ReadXml(reader.ReadInnerXml());
- }
- }
- }
- }
|