00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
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
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
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
00562
00563
00564
00565
00566
00567
00568
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
00611
00612 nextEG = null;
00613 }
00614 }
00615 currentEG.Default.EndPass();
00616
00617
00618
00619
00620
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
00648 device.Transform.World = SceneWater.WorldMat;
00649 device.SetStreamSource(0, SceneWater.waterVBuff, 0);
00650 device.Indices = SceneWater.waterIBuff;
00651
00652
00653 int passes = refractionMaskEffect.Begin(0);
00654 for (int pass = 0; pass < passes; pass++)
00655 {
00656 refractionMaskEffect.BeginPass(pass);
00657
00658
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
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
00700 RenderObjectAndSky(device);
00701
00702
00703 device.RenderState.Clipping = false;
00704 device.ClipPlanes[0].Enabled = false;
00705
00706
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
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
00845
00846
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)
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 }