aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/PrimitiveBaseShape.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Framework/PrimitiveBaseShape.cs1531
1 files changed, 1531 insertions, 0 deletions
diff --git a/OpenSim/Framework/PrimitiveBaseShape.cs b/OpenSim/Framework/PrimitiveBaseShape.cs
new file mode 100644
index 0000000..c8a5376
--- /dev/null
+++ b/OpenSim/Framework/PrimitiveBaseShape.cs
@@ -0,0 +1,1531 @@
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
28using System;
29using System.Collections.Generic;
30using System.Drawing;
31using System.Drawing.Imaging;
32using System.IO;
33using System.Reflection;
34using System.Xml;
35using System.Xml.Schema;
36using System.Xml.Serialization;
37using log4net;
38using OpenMetaverse;
39using OpenMetaverse.StructuredData;
40
41namespace OpenSim.Framework
42{
43 public enum ProfileShape : byte
44 {
45 Circle = 0,
46 Square = 1,
47 IsometricTriangle = 2,
48 EquilateralTriangle = 3,
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
187 /// <summary>
188 /// Entries to store media textures on each face
189 /// </summary>
190 /// Do not change this value directly - always do it through an IMoapModule.
191 /// Lock before manipulating.
192 public MediaList Media { get; set; }
193
194 public PrimitiveBaseShape()
195 {
196 PCode = (byte)PCodeEnum.Primitive;
197 m_textureEntry = DEFAULT_TEXTURE;
198 }
199
200 /// <summary>
201 /// Construct a PrimitiveBaseShape object from a OpenMetaverse.Primitive object
202 /// </summary>
203 /// <param name="prim"></param>
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 {
290 PrimitiveBaseShape shape = new PrimitiveBaseShape();
291 return shape;
292 }
293
294 public static PrimitiveBaseShape CreateBox()
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
306 public static PrimitiveBaseShape CreateSphere()
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
318 public static PrimitiveBaseShape CreateCylinder()
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
351 public PrimitiveBaseShape Copy()
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
597 public ProfileShape ProfileShape {
598 get {
599 return _profileShape;
600 }
601 set {
602 _profileShape = value;
603 }
604 }
605
606 public HollowShape HollowShape {
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 _lightColorR = value;
732 }
733 }
734
735 public float LightColorG {
736 get {
737 return _lightColorG;
738 }
739 set {
740 _lightColorG = value;
741 }
742 }
743
744 public float LightColorB {
745 get {
746 return _lightColorB;
747 }
748 set {
749 _lightColorB = value;
750 }
751 }
752
753 public float LightColorA {
754 get {
755 return _lightColorA;
756 }
757 set {
758 _lightColorA = value;
759 }
760 }
761
762 public float LightRadius {
763 get {
764 return _lightRadius;
765 }
766 set {
767 _lightRadius = value;
768 }
769 }
770
771 public float LightCutoff {
772 get {
773 return _lightCutoff;
774 }
775 set {
776 _lightCutoff = value;
777 }
778 }
779
780 public float LightFalloff {
781 get {
782 return _lightFalloff;
783 }
784 set {
785 _lightFalloff = value;
786 }
787 }
788
789 public float LightIntensity {
790 get {
791 return _lightIntensity;
792 }
793 set {
794 _lightIntensity = value;
795 }
796 }
797
798 public bool FlexiEntry {
799 get {
800 return _flexiEntry;
801 }
802 set {
803 _flexiEntry = value;
804 }
805 }
806
807 public bool LightEntry {
808 get {
809 return _lightEntry;
810 }
811 set {
812 _lightEntry = value;
813 }
814 }
815
816 public bool SculptEntry {
817 get {
818 return _sculptEntry;
819 }
820 set {
821 _sculptEntry = value;
822 }
823 }
824
825 public bool ProjectionEntry {
826 get {
827 return _projectionEntry;
828 }
829 set {
830 _projectionEntry = value;
831 }
832 }
833
834 public UUID ProjectionTextureUUID {
835 get {
836 return _projectionTextureID;
837 }
838 set {
839 _projectionTextureID = value;
840 }
841 }
842
843 public float ProjectionFOV {
844 get {
845 return _projectionFOV;
846 }
847 set {
848 _projectionFOV = value;
849 }
850 }
851
852 public float ProjectionFocus {
853 get {
854 return _projectionFocus;
855 }
856 set {
857 _projectionFocus = value;
858 }
859 }
860
861 public float ProjectionAmbiance {
862 get {
863 return _projectionAmb;
864 }
865 set {
866 _projectionAmb = value;
867 }
868 }
869
870 public ulong GetMeshKey(Vector3 size, float lod)
871 {
872 ulong hash = 5381;
873
874 hash = djb2(hash, this.PathCurve);
875 hash = djb2(hash, (byte)((byte)this.HollowShape | (byte)this.ProfileShape));
876 hash = djb2(hash, this.PathBegin);
877 hash = djb2(hash, this.PathEnd);
878 hash = djb2(hash, this.PathScaleX);
879 hash = djb2(hash, this.PathScaleY);
880 hash = djb2(hash, this.PathShearX);
881 hash = djb2(hash, this.PathShearY);
882 hash = djb2(hash, (byte)this.PathTwist);
883 hash = djb2(hash, (byte)this.PathTwistBegin);
884 hash = djb2(hash, (byte)this.PathRadiusOffset);
885 hash = djb2(hash, (byte)this.PathTaperX);
886 hash = djb2(hash, (byte)this.PathTaperY);
887 hash = djb2(hash, this.PathRevolutions);
888 hash = djb2(hash, (byte)this.PathSkew);
889 hash = djb2(hash, this.ProfileBegin);
890 hash = djb2(hash, this.ProfileEnd);
891 hash = djb2(hash, this.ProfileHollow);
892
893 // TODO: Separate scale out from the primitive shape data (after
894 // scaling is supported at the physics engine level)
895 byte[] scaleBytes = size.GetBytes();
896 for (int i = 0; i < scaleBytes.Length; i++)
897 hash = djb2(hash, scaleBytes[i]);
898
899 // Include LOD in hash, accounting for endianness
900 byte[] lodBytes = new byte[4];
901 Buffer.BlockCopy(BitConverter.GetBytes(lod), 0, lodBytes, 0, 4);
902 if (!BitConverter.IsLittleEndian)
903 {
904 Array.Reverse(lodBytes, 0, 4);
905 }
906 for (int i = 0; i < lodBytes.Length; i++)
907 hash = djb2(hash, lodBytes[i]);
908
909 // include sculpt UUID
910 if (this.SculptEntry)
911 {
912 scaleBytes = this.SculptTexture.GetBytes();
913 for (int i = 0; i < scaleBytes.Length; i++)
914 hash = djb2(hash, scaleBytes[i]);
915 }
916
917 return hash;
918 }
919
920 private ulong djb2(ulong hash, byte c)
921 {
922 return ((hash << 5) + hash) + (ulong)c;
923 }
924
925 private ulong djb2(ulong hash, ushort c)
926 {
927 hash = ((hash << 5) + hash) + (ulong)((byte)c);
928 return ((hash << 5) + hash) + (ulong)(c >> 8);
929 }
930
931 public byte[] ExtraParamsToBytes()
932 {
933// m_log.DebugFormat("[EXTRAPARAMS]: Called ExtraParamsToBytes()");
934
935 ushort FlexiEP = 0x10;
936 ushort LightEP = 0x20;
937 ushort SculptEP = 0x30;
938 ushort ProjectionEP = 0x40;
939
940 int i = 0;
941 uint TotalBytesLength = 1; // ExtraParamsNum
942
943 uint ExtraParamsNum = 0;
944 if (_flexiEntry)
945 {
946 ExtraParamsNum++;
947 TotalBytesLength += 16;// data
948 TotalBytesLength += 2 + 4; // type
949 }
950
951 if (_lightEntry)
952 {
953 ExtraParamsNum++;
954 TotalBytesLength += 16;// data
955 TotalBytesLength += 2 + 4; // type
956 }
957
958 if (_sculptEntry)
959 {
960 ExtraParamsNum++;
961 TotalBytesLength += 17;// data
962 TotalBytesLength += 2 + 4; // type
963 }
964
965 if (_projectionEntry)
966 {
967 ExtraParamsNum++;
968 TotalBytesLength += 28;// data
969 TotalBytesLength += 2 + 4;// type
970 }
971
972 byte[] returnbytes = new byte[TotalBytesLength];
973
974 // uint paramlength = ExtraParamsNum;
975
976 // Stick in the number of parameters
977 returnbytes[i++] = (byte)ExtraParamsNum;
978
979 if (_flexiEntry)
980 {
981 byte[] FlexiData = GetFlexiBytes();
982
983 returnbytes[i++] = (byte)(FlexiEP % 256);
984 returnbytes[i++] = (byte)((FlexiEP >> 8) % 256);
985
986 returnbytes[i++] = (byte)(FlexiData.Length % 256);
987 returnbytes[i++] = (byte)((FlexiData.Length >> 8) % 256);
988 returnbytes[i++] = (byte)((FlexiData.Length >> 16) % 256);
989 returnbytes[i++] = (byte)((FlexiData.Length >> 24) % 256);
990 Array.Copy(FlexiData, 0, returnbytes, i, FlexiData.Length);
991 i += FlexiData.Length;
992 }
993
994 if (_lightEntry)
995 {
996 byte[] LightData = GetLightBytes();
997
998 returnbytes[i++] = (byte)(LightEP % 256);
999 returnbytes[i++] = (byte)((LightEP >> 8) % 256);
1000
1001 returnbytes[i++] = (byte)(LightData.Length % 256);
1002 returnbytes[i++] = (byte)((LightData.Length >> 8) % 256);
1003 returnbytes[i++] = (byte)((LightData.Length >> 16) % 256);
1004 returnbytes[i++] = (byte)((LightData.Length >> 24) % 256);
1005 Array.Copy(LightData, 0, returnbytes, i, LightData.Length);
1006 i += LightData.Length;
1007 }
1008
1009 if (_sculptEntry)
1010 {
1011 byte[] SculptData = GetSculptBytes();
1012
1013 returnbytes[i++] = (byte)(SculptEP % 256);
1014 returnbytes[i++] = (byte)((SculptEP >> 8) % 256);
1015
1016 returnbytes[i++] = (byte)(SculptData.Length % 256);
1017 returnbytes[i++] = (byte)((SculptData.Length >> 8) % 256);
1018 returnbytes[i++] = (byte)((SculptData.Length >> 16) % 256);
1019 returnbytes[i++] = (byte)((SculptData.Length >> 24) % 256);
1020 Array.Copy(SculptData, 0, returnbytes, i, SculptData.Length);
1021 i += SculptData.Length;
1022 }
1023
1024 if (_projectionEntry)
1025 {
1026 byte[] ProjectionData = GetProjectionBytes();
1027
1028 returnbytes[i++] = (byte)(ProjectionEP % 256);
1029 returnbytes[i++] = (byte)((ProjectionEP >> 8) % 256);
1030 returnbytes[i++] = (byte)((ProjectionData.Length) % 256);
1031 returnbytes[i++] = (byte)((ProjectionData.Length >> 16) % 256);
1032 returnbytes[i++] = (byte)((ProjectionData.Length >> 20) % 256);
1033 returnbytes[i++] = (byte)((ProjectionData.Length >> 24) % 256);
1034 Array.Copy(ProjectionData, 0, returnbytes, i, ProjectionData.Length);
1035 i += ProjectionData.Length;
1036 }
1037
1038 if (!_flexiEntry && !_lightEntry && !_sculptEntry && !_projectionEntry)
1039 {
1040 byte[] returnbyte = new byte[1];
1041 returnbyte[0] = 0;
1042 return returnbyte;
1043 }
1044
1045 return returnbytes;
1046 }
1047
1048 public void ReadInUpdateExtraParam(ushort type, bool inUse, byte[] data)
1049 {
1050 const ushort FlexiEP = 0x10;
1051 const ushort LightEP = 0x20;
1052 const ushort SculptEP = 0x30;
1053 const ushort ProjectionEP = 0x40;
1054
1055 switch (type)
1056 {
1057 case FlexiEP:
1058 if (!inUse)
1059 {
1060 _flexiEntry = false;
1061 return;
1062 }
1063 ReadFlexiData(data, 0);
1064 break;
1065
1066 case LightEP:
1067 if (!inUse)
1068 {
1069 _lightEntry = false;
1070 return;
1071 }
1072 ReadLightData(data, 0);
1073 break;
1074
1075 case SculptEP:
1076 if (!inUse)
1077 {
1078 _sculptEntry = false;
1079 return;
1080 }
1081 ReadSculptData(data, 0);
1082 break;
1083 case ProjectionEP:
1084 if (!inUse)
1085 {
1086 _projectionEntry = false;
1087 return;
1088 }
1089 ReadProjectionData(data, 0);
1090 break;
1091 }
1092 }
1093
1094 public void ReadInExtraParamsBytes(byte[] data)
1095 {
1096 if (data == null || data.Length == 1)
1097 return;
1098
1099 const ushort FlexiEP = 0x10;
1100 const ushort LightEP = 0x20;
1101 const ushort SculptEP = 0x30;
1102 const ushort ProjectionEP = 0x40;
1103
1104 bool lGotFlexi = false;
1105 bool lGotLight = false;
1106 bool lGotSculpt = false;
1107 bool lGotFilter = false;
1108
1109 int i = 0;
1110 byte extraParamCount = 0;
1111 if (data.Length > 0)
1112 {
1113 extraParamCount = data[i++];
1114 }
1115
1116 for (int k = 0; k < extraParamCount; k++)
1117 {
1118 ushort epType = Utils.BytesToUInt16(data, i);
1119
1120 i += 2;
1121 // uint paramLength = Helpers.BytesToUIntBig(data, i);
1122
1123 i += 4;
1124 switch (epType)
1125 {
1126 case FlexiEP:
1127 ReadFlexiData(data, i);
1128 i += 16;
1129 lGotFlexi = true;
1130 break;
1131
1132 case LightEP:
1133 ReadLightData(data, i);
1134 i += 16;
1135 lGotLight = true;
1136 break;
1137
1138 case SculptEP:
1139 ReadSculptData(data, i);
1140 i += 17;
1141 lGotSculpt = true;
1142 break;
1143 case ProjectionEP:
1144 ReadProjectionData(data, i);
1145 i += 28;
1146 lGotFilter = true;
1147 break;
1148 }
1149 }
1150
1151 if (!lGotFlexi)
1152 _flexiEntry = false;
1153 if (!lGotLight)
1154 _lightEntry = false;
1155 if (!lGotSculpt)
1156 _sculptEntry = false;
1157 if (!lGotFilter)
1158 _projectionEntry = false;
1159 }
1160
1161 public void ReadSculptData(byte[] data, int pos)
1162 {
1163 UUID SculptUUID;
1164 byte SculptTypel;
1165
1166 if (data.Length-pos >= 17)
1167 {
1168 _sculptEntry = true;
1169 byte[] SculptTextureUUID = new byte[16];
1170 SculptTypel = data[16 + pos];
1171 Array.Copy(data, pos, SculptTextureUUID,0, 16);
1172 SculptUUID = new UUID(SculptTextureUUID, 0);
1173 }
1174 else
1175 {
1176 _sculptEntry = false;
1177 SculptUUID = UUID.Zero;
1178 SculptTypel = 0x00;
1179 }
1180
1181 if (_sculptEntry)
1182 {
1183 if (_sculptType != (byte)1 && _sculptType != (byte)2 && _sculptType != (byte)3 && _sculptType != (byte)4)
1184 _sculptType = 4;
1185 }
1186
1187 _sculptTexture = SculptUUID;
1188 _sculptType = SculptTypel;
1189 //m_log.Info("[SCULPT]:" + SculptUUID.ToString());
1190 }
1191
1192 public byte[] GetSculptBytes()
1193 {
1194 byte[] data = new byte[17];
1195
1196 _sculptTexture.GetBytes().CopyTo(data, 0);
1197 data[16] = (byte)_sculptType;
1198
1199 return data;
1200 }
1201
1202 public void ReadFlexiData(byte[] data, int pos)
1203 {
1204 if (data.Length-pos >= 16)
1205 {
1206 _flexiEntry = true;
1207 _flexiSoftness = ((data[pos] & 0x80) >> 6) | ((data[pos + 1] & 0x80) >> 7);
1208
1209 _flexiTension = (float)(data[pos++] & 0x7F) / 10.0f;
1210 _flexiDrag = (float)(data[pos++] & 0x7F) / 10.0f;
1211 _flexiGravity = (float)(data[pos++] / 10.0f) - 10.0f;
1212 _flexiWind = (float)data[pos++] / 10.0f;
1213 Vector3 lForce = new Vector3(data, pos);
1214 _flexiForceX = lForce.X;
1215 _flexiForceY = lForce.Y;
1216 _flexiForceZ = lForce.Z;
1217 }
1218 else
1219 {
1220 _flexiEntry = false;
1221 _flexiSoftness = 0;
1222
1223 _flexiTension = 0.0f;
1224 _flexiDrag = 0.0f;
1225 _flexiGravity = 0.0f;
1226 _flexiWind = 0.0f;
1227 _flexiForceX = 0f;
1228 _flexiForceY = 0f;
1229 _flexiForceZ = 0f;
1230 }
1231 }
1232
1233 public byte[] GetFlexiBytes()
1234 {
1235 byte[] data = new byte[16];
1236 int i = 0;
1237
1238 // Softness is packed in the upper bits of tension and drag
1239 data[i] = (byte)((_flexiSoftness & 2) << 6);
1240 data[i + 1] = (byte)((_flexiSoftness & 1) << 7);
1241
1242 data[i++] |= (byte)((byte)(_flexiTension * 10.01f) & 0x7F);
1243 data[i++] |= (byte)((byte)(_flexiDrag * 10.01f) & 0x7F);
1244 data[i++] = (byte)((_flexiGravity + 10.0f) * 10.01f);
1245 data[i++] = (byte)(_flexiWind * 10.01f);
1246 Vector3 lForce = new Vector3(_flexiForceX, _flexiForceY, _flexiForceZ);
1247 lForce.GetBytes().CopyTo(data, i);
1248
1249 return data;
1250 }
1251
1252 public void ReadLightData(byte[] data, int pos)
1253 {
1254 if (data.Length - pos >= 16)
1255 {
1256 _lightEntry = true;
1257 Color4 lColor = new Color4(data, pos, false);
1258 _lightIntensity = lColor.A;
1259 _lightColorA = 1f;
1260 _lightColorR = lColor.R;
1261 _lightColorG = lColor.G;
1262 _lightColorB = lColor.B;
1263
1264 _lightRadius = Utils.BytesToFloat(data, pos + 4);
1265 _lightCutoff = Utils.BytesToFloat(data, pos + 8);
1266 _lightFalloff = Utils.BytesToFloat(data, pos + 12);
1267 }
1268 else
1269 {
1270 _lightEntry = false;
1271 _lightColorA = 1f;
1272 _lightColorR = 0f;
1273 _lightColorG = 0f;
1274 _lightColorB = 0f;
1275 _lightRadius = 0f;
1276 _lightCutoff = 0f;
1277 _lightFalloff = 0f;
1278 _lightIntensity = 0f;
1279 }
1280 }
1281
1282 public byte[] GetLightBytes()
1283 {
1284 byte[] data = new byte[16];
1285
1286 // Alpha channel in color is intensity
1287 Color4 tmpColor = new Color4(_lightColorR,_lightColorG,_lightColorB,_lightIntensity);
1288
1289 tmpColor.GetBytes().CopyTo(data, 0);
1290 Utils.FloatToBytes(_lightRadius).CopyTo(data, 4);
1291 Utils.FloatToBytes(_lightCutoff).CopyTo(data, 8);
1292 Utils.FloatToBytes(_lightFalloff).CopyTo(data, 12);
1293
1294 return data;
1295 }
1296
1297 public void ReadProjectionData(byte[] data, int pos)
1298 {
1299 byte[] ProjectionTextureUUID = new byte[16];
1300
1301 if (data.Length - pos >= 28)
1302 {
1303 _projectionEntry = true;
1304 Array.Copy(data, pos, ProjectionTextureUUID,0, 16);
1305 _projectionTextureID = new UUID(ProjectionTextureUUID, 0);
1306
1307 _projectionFOV = Utils.BytesToFloat(data, pos + 16);
1308 _projectionFocus = Utils.BytesToFloat(data, pos + 20);
1309 _projectionAmb = Utils.BytesToFloat(data, pos + 24);
1310 }
1311 else
1312 {
1313 _projectionEntry = false;
1314 _projectionTextureID = UUID.Zero;
1315 _projectionFOV = 0f;
1316 _projectionFocus = 0f;
1317 _projectionAmb = 0f;
1318 }
1319 }
1320
1321 public byte[] GetProjectionBytes()
1322 {
1323 byte[] data = new byte[28];
1324
1325 _projectionTextureID.GetBytes().CopyTo(data, 0);
1326 Utils.FloatToBytes(_projectionFOV).CopyTo(data, 16);
1327 Utils.FloatToBytes(_projectionFocus).CopyTo(data, 20);
1328 Utils.FloatToBytes(_projectionAmb).CopyTo(data, 24);
1329
1330 return data;
1331 }
1332
1333
1334 /// <summary>
1335 /// Creates a OpenMetaverse.Primitive and populates it with converted PrimitiveBaseShape values
1336 /// </summary>
1337 /// <returns></returns>
1338 public Primitive ToOmvPrimitive()
1339 {
1340 // position and rotation defaults here since they are not available in PrimitiveBaseShape
1341 return ToOmvPrimitive(new Vector3(0.0f, 0.0f, 0.0f),
1342 new Quaternion(0.0f, 0.0f, 0.0f, 1.0f));
1343 }
1344
1345
1346 /// <summary>
1347 /// Creates a OpenMetaverse.Primitive and populates it with converted PrimitiveBaseShape values
1348 /// </summary>
1349 /// <param name="position"></param>
1350 /// <param name="rotation"></param>
1351 /// <returns></returns>
1352 public Primitive ToOmvPrimitive(Vector3 position, Quaternion rotation)
1353 {
1354 OpenMetaverse.Primitive prim = new OpenMetaverse.Primitive();
1355
1356 prim.Scale = this.Scale;
1357 prim.Position = position;
1358 prim.Rotation = rotation;
1359
1360 if (this.SculptEntry)
1361 {
1362 prim.Sculpt = new Primitive.SculptData();
1363 prim.Sculpt.Type = (OpenMetaverse.SculptType)this.SculptType;
1364 prim.Sculpt.SculptTexture = this.SculptTexture;
1365 }
1366
1367 prim.PrimData.PathShearX = this.PathShearX < 128 ? (float)this.PathShearX * 0.01f : (float)(this.PathShearX - 256) * 0.01f;
1368 prim.PrimData.PathShearY = this.PathShearY < 128 ? (float)this.PathShearY * 0.01f : (float)(this.PathShearY - 256) * 0.01f;
1369 prim.PrimData.PathBegin = (float)this.PathBegin * 2.0e-5f;
1370 prim.PrimData.PathEnd = 1.0f - (float)this.PathEnd * 2.0e-5f;
1371
1372 prim.PrimData.PathScaleX = (200 - this.PathScaleX) * 0.01f;
1373 prim.PrimData.PathScaleY = (200 - this.PathScaleY) * 0.01f;
1374
1375 prim.PrimData.PathTaperX = this.PathTaperX * 0.01f;
1376 prim.PrimData.PathTaperY = this.PathTaperY * 0.01f;
1377
1378 prim.PrimData.PathTwistBegin = this.PathTwistBegin * 0.01f;
1379 prim.PrimData.PathTwist = this.PathTwist * 0.01f;
1380
1381 prim.PrimData.ProfileBegin = (float)this.ProfileBegin * 2.0e-5f;
1382 prim.PrimData.ProfileEnd = 1.0f - (float)this.ProfileEnd * 2.0e-5f;
1383 prim.PrimData.ProfileHollow = (float)this.ProfileHollow * 2.0e-5f;
1384
1385 prim.PrimData.profileCurve = this.ProfileCurve;
1386 prim.PrimData.ProfileHole = (HoleType)this.HollowShape;
1387
1388 prim.PrimData.PathCurve = (PathCurve)this.PathCurve;
1389 prim.PrimData.PathRadiusOffset = 0.01f * this.PathRadiusOffset;
1390 prim.PrimData.PathRevolutions = 1.0f + 0.015f * this.PathRevolutions;
1391 prim.PrimData.PathSkew = 0.01f * this.PathSkew;
1392
1393 prim.PrimData.PCode = OpenMetaverse.PCode.Prim;
1394 prim.PrimData.State = 0;
1395
1396 if (this.FlexiEntry)
1397 {
1398 prim.Flexible = new Primitive.FlexibleData();
1399 prim.Flexible.Drag = this.FlexiDrag;
1400 prim.Flexible.Force = new Vector3(this.FlexiForceX, this.FlexiForceY, this.FlexiForceZ);
1401 prim.Flexible.Gravity = this.FlexiGravity;
1402 prim.Flexible.Softness = this.FlexiSoftness;
1403 prim.Flexible.Tension = this.FlexiTension;
1404 prim.Flexible.Wind = this.FlexiWind;
1405 }
1406
1407 if (this.LightEntry)
1408 {
1409 prim.Light = new Primitive.LightData();
1410 prim.Light.Color = new Color4(this.LightColorR, this.LightColorG, this.LightColorB, this.LightColorA);
1411 prim.Light.Cutoff = this.LightCutoff;
1412 prim.Light.Falloff = this.LightFalloff;
1413 prim.Light.Intensity = this.LightIntensity;
1414 prim.Light.Radius = this.LightRadius;
1415 }
1416
1417 prim.Textures = this.Textures;
1418
1419 prim.Properties = new Primitive.ObjectProperties();
1420 prim.Properties.Name = "Primitive";
1421 prim.Properties.Description = "";
1422 prim.Properties.CreatorID = UUID.Zero;
1423 prim.Properties.GroupID = UUID.Zero;
1424 prim.Properties.OwnerID = UUID.Zero;
1425 prim.Properties.Permissions = new Permissions();
1426 prim.Properties.SalePrice = 10;
1427 prim.Properties.SaleType = new SaleType();
1428
1429 return prim;
1430 }
1431
1432 /// <summary>
1433 /// Encapsulates a list of media entries.
1434 /// </summary>
1435 /// This class is necessary because we want to replace auto-serialization of MediaEntry with something more
1436 /// OSD like and less vulnerable to change.
1437 public class MediaList : List<MediaEntry>, IXmlSerializable
1438 {
1439 public const string MEDIA_TEXTURE_TYPE = "sl";
1440
1441 public MediaList() : base() {}
1442 public MediaList(IEnumerable<MediaEntry> collection) : base(collection) {}
1443 public MediaList(int capacity) : base(capacity) {}
1444
1445 public XmlSchema GetSchema()
1446 {
1447 return null;
1448 }
1449
1450 public string ToXml()
1451 {
1452 lock (this)
1453 {
1454 using (StringWriter sw = new StringWriter())
1455 {
1456 using (XmlTextWriter xtw = new XmlTextWriter(sw))
1457 {
1458 xtw.WriteStartElement("OSMedia");
1459 xtw.WriteAttributeString("type", MEDIA_TEXTURE_TYPE);
1460 xtw.WriteAttributeString("version", "0.1");
1461
1462 OSDArray meArray = new OSDArray();
1463 foreach (MediaEntry me in this)
1464 {
1465 OSD osd = (null == me ? new OSD() : me.GetOSD());
1466 meArray.Add(osd);
1467 }
1468
1469 xtw.WriteStartElement("OSData");
1470 xtw.WriteRaw(OSDParser.SerializeLLSDXmlString(meArray));
1471 xtw.WriteEndElement();
1472
1473 xtw.WriteEndElement();
1474
1475 xtw.Flush();
1476 return sw.ToString();
1477 }
1478 }
1479 }
1480 }
1481
1482 public void WriteXml(XmlWriter writer)
1483 {
1484 writer.WriteRaw(ToXml());
1485 }
1486
1487 public static MediaList FromXml(string rawXml)
1488 {
1489 MediaList ml = new MediaList();
1490 ml.ReadXml(rawXml);
1491 return ml;
1492 }
1493
1494 public void ReadXml(string rawXml)
1495 {
1496 using (StringReader sr = new StringReader(rawXml))
1497 {
1498 using (XmlTextReader xtr = new XmlTextReader(sr))
1499 {
1500 xtr.MoveToContent();
1501
1502 string type = xtr.GetAttribute("type");
1503 //m_log.DebugFormat("[MOAP]: Loaded media texture entry with type {0}", type);
1504
1505 if (type != MEDIA_TEXTURE_TYPE)
1506 return;
1507
1508 xtr.ReadStartElement("OSMedia");
1509
1510 OSDArray osdMeArray = (OSDArray)OSDParser.DeserializeLLSDXml(xtr.ReadInnerXml());
1511 foreach (OSD osdMe in osdMeArray)
1512 {
1513 MediaEntry me = (osdMe is OSDMap ? MediaEntry.FromOSD(osdMe) : new MediaEntry());
1514 Add(me);
1515 }
1516
1517 xtr.ReadEndElement();
1518 }
1519 }
1520 }
1521
1522 public void ReadXml(XmlReader reader)
1523 {
1524 if (reader.IsEmptyElement)
1525 return;
1526
1527 ReadXml(reader.ReadInnerXml());
1528 }
1529 }
1530 }
1531}