OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
PrimitiveBaseShape.cs
Go to the documentation of this file.
1 /*
2  * Copyright (c) Contributors, http://opensimulator.org/
3  * See CONTRIBUTORS.TXT for a full list of copyright holders.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of the OpenSimulator Project nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 using System;
29 using System.Collections.Generic;
30 using System.Drawing;
31 using System.Drawing.Imaging;
32 using System.IO;
33 using System.Reflection;
34 using System.Xml;
35 using System.Xml.Schema;
36 using System.Xml.Serialization;
37 using log4net;
38 using OpenMetaverse;
39 using OpenMetaverse.StructuredData;
40 
41 namespace OpenSim.Framework
42 {
43  public enum ProfileShape : byte
44  {
45  Circle = 0,
46  Square = 1,
49  RightTriangle = 4,
50  HalfCircle = 5
51  }
52 
53  public enum HollowShape : byte
54  {
55  Same = 0,
56  Circle = 16,
57  Square = 32,
58  Triangle = 48
59  }
60 
61  public enum PCodeEnum : byte
62  {
63  Primitive = 9,
64  Avatar = 47,
65  Grass = 95,
66  NewTree = 111,
67  ParticleSystem = 143,
68  Tree = 255
69  }
70 
71  public enum Extrusion : byte
72  {
73  Straight = 16,
74  Curve1 = 32,
75  Curve2 = 48,
76  Flexible = 128
77  }
78 
79  [Serializable]
80  public class PrimitiveBaseShape
81  {
82  private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
83 
84  private static readonly byte[] DEFAULT_TEXTURE = new Primitive.TextureEntry(new UUID("89556747-24cb-43ed-920b-47caed15465f")).GetBytes();
85 
86  private byte[] m_textureEntry;
87 
88  private ushort _pathBegin;
89  private byte _pathCurve;
90  private ushort _pathEnd;
91  private sbyte _pathRadiusOffset;
92  private byte _pathRevolutions;
93  private byte _pathScaleX;
94  private byte _pathScaleY;
95  private byte _pathShearX;
96  private byte _pathShearY;
97  private sbyte _pathSkew;
98  private sbyte _pathTaperX;
99  private sbyte _pathTaperY;
100  private sbyte _pathTwist;
101  private sbyte _pathTwistBegin;
102  private byte _pCode;
103  private ushort _profileBegin;
104  private ushort _profileEnd;
105  private ushort _profileHollow;
106  private Vector3 _scale;
107  private byte _state;
108  private byte _lastattach;
109  private ProfileShape _profileShape;
110  private HollowShape _hollowShape;
111 
112  // Sculpted
113  [XmlIgnore] private UUID _sculptTexture;
114  [XmlIgnore] private byte _sculptType;
115  [XmlIgnore] private byte[] _sculptData = Utils.EmptyBytes;
116 
117  // Flexi
118  [XmlIgnore] private int _flexiSoftness;
119  [XmlIgnore] private float _flexiTension;
120  [XmlIgnore] private float _flexiDrag;
121  [XmlIgnore] private float _flexiGravity;
122  [XmlIgnore] private float _flexiWind;
123  [XmlIgnore] private float _flexiForceX;
124  [XmlIgnore] private float _flexiForceY;
125  [XmlIgnore] private float _flexiForceZ;
126 
127  //Bright n sparkly
128  [XmlIgnore] private float _lightColorR;
129  [XmlIgnore] private float _lightColorG;
130  [XmlIgnore] private float _lightColorB;
131  [XmlIgnore] private float _lightColorA = 1.0f;
132  [XmlIgnore] private float _lightRadius;
133  [XmlIgnore] private float _lightCutoff;
134  [XmlIgnore] private float _lightFalloff;
135  [XmlIgnore] private float _lightIntensity = 1.0f;
136  [XmlIgnore] private bool _flexiEntry;
137  [XmlIgnore] private bool _lightEntry;
138  [XmlIgnore] private bool _sculptEntry;
139 
140  // Light Projection Filter
141  [XmlIgnore] private bool _projectionEntry;
142  [XmlIgnore] private UUID _projectionTextureID;
143  [XmlIgnore] private float _projectionFOV;
144  [XmlIgnore] private float _projectionFocus;
145  [XmlIgnore] private float _projectionAmb;
146 
147  public byte ProfileCurve
148  {
149  get { return (byte)((byte)HollowShape | (byte)ProfileShape); }
150 
151  set
152  {
153  // Handle hollow shape component
154  byte hollowShapeByte = (byte)(value & 0xf0);
155 
156  if (!Enum.IsDefined(typeof(HollowShape), hollowShapeByte))
157  {
158  m_log.WarnFormat(
159  "[SHAPE]: Attempt to set a ProfileCurve with a hollow shape value of {0}, which isn't a valid enum. Replacing with default shape.",
160  hollowShapeByte);
161 
162  this._hollowShape = HollowShape.Same;
163  }
164  else
165  {
166  this._hollowShape = (HollowShape)hollowShapeByte;
167  }
168 
169  // Handle profile shape component
170  byte profileShapeByte = (byte)(value & 0xf);
171 
172  if (!Enum.IsDefined(typeof(ProfileShape), profileShapeByte))
173  {
174  m_log.WarnFormat(
175  "[SHAPE]: Attempt to set a ProfileCurve with a profile shape value of {0}, which isn't a valid enum. Replacing with square.",
176  profileShapeByte);
177 
178  this._profileShape = ProfileShape.Square;
179  }
180  else
181  {
182  this._profileShape = (ProfileShape)profileShapeByte;
183  }
184  }
185  }
186 
192  public MediaList Media { get; set; }
193 
195  {
196  PCode = (byte)PCodeEnum.Primitive;
197  m_textureEntry = DEFAULT_TEXTURE;
198  }
199 
204  public PrimitiveBaseShape(Primitive prim)
205  {
206 // m_log.DebugFormat("[PRIMITIVE BASE SHAPE]: Creating from {0}", prim.ID);
207 
208  PCode = (byte)prim.PrimData.PCode;
209 
210  State = prim.PrimData.State;
211  LastAttachPoint = prim.PrimData.State;
212  PathBegin = Primitive.PackBeginCut(prim.PrimData.PathBegin);
213  PathEnd = Primitive.PackEndCut(prim.PrimData.PathEnd);
214  PathScaleX = Primitive.PackPathScale(prim.PrimData.PathScaleX);
215  PathScaleY = Primitive.PackPathScale(prim.PrimData.PathScaleY);
216  PathShearX = (byte)Primitive.PackPathShear(prim.PrimData.PathShearX);
217  PathShearY = (byte)Primitive.PackPathShear(prim.PrimData.PathShearY);
218  PathSkew = Primitive.PackPathTwist(prim.PrimData.PathSkew);
219  ProfileBegin = Primitive.PackBeginCut(prim.PrimData.ProfileBegin);
220  ProfileEnd = Primitive.PackEndCut(prim.PrimData.ProfileEnd);
221  Scale = prim.Scale;
222  PathCurve = (byte)prim.PrimData.PathCurve;
223  ProfileCurve = (byte)prim.PrimData.ProfileCurve;
224  ProfileHollow = Primitive.PackProfileHollow(prim.PrimData.ProfileHollow);
225  PathRadiusOffset = Primitive.PackPathTwist(prim.PrimData.PathRadiusOffset);
226  PathRevolutions = Primitive.PackPathRevolutions(prim.PrimData.PathRevolutions);
227  PathTaperX = Primitive.PackPathTaper(prim.PrimData.PathTaperX);
228  PathTaperY = Primitive.PackPathTaper(prim.PrimData.PathTaperY);
229  PathTwist = Primitive.PackPathTwist(prim.PrimData.PathTwist);
230  PathTwistBegin = Primitive.PackPathTwist(prim.PrimData.PathTwistBegin);
231 
232  m_textureEntry = prim.Textures.GetBytes();
233 
234  if (prim.Sculpt != null)
235  {
236  SculptEntry = (prim.Sculpt.Type != OpenMetaverse.SculptType.None);
237  SculptData = prim.Sculpt.GetBytes();
238  SculptTexture = prim.Sculpt.SculptTexture;
239  SculptType = (byte)prim.Sculpt.Type;
240  }
241  else
242  {
243  SculptType = (byte)OpenMetaverse.SculptType.None;
244  }
245  }
246 
247  [XmlIgnore]
248  public Primitive.TextureEntry Textures
249  {
250  get
251  {
252 // m_log.DebugFormat("[SHAPE]: get m_textureEntry length {0}", m_textureEntry.Length);
253  try { return new Primitive.TextureEntry(m_textureEntry, 0, m_textureEntry.Length); }
254  catch { }
255 
256  m_log.Warn("[SHAPE]: Failed to decode texture, length=" + ((m_textureEntry != null) ? m_textureEntry.Length : 0));
257  return new Primitive.TextureEntry(UUID.Zero);
258  }
259 
260  set { m_textureEntry = value.GetBytes(); }
261  }
262 
263  public byte[] TextureEntry
264  {
265  get { return m_textureEntry; }
266 
267  set
268  {
269  if (value == null)
270  m_textureEntry = new byte[1];
271  else
272  m_textureEntry = value;
273  }
274  }
275 
276  public static PrimitiveBaseShape Default
277  {
278  get
279  {
280  PrimitiveBaseShape boxShape = CreateBox();
281 
282  boxShape.SetScale(0.5f);
283 
284  return boxShape;
285  }
286  }
287 
288  public static PrimitiveBaseShape Create()
289  {
291  return shape;
292  }
293 
295  {
296  PrimitiveBaseShape shape = Create();
297 
298  shape._pathCurve = (byte) Extrusion.Straight;
299  shape._profileShape = ProfileShape.Square;
300  shape._pathScaleX = 100;
301  shape._pathScaleY = 100;
302 
303  return shape;
304  }
305 
307  {
308  PrimitiveBaseShape shape = Create();
309 
310  shape._pathCurve = (byte) Extrusion.Curve1;
311  shape._profileShape = ProfileShape.HalfCircle;
312  shape._pathScaleX = 100;
313  shape._pathScaleY = 100;
314 
315  return shape;
316  }
317 
319  {
320  PrimitiveBaseShape shape = Create();
321 
322  shape._pathCurve = (byte) Extrusion.Curve1;
323  shape._profileShape = ProfileShape.Square;
324 
325  shape._pathScaleX = 100;
326  shape._pathScaleY = 100;
327 
328  return shape;
329  }
330 
331  public void SetScale(float side)
332  {
333  _scale = new Vector3(side, side, side);
334  }
335 
336  public void SetHeigth(float height)
337  {
338  _scale.Z = height;
339  }
340 
341  public void SetRadius(float radius)
342  {
343  _scale.X = _scale.Y = radius * 2f;
344  }
345 
346  // TODO: void returns need to change of course
347  public virtual void GetMesh()
348  {
349  }
350 
352  {
353  return (PrimitiveBaseShape) MemberwiseClone();
354  }
355 
356  public static PrimitiveBaseShape CreateCylinder(float radius, float heigth)
357  {
358  PrimitiveBaseShape shape = CreateCylinder();
359 
360  shape.SetHeigth(heigth);
361  shape.SetRadius(radius);
362 
363  return shape;
364  }
365 
366  public void SetPathRange(Vector3 pathRange)
367  {
368  _pathBegin = Primitive.PackBeginCut(pathRange.X);
369  _pathEnd = Primitive.PackEndCut(pathRange.Y);
370  }
371 
372  public void SetPathRange(float begin, float end)
373  {
374  _pathBegin = Primitive.PackBeginCut(begin);
375  _pathEnd = Primitive.PackEndCut(end);
376  }
377 
378  public void SetSculptProperties(byte sculptType, UUID SculptTextureUUID)
379  {
380  _sculptType = sculptType;
381  _sculptTexture = SculptTextureUUID;
382  }
383 
384  public void SetProfileRange(Vector3 profileRange)
385  {
386  _profileBegin = Primitive.PackBeginCut(profileRange.X);
387  _profileEnd = Primitive.PackEndCut(profileRange.Y);
388  }
389 
390  public void SetProfileRange(float begin, float end)
391  {
392  _profileBegin = Primitive.PackBeginCut(begin);
393  _profileEnd = Primitive.PackEndCut(end);
394  }
395 
396  public byte[] ExtraParams
397  {
398  get
399  {
400  return ExtraParamsToBytes();
401  }
402  set
403  {
404  ReadInExtraParamsBytes(value);
405  }
406  }
407 
408  public ushort PathBegin {
409  get {
410  return _pathBegin;
411  }
412  set {
413  _pathBegin = value;
414  }
415  }
416 
417  public byte PathCurve {
418  get {
419  return _pathCurve;
420  }
421  set {
422  _pathCurve = value;
423  }
424  }
425 
426  public ushort PathEnd {
427  get {
428  return _pathEnd;
429  }
430  set {
431  _pathEnd = value;
432  }
433  }
434 
435  public sbyte PathRadiusOffset {
436  get {
437  return _pathRadiusOffset;
438  }
439  set {
440  _pathRadiusOffset = value;
441  }
442  }
443 
444  public byte PathRevolutions {
445  get {
446  return _pathRevolutions;
447  }
448  set {
449  _pathRevolutions = value;
450  }
451  }
452 
453  public byte PathScaleX {
454  get {
455  return _pathScaleX;
456  }
457  set {
458  _pathScaleX = value;
459  }
460  }
461 
462  public byte PathScaleY {
463  get {
464  return _pathScaleY;
465  }
466  set {
467  _pathScaleY = value;
468  }
469  }
470 
471  public byte PathShearX {
472  get {
473  return _pathShearX;
474  }
475  set {
476  _pathShearX = value;
477  }
478  }
479 
480  public byte PathShearY {
481  get {
482  return _pathShearY;
483  }
484  set {
485  _pathShearY = value;
486  }
487  }
488 
489  public sbyte PathSkew {
490  get {
491  return _pathSkew;
492  }
493  set {
494  _pathSkew = value;
495  }
496  }
497 
498  public sbyte PathTaperX {
499  get {
500  return _pathTaperX;
501  }
502  set {
503  _pathTaperX = value;
504  }
505  }
506 
507  public sbyte PathTaperY {
508  get {
509  return _pathTaperY;
510  }
511  set {
512  _pathTaperY = value;
513  }
514  }
515 
516  public sbyte PathTwist {
517  get {
518  return _pathTwist;
519  }
520  set {
521  _pathTwist = value;
522  }
523  }
524 
525  public sbyte PathTwistBegin {
526  get {
527  return _pathTwistBegin;
528  }
529  set {
530  _pathTwistBegin = value;
531  }
532  }
533 
534  public byte PCode {
535  get {
536  return _pCode;
537  }
538  set {
539  _pCode = value;
540  }
541  }
542 
543  public ushort ProfileBegin {
544  get {
545  return _profileBegin;
546  }
547  set {
548  _profileBegin = value;
549  }
550  }
551 
552  public ushort ProfileEnd {
553  get {
554  return _profileEnd;
555  }
556  set {
557  _profileEnd = value;
558  }
559  }
560 
561  public ushort ProfileHollow {
562  get {
563  return _profileHollow;
564  }
565  set {
566  _profileHollow = value;
567  }
568  }
569 
570  public Vector3 Scale {
571  get {
572  return _scale;
573  }
574  set {
575  _scale = value;
576  }
577  }
578 
579  public byte State {
580  get {
581  return _state;
582  }
583  set {
584  _state = value;
585  }
586  }
587 
588  public byte LastAttachPoint {
589  get {
590  return _lastattach;
591  }
592  set {
593  _lastattach = value;
594  }
595  }
596 
598  get {
599  return _profileShape;
600  }
601  set {
602  _profileShape = value;
603  }
604  }
605 
607  get {
608  return _hollowShape;
609  }
610  set {
611  _hollowShape = value;
612  }
613  }
614 
615  public UUID SculptTexture {
616  get {
617  return _sculptTexture;
618  }
619  set {
620  _sculptTexture = value;
621  }
622  }
623 
624  public byte SculptType
625  {
626  get
627  {
628  return _sculptType;
629  }
630  set
631  {
632  _sculptType = value;
633  }
634  }
635 
636  // This is only used at runtime. For sculpties this holds the texture data, and for meshes
637  // the mesh data.
638  public byte[] SculptData
639  {
640  get
641  {
642  return _sculptData;
643  }
644  set
645  {
646 // m_log.DebugFormat("[PRIMITIVE BASE SHAPE]: Setting SculptData to data with length {0}", value.Length);
647  _sculptData = value;
648  }
649  }
650 
651  public int FlexiSoftness
652  {
653  get
654  {
655  return _flexiSoftness;
656  }
657  set
658  {
659  _flexiSoftness = value;
660  }
661  }
662 
663  public float FlexiTension {
664  get {
665  return _flexiTension;
666  }
667  set {
668  _flexiTension = value;
669  }
670  }
671 
672  public float FlexiDrag {
673  get {
674  return _flexiDrag;
675  }
676  set {
677  _flexiDrag = value;
678  }
679  }
680 
681  public float FlexiGravity {
682  get {
683  return _flexiGravity;
684  }
685  set {
686  _flexiGravity = value;
687  }
688  }
689 
690  public float FlexiWind {
691  get {
692  return _flexiWind;
693  }
694  set {
695  _flexiWind = value;
696  }
697  }
698 
699  public float FlexiForceX {
700  get {
701  return _flexiForceX;
702  }
703  set {
704  _flexiForceX = value;
705  }
706  }
707 
708  public float FlexiForceY {
709  get {
710  return _flexiForceY;
711  }
712  set {
713  _flexiForceY = value;
714  }
715  }
716 
717  public float FlexiForceZ {
718  get {
719  return _flexiForceZ;
720  }
721  set {
722  _flexiForceZ = value;
723  }
724  }
725 
726  public float LightColorR {
727  get {
728  return _lightColorR;
729  }
730  set {
731  if (value < 0)
732  _lightColorR = 0;
733  else if (value > 1.0f)
734  _lightColorR = 1.0f;
735  else
736  _lightColorR = value;
737  }
738  }
739 
740  public float LightColorG {
741  get {
742  return _lightColorG;
743  }
744  set {
745  if (value < 0)
746  _lightColorG = 0;
747  else if (value > 1.0f)
748  _lightColorG = 1.0f;
749  else
750  _lightColorG = value;
751  }
752  }
753 
754  public float LightColorB {
755  get {
756  return _lightColorB;
757  }
758  set {
759  if (value < 0)
760  _lightColorB = 0;
761  else if (value > 1.0f)
762  _lightColorB = 1.0f;
763  else
764  _lightColorB = value;
765  }
766  }
767 
768  public float LightColorA {
769  get {
770  return _lightColorA;
771  }
772  set {
773  if (value < 0)
774  _lightColorA = 0;
775  else if (value > 1.0f)
776  _lightColorA = 1.0f;
777  else
778  _lightColorA = value;
779  }
780  }
781 
782  public float LightRadius {
783  get {
784  return _lightRadius;
785  }
786  set {
787  _lightRadius = value;
788  }
789  }
790 
791  public float LightCutoff {
792  get {
793  return _lightCutoff;
794  }
795  set {
796  _lightCutoff = value;
797  }
798  }
799 
800  public float LightFalloff {
801  get {
802  return _lightFalloff;
803  }
804  set {
805  _lightFalloff = value;
806  }
807  }
808 
809  public float LightIntensity {
810  get {
811  return _lightIntensity;
812  }
813  set {
814  _lightIntensity = value;
815  }
816  }
817 
818  public bool FlexiEntry {
819  get {
820  return _flexiEntry;
821  }
822  set {
823  _flexiEntry = value;
824  }
825  }
826 
827  public bool LightEntry {
828  get {
829  return _lightEntry;
830  }
831  set {
832  _lightEntry = value;
833  }
834  }
835 
836  public bool SculptEntry {
837  get {
838  return _sculptEntry;
839  }
840  set {
841  _sculptEntry = value;
842  }
843  }
844 
845  public bool ProjectionEntry {
846  get {
847  return _projectionEntry;
848  }
849  set {
850  _projectionEntry = value;
851  }
852  }
853 
854  public UUID ProjectionTextureUUID {
855  get {
856  return _projectionTextureID;
857  }
858  set {
859  _projectionTextureID = value;
860  }
861  }
862 
863  public float ProjectionFOV {
864  get {
865  return _projectionFOV;
866  }
867  set {
868  _projectionFOV = value;
869  }
870  }
871 
872  public float ProjectionFocus {
873  get {
874  return _projectionFocus;
875  }
876  set {
877  _projectionFocus = value;
878  }
879  }
880 
881  public float ProjectionAmbiance {
882  get {
883  return _projectionAmb;
884  }
885  set {
886  _projectionAmb = value;
887  }
888  }
889 
890  public ulong GetMeshKey(Vector3 size, float lod)
891  {
892  return GetMeshKey(size, lod, false);
893  }
894 
895  public ulong GetMeshKey(Vector3 size, float lod, bool convex)
896  {
897  ulong hash = 5381;
898 
899  hash = djb2(hash, this.PathCurve);
900  hash = djb2(hash, (byte)((byte)this.HollowShape | (byte)this.ProfileShape));
901  hash = djb2(hash, this.PathBegin);
902  hash = djb2(hash, this.PathEnd);
903  hash = djb2(hash, this.PathScaleX);
904  hash = djb2(hash, this.PathScaleY);
905  hash = djb2(hash, this.PathShearX);
906  hash = djb2(hash, this.PathShearY);
907  hash = djb2(hash, (byte)this.PathTwist);
908  hash = djb2(hash, (byte)this.PathTwistBegin);
909  hash = djb2(hash, (byte)this.PathRadiusOffset);
910  hash = djb2(hash, (byte)this.PathTaperX);
911  hash = djb2(hash, (byte)this.PathTaperY);
912  hash = djb2(hash, this.PathRevolutions);
913  hash = djb2(hash, (byte)this.PathSkew);
914  hash = djb2(hash, this.ProfileBegin);
915  hash = djb2(hash, this.ProfileEnd);
916  hash = djb2(hash, this.ProfileHollow);
917 
918  // TODO: Separate scale out from the primitive shape data (after
919  // scaling is supported at the physics engine level)
920  byte[] scaleBytes = size.GetBytes();
921  for (int i = 0; i < scaleBytes.Length; i++)
922  hash = djb2(hash, scaleBytes[i]);
923 
924  // Include LOD in hash, accounting for endianness
925  byte[] lodBytes = new byte[4];
926  Buffer.BlockCopy(BitConverter.GetBytes(lod), 0, lodBytes, 0, 4);
927  if (!BitConverter.IsLittleEndian)
928  {
929  Array.Reverse(lodBytes, 0, 4);
930  }
931  for (int i = 0; i < lodBytes.Length; i++)
932  hash = djb2(hash, lodBytes[i]);
933 
934  // include sculpt UUID
935  if (this.SculptEntry)
936  {
937  scaleBytes = this.SculptTexture.GetBytes();
938  for (int i = 0; i < scaleBytes.Length; i++)
939  hash = djb2(hash, scaleBytes[i]);
940  }
941 
942  if(convex)
943  hash = djb2(hash, 0xa5);
944 
945  return hash;
946  }
947 
948  private ulong djb2(ulong hash, byte c)
949  {
950  return ((hash << 5) + hash) + (ulong)c;
951  }
952 
953  private ulong djb2(ulong hash, ushort c)
954  {
955  hash = ((hash << 5) + hash) + (ulong)((byte)c);
956  return ((hash << 5) + hash) + (ulong)(c >> 8);
957  }
958 
959  public byte[] ExtraParamsToBytes()
960  {
961 // m_log.DebugFormat("[EXTRAPARAMS]: Called ExtraParamsToBytes()");
962 
963  ushort FlexiEP = 0x10;
964  ushort LightEP = 0x20;
965  ushort SculptEP = 0x30;
966  ushort ProjectionEP = 0x40;
967 
968  int i = 0;
969  uint TotalBytesLength = 1; // ExtraParamsNum
970 
971  uint ExtraParamsNum = 0;
972  if (_flexiEntry)
973  {
974  ExtraParamsNum++;
975  TotalBytesLength += 16;// data
976  TotalBytesLength += 2 + 4; // type
977  }
978 
979  if (_lightEntry)
980  {
981  ExtraParamsNum++;
982  TotalBytesLength += 16;// data
983  TotalBytesLength += 2 + 4; // type
984  }
985 
986  if (_sculptEntry)
987  {
988  ExtraParamsNum++;
989  TotalBytesLength += 17;// data
990  TotalBytesLength += 2 + 4; // type
991  }
992 
993  if (_projectionEntry)
994  {
995  ExtraParamsNum++;
996  TotalBytesLength += 28;// data
997  TotalBytesLength += 2 + 4;// type
998  }
999 
1000  byte[] returnbytes = new byte[TotalBytesLength];
1001 
1002  // uint paramlength = ExtraParamsNum;
1003 
1004  // Stick in the number of parameters
1005  returnbytes[i++] = (byte)ExtraParamsNum;
1006 
1007  if (_flexiEntry)
1008  {
1009  byte[] FlexiData = GetFlexiBytes();
1010 
1011  returnbytes[i++] = (byte)(FlexiEP % 256);
1012  returnbytes[i++] = (byte)((FlexiEP >> 8) % 256);
1013 
1014  returnbytes[i++] = (byte)(FlexiData.Length % 256);
1015  returnbytes[i++] = (byte)((FlexiData.Length >> 8) % 256);
1016  returnbytes[i++] = (byte)((FlexiData.Length >> 16) % 256);
1017  returnbytes[i++] = (byte)((FlexiData.Length >> 24) % 256);
1018  Array.Copy(FlexiData, 0, returnbytes, i, FlexiData.Length);
1019  i += FlexiData.Length;
1020  }
1021 
1022  if (_lightEntry)
1023  {
1024  byte[] LightData = GetLightBytes();
1025 
1026  returnbytes[i++] = (byte)(LightEP % 256);
1027  returnbytes[i++] = (byte)((LightEP >> 8) % 256);
1028 
1029  returnbytes[i++] = (byte)(LightData.Length % 256);
1030  returnbytes[i++] = (byte)((LightData.Length >> 8) % 256);
1031  returnbytes[i++] = (byte)((LightData.Length >> 16) % 256);
1032  returnbytes[i++] = (byte)((LightData.Length >> 24) % 256);
1033  Array.Copy(LightData, 0, returnbytes, i, LightData.Length);
1034  i += LightData.Length;
1035  }
1036 
1037  if (_sculptEntry)
1038  {
1039  byte[] SculptData = GetSculptBytes();
1040 
1041  returnbytes[i++] = (byte)(SculptEP % 256);
1042  returnbytes[i++] = (byte)((SculptEP >> 8) % 256);
1043 
1044  returnbytes[i++] = (byte)(SculptData.Length % 256);
1045  returnbytes[i++] = (byte)((SculptData.Length >> 8) % 256);
1046  returnbytes[i++] = (byte)((SculptData.Length >> 16) % 256);
1047  returnbytes[i++] = (byte)((SculptData.Length >> 24) % 256);
1048  Array.Copy(SculptData, 0, returnbytes, i, SculptData.Length);
1049  i += SculptData.Length;
1050  }
1051 
1052  if (_projectionEntry)
1053  {
1054  byte[] ProjectionData = GetProjectionBytes();
1055 
1056  returnbytes[i++] = (byte)(ProjectionEP % 256);
1057  returnbytes[i++] = (byte)((ProjectionEP >> 8) % 256);
1058  returnbytes[i++] = (byte)((ProjectionData.Length) % 256);
1059  returnbytes[i++] = (byte)((ProjectionData.Length >> 16) % 256);
1060  returnbytes[i++] = (byte)((ProjectionData.Length >> 20) % 256);
1061  returnbytes[i++] = (byte)((ProjectionData.Length >> 24) % 256);
1062  Array.Copy(ProjectionData, 0, returnbytes, i, ProjectionData.Length);
1063  i += ProjectionData.Length;
1064  }
1065 
1066  if (!_flexiEntry && !_lightEntry && !_sculptEntry && !_projectionEntry)
1067  {
1068  byte[] returnbyte = new byte[1];
1069  returnbyte[0] = 0;
1070  return returnbyte;
1071  }
1072 
1073  return returnbytes;
1074  }
1075 
1076  public void ReadInUpdateExtraParam(ushort type, bool inUse, byte[] data)
1077  {
1078  const ushort FlexiEP = 0x10;
1079  const ushort LightEP = 0x20;
1080  const ushort SculptEP = 0x30;
1081  const ushort ProjectionEP = 0x40;
1082 
1083  switch (type)
1084  {
1085  case FlexiEP:
1086  if (!inUse)
1087  {
1088  _flexiEntry = false;
1089  return;
1090  }
1091  ReadFlexiData(data, 0);
1092  break;
1093 
1094  case LightEP:
1095  if (!inUse)
1096  {
1097  _lightEntry = false;
1098  return;
1099  }
1100  ReadLightData(data, 0);
1101  break;
1102 
1103  case SculptEP:
1104  if (!inUse)
1105  {
1106  _sculptEntry = false;
1107  return;
1108  }
1109  ReadSculptData(data, 0);
1110  break;
1111  case ProjectionEP:
1112  if (!inUse)
1113  {
1114  _projectionEntry = false;
1115  return;
1116  }
1117  ReadProjectionData(data, 0);
1118  break;
1119  }
1120  }
1121 
1122  public void ReadInExtraParamsBytes(byte[] data)
1123  {
1124  if (data == null || data.Length == 1)
1125  return;
1126 
1127  const ushort FlexiEP = 0x10;
1128  const ushort LightEP = 0x20;
1129  const ushort SculptEP = 0x30;
1130  const ushort ProjectionEP = 0x40;
1131 
1132  bool lGotFlexi = false;
1133  bool lGotLight = false;
1134  bool lGotSculpt = false;
1135  bool lGotFilter = false;
1136 
1137  int i = 0;
1138  byte extraParamCount = 0;
1139  if (data.Length > 0)
1140  {
1141  extraParamCount = data[i++];
1142  }
1143 
1144  for (int k = 0; k < extraParamCount; k++)
1145  {
1146  ushort epType = Utils.BytesToUInt16(data, i);
1147 
1148  i += 2;
1149  // uint paramLength = Helpers.BytesToUIntBig(data, i);
1150 
1151  i += 4;
1152  switch (epType)
1153  {
1154  case FlexiEP:
1155  ReadFlexiData(data, i);
1156  i += 16;
1157  lGotFlexi = true;
1158  break;
1159 
1160  case LightEP:
1161  ReadLightData(data, i);
1162  i += 16;
1163  lGotLight = true;
1164  break;
1165 
1166  case SculptEP:
1167  ReadSculptData(data, i);
1168  i += 17;
1169  lGotSculpt = true;
1170  break;
1171  case ProjectionEP:
1172  ReadProjectionData(data, i);
1173  i += 28;
1174  lGotFilter = true;
1175  break;
1176  }
1177  }
1178 
1179  if (!lGotFlexi)
1180  _flexiEntry = false;
1181  if (!lGotLight)
1182  _lightEntry = false;
1183  if (!lGotSculpt)
1184  _sculptEntry = false;
1185  if (!lGotFilter)
1186  _projectionEntry = false;
1187  }
1188 
1189  public void ReadSculptData(byte[] data, int pos)
1190  {
1191  UUID SculptUUID;
1192  byte SculptTypel;
1193 
1194  if (data.Length-pos >= 17)
1195  {
1196  _sculptEntry = true;
1197  byte[] SculptTextureUUID = new byte[16];
1198  SculptTypel = data[16 + pos];
1199  Array.Copy(data, pos, SculptTextureUUID,0, 16);
1200  SculptUUID = new UUID(SculptTextureUUID, 0);
1201  }
1202  else
1203  {
1204  _sculptEntry = false;
1205  SculptUUID = UUID.Zero;
1206  SculptTypel = 0x00;
1207  }
1208 
1209  if (_sculptEntry)
1210  {
1211  if (_sculptType != (byte)1 && _sculptType != (byte)2 && _sculptType != (byte)3 && _sculptType != (byte)4)
1212  _sculptType = 4;
1213  }
1214 
1215  _sculptTexture = SculptUUID;
1216  _sculptType = SculptTypel;
1217  //m_log.Info("[SCULPT]:" + SculptUUID.ToString());
1218  }
1219 
1220  public byte[] GetSculptBytes()
1221  {
1222  byte[] data = new byte[17];
1223 
1224  _sculptTexture.GetBytes().CopyTo(data, 0);
1225  data[16] = (byte)_sculptType;
1226 
1227  return data;
1228  }
1229 
1230  public void ReadFlexiData(byte[] data, int pos)
1231  {
1232  if (data.Length-pos >= 16)
1233  {
1234  _flexiEntry = true;
1235  _flexiSoftness = ((data[pos] & 0x80) >> 6) | ((data[pos + 1] & 0x80) >> 7);
1236 
1237  _flexiTension = (float)(data[pos++] & 0x7F) / 10.0f;
1238  _flexiDrag = (float)(data[pos++] & 0x7F) / 10.0f;
1239  _flexiGravity = (float)(data[pos++] / 10.0f) - 10.0f;
1240  _flexiWind = (float)data[pos++] / 10.0f;
1241  Vector3 lForce = new Vector3(data, pos);
1242  _flexiForceX = lForce.X;
1243  _flexiForceY = lForce.Y;
1244  _flexiForceZ = lForce.Z;
1245  }
1246  else
1247  {
1248  _flexiEntry = false;
1249  _flexiSoftness = 0;
1250 
1251  _flexiTension = 0.0f;
1252  _flexiDrag = 0.0f;
1253  _flexiGravity = 0.0f;
1254  _flexiWind = 0.0f;
1255  _flexiForceX = 0f;
1256  _flexiForceY = 0f;
1257  _flexiForceZ = 0f;
1258  }
1259  }
1260 
1261  public byte[] GetFlexiBytes()
1262  {
1263  byte[] data = new byte[16];
1264  int i = 0;
1265 
1266  // Softness is packed in the upper bits of tension and drag
1267  data[i] = (byte)((_flexiSoftness & 2) << 6);
1268  data[i + 1] = (byte)((_flexiSoftness & 1) << 7);
1269 
1270  data[i++] |= (byte)((byte)(_flexiTension * 10.01f) & 0x7F);
1271  data[i++] |= (byte)((byte)(_flexiDrag * 10.01f) & 0x7F);
1272  data[i++] = (byte)((_flexiGravity + 10.0f) * 10.01f);
1273  data[i++] = (byte)(_flexiWind * 10.01f);
1274  Vector3 lForce = new Vector3(_flexiForceX, _flexiForceY, _flexiForceZ);
1275  lForce.GetBytes().CopyTo(data, i);
1276 
1277  return data;
1278  }
1279 
1280  public void ReadLightData(byte[] data, int pos)
1281  {
1282  if (data.Length - pos >= 16)
1283  {
1284  _lightEntry = true;
1285  Color4 lColor = new Color4(data, pos, false);
1286  _lightIntensity = lColor.A;
1287  _lightColorA = 1f;
1288  _lightColorR = lColor.R;
1289  _lightColorG = lColor.G;
1290  _lightColorB = lColor.B;
1291 
1292  _lightRadius = Utils.BytesToFloat(data, pos + 4);
1293  _lightCutoff = Utils.BytesToFloat(data, pos + 8);
1294  _lightFalloff = Utils.BytesToFloat(data, pos + 12);
1295  }
1296  else
1297  {
1298  _lightEntry = false;
1299  _lightColorA = 1f;
1300  _lightColorR = 0f;
1301  _lightColorG = 0f;
1302  _lightColorB = 0f;
1303  _lightRadius = 0f;
1304  _lightCutoff = 0f;
1305  _lightFalloff = 0f;
1306  _lightIntensity = 0f;
1307  }
1308  }
1309 
1310  public byte[] GetLightBytes()
1311  {
1312  byte[] data = new byte[16];
1313 
1314  // Alpha channel in color is intensity
1315  Color4 tmpColor = new Color4(_lightColorR,_lightColorG,_lightColorB,_lightIntensity);
1316 
1317  tmpColor.GetBytes().CopyTo(data, 0);
1318  Utils.FloatToBytes(_lightRadius).CopyTo(data, 4);
1319  Utils.FloatToBytes(_lightCutoff).CopyTo(data, 8);
1320  Utils.FloatToBytes(_lightFalloff).CopyTo(data, 12);
1321 
1322  return data;
1323  }
1324 
1325  public void ReadProjectionData(byte[] data, int pos)
1326  {
1327  byte[] ProjectionTextureUUID = new byte[16];
1328 
1329  if (data.Length - pos >= 28)
1330  {
1331  _projectionEntry = true;
1332  Array.Copy(data, pos, ProjectionTextureUUID,0, 16);
1333  _projectionTextureID = new UUID(ProjectionTextureUUID, 0);
1334 
1335  _projectionFOV = Utils.BytesToFloat(data, pos + 16);
1336  _projectionFocus = Utils.BytesToFloat(data, pos + 20);
1337  _projectionAmb = Utils.BytesToFloat(data, pos + 24);
1338  }
1339  else
1340  {
1341  _projectionEntry = false;
1342  _projectionTextureID = UUID.Zero;
1343  _projectionFOV = 0f;
1344  _projectionFocus = 0f;
1345  _projectionAmb = 0f;
1346  }
1347  }
1348 
1349  public byte[] GetProjectionBytes()
1350  {
1351  byte[] data = new byte[28];
1352 
1353  _projectionTextureID.GetBytes().CopyTo(data, 0);
1354  Utils.FloatToBytes(_projectionFOV).CopyTo(data, 16);
1355  Utils.FloatToBytes(_projectionFocus).CopyTo(data, 20);
1356  Utils.FloatToBytes(_projectionAmb).CopyTo(data, 24);
1357 
1358  return data;
1359  }
1360 
1361 
1367  {
1368  // position and rotation defaults here since they are not available in PrimitiveBaseShape
1369  return ToOmvPrimitive(new Vector3(0.0f, 0.0f, 0.0f),
1370  new Quaternion(0.0f, 0.0f, 0.0f, 1.0f));
1371  }
1372 
1373 
1380  public Primitive ToOmvPrimitive(Vector3 position, Quaternion rotation)
1381  {
1382  OpenMetaverse.Primitive prim = new OpenMetaverse.Primitive();
1383 
1384  prim.Scale = this.Scale;
1385  prim.Position = position;
1386  prim.Rotation = rotation;
1387 
1388  if (this.SculptEntry)
1389  {
1390  prim.Sculpt = new Primitive.SculptData();
1391  prim.Sculpt.Type = (OpenMetaverse.SculptType)this.SculptType;
1392  prim.Sculpt.SculptTexture = this.SculptTexture;
1393  }
1394 
1395  prim.PrimData.PathShearX = this.PathShearX < 128 ? (float)this.PathShearX * 0.01f : (float)(this.PathShearX - 256) * 0.01f;
1396  prim.PrimData.PathShearY = this.PathShearY < 128 ? (float)this.PathShearY * 0.01f : (float)(this.PathShearY - 256) * 0.01f;
1397  prim.PrimData.PathBegin = (float)this.PathBegin * 2.0e-5f;
1398  prim.PrimData.PathEnd = 1.0f - (float)this.PathEnd * 2.0e-5f;
1399 
1400  prim.PrimData.PathScaleX = (200 - this.PathScaleX) * 0.01f;
1401  prim.PrimData.PathScaleY = (200 - this.PathScaleY) * 0.01f;
1402 
1403  prim.PrimData.PathTaperX = this.PathTaperX * 0.01f;
1404  prim.PrimData.PathTaperY = this.PathTaperY * 0.01f;
1405 
1406  prim.PrimData.PathTwistBegin = this.PathTwistBegin * 0.01f;
1407  prim.PrimData.PathTwist = this.PathTwist * 0.01f;
1408 
1409  prim.PrimData.ProfileBegin = (float)this.ProfileBegin * 2.0e-5f;
1410  prim.PrimData.ProfileEnd = 1.0f - (float)this.ProfileEnd * 2.0e-5f;
1411  prim.PrimData.ProfileHollow = (float)this.ProfileHollow * 2.0e-5f;
1412 
1413  prim.PrimData.profileCurve = this.ProfileCurve;
1414  prim.PrimData.ProfileHole = (HoleType)this.HollowShape;
1415 
1416  prim.PrimData.PathCurve = (PathCurve)this.PathCurve;
1417  prim.PrimData.PathRadiusOffset = 0.01f * this.PathRadiusOffset;
1418  prim.PrimData.PathRevolutions = 1.0f + 0.015f * this.PathRevolutions;
1419  prim.PrimData.PathSkew = 0.01f * this.PathSkew;
1420 
1421  prim.PrimData.PCode = OpenMetaverse.PCode.Prim;
1422  prim.PrimData.State = 0;
1423 
1424  if (this.FlexiEntry)
1425  {
1426  prim.Flexible = new Primitive.FlexibleData();
1427  prim.Flexible.Drag = this.FlexiDrag;
1428  prim.Flexible.Force = new Vector3(this.FlexiForceX, this.FlexiForceY, this.FlexiForceZ);
1429  prim.Flexible.Gravity = this.FlexiGravity;
1430  prim.Flexible.Softness = this.FlexiSoftness;
1431  prim.Flexible.Tension = this.FlexiTension;
1432  prim.Flexible.Wind = this.FlexiWind;
1433  }
1434 
1435  if (this.LightEntry)
1436  {
1437  prim.Light = new Primitive.LightData();
1438  prim.Light.Color = new Color4(this.LightColorR, this.LightColorG, this.LightColorB, this.LightColorA);
1439  prim.Light.Cutoff = this.LightCutoff;
1440  prim.Light.Falloff = this.LightFalloff;
1441  prim.Light.Intensity = this.LightIntensity;
1442  prim.Light.Radius = this.LightRadius;
1443  }
1444 
1445  prim.Textures = this.Textures;
1446 
1447  prim.Properties = new Primitive.ObjectProperties();
1448  prim.Properties.Name = "Object";
1449  prim.Properties.Description = "";
1450  prim.Properties.CreatorID = UUID.Zero;
1451  prim.Properties.GroupID = UUID.Zero;
1452  prim.Properties.OwnerID = UUID.Zero;
1453  prim.Properties.Permissions = new Permissions();
1454  prim.Properties.SalePrice = 10;
1455  prim.Properties.SaleType = new SaleType();
1456 
1457  return prim;
1458  }
1459 
1465  public class MediaList : List<MediaEntry>, IXmlSerializable
1466  {
1467  public const string MEDIA_TEXTURE_TYPE = "sl";
1468 
1469  public MediaList() : base() {}
1470  public MediaList(IEnumerable<MediaEntry> collection) : base(collection) {}
1471  public MediaList(int capacity) : base(capacity) {}
1472 
1473  public XmlSchema GetSchema()
1474  {
1475  return null;
1476  }
1477 
1478  public string ToXml()
1479  {
1480  lock (this)
1481  {
1482  using (StringWriter sw = new StringWriter())
1483  {
1484  using (XmlTextWriter xtw = new XmlTextWriter(sw))
1485  {
1486  xtw.WriteStartElement("OSMedia");
1487  xtw.WriteAttributeString("type", MEDIA_TEXTURE_TYPE);
1488  xtw.WriteAttributeString("version", "0.1");
1489 
1490  OSDArray meArray = new OSDArray();
1491  foreach (MediaEntry me in this)
1492  {
1493  OSD osd = (null == me ? new OSD() : me.GetOSD());
1494  meArray.Add(osd);
1495  }
1496 
1497  xtw.WriteStartElement("OSData");
1498  xtw.WriteRaw(OSDParser.SerializeLLSDXmlString(meArray));
1499  xtw.WriteEndElement();
1500 
1501  xtw.WriteEndElement();
1502 
1503  xtw.Flush();
1504  return sw.ToString();
1505  }
1506  }
1507  }
1508  }
1509 
1510  public void WriteXml(XmlWriter writer)
1511  {
1512  writer.WriteRaw(ToXml());
1513  }
1514 
1515  public static MediaList FromXml(string rawXml)
1516  {
1517  MediaList ml = new MediaList();
1518  ml.ReadXml(rawXml);
1519  return ml;
1520  }
1521 
1522  public void ReadXml(string rawXml)
1523  {
1524  using (StringReader sr = new StringReader(rawXml))
1525  {
1526  using (XmlTextReader xtr = new XmlTextReader(sr))
1527  {
1528  xtr.MoveToContent();
1529 
1530  string type = xtr.GetAttribute("type");
1531  //m_log.DebugFormat("[MOAP]: Loaded media texture entry with type {0}", type);
1532 
1533  if (type != MEDIA_TEXTURE_TYPE)
1534  return;
1535 
1536  xtr.ReadStartElement("OSMedia");
1537 
1538  OSDArray osdMeArray = (OSDArray)OSDParser.DeserializeLLSDXml(xtr.ReadInnerXml());
1539  foreach (OSD osdMe in osdMeArray)
1540  {
1541  MediaEntry me = (osdMe is OSDMap ? MediaEntry.FromOSD(osdMe) : new MediaEntry());
1542  Add(me);
1543  }
1544 
1545  xtr.ReadEndElement();
1546  }
1547  }
1548  }
1549 
1550  public void ReadXml(XmlReader reader)
1551  {
1552  if (reader.IsEmptyElement)
1553  return;
1554 
1555  ReadXml(reader.ReadInnerXml());
1556  }
1557  }
1558  }
1559 }
OpenMetaverse.StructuredData.OSDArray OSDArray
void SetPathRange(float begin, float end)
static PrimitiveBaseShape Create()
void SetProfileRange(float begin, float end)
OpenMetaverse.StructuredData.OSDMap OSDMap
Encapsulates a list of media entries.
ulong GetMeshKey(Vector3 size, float lod)
void SetProfileRange(Vector3 profileRange)
static PrimitiveBaseShape CreateCylinder()
OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion rotation
Definition: ICM_Api.cs:32
void ReadFlexiData(byte[] data, int pos)
void ReadProjectionData(byte[] data, int pos)
void SetSculptProperties(byte sculptType, UUID SculptTextureUUID)
OpenSim.Region.OptionalModules.Scripting.Minimodule.Object.SculptType SculptType
Definition: SOPObject.cs:39
void ReadInUpdateExtraParam(ushort type, bool inUse, byte[] data)
OpenMetaverse.StructuredData.OSD OSD
void ReadSculptData(byte[] data, int pos)
ulong GetMeshKey(Vector3 size, float lod, bool convex)
Primitive ToOmvPrimitive(Vector3 position, Quaternion rotation)
Creates a OpenMetaverse.Primitive and populates it with converted PrimitiveBaseShape values ...
static PrimitiveBaseShape CreateCylinder(float radius, float heigth)
System.Collections.IEnumerable IEnumerable
Primitive ToOmvPrimitive()
Creates a OpenMetaverse.Primitive and populates it with converted PrimitiveBaseShape values ...
static PrimitiveBaseShape CreateSphere()
void ReadLightData(byte[] data, int pos)
static PrimitiveBaseShape CreateBox()
PrimitiveBaseShape(Primitive prim)
Construct a PrimitiveBaseShape object from a OpenMetaverse.Primitive object
MediaList(IEnumerable< MediaEntry > collection)