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.cycle(); + return true; + } + + public static void ConsumerEnter(){ + consumerProducerLock.ConsumerEnter(); + } + public static void ConsumerExit(){ + consumerProducerLock.ConsumerExit(); + } + + + public static SceneWindow createSceneWindow(){ + return sceneWindowJobs.execute(delegate { return new SceneWindow(); }); + } + + static void sceneWindowsThread(){ + + while (Engine.ShouldContinue){ + sceneWindowJobs.execute(); + + lock(Engine.sceneWindows){ + foreach (SceneWindow sceneWindow in Engine.sceneWindows.ToArray()){ + if (sceneWindow.Visible){ + sceneWindow.ProcessEvents(); + } + } + + foreach (SceneWindow sceneWindow in Engine.sceneWindows.ToArray()){ + sceneWindow.paint(); + } + } + } + } + + static void updateWorldThread(){ + + long lastWorldUpdateTick = Stopwatch.GetTimestamp(); + float elapsed = 0; + float update_needs; + + while (Engine.ShouldContinue){ + long ticks = Stopwatch.GetTimestamp(); + elapsed = tickTimeSpan * (ticks - lastWorldUpdateTick); + + updateWorld(elapsed); + + update_needs = tickTimeSpanMS * (Stopwatch.GetTimestamp() - ticks); + + lastWorldUpdateTick = ticks; + + if (update_needs < targetUpdatePeriod){ + Thread.Sleep( (int)(targetUpdatePeriod - update_needs) ); + } + } + } + + } +} diff --git a/org.budnhead/core/Geometry.cs b/org.budnhead/core/Geometry.cs index 4defd82..6c9abac 100644 --- a/org.budnhead/core/Geometry.cs +++ b/org.budnhead/core/Geometry.cs @@ -73,8 +73,8 @@ namespace org.budnhead.core .requires(intersectPlainCoeff(P,V,A,B,C,out coeff)) .requires(coeff.Y >= 0) .requires(coeff.Z >= 0) - .requires(coeff.Y <= 1) - .requires(coeff.Z <= 1) + .requires(coeff.Y <= 1.00001f) + .requires(coeff.Z <= 1.00001f) .assigns(ref p, delegate { return P + (coeff.X * V); }) .isSuccess(); } @@ -89,9 +89,9 @@ namespace org.budnhead.core .requires(intersectPlainCoeff(P,V,A,B,C,out coeff)) .requires(coeff.Y >= 0) .requires(coeff.Z >= 0) - .requires(coeff.Y <= 1) - .requires(coeff.Z <= 1) - .requires(coeff.Y + coeff.Z <= 1) + .requires(coeff.Y <= 1.00001f) + .requires(coeff.Z <= 1.00001f) + .requires(coeff.Y + coeff.Z <= 1.00001f) .assigns(ref p, delegate { return A + (coeff.Y * (B-A)) + (coeff.Z * (C-A)); }) .isSuccess(); } diff --git a/org.budnhead/graphics/GlobalDefaults.cs b/org.budnhead/core/GlobalDefaults.cs similarity index 51% rename from org.budnhead/graphics/GlobalDefaults.cs rename to org.budnhead/core/GlobalDefaults.cs index 0034c2b..e660efc 100644 --- a/org.budnhead/graphics/GlobalDefaults.cs +++ b/org.budnhead/core/GlobalDefaults.cs @@ -2,55 +2,29 @@ using OpenTK.Graphics.OpenGL; -namespace org.budnhead.graphics +using org.budnhead.graphics; +using org.budnhead.tools; + +namespace org.budnhead.core { - public class GlobalDefaults + public static class GlobalDefaults { - private static GlobalDefaults _instance = new GlobalDefaults(); - public static GlobalDefaults instance(){ - return _instance; - } + internal static bool initialize(){ + ResourceLibrary.initializeResourceType(typeof(Shader), "shader/", ""); + ResourceLibrary.initializeResourceType(typeof(ShaderProgram), "shader/", ".program"); + ResourceLibrary.initializeResourceType(typeof(LoadedModel), "models/", ".obj"); - private Shader defVertexShader, - defFragmentShader; - private ShaderProgram - defShaderProgram; + ResourceLibrary.cacheInstance("default.vshader",new Shader(OpenTK.Graphics.OpenGL.ShaderType.VertexShader, defVertexShaderSource)); + ResourceLibrary.cacheInstance("default.fshader",new Shader(OpenTK.Graphics.OpenGL.ShaderType.FragmentShader, defFragmentShaderSource)); - private GLSceneOrientation activeScene; + ResourceLibrary.cacheInstance("default",new ShaderProgram("default.vshader","default.fshader")); - private GlobalDefaults(){ - - Console.WriteLine("GlobalDefaults: Shader Version: {0}", GL.GetString(StringName.ShadingLanguageVersion)); - - defVertexShader = new Shader(OpenTK.Graphics.OpenGL.ShaderType.VertexShader, defVertexShaderSource); - defFragmentShader = new Shader(OpenTK.Graphics.OpenGL.ShaderType.FragmentShader, defFragmentShaderSource); - - defShaderProgram = new ShaderProgram(defVertexShader, defFragmentShader); - - activeScene = new GLSceneOrientation(); - } - - public ShaderProgram DefaultShaderProgram { - get { return this.defShaderProgram;} - } - - public Shader DefaultVertexShader - { - get { return defVertexShader; } - } - - public Shader DefaultFragmentShader - { - get { return defFragmentShader; } - } - - public GLSceneOrientation ActiveScene { - get { return this.activeScene; } - set { this.activeScene = value; } + return true; } -private string defVertexShaderSource = @"#version 330 + +private static string defVertexShaderSource = @"#version 330 layout(location = 0) in vec3 iv_position; layout(location = 1) in vec4 iv_color; @@ -94,7 +68,7 @@ void main() "; -private string defFragmentShaderSource = @"#version 330 +private static string defFragmentShaderSource = @"#version 330 in vec4 color; in vec3 norm; @@ -119,7 +93,5 @@ void main() "; - } - } diff --git a/org.budnhead/core/Linear.cs b/org.budnhead/core/Linear.cs index 9515e7a..a52d44b 100644 --- a/org.budnhead/core/Linear.cs +++ b/org.budnhead/core/Linear.cs @@ -13,8 +13,8 @@ namespace org.budnhead.core rows[2] = new Vector4(X.Z,Y.Z,Z.Z,W.Z); c = new Vector3(); - Console.WriteLine("New Linear Equation System to solve:"); - dumpLinearSystem(rows); + //Console.WriteLine("New Linear Equation System to solve:"); + //dumpLinearSystem(rows); if (rows[0].Z == 0){ Vector4 t = rows[0]; @@ -34,7 +34,7 @@ namespace org.budnhead.core rows[2] -= rows[0] * (rows[2].Z / rows[0].Z); } - dumpLinearSystem(rows); + //dumpLinearSystem(rows); if (rows[1].Y == 0){ Vector4 t = rows[1]; @@ -48,7 +48,7 @@ namespace org.budnhead.core rows[2] -= rows[1] * (rows[2].Y / rows[1].Y); } - dumpLinearSystem(rows); + //dumpLinearSystem(rows); rows[2] /= rows[2].X; c.X = rows[2].W; @@ -65,8 +65,8 @@ namespace org.budnhead.core rows[0] /= rows[0].Z; c.Z = rows[0].W; - dumpLinearSystem(rows); - Console.WriteLine("Solved to {0}",c); + //dumpLinearSystem(rows); + //Console.WriteLine("Solved to {0}",c); return true; } diff --git a/org.budnhead/graphics/SquaredMap.cs b/org.budnhead/core/SquaredMap.cs similarity index 82% rename from org.budnhead/graphics/SquaredMap.cs rename to org.budnhead/core/SquaredMap.cs index c1b0243..f8fa27c 100644 --- a/org.budnhead/graphics/SquaredMap.cs +++ b/org.budnhead/core/SquaredMap.cs @@ -9,11 +9,10 @@ using OpenTK.Graphics.OpenGL4; using OpenTK; using org.hwo.contracts; - -using org.budnhead.core; using org.budnhead.exceptions; +using org.budnhead.graphics; -namespace org.budnhead.graphics +namespace org.budnhead.core { public class SquaredMap : WorldObject { @@ -197,7 +196,7 @@ namespace org.budnhead.graphics public Vector2 toTileBorderless(Vector2 world){ Vector2 tile = world / edge; - return tile; + return new Vector2((int)tile.X,(int)tile.Y); } public Vector2 toTile(Vector2 world){ @@ -211,7 +210,7 @@ namespace org.budnhead.graphics .requires(tile.Y < height) .throws(); - return tile; + return new Vector2((int)tile.X,(int)tile.Y); } public Vector2 intersectTile(Vector3 P,Vector3 V){ @@ -225,57 +224,63 @@ namespace org.budnhead.graphics Console.WriteLine("P: {0} V: {1}",P,V); - if (!Geometry.intersectPlain(P,V,corners[0],corners[1],corners[3],out A)){ - throw new OutOfWorldException(); - } - - if (!Geometry.intersectPlain(P,V,corners[4],corners[5],corners[7],out B)){ - throw new OutOfWorldException(); - } - - Console.WriteLine("Lower Plane Intersection (LIN): {0}",A); A = P + ( V * ( -P.Z / V.Z) ); Console.WriteLine("Lower Plane Intersection: {0}",A); - Console.WriteLine("Higher Plane Intersection (LIN): {0}",B); B = P + ( V * ( (SquaredMap.maxHeight-P.Z) / V.Z) ); Console.WriteLine("Higher Plane Intersection: {0}",B); - Vector2 a,b,min,max; + Vector2 start = Vector2.ComponentMin(A.Xy,B.Xy); + Vector2 finish = Vector2.ComponentMax(A.Xy,B.Xy); + Vector2 step = finish - start; - a = toTileBorderless(A.Xy); - b = toTileBorderless(B.Xy); + float steps = (step.X * step.Y) / 25.0f; + step /= steps; - min = Vector2.ComponentMax(Vector2.ComponentMin(a,b)-new Vector2(1,1),new Vector2()); - max = Vector2.ComponentMin(Vector2.ComponentMax(a,b)+new Vector2(1,1),new Vector2(width,height)); + int isteps = (int)steps; - Console.WriteLine("Checking Intersections: {0} -> {1}",min,max); + Vector2 pos = start, + tile = toTileBorderless(pos); - for (int nx = (int)min.X; nx < max.X; nx++){ - for (int ny = (int)min.Y; ny < max.Y; ny++){ - Vector3 isect = new Vector3(); - //Console.WriteLine("Check Intersection: {0}/{1}",nx,ny); + Console.WriteLine("Interpolation: {0} - {1} - {2}",start,step,finish); - for (int n=0;n<4;n++){ - try { - Model3D.Triangle t = model.triangles[tileIndex(nx,ny)]; - if (Geometry.intersectTriangle( - P, - V, - t.VertexA, - t.VertexB, - t.VertexC, - out isect - )){ - return isect; + for (int n=0;n<=isteps;){ + Console.WriteLine("IP RUN[{0}]: {1} Tile: {2}",n,pos,tile); + if (new BooleanConditional() + .requires( tile.X >= 0) + .requires( tile.Y >= 0) + .requires( tile.X < width) + .requires( tile.Y < height) + .isSuccess() + ){ + Vector3 isect = new Vector3(); + for (int nt=0;nt<4;nt++){ + try { + Model3D.Triangle t = model.triangles[tileIndex((int)tile.X,(int)tile.Y)]; + if (Geometry.intersectTriangle( + P, + V, + t.VertexA, + t.VertexB, + t.VertexC, + out isect + )){ + return isect; + } + + } catch (OutOfWorldException){ } - - } catch (OutOfWorldException owe){ } } - } - } + Vector2 nextTile = tile; + while (nextTile.Equals(tile)){ + pos += step; + nextTile = toTileBorderless(pos); + n++; + } + tile = nextTile; + } throw new OutOfWorldException(); } diff --git a/org.budnhead/core/WorldObject.cs b/org.budnhead/core/WorldObject.cs index e709f0f..46dbe57 100644 --- a/org.budnhead/core/WorldObject.cs +++ b/org.budnhead/core/WorldObject.cs @@ -20,15 +20,17 @@ namespace org.budnhead.core return null; } - public Vector3 Position{ get; set; } = new Vector3(); - public Matrix4 Rotation { get; set; } = Matrix4.Identity; - public Matrix4 Scale { get; set; } = Matrix4.Identity; - + public readonly BufferedValueInstance Position = new BufferedValueInstance(new Vector3()); + public readonly BufferedValueInstance Rotation = new BufferedValueInstance(Matrix4.Identity); + public readonly BufferedValueInstance Scale = new BufferedValueInstance(Matrix4.Identity); public Matrix4 Transformation { - get { return (Scale * Rotation) * Matrix4.CreateTranslation( Position ) ; } + get { return (Scale.Value * Rotation.Value) * Matrix4.CreateTranslation( Position.Value ) ; } } - + public Matrix4 BufferedTransformation { + get { return (Scale.BufferedValue * Rotation.BufferedValue) * Matrix4.CreateTranslation( Position.BufferedValue ) ; } + } + public void addChild(WorldObject wo){ if (!children.Contains(wo)){ children.Add(wo); @@ -44,7 +46,6 @@ namespace org.budnhead.core public WorldObject[] Children{ get { return this.children.ToArray(); } } - } public class ObjectGroup : WorldObject { diff --git a/org.budnhead/graphics/GLCamera.cs b/org.budnhead/graphics/GLCamera.cs index 42a1169..982ab34 100644 --- a/org.budnhead/graphics/GLCamera.cs +++ b/org.budnhead/graphics/GLCamera.cs @@ -34,7 +34,7 @@ namespace org.budnhead.graphics buildMatrices(); } - public void setViewport(int width, int height) + override public void setViewport(int width, int height) { this.width = (float)width; this.height = (float)height; @@ -54,7 +54,7 @@ namespace org.budnhead.graphics aspect, 1.0f, 100000.0f - ); + ); } public Vector3 Position @@ -136,6 +136,21 @@ namespace org.budnhead.graphics } + /** + * Group of Methods: LookXXXX + * + * Arrange Camera to point on/to/... + * + **/ + + public void lookAt(Vector3 position){ + Vector3 v = position - Position; + v.Normalize(); + + View = v; + } + + } diff --git a/org.budnhead/graphics/GLObject.cs b/org.budnhead/graphics/GLObject.cs index 3c5146d..86fc153 100644 --- a/org.budnhead/graphics/GLObject.cs +++ b/org.budnhead/graphics/GLObject.cs @@ -4,6 +4,7 @@ using OpenTK.Graphics.OpenGL; using OpenTK.Graphics; using OpenTK; +using org.budnhead.tools; namespace org.budnhead.graphics { @@ -33,13 +34,13 @@ namespace org.budnhead.graphics public GLObject(int vertexes) { - shaderProgram = GlobalDefaults.instance().DefaultShaderProgram; + shaderProgram = ResourceLibrary.getResource("default"); init(vertexes); prepareGL(); } public GLObject(){ - shaderProgram = GlobalDefaults.instance().DefaultShaderProgram; + shaderProgram = ResourceLibrary.getResource("default"); init(0); prepareGL(); } @@ -194,7 +195,7 @@ namespace org.budnhead.graphics public void paint() { - paint(GlobalDefaults.instance().ActiveScene); + paint(new GLCamera()); } public void paint(GLSceneOrientation scene) diff --git a/org.budnhead/graphics/GLScene.cs b/org.budnhead/graphics/GLScene.cs deleted file mode 100644 index b8777bf..0000000 --- a/org.budnhead/graphics/GLScene.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System; - -using OpenTK; -using org.budnhead.core; - -namespace org.budnhead.graphics -{ - public class GLScene - { - GLSceneOrientation sceneOrientation; - ShaderProgram shader; - WorldObject root; - - public GLScene() - { - sceneOrientation = GlobalDefaults.instance().ActiveScene; - shader = GlobalDefaults.instance().DefaultShaderProgram; - root = new ObjectGroup(); - } - - public GLScene(GLSceneOrientation sceneOrientation) - { - this.sceneOrientation = sceneOrientation; - shader = GlobalDefaults.instance().DefaultShaderProgram; - root = new ObjectGroup(); - } - - - - public WorldObject RootObject { - get { return this.root; } - set { this.root = value; } - } - - public void draw(){ - Matrix4 objectMatrix = Matrix4.Identity; - - shader.use(); - - if (root != null){ - draw( objectMatrix, root ); - } - - foreach (WorldObject child in Actor.activeActors){ - draw( objectMatrix, child ); - } - - } - - public void draw(Matrix4 baseMatrix,WorldObject wo){ - Matrix4 objectMatrix = wo.Transformation * baseMatrix; - - //Console.WriteLine("draw(,{0}",wo); - - //Console.WriteLine("draw(): o={0}\noM=\n{1}",wo,objectMatrix); - shader.setup(objectMatrix, sceneOrientation); - - Model3D m3d = wo.getModel3D(); - if (m3d != null){ - m3d.draw(); - } - - foreach (WorldObject child in wo.Children){ - draw( objectMatrix, child ); - } - - } - - - - } -} diff --git a/org.budnhead/graphics/GLSceneOrientation.cs b/org.budnhead/graphics/GLSceneOrientation.cs index 4d4260a..4b9e698 100644 --- a/org.budnhead/graphics/GLSceneOrientation.cs +++ b/org.budnhead/graphics/GLSceneOrientation.cs @@ -28,5 +28,16 @@ namespace org.budnhead.graphics public Matrix4 mProjection(){ return this._mProjection; } + + public virtual void setViewport(int width, int height){ + float aspect = width / height; + + _mProjection = Matrix4.CreatePerspectiveFieldOfView( + MathHelper.PiOver2, + aspect, + 1.0f, + 100000.0f + ); + } } } diff --git a/bnhdemo/OpenGLWindow.cs b/org.budnhead/graphics/GLWindow.cs similarity index 80% rename from bnhdemo/OpenGLWindow.cs rename to org.budnhead/graphics/GLWindow.cs index ddab7dc..16d18ff 100644 --- a/bnhdemo/OpenGLWindow.cs +++ b/org.budnhead/graphics/GLWindow.cs @@ -1,6 +1,7 @@ using System; using System.Drawing; using System.Collections.Generic; +using System.Threading; using OpenTK.Graphics; using OpenTK.Graphics.OpenGL; @@ -8,13 +9,12 @@ using OpenTK; using org.budnhead.core; using org.budnhead.exceptions; -using org.budnhead.graphics; using org.budnhead.graphics.primitives; -namespace bnhdemo +namespace org.budnhead.graphics { - public class OpenGLWindow : GameWindow + public class GLWindow : GameWindow { private Point mouseCapturePosition; private bool mouseCaptured; @@ -25,15 +25,11 @@ namespace bnhdemo private Vector3 lookAt; private float lookDistance; - private Cube cube, - c1, c2, c3; - - private string titleMsg = ""; GLCamera sceneCamera; - GLScene scene; + Scene scene; - public OpenGLWindow() + public GLWindow() :base(600, 600, GraphicsMode.Default, "nhEngine", @@ -44,37 +40,29 @@ namespace bnhdemo { VSync = VSyncMode.On; sceneCamera = new GLCamera(); - scene = new GLScene(sceneCamera); + scene = new Scene(sceneCamera); + } + + public Scene Scene { + get { return this.scene; } } protected override void OnLoad(EventArgs e) { base.OnLoad(e); - GL.ClearColor(0.05f, 0.05f, 0.05f, 0.0f); + GL.ClearColor(0.15f, 0.15f, 0.15f, 0.0f); GL.Enable(EnableCap.DepthTest); GL.Enable(EnableCap.Normalize); GL.Enable(EnableCap.Blend); GL.BlendFunc(BlendingFactorSrc.SrcAlpha,BlendingFactorDest.OneMinusSrcAlpha); - cube = new Cube(new Vector3(0,0,150), 16.0f); - c1 = new Cube(new Vector3(16,0,150), 8.0f); - c2 = new Cube(new Vector3(0,150,150), 8.0f); - c3 = new Cube(new Vector3(175,175,150), 8.0f); - lookAt = new Vector3(0,0,SquaredMap.maxHeight); lookDistance = 2048; arcUpDown = MathHelper.PiOver6; arcLeftRight = MathHelper.PiOver4; - - sceneCamera.setFoV(MathHelper.PiOver4); + sceneCamera.setFoV(MathHelper.PiOver2); setupCamera(); - - scene.RootObject.addChild( cube ); - scene.RootObject.addChild( c1 ); - scene.RootObject.addChild( c2 ); - scene.RootObject.addChild( c3 ); - } protected override void OnResize(EventArgs e) @@ -85,32 +73,6 @@ namespace bnhdemo sceneCamera.setViewport(ClientRectangle.Width, ClientRectangle.Height); } - protected override void OnRenderFrame(FrameEventArgs e) - { - base.OnRenderFrame(e); - GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); - - scene.draw(); - - SwapBuffers(); - - Title = string.Format("{0:F}/s {1:F}/s [{2:F}s] {3}", RenderFrequency,UpdateFrequency,UpdatePeriod,titleMsg); - } - - protected override void OnUpdateFrame(FrameEventArgs e) - { - base.OnUpdateFrame(e); - Matrix4 m4 = Matrix4.CreateRotationZ(MathHelper.Pi / 90.0f); - - cube.Rotation = m4 * cube.Rotation; - c1.Position = (m4.Inverted() * new Vector4(c1.Position)).Xyz; - c2.Rotation = (m4 * c2.Rotation); - c3.Position = (m4 * new Vector4(c3.Position)).Xyz; - - - Actor.updateAll( (float)UpdatePeriod ); - } - private void captureMouse(){ mouseCapturePosition = new Point(Mouse.X, Mouse.Y); mouseCaptured = true; @@ -141,7 +103,7 @@ namespace bnhdemo { switch (e.Button){ case OpenTK.Input.MouseButton.Left: - markMouse(e.X,e.Y); + //markMouse(e.X,e.Y); break; case OpenTK.Input.MouseButton.Right: captureMouse(); @@ -211,7 +173,7 @@ namespace bnhdemo break; case OpenTK.Input.Key.Space: - fireBallistic(); + //fireBallistic(); break; case OpenTK.Input.Key.Number1: @@ -234,7 +196,7 @@ namespace bnhdemo } } - +/* private void fireBallistic(){ Console.WriteLine("Fire Ballistic..."); BallisticActor ba = new BallisticActor(0); @@ -245,7 +207,7 @@ namespace bnhdemo ba.Velocity.Normalize(); ba.Velocity *= 50; } - +*/ public void rotateUpDown(float arc) { @@ -289,10 +251,20 @@ namespace bnhdemo sceneCamera.Position = pos; } - public GLScene Scene { - get { return this.scene; } + + + + + +/* private void startTimers(){ + timerGraphics.Change(0,50); + timerUpdates.Change(0,50); } - + private void stopTimers(){ + timerGraphics.Change(Timeout.Infinite,Timeout.Infinite); + timerUpdates.Change(Timeout.Infinite,Timeout.Infinite); + } +*/ } } diff --git a/org.budnhead/graphics/LoadedModel.cs b/org.budnhead/graphics/LoadedModel.cs index ae579c0..26a2460 100644 --- a/org.budnhead/graphics/LoadedModel.cs +++ b/org.budnhead/graphics/LoadedModel.cs @@ -22,6 +22,10 @@ namespace org.budnhead.graphics load(new StreamReader(filename),scale); } + public LoadedModel(Stream stream){ + load(new StreamReader(stream),1.0f); + } + private void load(TextReader reader){ load(reader,1); } diff --git a/org.budnhead/graphics/Model3D.cs b/org.budnhead/graphics/Model3D.cs index c075442..67ebac9 100644 --- a/org.budnhead/graphics/Model3D.cs +++ b/org.budnhead/graphics/Model3D.cs @@ -9,7 +9,7 @@ namespace org.budnhead.graphics { public class Model3D { - protected int vao, + protected int vao = 0, vbo, // Vertex Buffer cbo, // Color Buffer cbo2, // Second Color Buffer @@ -24,15 +24,14 @@ namespace org.budnhead.graphics { public Triangle[] triangles = new Triangle[0]; - - protected Model3D(){ - vao = GL.GenVertexArray(); + public Model3D(){ nTriangles = 0; prepare(); } protected void prepare(){ + vao = GL.GenVertexArray(); vbo = GL.GenBuffer(); cbo = GL.GenBuffer(); cbo2 = GL.GenBuffer(); @@ -110,6 +109,10 @@ namespace org.budnhead.graphics { } public void rebind(){ + if (vao != 0){ + prepare(); + } + bindVertexes(); bindNormals(); bindColors(); diff --git a/org.budnhead/graphics/ModelManager.cs b/org.budnhead/graphics/ModelManager.cs index fe1cc0d..5c27204 100644 --- a/org.budnhead/graphics/ModelManager.cs +++ b/org.budnhead/graphics/ModelManager.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using org.budnhead.core; +using org.budnhead.tools; namespace org.budnhead.graphics { diff --git a/org.budnhead/graphics/Scene.cs b/org.budnhead/graphics/Scene.cs new file mode 100644 index 0000000..b05c320 --- /dev/null +++ b/org.budnhead/graphics/Scene.cs @@ -0,0 +1,77 @@ +using System; + +using OpenTK; +using org.budnhead.core; +using org.budnhead.tools; + +using System.Drawing; + + +namespace org.budnhead.graphics +{ + public class Scene + { + ShaderProgram shader; + WorldObject root; + + public Scene() + { + shader = ResourceLibrary.getResource("default"); + root = new ObjectGroup(); + } + + public Scene(GLSceneOrientation sceneOrientation) + { + shader = ResourceLibrary.getResource("default"); + root = new ObjectGroup(); + } + + public Scene(Scene source){ + this.shader = source.shader; + this.root = source.root; + } + + + public WorldObject RootObject { + get { return this.root; } + set { this.root = value; } + } + + public void draw(Viewport viewport){ + Matrix4 objectMatrix = Matrix4.Identity; + + shader.use(); + + if (root != null){ + draw( viewport, objectMatrix, root ); + } + + foreach (WorldObject child in Actor.activeActors.ToArray()){ + draw( viewport, objectMatrix, child ); + } + + } + + public void draw(Viewport viewport,Matrix4 baseMatrix,WorldObject wo){ + Matrix4 objectMatrix = wo.Transformation * baseMatrix; + + //Console.WriteLine("draw(,{0}",wo); + + //Console.WriteLine("draw(): o={0}\noM=\n{1}",wo,objectMatrix); + shader.setup(objectMatrix, viewport.SceneOrientation); + + Model3D m3d = wo.getModel3D(); + if (m3d != null){ + m3d.draw(); + } + + foreach (WorldObject child in wo.Children){ + draw( viewport, objectMatrix, child ); + } + + } + + + + } +} diff --git a/org.budnhead/graphics/SceneWindow.cs b/org.budnhead/graphics/SceneWindow.cs new file mode 100644 index 0000000..8f0213d --- /dev/null +++ b/org.budnhead/graphics/SceneWindow.cs @@ -0,0 +1,120 @@ +using System; +using System.Threading; +using System.Collections.Generic; + +using OpenTK; +using OpenTK.Graphics; +using OpenTK.Graphics.OpenGL; + +using org.budnhead.core; + +namespace org.budnhead.graphics +{ + public class SceneWindow : GameWindow + { + Scene scene; + + Viewport primaryViewport; + List viewports = new List(); + + internal SceneWindow() + :base(600, 600, + GraphicsMode.Default, + "nhEngine", + GameWindowFlags.Default, + DisplayDevice.Default, + 3, 3, + GraphicsContextFlags.ForwardCompatible) + { + this.primaryViewport = new Viewport(); + addViewport(primaryViewport); + + lock(Engine.sceneWindows){ + Engine.sceneWindows.Add(this); + } + } + + public Viewport PrimaryViewport { + get { return this.primaryViewport; } + } + + public Viewport[] Viewports { + get { return this.viewports.ToArray(); } + } + + public override void Dispose() + { + lock (Engine.sceneWindows){ + Engine.sceneWindows.Remove(this); + if (Engine.sceneWindows.Count == 0){ + Engine.Shutdown(); + } + } + base.Dispose(); + } + + public void addViewport(Viewport viewport){ + if (viewport.Parent != null){ + viewport.Parent.removeViewport(viewport); + } + this.viewports.Add(viewport); + viewport.Parent = this; + } + + public void removeViewport(Viewport viewport){ + if ((primaryViewport!=viewport) && (viewports.Contains(viewport))){ + viewport.Parent = null; + viewports.Remove(viewport); + } + } + + public Scene Scene { + get { return this.primaryViewport.Scene; } + set { lock(this){ + this.primaryViewport.Scene = value; + } } + } + + protected override void OnResize(EventArgs e) + { + base.OnResize(e); + } + + + protected override void OnRenderFrame(FrameEventArgs e) + { + paint(); + } + + protected override void OnClosed(EventArgs e) + { + base.OnClosed(e); + Dispose(); + } + + public void paint(){ + lock(this){ + MakeCurrent(); + + paintViewports(); + paintControls(); + + SwapBuffers(); + } + } + + public void paintViewports(){ + Engine.ConsumerEnter(); + + foreach (Viewport viewport in this.viewports){ + viewport.paint(); + } + + Engine.ConsumerExit(); + } + + public void paintControls(){ + } + } + +} diff --git a/org.budnhead/graphics/ShaderProgram.cs b/org.budnhead/graphics/ShaderProgram.cs index d185f6c..176cb5b 100644 --- a/org.budnhead/graphics/ShaderProgram.cs +++ b/org.budnhead/graphics/ShaderProgram.cs @@ -4,6 +4,8 @@ using System.IO; using OpenTK.Graphics.OpenGL; using OpenTK; +using org.budnhead.tools; + /** * ShaderProgram Class * @@ -70,8 +72,8 @@ namespace org.budnhead.graphics public ShaderProgram(String vertexShader, String fragmentShader) { init( - new Shader(ShaderType.VertexShader, vertexShader), - new Shader(ShaderType.FragmentShader, fragmentShader) + ResourceLibrary.getResource(vertexShader), + ResourceLibrary.getResource(fragmentShader) ); } diff --git a/org.budnhead/graphics/Viewport.cs b/org.budnhead/graphics/Viewport.cs new file mode 100644 index 0000000..5891e20 --- /dev/null +++ b/org.budnhead/graphics/Viewport.cs @@ -0,0 +1,67 @@ +using System; + +using System.Drawing; + +using org.budnhead.core; +using org.budnhead.tools; +using OpenTK; +using OpenTK.Graphics.OpenGL; + +namespace org.budnhead.graphics +{ + public class Viewport + { + GLSceneOrientation sceneOrientation; + Scene scene; + ShaderProgram shader; + + public float Left { get; set; } + public float Top { get; set; } + public float Width { get; set; } + public float Height { get; set; } + + public Viewport() + { + sceneOrientation = new GLSceneOrientation(); + Left = 0.0f; + Top = 0.0f; + Width = 1.0f; + Height = 1.0f; + } + + internal SceneWindow Parent { get; set; } + + public Scene Scene { + get { return this.scene; } + set { this.scene = value; } + } + + public GLSceneOrientation SceneOrientation { + get { return this.sceneOrientation; } + set { this.sceneOrientation = value; } + } + + public void paint(){ + Console.WriteLine("Viewport.paint()"); + if (Parent != null){ + Rectangle cr = Parent.ClientRectangle; + Rectangle vpr = new Rectangle( + (int)(cr.Left + (cr.Width * Left)), + (int)(cr.Top + (cr.Height * Top)), + (int)(cr.Width * Width), + (int)(cr.Height * Height) + ); + + Console.WriteLine(String.Format("Viewport: {0}",vpr)); + + GL.Viewport( vpr ); + sceneOrientation.setViewport( cr.Width, cr.Height ); + + GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); + + Scene.draw(this); + } + } + + } +} diff --git a/org.budnhead/graphics/primitives/Cube.cs b/org.budnhead/graphics/primitives/Cube.cs index c69e5cf..9301f9a 100644 --- a/org.budnhead/graphics/primitives/Cube.cs +++ b/org.budnhead/graphics/primitives/Cube.cs @@ -9,8 +9,8 @@ namespace org.budnhead.graphics.primitives { public Cube(Vector3 position, float width) { - Scale = Matrix4.CreateScale(width); - Position = position; + Scale.Value = Matrix4.CreateScale(width); + Position.Value = position; } public override Model3D getModel3D() diff --git a/org.budnhead/org.budnhead.csproj b/org.budnhead/org.budnhead.csproj index 5af4595..082617f 100644 --- a/org.budnhead/org.budnhead.csproj +++ b/org.budnhead/org.budnhead.csproj @@ -50,18 +50,15 @@ - - + - - @@ -77,6 +74,25 @@ + + + + + + + + + + + + + + + + + + + @@ -159,6 +175,10 @@ + + + + diff --git a/org.budnhead/FileHelper.cs b/org.budnhead/tools/FileHelper.cs similarity index 94% rename from org.budnhead/FileHelper.cs rename to org.budnhead/tools/FileHelper.cs index 2b99f7a..06769f4 100644 --- a/org.budnhead/FileHelper.cs +++ b/org.budnhead/tools/FileHelper.cs @@ -1,7 +1,7 @@ using System; using System.IO; -namespace org.budnhead.core +namespace org.budnhead.tools { public static class FileHelper { diff --git a/org.budnhead/tools/JobThreader.cs b/org.budnhead/tools/JobThreader.cs new file mode 100644 index 0000000..1b80927 --- /dev/null +++ b/org.budnhead/tools/JobThreader.cs @@ -0,0 +1,84 @@ +using System; +using System.Threading; +using System.Collections.Generic; + +namespace org.budnhead.tools +{ + public delegate T JobDelegate(); + + public class JobThreader + { + Thread workerThread; + List queuedJobs; + + + public JobThreader() + { + workerThread = Thread.CurrentThread; + queuedJobs = new List(); + } + public JobThreader(Thread workerThread){ + this.workerThread = workerThread; + queuedJobs = new List(); + } + + public void execute(){ + Monitor.Enter(queuedJobs); + + foreach (Job j in queuedJobs){ + j.execute(); + } + + queuedJobs.Clear(); + + Monitor.PulseAll(queuedJobs); + Monitor.Exit(queuedJobs); + } + + public T execute(JobDelegate jobDelegate) where T : class{ + if (workerThread.Equals(Thread.CurrentThread)){ + return jobDelegate(); + } else { + return Enqueue(jobDelegate); + } + } + + private T Enqueue(JobDelegate jobDelegate) where T : class { + Job job; + Monitor.Enter(queuedJobs); + + job = new Job(jobDelegate); + + queuedJobs.Add(job); + + Monitor.Wait(queuedJobs); + Monitor.Exit(queuedJobs); + + return job.Result; + } + + public abstract class Job{ + public virtual void execute(){ + } + } + + public class Job : Job{ + T result; + JobDelegate jobDelegate; + + public Job(JobDelegate jobDelegate){ + this.jobDelegate = jobDelegate; + } + + public override void execute() + { + this.result = this.jobDelegate(); + } + + public T Result { + get { return this.result; } + } + + } + } +} \ No newline at end of file diff --git a/org.budnhead/tools/ResourceLibrary.cs b/org.budnhead/tools/ResourceLibrary.cs new file mode 100644 index 0000000..0e715b2 --- /dev/null +++ b/org.budnhead/tools/ResourceLibrary.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.IO; + +using org.hwo.contracts; + +namespace org.budnhead.tools +{ + public static class ResourceLibrary + { + static Dictionary> + resourceTypes = new Dictionary>(); + static List + resourcePaths = new List(new string[]{"."}); + + static Dictionary prefixes = new Dictionary(); + static Dictionary suffixes = new Dictionary(); + + internal static bool initializeResourceType(Type t,string prefix,string suffix,bool initializeBases){ + ConstructorInfo ci = null; + + new BooleanConditional() + .requiresValid(ref ci,delegate { return t.GetConstructor(new Type[]{ typeof(Stream) }); }) + .does( delegate { initializeResourceType(t,prefix,suffix); } ); + + if (initializeBases && (t.BaseType != null)){ + initializeResourceType(t.BaseType,prefix,suffix,true); + } + + + return true; + } + internal static bool initializeResourceType(Type t,string prefix,string suffix){ + if (prefix != null) + prefixes.Add(t,prefix); + if (suffix != null) + suffixes.Add(t,suffix); + + return true; + } + + static T findLoadedInstance(string name){ + if (resourceTypes.ContainsKey(typeof(T))){ + if (resourceTypes[typeof(T)].ContainsKey(name)){ + return (T)resourceTypes[typeof(T)][name]; + } + } + throw new KeyNotFoundException(""); + } + + public static void cacheInstance(string name,T instance){ + if (!resourceTypes.ContainsKey(typeof(T))){ + resourceTypes.Add(typeof(T),new Dictionary()); + } + resourceTypes[typeof(T)].Add(name,instance); + } + + public static T getResource(string name){ + try { + return findLoadedInstance(name); + } catch (KeyNotFoundException){ + string p="",s=""; + + if (prefixes.ContainsKey(typeof(T))){ + p = prefixes[typeof(T)]; + } + if (suffixes.ContainsKey(typeof(T))){ + s = suffixes[typeof(T)]; + } + + string resFileName = FileHelper.findFile(String.Format("{0}{1}{2}",p,name,s),resourcePaths.ToArray()); + if (resFileName != null){ + Stream resStream = new FileStream(resFileName,FileMode.Open); + ConstructorInfo ci = typeof(T).GetConstructor(new Type[]{ typeof(Stream) }); + T o = (T)ci.Invoke(new object[]{ resStream }); + + cacheInstance(name,o); + + return o; + } + throw new KeyNotFoundException(String.Format("ResourceLibrary[{0}:{1}]",typeof(T).ToString(),name)); + } + } + + + + } +} diff --git a/org.budnhead/ui/Container.cs b/org.budnhead/ui/Container.cs new file mode 100644 index 0000000..d1a79e2 --- /dev/null +++ b/org.budnhead/ui/Container.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; + +namespace org.budnhead +{ + public class Container : Control + { + private List children; + + public Container() + { + this.children = new List(); + } + + public void addChild(Control control){ + if (control.parent != null){ + control.parent.removeChild(control); + } + this.children.Add(control); + } + public void removeChild(Control control){ + this.children.Remove(control); + } + public Control[] Children { + get { return this.children.ToArray(); } + } + + + + + } +} diff --git a/org.budnhead/ui/Control.cs b/org.budnhead/ui/Control.cs new file mode 100644 index 0000000..5f9cae0 --- /dev/null +++ b/org.budnhead/ui/Control.cs @@ -0,0 +1,33 @@ +using System; +using OpenTK; + +namespace org.budnhead +{ + public class Control + { + internal Container parent; + + public Control() + { + } + + public Vector2 Position { get; set; } + public Vector2 Size { get; set; } + + + public Container Parent { + get { return this.parent; } + set { if (value == null) { if (this.parent != null) this.parent.removeChild(this); } else { value.addChild(this); } } + } + + + public virtual void paint(){ + paintBorder(); + paintControl(); + } + public virtual void paintBorder(){ + } + public virtual void paintControl(){ + } + } +} diff --git a/org.budnhead/ui/ModifierKeys.cs b/org.budnhead/ui/ModifierKeys.cs new file mode 100644 index 0000000..ab98207 --- /dev/null +++ b/org.budnhead/ui/ModifierKeys.cs @@ -0,0 +1,8 @@ +using System; +namespace org.budnhead +{ + public enum ModifierKeys + { + NONE,SHIFT,CONTROL,COMMAND,WIN,CONTEXT + } +} diff --git a/org.budnhead/ui/SceneInScene.cs b/org.budnhead/ui/SceneInScene.cs new file mode 100644 index 0000000..922b5b8 --- /dev/null +++ b/org.budnhead/ui/SceneInScene.cs @@ -0,0 +1,27 @@ +using System; + +using org.budnhead.graphics; + +using OpenTK.Graphics.OpenGL; + +namespace org.budnhead +{ + public class SceneInScene : Control + { + Scene scene; + + public SceneInScene() + { + } + + public override void paintControl() + { + if (scene != null){ + + // ToDo: Prepare Transformation Matrix and Clipping + // ... scene.draw(); + + } + } + } +} diff --git a/org.budnhead/ui/events/KeyPressedEvent.cs b/org.budnhead/ui/events/KeyPressedEvent.cs new file mode 100644 index 0000000..092186e --- /dev/null +++ b/org.budnhead/ui/events/KeyPressedEvent.cs @@ -0,0 +1,16 @@ +using System; +namespace org.budnhead +{ + public class KeyPressedEvent : UIEvent + { + public KeyPressedEvent(char keyChar,ModifierKeys modifierKeys) + { + KeyChar = keyChar; + Modifier = modifierKeys; + } + + public char KeyChar { get; private set; } + public ModifierKeys Modifier { get; private set; } + + } +} diff --git a/org.budnhead/ui/events/UIEvent.cs b/org.budnhead/ui/events/UIEvent.cs new file mode 100644 index 0000000..25c7279 --- /dev/null +++ b/org.budnhead/ui/events/UIEvent.cs @@ -0,0 +1,12 @@ +using System; +namespace org.budnhead +{ + public class UIEvent + { + + public UIEvent() + { + } + + } +} diff --git a/org.hwo.contracts/Conditional.cs b/org.hwo.contracts/Conditional.cs index 2d51975..d4e7ee7 100644 --- a/org.hwo.contracts/Conditional.cs +++ b/org.hwo.contracts/Conditional.cs @@ -41,13 +41,21 @@ namespace org.hwo.contracts return this; } - public Conditional assigns(ref AT target,assignDelegate assigner){ + public Conditional assigns(ref AT target,assignDelegate assigner) { if (success){ target = assigner(); } return this; } + public Conditional requiresValid(ref AT target,assignDelegate assigner){ + if (success){ + target = assigner(); + success = target != null; + } + return this; + } + public bool isSuccess(){ return this.success; }