KinPortal/Game/Scene.cs
2020-05-15 12:18:51 +02:00

162 lines
4.8 KiB
C#
Executable File

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<DrawableGameComponent> 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<DrawableGameComponent>();
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);
}
}
}