- Main Page
- Packages
- Classes
- Files

- File List
- File Members

# D:/guillaume/guillara/3D/DXGfx/Backup/DXGfxLib/OutDoorScene.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;
    00019 using System.Collections.Generic;
    00020 using System.Collections.Specialized;
    00021 using System.Text;
    00022 using System.Drawing;
    00023 using System.Diagnostics;
    00024 using Microsoft.DirectX;
    00025 using Microsoft.DirectX.Direct3D;
    00026 using Microsoft.Samples.DirectX.UtilityToolkit;
    00027
    00028 namespace DXGfxLib
    00029 {
    00038     public class OutDoorScene : Scene, IPositionConstraint
    00039     {
    00040         #region MovedFromDXGfxManager
    00045         public Avatar CurrentAvatar
    00046         {
    00047             get
    00048             {
    00049                 return currentInputHandler.CurrentAvatar;
    00050             }
    00051             set
    00052             {
    00053                 CurrentInputHandler.CurrentAvatar = value;
    00054                 CurrentCamera.Person = currentInputHandler.CurrentAvatar.associatedSceneObject;
    00055                 avatarName = currentInputHandler.CurrentAvatar.associatedSceneObject.name;
    00056
    00057                 CurrentCamera.camera.positionConstraint = this;
    00058                 CurrentCamera.Person.positionConstraint = this;
    00059             }
    00060         }
    00061
    00062         public string avatarName = "";
    00063
    00064         private ThirdPersonCamera currentCamera = null;
    00065
    00066         public ThirdPersonCamera CurrentCamera
    00067         {
    00068             get
    00069             {
    00070                 if (currentCamera == null)
    00071                     currentCamera = new ThirdPersonCamera();
    00072
    00073                 return currentCamera;
    00074             }
    00075             set
    00076             {
    00077                 currentCamera = value;
    00078             }
    00079         }
    00080
    00081         public Frustrum frustrum = null;
    00082
    00083         public Matrix matView;
    00084         public Matrix matProj;
    00085
    00090         private IInputHandler currentInputHandler = null;
    00091
    00092         public IInputHandler CurrentInputHandler
    00093         {
    00094             get
    00095             {
    00096                 if (currentInputHandler == null)
    00097                 {
    00098                     currentInputHandler = new PointAndClickHandler();
    00099                 }
    00100                 return currentInputHandler;
    00101             }
    00102             set
    00103             {
    00104                 currentInputHandler = value;
    00105             }
    00106         }
    00107         #endregion
    00108
    00109         // For  refraction reflection
    00110         private Texture backBufferTex = null;
    00111         private Texture reflectionMap = null;
    00112         private RenderToSurface rts = null;
    00113         private Plane reflectPlane;
    00114         private Rectangle rect;
    00115
    00120         public float cameraHeightOffset = 3.0f;
    00121
    00125         internal QuadTreeNode[][] nodes = null;
    00126
    00130         private int[] levelNumCells;
    00131
    00135         private float[] sizeOfCells;
    00136
    00140         public int depth = -1;
    00141
    00147         public const int maxDepth = 8;
    00148
    00154         private List<SceneNode> nodesToPositionInTree = null;
    00155
    00156
    00157         private Vector3 scale;
    00158         private Vector3 extents;
    00159
    00163         public Vector3 Extents
    00164         {
    00165             get { return extents; }
    00166         }
    00167
    00171         private AABBox worldAABBox;
    00172
    00176         private const int numDimCells = 256;
    00177
    00181         private const int numHeigthCells = 32;
    00182
    00186         private Terrain sceneTerrain;
    00187
    00191         public Terrain SceneTerrain
    00192         {
    00193             get { return sceneTerrain; }
    00194             set { sceneTerrain = value; }
    00195         }
    00196
    00197
    00202         private Water2 sceneWater;
    00203
    00207         public Water2 SceneWater
    00208         {
    00209             set { sceneWater = value; }
    00210             get { return sceneWater; }
    00211         }
    00212
    00216         private SkyDome sceneSky;
    00217
    00221         public SkyDome SceneSky
    00222         {
    00223             set { sceneSky = value; }
    00224             get { return sceneSky; }
    00225         }
    00226
    00227         public Texture env = null;
    00228
    00229         private Effect refractionMaskEffect = null;
    00230
    00240                 public OutDoorScene(AABBox worldBBox, int depth) : base()
    00241                 {
    00242             Initialize(worldBBox, depth);
    00243         }
    00244
    00245         public void Initialize(AABBox worldBBox, int depth)
    00246         {
    00247             base.Initialize();
    00248
    00249                         nodesToPositionInTree = new List<SceneNode>();
    00250
    00251                         if(depth>maxDepth)
    00252                                 depth=maxDepth;
    00253
    00254                         this.depth = depth;
    00255                         this.extents = worldBBox.Size();
    00256
    00257                         this.worldAABBox = worldBBox;
    00258
    00259                         scale.X = numDimCells/extents.X;
    00260                         scale.Z = numDimCells/extents.Z;
    00261                         scale.Y = numHeigthCells/extents.Y;
    00262
    00263                         nodes = new QuadTreeNode[depth+1][];
    00264                         levelNumCells = new int[depth+1];
    00265                         sizeOfCells = new float[depth+1];
    00266
    00267                         for(int i=0; i<depth+1; i++)
    00268                         {
    00269                                 levelNumCells[i] = (int)(System.Math.Pow(2, i));
    00270                                 sizeOfCells[i] = extents.X / levelNumCells[i];
    00271                                 nodes[i] = new QuadTreeNode[levelNumCells[i]*levelNumCells[i]];
    00272                         }
    00273
    00274                         nodes[0][0] = new QuadTreeNode();
    00275                         rootNode = nodes[0][0];
    00276             rootNode.scene = this;
    00277             rootNode.Moved +=new NodeMovedEventHandler(RegisterForPositionUpdate);
    00278                         rootNode.worldAABBox.vMin.X = worldBBox.vMin.X;
    00279                         rootNode.worldAABBox.vMin.Y = worldBBox.vMin.Y;
    00280                         rootNode.worldAABBox.vMin.Z = worldBBox.vMin.Z;
    00281
    00282                         rootNode.worldAABBox.vMax.X = worldBBox.vMax.X;
    00283                         rootNode.worldAABBox.vMax.Y = worldBBox.vMax.Y;
    00284                         rootNode.worldAABBox.vMax.Z = worldBBox.vMax.Z;
    00285
    00286                         for(int i=1; i<depth+1; i++)
    00287                         {
    00288                                 for(int z=0; z<levelNumCells[i]; z++)
    00289                                 {
    00290                                         for(int x=0; x<levelNumCells[i]; x++)
    00291                                         {
    00292                                                 QuadTreeNode tmpNode = new QuadTreeNode();
    00293                         tmpNode.Moved +=new NodeMovedEventHandler(RegisterForPositionUpdate);
    00294                                                 AABBox tmpBBox = new AABBox();
    00295                                                 tmpBBox.vMin.Y = this.worldAABBox.vMin.Y;
    00296                                                 tmpBBox.vMax.Y = this.worldAABBox.vMax.Y;
    00297
    00298                                                 tmpBBox.vMin.X = this.worldAABBox.vMin.X + (this.extents.X / (levelNumCells[i])) * x;
    00299                                                 tmpBBox.vMax.X = this.worldAABBox.vMin.X + (this.extents.X / (levelNumCells[i])) * (x+1);
    00300
    00301                                                 tmpBBox.vMin.Z = this.worldAABBox.vMin.Z + (this.extents.Z / (levelNumCells[i])) * (z);
    00302                                                 tmpBBox.vMax.Z = this.worldAABBox.vMin.Z + (this.extents.Z / (levelNumCells[i])) * (z+1);
    00303
    00304                                                 tmpNode.worldAABBox = tmpBBox;
    00305                         tmpNode.ForceWorldMatValueWithoutUpdate(Matrix.Translation(tmpBBox.MinPoint()));
    00306
    00307                                                 nodes[i][x+z*levelNumCells[i]] = tmpNode;
    00308
    00309                                                 int xParent = (int)System.Math.Floor((double)x/2);
    00310                                                 int zParent = (int)System.Math.Floor((double)z/2);
    00311                                                 (nodes[i-1][xParent+zParent*levelNumCells[i-1]]).AddChild(tmpNode);
    00312                                         }
    00313                                 }
    00314                         }
    00315                 }
    00316
    00317         private void InitRefractionReflection()
    00318         {
    00319             Device dev = DXGfxManager.GetGlobalInstance().d3dDevice;
    00320             SurfaceDescription backBufferDescription = DXGfxManager.GetGlobalInstance().backBufferDescription;
    00321
    00322             reflectPlane = Microsoft.DirectX.Plane.FromPointNormal(new Vector3(0, 0.0f, 0), new Vector3(0, 1, 0));
    00323
    00324             reflectionMap = new Texture(dev, backBufferDescription.Width, backBufferDescription.Height, 1, Usage.RenderTarget, backBufferDescription.Format, Pool.Default);
    00325             backBufferTex = new Texture(dev, backBufferDescription.Width, backBufferDescription.Height, 1, Usage.RenderTarget, backBufferDescription.Format, Pool.Default);
    00326             rts = new RenderToSurface(dev, backBufferDescription.Width, backBufferDescription.Height, backBufferDescription.Format, true, DepthFormat.D16);
    00327             rect = new Rectangle(0, 0, backBufferDescription.Width, backBufferDescription.Height);
    00328         }
    00329
    00330         public override void GetPrepared()
    00331         {
    00332             IDictionaryEnumerator sceneObjects = sceneContent.GetEnumerator();
    00333
    00334             while (sceneObjects.MoveNext())
    00335             {
    00336                 SceneObject currObj = sceneObjects.Value as SceneObject;
    00337                 if ((currObj != null)&&(currObj.GetType()!=typeof(Water))&&(currObj.GetType()!=typeof(SkyBox))&&
    00338                     (currObj.GetType() != typeof(Water2)) && (currObj.GetType() != typeof(SkyDome)))
    00339                 {
    00340                     currObj.GetPrepared();
    00341                     Attach(currObj);
    00342                 }
    00343             }
    00344
    00345             if (sceneSky != null)
    00346             {
    00347                 sceneSky.GetPrepared();
    00348             }
    00349             if (sceneWater != null)
    00350             {
    00351                 sceneWater.GetPrepared();
    00352             }
    00353
    00354             if (avatarName != "")
    00355             {
    00356                 CurrentAvatar = new Avatar(sceneContent[avatarName] as SceneObject);
    00357             }
    00358         }
    00359
    00360         public override void Dispose()
    00361         {
    00362             if (currentInputHandler != null)
    00363             {
    00364                 currentInputHandler.Dispose();
    00365                 currentInputHandler = null;
    00366             }
    00367             if (rootNode != null)
    00368             {
    00369             }
    00370         }
    00371
    00380         public void ValidateOrMove(ref SceneNode node)
    00381         {
    00382             ValidateOrMove(ref node, 0);
    00383         }
    00384
    00392         public void ValidateOrMove(ref SceneNode node, float offset)
    00393         {
    00394             Vector3 pos = node.Position;
    00395             float y = GetHeigth(pos.X, pos.Z)+offset;
    00396             if ((y > pos.Y) && (y < 1000))
    00397             {
    00398                 pos.Y = y;
    00399                 node.Position = pos;
    00400             }
    00401         }
    00402
    00413         public Matrix ValidateOrMove(Vector3 pos, BBox localBBox)
    00414         {
    00415             Matrix res = Matrix.Identity;
    00416
    00417             float y = GetHeigth(pos.X, pos.Z) + 0.5f * localBBox.Size().Y;
    00418             if ((y > pos.Y) && (y < 1000))
    00419             {
    00420                 res = Matrix.Translation(0.0f, y - pos.Y, 0.0f);
    00421             }
    00422
    00423             return res;
    00424         }
    00425
    00431         public void ValidateCameraOrMove(ref SceneNode camera, ref SceneNode subject)
    00432         {
    00433             // First let's validate or move our two nodes
    00434             ValidateOrMove(ref subject);
    00435             ValidateOrMove(ref camera, 3.0f);
    00436         }
    00437
    00443         public virtual void DeviceChanged(Device d3ddevice)
    00444         {
    00445             sceneTerrain.DeviceChanged(d3ddevice, this);
    00446             defaultState = null;
    00447         }
    00448
    00456         public float GetHeigth(float x, float z)
    00457         {
    00458             float heigth = 0.0f;
    00459
    00460             if (sceneTerrain != null)
    00461             {
    00462                 heigth = sceneTerrain.GetHeigth(this, x, z);
    00463             }
    00464             return heigth;
    00465         }
    00466
    00479         public override void Update(double appTime, float elapsedTime, Frustrum frustrum, List<IDrawable> objectsToBeRendered)
    00480         {
    00481             this.frustrum = frustrum;
    00482
    00483             base.Update(appTime, elapsedTime, frustrum, objectsToBeRendered);
    00484
    00485             if (sceneWater != null)
    00486             {
    00487                 sceneWater.Update(frustrum, appTime, elapsedTime);
    00488             }
    00489
    00490             if (sceneSky != null)
    00491             {
    00492                 sceneSky.Update(frustrum, appTime, elapsedTime);
    00493             }
    00494
    00495             UpdatePositionInTree();
    00496         }
    00497
    00498         public void Update(Device d3ddevice, double appTime, float elapsedTime)
    00499         {
    00500             matView = Matrix.Multiply(currentCamera.WorldMatrix, currentCamera.ViewMatrix);
    00501             matProj = currentCamera.ProjectionMatrix;
    00502             Update(d3ddevice, matView, currentCamera.ProjectionMatrix, appTime, elapsedTime);
    00503         }
    00504
    00505         public override void RenderScene(Device d3ddevice, Frustrum frustrum)
    00506         {
    00507             d3ddevice.SetTransform(TransformType.World, Matrix.Identity);
    00508             RenderScene(d3ddevice, frustrum.matView, frustrum.matProj);
    00509         }
    00510
    00516         public override void RenderScene(Device d3ddevice, Matrix matView, Matrix matProj)
    00517         {
    00518             d3ddevice.SetTransform(TransformType.World, Matrix.Identity);
    00519
    00520             if (SceneWater != null)
    00521             {
    00522                 CheckRefractionReflectionReady();
    00523                 CreateReflectionMap(d3ddevice);
    00524             }
    00525
    00526             // Clear the render target and the zbuffer
    00527             d3ddevice.Clear(ClearFlags.ZBuffer | ClearFlags.Target, 0x002D32AA, 1.0f, 0);
    00528             d3ddevice.Transform.World = Matrix.Identity;
    00529             d3ddevice.Transform.View = matView;
    00530             d3ddevice.Transform.Projection = matProj;
    00531
    00532                 d3ddevice.BeginScene();
    00533
    00534             RenderObjectAndSky(d3ddevice);
    00535
    00536             if (SceneWater != null)
    00537             {
    00538                 CreateRefractionMap(d3ddevice);
    00539                 SceneWater.Render(d3ddevice, backBufferTex, reflectionMap);
    00540             }
    00541
    00542                 d3ddevice.EndScene();
    00543         }
    00544
    00545         public void CheckRefractionReflectionReady()
    00546         {
    00547             if ((reflectionMap == null) || (backBufferTex == null))
    00548             {
    00549                 InitRefractionReflection();
    00550             }
    00551         }
    00552
    00553         private void RenderObjectAndSky(Device d3ddevice)
    00554         {
    00555
    00556             RenderObjects(d3ddevice);
    00557
    00558             if (sceneSky != null)
    00559             {
    00560                 sceneSky.RenderSky(d3ddevice);
    00561                 //int skyPasses = sceneSky.AssociatedEffectGroup.Default.Begin(0);
    00562                 //for (int skyPass = 0; skyPass < skyPasses; skyPass++)
    00563                 //{
    00564                 //    sceneSky.AssociatedEffectGroup.Default.BeginPass(skyPass);
    00565                 //    sceneSky.Draw(d3ddevice);
    00566                 //    sceneSky.AssociatedEffectGroup.Default.EndPass();
    00567                 //}
    00568                 //sceneSky.AssociatedEffectGroup.Default.End();
    00569             }
    00570         }
    00571
    00572         private void RenderObjects(Device d3ddevice)
    00573         {
    00574             EffectGroup nextEG = DXGfxManager.GetGlobalInstance().defaultEffectGroup;
    00575             EffectGroup currentEG = null;
    00576             int startAt = 0;
    00577
    00578             while ((nextEG != null) && (objectsToBeRendered.Count > 0))
    00579             {
    00580                 currentEG = nextEG;
    00581                 int passes = currentEG.Default.Begin(0);
    00582                 bool lastPassDone = false;
    00583
    00584                 for (int pass = 0; pass < passes; pass++)
    00585                 {
    00586                     currentEG.Default.BeginPass(pass);
    00587
    00588                     for (int i = startAt; i < objectsToBeRendered.Count; i++)
    00589                     {
    00590                         if (currentEG.CompareTo(objectsToBeRendered[i].AssociatedEffectGroup) == 0)
    00591                         {
    00592                             objectsToBeRendered[i].SetEffectsValues(d3ddevice, currentEG.Default, pass);
    00593
    00594                             objectsToBeRendered[i].Draw(d3ddevice);
    00595
    00596                         }
    00597                         else
    00598                         {
    00599                             if (pass == passes - 1)
    00600                             {
    00601                                 nextEG = objectsToBeRendered[i].AssociatedEffectGroup;
    00602                                 startAt = i;
    00603                                 lastPassDone = true;
    00604                             }
    00605                             break;
    00606                         }
    00607
    00608                         if (i == objectsToBeRendered.Count - 1)
    00609                         {
    00610                             // If we are here we have rendered everything so just set effectToUse==null
    00611                             // to avoid rendering everything again.
    00612                             nextEG = null;
    00613                         }
    00614                     }
    00615                     currentEG.Default.EndPass();
    00616
    00617                     // We have two different situation to deal with here.
    00618                     // If this is the last pass then change nextEG and startAt.
    00619                     // else just break to draw all the objects that have been rendered
    00620                     // but with second pass of the defaul effect.
    00621                     if (lastPassDone)
    00622                     {
    00623                         break;
    00624                     }
    00625
    00626
    00627                 }
    00628                 currentEG.Default.End();
    00629             }
    00630             TerrainTile.settedPass = -1;
    00631         }
    00632
    00633         public void CreateRefractionMap(Device device)
    00634         {
    00635             device.RenderState.ZBufferFunction = Compare.LessEqual;
    00636             device.RenderState.ColorWriteEnable = ColorWriteEnable.Alpha;
    00637
    00638             if (refractionMaskEffect == null)
    00639             {
    00640                 DXGfxManager.GetGlobalInstance().LoadEffect(device, "RefeactionMaskHLSL.fx", ref refractionMaskEffect);
    00641             }
    00642
    00643             refractionMaskEffect.SetValue("g_WorldViewProj", SceneWater.WorldMat * frustrum.matView * frustrum.matProj);
    00644             refractionMaskEffect.Technique = "RenderRefractionMask14";
    00645
    00646             device.VertexFormat = CustomVertex.PositionNormalTextured.Format;
    00647             // Water
    00648             device.Transform.World = SceneWater.WorldMat;
    00649             device.SetStreamSource(0, SceneWater.waterVBuff, 0);
    00650             device.Indices = SceneWater.waterIBuff;
    00651
    00652             // Apply the technique contained in the effect
    00653             int passes = refractionMaskEffect.Begin(0);
    00654             for (int pass = 0; pass < passes; pass++)
    00655             {
    00656                 refractionMaskEffect.BeginPass(pass);
    00657
    00658                 // Draw the mesh subset
    00659                 device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, SceneWater.numberVertices, 0, SceneWater.numberTri);
    00660
    00661                 refractionMaskEffect.EndPass();
    00662             }
    00663             refractionMaskEffect.End();
    00664             device.RenderState.ColorWriteEnable = ColorWriteEnable.RedGreenBlueAlpha;
    00665
    00666             device.StretchRectangle(device.GetBackBuffer(0, 0, BackBufferType.Mono),
    00667                 rect, backBufferTex.GetSurfaceLevel(0), rect, TextureFilter.Linear);
    00668         }
    00669
    00670         public void CreateReflectionMap(Device device)
    00671         {
    00672             bool fogStatus = device.RenderState.FogEnable;
    00673             device.RenderState.FogEnable = false;
    00674
    00675             Surface surface = reflectionMap.GetSurfaceLevel(0);
    00676
    00677             Viewport view = new Viewport();
    00678             view.Width = DXGfxManager.GetGlobalInstance().backBufferDescription.Width;
    00679             view.Height = DXGfxManager.GetGlobalInstance().backBufferDescription.Height;
    00680             view.MaxZ = 1.0f;
    00681
    00682             rts.BeginScene(surface, view);
    00683
    00684             device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, 0x00efefff, 1.0f, 0);
    00685
    00686
    00687             // Do magic reflection stuff
    00688             Matrix reflectViewMatrix = Matrix.Identity;
    00689             reflectViewMatrix.Reflect(reflectPlane);
    00690             reflectViewMatrix = reflectViewMatrix * frustrum.matView;
    00691
    00692             device.Transform.View = reflectViewMatrix;
    00693             device.Transform.Projection = frustrum.matProj;
    00694
    00695             device.ClipPlanes[0].Enabled = true;
    00696             device.ClipPlanes[0].Plane = reflectPlane;
    00697             device.RenderState.Clipping = true;
    00698
    00699             // render scene
    00700             RenderObjectAndSky(device);
    00701
    00702             // reset render states
    00703             device.RenderState.Clipping = false;
    00704             device.ClipPlanes[0].Enabled = false;
    00705
    00706             // end RTS
    00707             rts.EndScene(Filter.None);
    00708
    00709             device.RenderState.FogEnable = fogStatus;
    00710         }
    00711
    00721         public QuadTreeNode GetNode(int level, int x, int z)
    00722         {
    00723             QuadTreeNode res = null;
    00724
    00725             if ((level <= depth) && (x < levelNumCells[level]) && (z < levelNumCells[level]))
    00726                 res = nodes[level][x + z * levelNumCells[level]];
    00727
    00728             if (res == null)
    00729                 res = rootNode as QuadTreeNode;
    00730
    00731             return res;
    00732         }
    00733
    00743         public SceneNode GetParent(BBox boundingBox)
    00744         {
    00745             // Guess what, if we are not passed a valid boundingbox we just return the rootNode.
    00746             if (boundingBox == null)
    00747             {
    00748                 return rootNode;
    00749             }
    00750
    00751             int xMinEnclosedRow;
    00752             int xMaxEnclosedRow;
    00753
    00754             int zMinEnclosedRow;
    00755             int zMaxEnclosedRow;
    00756
    00757             AABBox aaBox = new AABBox(boundingBox);
    00758
    00759             aaBox.vMin += new Vector3(0.01f, 0.01f, 0.01f);
    00760             aaBox.vMax -= new Vector3(0.01f, 0.01f, 0.01f);
    00761
    00762             xMinEnclosedRow = (int)System.Math.Floor(((aaBox.vMin.X - this.worldAABBox.vMin.X) / extents.X) * numDimCells);
    00763             xMaxEnclosedRow = (int)System.Math.Floor(((aaBox.vMax.X - this.worldAABBox.vMin.X) / extents.X) * numDimCells);
    00764
    00765             zMinEnclosedRow = (int)System.Math.Floor(((aaBox.vMin.Z - this.worldAABBox.vMin.Z) / extents.Z) * numDimCells);
    00766             zMaxEnclosedRow = (int)System.Math.Floor(((aaBox.vMax.Z - this.worldAABBox.vMin.Z) / extents.Z) * numDimCells);
    00767
    00768             xMinEnclosedRow = (int)MathUtil.Clamp(xMinEnclosedRow, 0, 255);
    00769             xMaxEnclosedRow = (int)MathUtil.Clamp(xMaxEnclosedRow, xMinEnclosedRow + 1, 255);
    00770
    00771             zMinEnclosedRow = (int)MathUtil.Clamp(zMinEnclosedRow, 0, 255);
    00772             zMaxEnclosedRow = (int)MathUtil.Clamp(zMaxEnclosedRow, zMinEnclosedRow + 1, 255);
    00773
    00774             int xPattern = (xMinEnclosedRow ^ xMaxEnclosedRow);
    00775             int zPattern = (zMinEnclosedRow ^ zMaxEnclosedRow);
    00776
    00777             int bitPattern = System.Math.Max(xPattern, zPattern);
    00778
    00779             BitVector32 bitVec = new BitVector32(bitPattern);
    00780             int myBit1 = BitVector32.CreateMask();
    00781             int myBit2 = BitVector32.CreateMask(myBit1);
    00782             int myBit3 = BitVector32.CreateMask(myBit2);
    00783             int myBit4 = BitVector32.CreateMask(myBit3);
    00784             int myBit5 = BitVector32.CreateMask(myBit4);
    00785             int myBit6 = BitVector32.CreateMask(myBit5);
    00786             int myBit7 = BitVector32.CreateMask(myBit6);
    00787             int myBit8 = BitVector32.CreateMask(myBit7);
    00788
    00789             int destLevel = 0;
    00790
    00791             if (bitVec[myBit1])
    00792                 destLevel = maxDepth - 1;
    00793             if (bitVec[myBit2])
    00794                 destLevel = maxDepth - 2;
    00795             if (bitVec[myBit3])
    00796                 destLevel = maxDepth - 3;
    00797             if (bitVec[myBit4])
    00798                 destLevel = maxDepth - 4;
    00799             if (bitVec[myBit5])
    00800                 destLevel = maxDepth - 5;
    00801             if (bitVec[myBit6])
    00802                 destLevel = maxDepth - 6;
    00803             if (bitVec[myBit7])
    00804                 destLevel = maxDepth - 7;
    00805             if (bitVec[myBit8])
    00806                 destLevel = maxDepth - 8;
    00807
    00808             destLevel = (int)MathUtil.Clamp(destLevel, 0, depth);
    00809
    00810             int x = (int)System.Math.Floor(((aaBox.vMin.X - this.worldAABBox.vMin.X) / extents.X) * levelNumCells[destLevel]);
    00811             int z = (int)System.Math.Floor(((aaBox.vMin.Z - this.worldAABBox.vMin.Z) / extents.Z) * levelNumCells[destLevel]);
    00812
    00813             SceneNode res = GetNode(destLevel, (int)MathUtil.Clamp(x, 0, levelNumCells[destLevel]),
    00814                 (int)MathUtil.Clamp(z, 0, levelNumCells[destLevel]));
    00815
    00816             if (aaBox.IsInside(res.worldAABBox))
    00817             {
    00818                 return res;
    00819             }
    00820             else
    00821             {
    00822                 return rootNode;
    00823             }
    00824         }
    00825
    00832         public SceneNode GetParent(SceneNode node)
    00833         {
    00834             return GetParent(node.worldAABBox);
    00835         }
    00836
    00842         public void RegisterForPositionUpdate(SceneNode node)
    00843         {
    00844             // Check a simple check! QuadTree nodes should not move in the tree.
    00845             // SceneNode can move but QuedTree nodes are not expected to move!
    00846             // Let's check it
    00847             QuadTreeNode testNode = node as QuadTreeNode;
    00848             if (testNode != null)
    00849             {
    00850                 throw new ArgumentException("Any SceneNode can move but we don't expect to see quadtree nodes here!?");
    00851             }
    00852
    00853             nodesToPositionInTree.Add(node);
    00854         }
    00855
    00861         public void UpdatePositionInTree()
    00862         {
    00863             foreach (SceneNode tmpNode in this.nodesToPositionInTree)
    00864             {
    00865                 SceneNode oldParent = tmpNode.parent;
    00866                 SceneNode newParent = GetParent(tmpNode);
    00867
    00868                 if (oldParent == null)
    00869                 {
    00870                     throw new NullReferenceException("This should not ever happen!");
    00871                 }
    00872                 if (newParent == null)
    00873                 {
    00874                     throw new NullReferenceException("This should not ever happen!");
    00875                 }
    00876                 if (oldParent != newParent)
    00877                 {
    00878                     oldParent.RemoveChild(tmpNode);
    00879                     newParent.AddChild(tmpNode);
    00880                 }
    00881             }
    00882             this.nodesToPositionInTree.Clear();
    00883         }
    00884
    00892         public override void Attach(SceneObject sceneObj)
    00893         {
    00894             SceneNode parent = GetParent(sceneObj);
    00895             sceneObj.parent = parent;
    00896             sceneObj.scene = this;
    00897             parent.AddChild(sceneObj);
    00898         }
    00899
    00907         public virtual void AttachStatic(SceneObject sceneObj)
    00908         {
    00909             TerrainTile tile = sceneTerrain.FindTile(this, sceneObj.Position.X, sceneObj.Position.Z);
    00910             tile.AddChild(sceneObj);
    00911         }
    00912
    00913         struct BatchInterm
    00914         {
    00915             public Mesh theMesh;
    00916             public Material[] materials;
    00917             public Texture[] textures;
    00918             public List<Matrix> matrices;
    00919         }
    00920
    00928         public virtual void AttachBatch(Mesh mesh, Material[] materials, Texture[] textures, Matrix[] matrices)
    00929         {
    00930             Hashtable tmpBatches = new Hashtable();
    00931
    00932             foreach (Matrix mat in matrices)
    00933             {
    00934                 TerrainTile tile = sceneTerrain.FindTile(this, mat.M41, mat.M43);
    00935
    00936
    00937
    00938                 if (tmpBatches.ContainsKey(tile))
    00939                 {
    00940                     BatchInterm interm = (BatchInterm)tmpBatches[tile];
    00941                     interm.matrices.Add(mat);
    00942                 }
    00943                 else
    00944                 {
    00945                     BatchInterm interm = new BatchInterm();
    00946                     interm.theMesh = mesh;
    00947                     interm.materials = materials;
    00948                     interm.textures = textures;
    00949                     interm.matrices = new List<Matrix>();
    00950                     interm.matrices.Add(mat);
    00951                     tmpBatches.Add(tile, interm);
    00952                 }
    00953             }
    00954
    00955             IDictionaryEnumerator enumerator = tmpBatches.GetEnumerator();
    00956
    00957             while (enumerator.MoveNext())
    00958             {
    00959                 TerrainTile tile = (TerrainTile)enumerator.Key;
    00960                 BatchInterm interm = (BatchInterm)enumerator.Value;
    00961
    00962                 Batch batch = new Batch();
    00963                 batch.Populate(interm.theMesh, interm.materials, interm.textures, interm.matrices.ToArray());
    00964
    00965                 tile.batches.Add(batch);
    00966             }
    00967         }
    00968
    00974         public void Add(SceneNode node)
    00975         {
    00976             SceneNode parent = GetParent(node);
    00977
    00978
    00979             if (parent == null) // Means we don't have container, in that case we just attach to the rootNode.
    00980                 parent = rootNode;
    00981             parent.AddChild(node);
    00982         }
    00983
    00997         public override bool Collide(SceneNode sceneNode, ref List<SceneObject> collidingSceneObjects)
    00998         {
    00999             SceneNode parentSceneNode = GetParent(sceneNode);
    01000
    01001             return parentSceneNode.Collide(sceneNode, ref collidingSceneObjects);
    01002         }
    01003
    01021         public override bool CollideSolid(SceneNode sceneNode, ref List<SceneObject> collidingSceneObjects)
    01022         {
    01023             SceneNode parentSceneNode = GetParent(sceneNode);
    01024
    01025             return parentSceneNode.CollideSolid(sceneNode, ref collidingSceneObjects);
    01026         }
    01027
    01036         public override bool Collide(SceneNode sceneNode, ref List<SceneObject> collidingSceneObjects, System.Type desiredType)
    01037         {
    01038             SceneNode parentSceneNode = GetParent(sceneNode);
    01039
    01040             return parentSceneNode.Collide(sceneNode, ref collidingSceneObjects, desiredType);
    01041         }
    01042
    01050         public override bool CollideSolid(SceneNode sceneNode, ref List<SceneObject> collidingSceneObjects, System.Type desiredType)
    01051         {
    01052             SceneNode parentSceneNode = GetParent(sceneNode);
    01053
    01054             return parentSceneNode.CollideSolid(sceneNode, ref collidingSceneObjects, desiredType);
    01055         }
    01056
    01065         public Terrain LoadTerrain(string filename)
    01066         {
    01067             if (DXGfxManager.GetGlobalInstance().d3dDevice == null)
    01068             {
    01069                 throw new Exception("DXGfxManager.d3dDevice is null, loading of terrain is impossible without a valid device!");
    01070             }
    01071
    01072             return LoadTerrain(DXGfxManager.GetGlobalInstance().d3dDevice, filename);
    01073         }
    01074
    01083         public Terrain LoadTerrain(Device d3ddevice, string filename)
    01084         {
    01085             sceneTerrain = new Terrain(1024, 1024);
    01086             sceneTerrain.Load(d3ddevice, this, filename);
    01087
    01088             return sceneTerrain;
    01089         }
    01090
    01101         public Terrain LoadTerrain(Device d3ddevice, string fileName, string baseTextureFile, string secondTextureFile, string alphaMapFile)
    01102         {
    01103             sceneTerrain = new Terrain(1024, 1024);
    01104             sceneTerrain.Load(d3ddevice, this, fileName, baseTextureFile, secondTextureFile);
    01105
    01106             return sceneTerrain;
    01107         }
    01108
    01120         public override SceneObject PickObject(Viewport viewport, Matrix proj, Matrix view, Vector2 screenPos)
    01121         {
    01122             return base.PickObject(viewport, proj, view, screenPos);
    01123         }
    01124
    01134         public override Vector3 PickEnvironmentPosition(Viewport viewport, Matrix proj, Matrix view, Vector2 screenPos)
    01135         {
    01136             Vector3 rayOrig;
    01137             Vector3 rayDir;
    01138             MathUtil.RayFromScreenPos(viewport, proj, view, screenPos, out rayOrig, out rayDir);
    01139
    01140             List<SceneObject> collidingSceneObjects = new List<SceneObject>();
    01141
    01142             bool any = Intersect(rayOrig, rayDir, ref collidingSceneObjects, typeof(TerrainTile));
    01143
    01144             Vector3 position = new Vector3();
    01145             if (any)
    01146             {
    01147                 float refVal = 10000.0f;
    01148                 TerrainTile res = null;
    01149
    01150                 foreach (SceneObject sceneObj in collidingSceneObjects)
    01151                 {
    01152                     TerrainTile tile = sceneObj as TerrainTile;
    01153
    01154                     if (tile == null)
    01155                         continue;
    01156
    01157                     Microsoft.DirectX.Direct3D.IntersectInformation closestHit = new IntersectInformation();
    01158
    01159                     bool intersect = tile.Intersect(rayOrig, rayDir, out closestHit);
    01160
    01161                     if (!intersect)
    01162                         continue;
    01163
    01164                     if (closestHit.Dist < refVal)
    01165                     {
    01166                         res = tile;
    01167                         refVal = closestHit.Dist;
    01168                     }
    01169                 }
    01170
    01171                 position = rayOrig + refVal * rayDir;
    01172             }
    01173             return position;
    01174         }
    01175
    01182         public void AddInstances(FrameworkMesh mesh, InstanceInfo[] instancesInfo)
    01183         {
    01184             if (sceneTerrain == null)
    01185             {
    01186                 throw new Exception("terrain is null. It should be initialized before calling this method!");
    01187             }
    01188
    01189         }
    01190     }
    01191 }