/* * VisualGrid.cs * Authors: Mike Dapiran * Copyright (c) 2007-2008 Cornell University This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ using System; using Microsoft.Xna.Framework; using tAC_Engine.Graphics.Cameras; using Util; namespace ColonySim { class VisualGrid : DrawableGameScreenComponent { private readonly Perspective3DCamera mPlayerCam; private BoundingFrustum mFrustum; private readonly Plane mZeroPlane = new Plane(Vector3.Left, Vector3.Forward, Vector3.Zero); public VisualGrid(Perspective3DCamera pCamera) { mPlayerCam = pCamera; } public override void Update(GameTime gameTime) { mFrustum = new BoundingFrustum(mPlayerCam.View * mPlayerCam.Projection); if (mFrustum.Intersects(mZeroPlane) == PlaneIntersectionType.Intersecting) { Vector3[] corners = mFrustum.GetCorners(); Vector3[] areaOfGridViewable = new Vector3[4]; int curAreaIndex = 0; for(int i = 0; i < 4; i++) { if(i != 3) { float? distanceToPlane = Intersects(new Ray(corners[i], corners[i] - corners[i + 1]), mZeroPlane); if(distanceToPlane != null) { areaOfGridViewable[curAreaIndex] = corners[i] + ((corners[i] - corners[i+1]) * distanceToPlane.Value); curAreaIndex++; } } else { float? distanceToPlane = Intersects(new Ray(corners[i], corners[i] - corners[0]), mZeroPlane); if(distanceToPlane != null) { areaOfGridViewable[curAreaIndex] = corners[i] + ((corners[i] - corners[0]) * distanceToPlane.Value); curAreaIndex++; } } } for(int i = 4; i < 8; i++) { if(i != 7) { float? distanceToPlane = Intersects(new Ray(corners[i], corners[i] - corners[i + 1]), mZeroPlane); if(distanceToPlane != null) { areaOfGridViewable[curAreaIndex] = corners[i] + ((corners[i] - corners[i+1]) * distanceToPlane.Value); curAreaIndex++; } } else { float? distanceToPlane = Intersects(new Ray(corners[i], corners[i] - corners[4]), mZeroPlane); if(distanceToPlane != null) { areaOfGridViewable[curAreaIndex] = corners[i] + ((corners[i] - corners[4]) * distanceToPlane.Value); curAreaIndex++; } } } Vector2[] areaToDrawGrid = new Vector2[4]; areaToDrawGrid[0] = new Vector2(areaOfGridViewable[0].X, areaOfGridViewable[0].Z); areaToDrawGrid[1] = new Vector2(areaOfGridViewable[1].X, areaOfGridViewable[1].Z); areaToDrawGrid[2] = new Vector2(areaOfGridViewable[2].X, areaOfGridViewable[2].Z); areaToDrawGrid[3] = new Vector2(areaOfGridViewable[3].X, areaOfGridViewable[3].Z); for (int i = 0; i < 4; i++) { areaToDrawGrid[0].X = areaToDrawGrid[3].X = Math.Min(areaToDrawGrid[0].X, areaOfGridViewable[i].X); areaToDrawGrid[0].Y = areaToDrawGrid[1].Y = Math.Min(areaToDrawGrid[0].Y, areaOfGridViewable[i].Z); areaToDrawGrid[1].X = areaToDrawGrid[2].X = Math.Max(areaToDrawGrid[1].X, areaOfGridViewable[i].X); areaToDrawGrid[2].Y = areaToDrawGrid[3].Y = Math.Max(areaToDrawGrid[2].Y, areaOfGridViewable[i].Y); } } } private static float? Intersects(Ray ray, Plane plane) { float denom = Vector3.Dot(plane.Normal, ray.Direction); if (Math.Abs(denom) >= float.Epsilon) { float nom = Vector3.Dot(plane.Normal, ray.Position) + plane.D; float t = -(nom / denom); if (t >= 0) { return t; } } return null; } } }