diff --git a/bnhdemo/BootStrap.cs b/bnhdemo/BootStrap.cs
index 376a595..5e98825 100644
--- a/bnhdemo/BootStrap.cs
+++ b/bnhdemo/BootStrap.cs
@@ -18,85 +18,77 @@ using org.budnhead.core;
namespace bnhdemo
{
- public class BootStrap
+ public static class BootStrap
{
- public static BootStrap _instance;
- public static BootStrap instance()
- {
- return _instance;
- }
+ static SquaredMap map;
- OpenGLWindow glWindow;
-
- SquaredMap map;
+ static Actor trackedActor;
+ static GLCamera trackingCamera;
public static void Main(string[] args){
- _instance = new BootStrap();
+ Engine.InitializeGraphics();
- _instance.run();
+ Engine.SceneWindows[0].Scene = new Scene();
+
+ loadMap();
+
+ Engine.SceneWindows[0].Visible = true;
+
+ Engine.SceneWindows[0].KeyPress += (sender, e) => {
+ switch (e.KeyChar){
+ case 'r':
+ SceneWindow sw = Engine.createSceneWindow();
+ sw.Visible = true;
+ sw.Scene = new Scene(Engine.SceneWindows[0].Scene);
+ GLCamera cam = new GLCamera();
+
+ cam.Position = new Vector3(800,800,384);
+ cam.View = new Vector3(-1,-1,-1);
+ cam.Top = Vector3.UnitZ;
+
+ CameraRotator cr = new CameraRotator(cam);
+
+ sw.PrimaryViewport.SceneOrientation = cam;
+
+ trackingCamera = cam;
+ break;
+
+ case ' ':
+ Console.WriteLine("Fire Ballistic...");
+ BallisticActor ba = new BallisticActor(0);
+ ba.Position.Value = map.ground(new Vector2(10,10));
+ ba.Velocity.Value = new Vector3(1,1,1).Normalized();
+ ba.Velocity.Value *= 100.0f;
+ ba.fire();
+
+ trackedActor = ba;
+
+ break;
+ }
+ };
+
+ Engine.AfterUpdate += delegate {
+ if ((trackedActor != null)&&(trackingCamera != null)){
+ if (trackedActor.IsActive){
+ trackingCamera.lookAt(trackedActor.Position.Value);
+ } else {
+ trackedActor = null;
+ }
+ }
+ };
+
+ Engine.run();
}
- public BootStrap()
- {
- bootGraphics();
- bootAudio();
- bootMap();
- }
-
- public SquaredMap SquaredMap {
- get { return this.map; }
- }
-
- public void bootGraphics(){
- glWindow = new OpenGLWindow();
- glWindow.MakeCurrent();
-
- GlobalDefaults.instance();
-
- }
-
- public void bootAudio(){
-
-
-
- AudioDelegate.init();
- AudioDelegate.DistanceModel("exponential", true);
- nhBuffers.addSearchPath("./sounds");
- nhBuffers.loadSound("HowFire", "HowHit", "st1");
- //AudioDelegate.test();
-
- }
-
-
-
- public void bootMap(){
+ public static void loadMap(){
ImageSharp.Image i = ImageSharp.Image.Load( new FileStream("M3-wip.png",FileMode.Open));
i.Flip(ImageSharp.Processing.FlipType.Vertical);
- i.Resize(500,500);
map = new SquaredMap(i);
- glWindow.Scene.RootObject.addChild( map );
-
- ModelManager.instance.addSearchPath("./models");
-
- DumpObject dobj = new DumpObject();
- dobj.Model3D = ModelManager.instance.loadModel("alfa147",0.0254f);
- Vector3 v3 = map.ground(new Vector2(24,24));
- dobj.Position = v3;
-
- glWindow.Scene.RootObject.addChild( dobj );
- }
-
-
- public void run(){
- glWindow.MakeCurrent();
- glWindow.Run(25,25);
+ Engine.SceneWindows[0].Scene.RootObject.addChild(map);
}
-
-
-
}
}
diff --git a/bnhdemo/Graphics.cs b/bnhdemo/Graphics.cs
deleted file mode 100644
index bd0c21c..0000000
--- a/bnhdemo/Graphics.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-using System;
-using System.IO;
-
-using OpenTK.Graphics.OpenGL;
-using OpenTK;
-
-namespace bnhdemo
-{
- public class Graphics
- {
- private TextureManager textureManager;
-
- public Graphics()
- {
- this.textureManager = new TextureManager();
- }
-
-
- TextureManager TextureManager {
- get { return this.textureManager; }
- }
-
-
- }
-}
diff --git a/bnhdemo/bnhdemo.csproj b/bnhdemo/bnhdemo.csproj
index 629e5ad..a64d14a 100644
--- a/bnhdemo/bnhdemo.csproj
+++ b/bnhdemo/bnhdemo.csproj
@@ -60,9 +60,8 @@
-
-
+
@@ -114,6 +113,7 @@
+
diff --git a/bnhdemo/demo/CameraRotator.cs b/bnhdemo/demo/CameraRotator.cs
new file mode 100644
index 0000000..71d941a
--- /dev/null
+++ b/bnhdemo/demo/CameraRotator.cs
@@ -0,0 +1,34 @@
+using System;
+
+using OpenTK;
+using org.budnhead.core;
+using org.budnhead.graphics;
+
+namespace bnhdemo
+{
+ public class CameraRotator : Actor
+ {
+ GLCamera camera;
+ Matrix3 m3 = Matrix3.CreateRotationZ(MathHelper.PiOver2 / 45.0f);
+
+ Vector3 p = new Vector3(400,400,256);
+ Vector3 offset = new Vector3(150,0,0);
+ Vector3 view = new Vector3(-1,0,-1);
+
+ public CameraRotator(GLCamera camera)
+ :base(0)
+ {
+ this.camera = camera;
+ }
+
+ public override void update(float timespan)
+ {
+ offset = m3 * offset;
+ view = m3 * view;
+
+ camera.Position = p + offset;
+ camera.View = view.Normalized();
+ }
+
+ }
+}
diff --git a/org.budnhead/core/Actor.cs b/org.budnhead/core/Actor.cs
index 1c05c48..2ebac3a 100644
--- a/org.budnhead/core/Actor.cs
+++ b/org.budnhead/core/Actor.cs
@@ -10,25 +10,20 @@ namespace org.budnhead.core
{
public class Actor : WorldObject
{
- public static List activeActors = new List();
- public static List finishedActors = new List();
+ internal static List activeActors = new List();
+ private static List finishedActors = new List();
-
- public static void updateAll(float timespan)
- {
- foreach (Actor a in activeActors)
- {
- a.update(timespan);
+ internal static void updateActors(float elapsed){
+ // Update all active Actors...
+ foreach (Actor a in activeActors.ToArray()){
+ a.update(elapsed);
}
- foreach (Actor a in finishedActors)
- {
+ // Remove finished Actors
+ foreach (Actor a in finishedActors.ToArray()){
activeActors.Remove(a);
-
-
}
finishedActors.Clear();
-
}
private int id;
@@ -39,26 +34,30 @@ namespace org.budnhead.core
this.id = id;
activeActors.Add(this);
- _player = new nhPlayer();
- activePlayers.Add(_player);
+ //_player = new nhPlayer();
+ //activePlayers.Add(_player);
}
public void destroy(){
finishedActors.Add(this);
- _player.deletePlayer();
+ //_player.deletePlayer();
}
- public Vector3 Heading { get; set; }
- public Vector3 Velocity { get; set; }
- public float Weight { get; set; }
+ public readonly BufferedValueInstance Heading = new BufferedValueInstance(new Vector3(0,0,1));
+ public readonly BufferedValueInstance Velocity = new BufferedValueInstance(new Vector3());
+ public readonly BufferedValueInstance Weight = new BufferedValueInstance(0);
+
+ public bool IsActive {
+ get { return activeActors.Contains(this); }
+ }
public virtual void update(float timespan){
- if (soundPlaying()){
+/* if (soundPlaying()){
syncSoundPosition();
}
- }
+*/ }
public void setHeading(Vector3 heading,Vector3 top){
Vector3 x,y,z;
@@ -74,7 +73,7 @@ namespace org.budnhead.core
new Vector4(0,0,0,1)
);
- Rotation = Matrix4.CreateRotationX(MathHelper.PiOver2) * mRotation;
+ Rotation.Value = Matrix4.CreateRotationX(MathHelper.PiOver2) * mRotation;
}
public Model3D Model3D { get; set; }
@@ -99,35 +98,34 @@ namespace org.budnhead.core
public void setDistanceAttenuation(float rollOf = 2.0f, float refDistance = 1.0f, float maxDistance = 100.0f)
{
- _player.setDistanceAttenuation(rollOf, refDistance, maxDistance);
+ // _player.setDistanceAttenuation(rollOf, refDistance, maxDistance);
}
public void setBuffers(params string[] buffers)
{
- foreach (string i in buffers)
+/* foreach (string i in buffers)
{
if(!aBuffers.ContainsKey(i))
aBuffers.Add(i, nhBuffers.buffers[i]);
- }
+ }*/
}
public void playSound(string sound, float gain = 1.0f, bool loop = false)
{
-
- _player.position = this.Position;
- _player.velocity = this.Velocity;
- _player.play(aBuffers[sound], gain, loop);
+ // _player.position = this.Position.Value;
+ // _player.velocity = this.Velocity.Value;
+ // _player.play(aBuffers[sound], gain, loop);
}
private void syncSoundPosition()
{
- _player.setPosition(this.Position);
- _player.setVelocity(this.Velocity);
+ // _player.setPosition(this.Position.Value);
+ // _player.setVelocity(this.Velocity.Value);
}
public Boolean soundPlaying(){
- return _player.state();
+ return false; //_player.state();
}
}
diff --git a/org.budnhead/core/BallisticActor.cs b/org.budnhead/core/BallisticActor.cs
index 23437f8..4c60ca5 100644
--- a/org.budnhead/core/BallisticActor.cs
+++ b/org.budnhead/core/BallisticActor.cs
@@ -2,6 +2,7 @@
using org.budnhead.graphics.primitives;
using org.budnhead.graphics;
using org.budnhead.exceptions;
+using org.budnhead.tools;
using OpenTK;
@@ -17,7 +18,7 @@ namespace org.budnhead.core
:base(id)
{
this.actorState = BallisticActorStates.FLYING;
- this.Model3D = ModelManager.instance.findModel("ballistisch");
+ this.Model3D = ResourceLibrary.getResource("ballistisch");
for (int n=0;n < this.Model3D.vertexes.Length;n++){
this.Model3D.colors[n] = new Vector4(1.0f,0.2f + (0.5f * this.Model3D.vertexes[n].Z / -4.0f),0,1.0f);
@@ -35,16 +36,16 @@ namespace org.budnhead.core
switch (actorState){
case BallisticActorStates.FLYING:
- Velocity += (Physics.Gravitation * timespan);
- Position += Velocity * timespan;
+ Velocity.Value += (Physics.Gravitation * timespan);
+ Position.Value += Velocity.Value * timespan;
- setHeading( Velocity, Physics.Gravitation);
+ setHeading( Velocity.Value, Physics.Gravitation);
try
{
- Vector3 ground = SquaredMap.activeMap.ground(Position.Xy);
+ Vector3 ground = SquaredMap.activeMap.ground(Position.Value.Xy);
- if (Position.Z <= ground.Z){
+ if (Position.Value.Z <= ground.Z){
Console.WriteLine("BallisticActor hit ground!");
actorState = BallisticActorStates.HIT;
playSound("HowHit");
@@ -71,7 +72,7 @@ namespace org.budnhead.core
public void fire()
{
- playSound("HowFire");
+ //playSound("HowFire");
}
diff --git a/org.budnhead/core/BufferedValue.cs b/org.budnhead/core/BufferedValue.cs
new file mode 100644
index 0000000..6d12f54
--- /dev/null
+++ b/org.budnhead/core/BufferedValue.cs
@@ -0,0 +1,61 @@
+
+using System;
+using System.Collections.Generic;
+
+namespace org.budnhead
+{
+ public interface IBufferedValue {
+ void buffer();
+ object getBufferedValue();
+ object getValue();
+ }
+
+ public class BufferedValueInstance : IDisposable,IBufferedValue
+ {
+ static List bufferedValues = new List();
+ static public void cycle(){
+ foreach (IBufferedValue bvi in bufferedValues){
+ bvi.buffer();
+ }
+ }
+
+ T value,bufferedValue;
+
+ public BufferedValueInstance(){
+ bufferedValues.Add(this);
+ }
+
+ public BufferedValueInstance(T initialValue){
+ Value = initialValue;
+ bufferedValues.Add(this);
+ }
+
+ public T Value {
+ get { return this.value; }
+ set { this.value = value; }
+ }
+
+ public T BufferedValue{
+ get { return this.bufferedValue; }
+ }
+
+ public void Dispose(){
+ bufferedValues.Remove(this);
+ }
+
+ public void buffer(){
+ this.bufferedValue = this.value;
+ }
+
+ public object getBufferedValue()
+ {
+ return this.bufferedValue;
+ }
+
+ public object getValue()
+ {
+ return this.value;
+ }
+
+ }
+}
diff --git a/org.budnhead/core/ConsumerProducerLock.cs b/org.budnhead/core/ConsumerProducerLock.cs
new file mode 100644
index 0000000..b401909
--- /dev/null
+++ b/org.budnhead/core/ConsumerProducerLock.cs
@@ -0,0 +1,71 @@
+using System;
+using System.Threading;
+
+namespace org.budnhead
+{
+ /**
+ * ConsumerProducerLock
+ *
+ * Lock a Resource for one producer, mutliple consumers (read-only)
+ *
+ * Producer Lock: Producer will receive and hold lock if no other producer is active
+ * Producer Exclusive Lock: Producer will receive and hold lock, while no consumers are active
+ * Consumer Lock: Consumers will get lock while no Producer Exclusive Lock is held
+ *
+ **/
+
+ public class ConsumerProducerLock
+ {
+ Object producer;
+ Object producerExclusiveLock;
+ Object consumerLock;
+
+ Int32 consumers;
+
+ bool producerIsExclusive;
+
+ public ConsumerProducerLock(){
+ producer = new object();
+ producerExclusiveLock = new object();
+ consumerLock = new object();
+
+ consumers = 0;
+ }
+
+ public void ConsumerEnter(){
+ Monitor.Enter(producerExclusiveLock);
+ Monitor.Enter(consumerLock);
+ consumers ++;
+ Monitor.Exit(consumerLock);
+ Monitor.Exit(producerExclusiveLock);
+ }
+ public void ConsumerExit(){
+ Monitor.Enter(producerExclusiveLock);
+ Monitor.Enter(consumerLock);
+ consumers --;
+ if (consumers == 0){
+ Monitor.Pulse(producerExclusiveLock);
+ }
+ Monitor.Exit(consumerLock);
+ Monitor.Exit(producerExclusiveLock);
+ }
+
+ public void ProducerEnter(){
+ Monitor.Enter(producer);
+ }
+ public void ProducerExit(){
+ Monitor.Exit(producer);
+ if (Monitor.IsEntered(producerExclusiveLock)){
+ Monitor.Exit(producerExclusiveLock);
+ }
+ }
+
+ public void producerExclusive(){
+ Monitor.Enter(producerExclusiveLock);
+ if (consumers > 0){
+ Monitor.Wait(producerExclusiveLock);
+ }
+ }
+
+ }
+}
diff --git a/org.budnhead/core/Engine.cs b/org.budnhead/core/Engine.cs
new file mode 100644
index 0000000..d955aca
--- /dev/null
+++ b/org.budnhead/core/Engine.cs
@@ -0,0 +1,174 @@
+using System;
+using System.Collections.Generic;
+
+using System.Threading;
+using System.Diagnostics;
+
+using org.budnhead.graphics;
+using org.budnhead.tools;
+
+using OpenTK.Graphics;
+
+namespace org.budnhead.core
+{
+ public delegate void UpdateDelegate(float elapsed);
+
+ public static class Engine
+ {
+ /** Objects of the Game World **/
+
+
+ /** Engine management stuff **/
+ private static Object engineLock = new object();
+ private static Boolean initialized = false;
+
+ private static readonly float tickTimeSpan = (1.0f / Stopwatch.Frequency);
+ private static readonly float tickTimeSpanMS = (1000.0f / Stopwatch.Frequency);
+ private static long lastWorldUpdateTick;
+ private static ConsumerProducerLock
+ consumerProducerLock = new ConsumerProducerLock();
+ internal static List
+ sceneWindows = new List();
+ private static JobThreader sceneWindowJobs;
+
+ private static Thread updateThread = new Thread(updateWorldThread);
+
+ public static event UpdateDelegate
+ BeforeUpdate,
+ AfterUpdate;
+
+ private static Boolean exiting;
+ private static Object syncGraphicsStartup = new object();
+
+ private static float targetUpdatePeriod = 100;
+
+ public static SceneWindow[] SceneWindows {
+ get { lock (sceneWindows) { return sceneWindows.ToArray(); } }
+ }
+
+ public static float TargetUpdatePeriod {
+ get { return targetUpdatePeriod; }
+ set { targetUpdatePeriod = value; }
+ }
+
+ public static float TargetUpdateFrequency {
+ get { return targetUpdatePeriod == 0 ? 0 : 1.0f / targetUpdatePeriod; }
+ set { targetUpdatePeriod = value == 0 ? 0 : 1.0f / value; }
+ }
+
+ public static Boolean ShouldContinue {
+ get { lock(engineLock) { return !Engine.exiting; } }
+ }
+
+ public static void Shutdown(){
+ lock (engineLock){
+ exiting = true;
+ }
+ }
+
+ public static void Initialize(){
+ InitializeGraphics();
+ InitializeUpdateThread();
+ }
+
+ public static void InitializeUpdateThread(){
+ }
+
+ public static void InitializeGraphics(){
+ GraphicsContext.ShareContexts = true;
+
+ sceneWindowJobs = new JobThreader();
+
+ SceneWindow primaryWindow = new SceneWindow();
+ primaryWindow.MakeCurrent();
+
+ initialized = GlobalDefaults.initialize();
+ }
+
+ public static void run(){
+ updateThread.Start();
+
+ sceneWindowsThread();
+ }
+
+
+ private static void updateWorld(float elapsed){
+ consumerProducerLock.ProducerEnter();
+
+ if (BeforeUpdate!=null){
+ BeforeUpdate(elapsed);
+ }
+
+ Actor.updateActors(elapsed);
+
+ if (AfterUpdate!=null){
+ AfterUpdate(elapsed);
+ }
+
+ consumerProducerLock.producerExclusive();
+
+ cycleBufferedValues();
+
+ consumerProducerLock.ProducerExit();
+ }
+
+ public static bool cycleBufferedValues(){
+ BufferedValueInstance