using System; using System.Collections.Generic; using Microsoft.Xna.Framework; using Jitter; using Jitter.LinearMath; using Jitter.Collision; using Jitter.Dynamics; namespace KinPortal { public class Scene : DrawableGameComponent { private Camera m_camera = null; public Camera Camera { get { return m_camera; } set { if(m_camera != null) { Game.Components.Remove(m_camera); } m_camera = value; Game.Components.Add(m_camera); } } public List Components {get; private set;} public World PhysicWorld {get; private set;} public PortalManager PortalManager {get; private set;} public Scene(KinPortal.Game game, Camera camera) : base(game) { Camera = camera; Components = new List(); PhysicWorld = new World(new CollisionSystemSAP()); PhysicWorld.Gravity = new JVector(0, 0, -9.81f); PortalManager = new PortalManager(this); PhysicWorld.CollisionSystem.CollisionDetected += this.CollisionEvent; UpdateOrder = 0; } public void AddComponent(DrawableGameComponent obj) { Components.Add(obj); Game.Components.Add(obj); if(obj is DynamicObject) { PhysicWorld.AddBody(((DynamicObject) obj).PhysicModel); } } public void RemoveComponent(DrawableGameComponent obj) { Components.Remove(obj); Game.Components.Remove(obj); if(obj is DynamicObject) { PhysicWorld.RemoveBody(((DynamicObject) obj).PhysicModel); } } private bool RaycastCallback(RigidBody body, JVector normal, float fraction) { return true; } public override void Update(GameTime gameTime) { float phyStep = gameTime.ElapsedGameTime.Milliseconds / 1000.0f; PhysicWorld.Step(phyStep, true); KinPortal.Game game = (KinPortal.Game) Game; JVector ray; float fraction; JVector normal; HandsProjection leftHand = new HandsProjection(); HandsProjection rightHand = new HandsProjection(); JVector camPos = Geometry.GetJitterVector(Camera.Pos); RigidBody leftBody = null, rightBody = null; /* Left Hand projection */ ray = Geometry.GetJitterVector(Camera.Unproject(game.HandsTracker.LeftHand.Pos.X, game.HandsTracker.LeftHand.Pos.Y)); ray = JVector.Normalize(ray) * 100.0f; if(PhysicWorld.CollisionSystem.Raycast(camPos, ray, RaycastCallback, out leftBody, out normal, out fraction)) { leftHand.HitPoint = Geometry.GetXnaVector(camPos + fraction * ray); leftHand.HitNormal = Geometry.GetXnaVector(JVector.Normalize(normal)); leftHand.IsProjected = true; } else { leftHand.IsProjected = false; } /* Right Hand projection */ ray = Geometry.GetJitterVector(Camera.Unproject(game.HandsTracker.RightHand.Pos.X, game.HandsTracker.RightHand.Pos.Y)); ray = JVector.Normalize(ray) * 100.0f; if(PhysicWorld.CollisionSystem.Raycast(camPos, ray, RaycastCallback, out rightBody, out normal, out fraction)) { rightHand.HitPoint = Geometry.GetXnaVector(camPos + fraction * ray); rightHand.HitNormal = Geometry.GetXnaVector(JVector.Normalize(normal)); rightHand.IsProjected = true; } else { rightHand.IsProjected = false; } DynamicObject leftObj = null, rightObj = null; foreach(DrawableGameComponent obj in Components) { if(obj is DynamicObject) { DynamicObject dobj = (DynamicObject) obj; if(dobj.PhysicModel == leftBody) { leftObj = dobj; } if(dobj.PhysicModel == rightBody) { rightObj = dobj; } } } if(leftObj == rightObj && leftObj != null) { leftObj.Target(leftHand, rightHand); } else { if(leftObj != null) { leftObj.Target(leftHand, new HandsProjection(false, Vector3.Zero, Vector3.Zero)); } if(rightObj != null) { rightObj.Target(new HandsProjection(false, Vector3.Zero, Vector3.Zero), rightHand); } } base.Update(gameTime); } public void CollisionEvent(RigidBody body1, RigidBody body2, JVector point1, JVector point2, JVector normal, float penetration) { DynamicObject dobj1 = null; DynamicObject dobj2 = null; foreach(DrawableGameComponent obj in Components) { if(obj is DynamicObject) { DynamicObject dobj = (DynamicObject) obj; if(dobj.PhysicModel == body1) { dobj1 = dobj; } if(dobj.PhysicModel == body2) { dobj2 = dobj; } } } if(dobj1 == null || dobj2 == null) { return; } if(dobj1 is InterruptorObject) { ((InterruptorObject) dobj1).Collision(dobj2); } if(dobj2 is InterruptorObject) { ((InterruptorObject) dobj2).Collision(dobj1); } } public override void Draw(GameTime gameTime) { foreach(DrawableGameComponent obj in Components) { obj.Draw(gameTime); } base.Draw(gameTime); } } }