diff options
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Framework/PrimitiveBaseShape.cs | 1531 |
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 | |||
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, | ||
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 | } | ||