00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 using System;
00018 using System.Collections.Generic;
00019 using System.Text;
00020 using Microsoft.DirectX;
00021 using Microsoft.DirectX.Direct3D;
00022 using Microsoft.Samples.DirectX.UtilityToolkit;
00023
00024 namespace DXGfxLib
00025 {
00032 public delegate void NodeMovedEventHandler(SceneNode node);
00033
00040 public class SceneNode
00041 {
00050 public bool useFrustrumCulling;
00051
00057 public static bool defaultForFrustrumCulling = true;
00058
00062 public SceneNode parent = null;
00063
00068 public Scene scene = null;
00069
00073 public string name;
00074
00079 public Vector3[] axes = new Vector3[3];
00080
00084 public Vector3 extents = new Vector3();
00085
00091 public event NodeMovedEventHandler Moved;
00092
00096 public bool moved = true;
00097
00102 internal Matrix worldMat = Matrix.Identity;
00103
00109 public IPositionConstraint positionConstraint = null;
00110
00115 [System.ComponentModel.BrowsableAttribute(false)]
00116 public Matrix WorldMat
00117 {
00118 get { return worldMat; }
00119 set
00120 {
00121 Matrix equivalentWorldTransform = Matrix.Multiply(Matrix.Invert(worldMat), value);
00122 ApplyWorldTransform(equivalentWorldTransform);
00123 }
00124 }
00125
00130 [System.ComponentModel.BrowsableAttribute(false)]
00131 public Vector3 Position
00132 {
00133 get { return MathUtil.PositionFromMat(worldMat); }
00134 set
00135 {
00136 Matrix translation = Matrix.Translation(value.X - worldMat.M41,
00137 value.Y - worldMat.M42,
00138 value.Z - worldMat.M43);
00139 ApplyWorldTransform(translation);
00140 }
00141 }
00142
00146 [System.ComponentModel.CategoryAttribute("Position"),
00147 System.ComponentModel.RefreshProperties( System.ComponentModel.RefreshProperties.Repaint )]
00148 public float X
00149 {
00150 get { return worldMat.M41; }
00151 set
00152 {
00153 Matrix translation = Matrix.Translation(value - worldMat.M41, 0.0f, 0.0f);
00154 ApplyWorldTransform(translation);
00155 }
00156 }
00157
00161 [System.ComponentModel.CategoryAttribute("Position"),
00162 System.ComponentModel.RefreshProperties(System.ComponentModel.RefreshProperties.Repaint)]
00163 public float Y
00164 {
00165 get { return worldMat.M42; }
00166 set
00167 {
00168 Matrix translation = Matrix.Translation(0.0f, value - worldMat.M42, 0.0f);
00169 ApplyWorldTransform(translation);
00170 }
00171 }
00172
00176 [System.ComponentModel.CategoryAttribute("Position"),
00177 System.ComponentModel.RefreshProperties(System.ComponentModel.RefreshProperties.Repaint)]
00178 public float Z
00179 {
00180 get { return worldMat.M43; }
00181 set
00182 {
00183 Matrix translation = Matrix.Translation(0.0f, 0.0f, value - worldMat.M43);
00184 ApplyWorldTransform(translation);
00185 }
00186 }
00187
00192 [System.ComponentModel.BrowsableAttribute(false)]
00193 public Vector3 PositionToParent
00194 {
00195 get { return MathUtil.PositionFromMat(LocalMat); }
00196 set
00197 {
00198 Matrix localMat = LocalMat;
00199 Matrix translation = Matrix.Translation(value.X - localMat.M41,
00200 value.Y - localMat.M42,
00201 value.Z - localMat.M43);
00202 ApplyLocalTransform(translation);
00203 }
00204 }
00205
00210 private double threshold = 0.001;
00211
00216 [System.ComponentModel.BrowsableAttribute(false)]
00217 public Vector3 Orientation
00218 {
00219 get
00220 {
00221 Vector3 ypr = MathUtil.YawPitchRollFromMat(worldMat);
00222
00223 ypr.X = MathUtil.ResetToNullIfTooSmall(ypr.X, threshold);
00224 ypr.Y = MathUtil.ResetToNullIfTooSmall(ypr.Y, threshold);
00225 ypr.Z = MathUtil.ResetToNullIfTooSmall(ypr.Z, threshold);
00226
00227 return ypr;
00228 }
00229 set
00230 {
00231 Vector3 currentOrientation = Orientation;
00232
00233 float yaw = value.X - currentOrientation.X;
00234 float pitch = value.Y - currentOrientation.Y;
00235 float roll = value.Z - currentOrientation.Z;
00236
00237 yaw = MathUtil.ResetToNullIfTooSmall(yaw, threshold);
00238 pitch = MathUtil.ResetToNullIfTooSmall(pitch, threshold);
00239 roll = MathUtil.ResetToNullIfTooSmall(roll, threshold);
00240
00241 Matrix rotation = Matrix.RotationYawPitchRoll(yaw,
00242 pitch,
00243 roll);
00244 ApplyWorldTransform(rotation);
00245 }
00246 }
00247
00251 [System.ComponentModel.CategoryAttribute("Orientation"),
00252 System.ComponentModel.RefreshProperties(System.ComponentModel.RefreshProperties.Repaint)]
00253 public float Yaw
00254 {
00255 get
00256 {
00257 return MathUtil.YawPitchRollFromMatInDegree(worldMat).X;
00258 }
00259 set
00260 {
00261 Vector3 current = Orientation;
00262 Orientation = new Vector3(Geometry.DegreeToRadian(value),
00263 current.Y,
00264 current.Z);
00265 }
00266 }
00267
00271 [System.ComponentModel.CategoryAttribute("Orientation"),
00272 System.ComponentModel.RefreshProperties(System.ComponentModel.RefreshProperties.Repaint)]
00273 public float Pitch
00274 {
00275 get
00276 {
00277 return MathUtil.YawPitchRollFromMatInDegree(worldMat).Y;
00278 }
00279 set
00280 {
00281 Vector3 current = Orientation;
00282 Orientation = new Vector3(current.X,
00283 Geometry.DegreeToRadian(value),
00284 current.Z);
00285 }
00286 }
00287
00291 [System.ComponentModel.CategoryAttribute("Orientation"),
00292 System.ComponentModel.RefreshProperties(System.ComponentModel.RefreshProperties.Repaint)]
00293 public float Roll
00294 {
00295 get
00296 {
00297 return MathUtil.YawPitchRollFromMatInDegree(worldMat).Z;
00298 }
00299 set
00300 {
00301 Vector3 current = Orientation;
00302 Orientation = new Vector3(current.X,
00303 current.Y,
00304 Geometry.DegreeToRadian(value));
00305 }
00306 }
00307
00312 [System.ComponentModel.BrowsableAttribute(false)]
00313 public Vector3 OrientationToParent
00314 {
00315 get
00316 {
00317 return MathUtil.YawPitchRollFromMat(LocalMat);
00318 }
00319 set
00320 {
00321 Vector3 currentOrientation = Orientation;
00322 Matrix rotation = Matrix.RotationYawPitchRoll(value.X - currentOrientation.X,
00323 value.Y - currentOrientation.Y,
00324 value.Z - currentOrientation.Z);
00325 ApplyLocalTransform(rotation);
00326 }
00327 }
00328
00335 public void ForcePositionWithoutUpdate(Vector3 position)
00336 {
00337 Matrix translation = Matrix.Translation(position.X - worldMat.M41,
00338 position.Y - worldMat.M42,
00339 position.Z - worldMat.M43);
00340 Vector3 orientation = Orientation;
00341 worldMat = Matrix.Multiply(Matrix.RotationYawPitchRoll(orientation.X, orientation.Y, orientation.Z),
00342 translation);
00343 OnMove();
00344 }
00345
00351 public void ForceOrientationWithoutUpdate(Vector3 orientation)
00352 {
00353 worldMat = Matrix.Multiply(Matrix.RotationYawPitchRoll(orientation.X, orientation.Y, orientation.Z),
00354 Matrix.Translation(Position));
00355 OnMove();
00356 }
00357
00364 public void ForceWorldMatValueWithoutUpdate(Matrix desiredWorldMat)
00365 {
00366 worldMat = desiredWorldMat;
00367 }
00368
00378 [System.ComponentModel.BrowsableAttribute(false)]
00379 public Matrix LocalMat
00380 {
00381 get
00382 {
00383 Matrix parentMat;
00384
00385 if(parent==null)
00386 {
00387 parentMat = Matrix.Identity;
00388 }
00389 else
00390 {
00391 parentMat = parent.WorldMat;
00392 }
00393 return Matrix.Multiply(worldMat, Matrix.Invert(parentMat));
00394 }
00395 set
00396 {
00397 Matrix newWorldMat;
00398
00399 if (parent == null)
00400 {
00401 newWorldMat = value;
00402 }
00403 else
00404 {
00405 newWorldMat = Matrix.Multiply(value, parent.worldMat);
00406 }
00407
00408 Matrix equivalentWorldTransform = Matrix.Multiply(Matrix.Invert(worldMat), newWorldMat);
00409 ApplyWorldTransform(equivalentWorldTransform);
00410 }
00411 }
00412
00417 public virtual void OnMove()
00418 {
00419 moved = true;
00420
00421 if (Moved != null)
00422 {
00423 Moved(this);
00424 }
00425 UpdateAxes();
00426 UpdateExtents();
00427 }
00428
00432 protected List<SceneNode> children = null;
00433
00437 public AABBox worldAABBox = null;
00438
00442 public SceneNode()
00443 {
00444 Initialize();
00445 }
00446
00447 public virtual void Initialize()
00448 {
00449 if (children == null)
00450 {
00451 children = new List<SceneNode>();
00452 }
00453 if (worldAABBox == null)
00454 {
00455 worldAABBox = new AABBox();
00456 }
00457 useFrustrumCulling = defaultForFrustrumCulling;
00458 }
00459
00465 public SceneNode(SceneNode sceneNode)
00466 {
00467 children = new List<SceneNode>(sceneNode.children);
00468 worldAABBox = sceneNode.worldAABBox;
00469 useFrustrumCulling = sceneNode.useFrustrumCulling;
00470
00471 worldMat = sceneNode.worldMat;
00472
00473 parent = sceneNode.parent;
00474 scene = sceneNode.scene;
00475 }
00476
00477 public virtual void Dispose()
00478 {
00479 foreach (SceneNode node in children)
00480 {
00481 node.Dispose();
00482 }
00483 children.Clear();
00484 children = null;
00485 }
00486
00493 public virtual void AddChild(SceneNode node)
00494 {
00495 if (children != null)
00496 {
00497 children.Add(node);
00498 node.parent = this;
00499 node.scene = scene;
00500 }
00501 }
00502
00509 public virtual void RemoveChild(SceneNode node)
00510 {
00511 if (children != null)
00512 {
00513 children.Remove(node);
00514 node.parent = null;
00515 node.scene = null;
00516 }
00517 }
00518
00525 public virtual void ApplyWorldTransform(Matrix transform)
00526 {
00527 worldMat = Matrix.Multiply(worldMat, transform);
00528
00529
00530
00531
00532
00533 foreach (SceneNode node in children)
00534 {
00535 node.ApplyWorldTransform(transform);
00536 }
00537
00538 OnMove();
00539 }
00540
00546 public void ApplyLocalTransform(Matrix transform)
00547 {
00548 Matrix newWorldMat = Matrix.Multiply(transform, worldMat);
00549
00550 Matrix equivalentWorldTransform = Matrix.Multiply(Matrix.Invert(worldMat), newWorldMat);
00551 ApplyWorldTransform(equivalentWorldTransform);
00552 }
00553
00559 public virtual void GetPrepared()
00560 {
00561 Initialize();
00562 if (children == null)
00563 {
00564 children = new List<SceneNode>();
00565 }
00566
00567 foreach (SceneNode child in children)
00568 {
00569 child.GetPrepared();
00570 }
00571 }
00572
00582 public virtual void Update(Frustrum frustrum, float elapsedTime, double appTime, List<IDrawable> objectsToBeRendered)
00583 {
00584 Update(frustrum, appTime, elapsedTime);
00585 AttachForRendering(frustrum, objectsToBeRendered);
00586 }
00587
00597 public virtual void Update(Frustrum frustrum, double appTime, float elapsedTime)
00598 {
00599
00600 worldAABBox.Reset();
00601 worldAABBox.Transform(worldMat);
00602 foreach (SceneNode child in children)
00603 {
00604 child.Update(frustrum, appTime, elapsedTime);
00605 worldAABBox.BoxFromBoxes(child.worldAABBox);
00606 }
00607 }
00608
00617 public virtual void AttachForRendering(Frustrum frustrum, List<IDrawable> objectsToBeRendered)
00618 {
00619
00620
00621 if (useFrustrumCulling)
00622 {
00623 if(!frustrum.IsInFrustrum(worldAABBox))
00624 return;
00625 }
00626
00627 foreach (SceneNode child in children)
00628 {
00629 child.AttachForRendering(frustrum, objectsToBeRendered);
00630 }
00631 }
00632
00636 public virtual void DetachAll()
00637 {
00638
00639
00640
00641
00642 }
00643
00648 public virtual void Detach(SceneNode sceneNodeToDetach)
00649 {
00650 bool directChild = false;
00651
00652 foreach (SceneNode child in children)
00653 {
00654 if (child == sceneNodeToDetach)
00655 {
00656 directChild = true;
00657 }
00658 }
00659
00660 if (directChild)
00661 {
00662 sceneNodeToDetach.DetachAll();
00663 children.Remove(sceneNodeToDetach);
00664 }
00665 else
00666 {
00667 foreach (SceneNode child in children)
00668 {
00669 child.Detach(sceneNodeToDetach);
00670 }
00671 }
00672 }
00673
00682 public virtual bool Collide(SceneNode sceneNode, ref List<SceneObject> collidingSceneObjects)
00683 {
00684 bool res = false;
00685
00686 if (CollideWithAABox(sceneNode))
00687 {
00688 SceneObject obj = this as SceneObject;
00689 if (obj != null)
00690 {
00691 res = true;
00692 collidingSceneObjects.Add(obj);
00693 }
00694
00695 foreach (SceneNode childNode in children)
00696 {
00697 SceneObject obj2 = childNode as SceneObject;
00698 if (obj2 != null)
00699 {
00700 if (obj2.Collide(sceneNode, ref collidingSceneObjects))
00701 res = true;
00702 }
00703 }
00704 }
00705
00706 return res;
00707 }
00708
00720 public virtual bool CollideSolid(SceneNode sceneNode, ref List<SceneObject> collidingSceneObjects)
00721 {
00722 bool res = false;
00723
00724 if (CollideWithAABox(sceneNode))
00725 {
00726 SceneObject obj = this as SceneObject;
00727 if ((obj != null)&&(obj.Solid))
00728 {
00729 res = true;
00730 collidingSceneObjects.Add(obj);
00731 }
00732
00733 foreach (SceneNode childNode in children)
00734 {
00735 SceneObject obj2 = childNode as SceneObject;
00736 if (obj2 != null)
00737 {
00738 if (obj2.Collide(sceneNode, ref collidingSceneObjects))
00739 res = true;
00740 }
00741 }
00742 }
00743
00744 return res;
00745 }
00746
00754 public virtual bool Collide(SceneNode sceneNode, ref List<SceneObject> collidingSceneObjects, System.Type desiredType)
00755 {
00756 bool res = false;
00757
00758 if (CollideWithAABox(sceneNode))
00759 {
00760 SceneObject obj = this as SceneObject;
00761
00762 if (obj != null)
00763 {
00764 if (this == sceneNode)
00765 return res;
00766 if (!desiredType.IsInstanceOfType(this))
00767 return res;
00768
00769 res = true;
00770 collidingSceneObjects.Add(obj);
00771
00772 }
00773
00774 foreach (SceneNode childNode in children)
00775 {
00776 if (childNode.Collide(sceneNode, ref collidingSceneObjects, desiredType))
00777 res = true;
00778 }
00779 }
00780
00781 return res;
00782 }
00783
00791 public virtual bool CollideSolid(SceneNode sceneNode, ref List<SceneObject> collidingSceneObjects, System.Type desiredType)
00792 {
00793 bool res = false;
00794
00795 if (CollideWithAABox(sceneNode))
00796 {
00797 SceneObject obj = this as SceneObject;
00798
00799 if ((obj != null)&&(obj.Solid))
00800 {
00801 if (this == sceneNode)
00802 return res;
00803 if (!desiredType.IsInstanceOfType(this))
00804 return res;
00805
00806 res = true;
00807 collidingSceneObjects.Add(obj);
00808
00809 }
00810
00811 foreach (SceneNode childNode in children)
00812 {
00813 if (childNode.Collide(sceneNode, ref collidingSceneObjects, desiredType))
00814 res = true;
00815 }
00816 }
00817
00818 return res;
00819 }
00820
00827 public bool CollideWithAABox(SceneNode sceneNode)
00828 {
00829 return this.worldAABBox.Collide(sceneNode.worldAABBox);
00830 }
00831
00835 public void UpdateAxes()
00836 {
00837 if(axes==null)
00838 axes = new Vector3[3];
00839
00840 axes[0].X = worldMat.M11;
00841 axes[0].Y = worldMat.M12;
00842 axes[0].Z = worldMat.M13;
00843
00844 axes[1].X = worldMat.M21;
00845 axes[1].Y = worldMat.M22;
00846 axes[1].Z = worldMat.M23;
00847
00848 axes[2].X = worldMat.M31;
00849 axes[2].Y = worldMat.M32;
00850 axes[2].Z = worldMat.M33;
00851 }
00852
00857 public Vector3[] Axes()
00858 {
00859 return axes;
00860 }
00861
00867 public void UpdateExtents()
00868 {
00869 Vector3 diag = worldAABBox.vMax - worldAABBox.vMin;
00870
00871 extents.X = System.Math.Abs(Vector3.Dot(diag, axes[0]));
00872 extents.Y = System.Math.Abs(Vector3.Dot(diag, axes[1]));
00873 extents.Z = System.Math.Abs(Vector3.Dot(diag, axes[2]));
00874 }
00875
00880 public Vector3 Extents()
00881 {
00882 return extents;
00883 }
00884
00892 public virtual bool Intersect(Vector3 rayOri, Vector3 rayDir, ref List<SceneObject> collidingSceneObjects)
00893 {
00894 bool any = false;
00895
00896 AABBox aabox = worldAABBox;
00897 bool collision = true;
00898 if (((rayOri.X < aabox.vMin.X) && (rayDir.X <= 0))
00899 || ((rayOri.X > aabox.vMax.X) && (rayDir.X >= 0)))
00900 collision = false;
00901 if (((rayOri.Y < aabox.vMin.Y) && (rayDir.Y <= 0))
00902 || ((rayOri.Y > aabox.vMax.Y) && (rayDir.Y >= 0)))
00903 collision = false;
00904 if (((rayOri.Z < aabox.vMin.Z) && (rayDir.Z <= 0))
00905 || ((rayOri.Z > aabox.vMax.Z) && (rayDir.Z >= 0)))
00906 collision = false;
00907
00908 if (collision)
00909 {
00910 foreach (SceneNode child in children)
00911 {
00912 if (child.Intersect(rayOri, rayDir, ref collidingSceneObjects))
00913 any = true;
00914 }
00915 }
00916
00917 return any;
00918 }
00919
00928 public virtual bool Intersect(Vector3 rayOri, Vector3 rayDir, ref List<SceneObject> collidingSceneObjects, System.Type desiredType)
00929 {
00930 bool any = false;
00931
00932 AABBox aabox = worldAABBox;
00933 bool collision = true;
00934 if (((rayOri.X < aabox.vMin.X) && (rayDir.X <= 0))
00935 || ((rayOri.X > aabox.vMax.X) && (rayDir.X >= 0)))
00936 collision = false;
00937 if (((rayOri.Y < aabox.vMin.Y) && (rayDir.Y <= 0))
00938 || ((rayOri.Y > aabox.vMax.Y) && (rayDir.Y >= 0)))
00939 collision = false;
00940 if (((rayOri.Z < aabox.vMin.Z) && (rayDir.Z <= 0))
00941 || ((rayOri.Z > aabox.vMax.Z) && (rayDir.Z >= 0)))
00942 collision = false;
00943
00944 if (collision)
00945 {
00946 foreach (SceneNode child in children)
00947 {
00948 if (child.Intersect(rayOri, rayDir, ref collidingSceneObjects, desiredType))
00949 any = true;
00950 }
00951 }
00952
00953 return any;
00954 }
00955 }
00956 }