- Main Page
- Packages
- Classes
- Files

- File List
- File Members

# D:/guillaume/guillara/3D/DXGfx/DXGfxLib/SceneNode.cs

Go to the documentation of this file.

    00001 //BSD License
    00002 //DXGfx® - http://www.eteractions.com
    00003 //Copyright (c) 2005
    00004 //by Guillaume Randon
    00005 //Permission is hereby granted, free of charge, to any person obtaining a copy of this software
    00006 //and associated documentation files (the "Software"), to deal in the Software without restriction,
    00007 //including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
    00008 //and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
    00009 //subject to the following conditions:
    00010 //The above copyright notice and this permission notice shall be included in all copies or substantial
    00011 //portions of the Software.
    00012 //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
    00013 //INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
    00014 //AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
    00015 //DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    00016 //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    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             // Let's update our children if we have any.
    00530             // We apply the same world transform on the children.
    00531             // !!!!!!!!!!! This need to be done after the update of the worldMat, as in any
    00532             // children we will use parent.worldMat to compute localMat !!!!!!!!!!!!!!!
    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             // If we are in the frustrum let's our children decide for
    00620             // themselves.
    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             //foreach (SceneNode child in children)
    00639             //{
    00640             //    child.DetachAll();
    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 }