WIP (Threaded Rendering, CP-Lock, MultiDisplay)

graphics
Harald Christian Joachim Wolff 2017-05-26 15:12:22 +02:00
parent 634da6fe0b
commit dd4dc701f9
38 changed files with 1196 additions and 382 deletions

View File

@ -18,85 +18,77 @@ using org.budnhead.core;
namespace bnhdemo namespace bnhdemo
{ {
public class BootStrap public static class BootStrap
{ {
public static BootStrap _instance; static SquaredMap map;
public static BootStrap instance()
{
return _instance;
}
OpenGLWindow glWindow; static Actor trackedActor;
static GLCamera trackingCamera;
SquaredMap map;
public static void Main(string[] args){ 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() public static void loadMap(){
{
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(){
ImageSharp.Image i = ImageSharp.Image.Load( new FileStream("M3-wip.png",FileMode.Open)); ImageSharp.Image i = ImageSharp.Image.Load( new FileStream("M3-wip.png",FileMode.Open));
i.Flip(ImageSharp.Processing.FlipType.Vertical); i.Flip(ImageSharp.Processing.FlipType.Vertical);
i.Resize(500,500);
map = new SquaredMap(i); map = new SquaredMap(i);
glWindow.Scene.RootObject.addChild( map ); Engine.SceneWindows[0].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);
} }
} }
} }

View File

@ -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; }
}
}
}

View File

@ -60,9 +60,8 @@
<ItemGroup> <ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="BootStrap.cs" /> <Compile Include="BootStrap.cs" />
<Compile Include="Graphics.cs" />
<Compile Include="OpenGLWindow.cs" />
<Compile Include="TextureManager.cs" /> <Compile Include="TextureManager.cs" />
<Compile Include="demo\CameraRotator.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="OpenTK.dll.config"> <None Include="OpenTK.dll.config">
@ -114,6 +113,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Folder Include="sounds\" /> <Folder Include="sounds\" />
<Folder Include="demo\" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project> </Project>

View File

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

View File

@ -10,25 +10,20 @@ namespace org.budnhead.core
{ {
public class Actor : WorldObject public class Actor : WorldObject
{ {
public static List<Actor> activeActors = new List<Actor>(); internal static List<Actor> activeActors = new List<Actor>();
public static List<Actor> finishedActors = new List<Actor>(); private static List<Actor> finishedActors = new List<Actor>();
internal static void updateActors(float elapsed){
public static void updateAll(float timespan) // Update all active Actors...
{ foreach (Actor a in activeActors.ToArray()){
foreach (Actor a in activeActors) a.update(elapsed);
{
a.update(timespan);
} }
foreach (Actor a in finishedActors) // Remove finished Actors
{ foreach (Actor a in finishedActors.ToArray()){
activeActors.Remove(a); activeActors.Remove(a);
} }
finishedActors.Clear(); finishedActors.Clear();
} }
private int id; private int id;
@ -39,26 +34,30 @@ namespace org.budnhead.core
this.id = id; this.id = id;
activeActors.Add(this); activeActors.Add(this);
_player = new nhPlayer(); //_player = new nhPlayer();
activePlayers.Add(_player); //activePlayers.Add(_player);
} }
public void destroy(){ public void destroy(){
finishedActors.Add(this); finishedActors.Add(this);
_player.deletePlayer(); //_player.deletePlayer();
} }
public Vector3 Heading { get; set; } public readonly BufferedValueInstance<Vector3> Heading = new BufferedValueInstance<Vector3>(new Vector3(0,0,1));
public Vector3 Velocity { get; set; } public readonly BufferedValueInstance<Vector3> Velocity = new BufferedValueInstance<Vector3>(new Vector3());
public float Weight { get; set; } public readonly BufferedValueInstance<float> Weight = new BufferedValueInstance<float>(0);
public bool IsActive {
get { return activeActors.Contains(this); }
}
public virtual void update(float timespan){ public virtual void update(float timespan){
if (soundPlaying()){ /* if (soundPlaying()){
syncSoundPosition(); syncSoundPosition();
} }
} */ }
public void setHeading(Vector3 heading,Vector3 top){ public void setHeading(Vector3 heading,Vector3 top){
Vector3 x,y,z; Vector3 x,y,z;
@ -74,7 +73,7 @@ namespace org.budnhead.core
new Vector4(0,0,0,1) new Vector4(0,0,0,1)
); );
Rotation = Matrix4.CreateRotationX(MathHelper.PiOver2) * mRotation; Rotation.Value = Matrix4.CreateRotationX(MathHelper.PiOver2) * mRotation;
} }
public Model3D Model3D { get; set; } 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) 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) public void setBuffers(params string[] buffers)
{ {
foreach (string i in buffers) /* foreach (string i in buffers)
{ {
if(!aBuffers.ContainsKey(i)) if(!aBuffers.ContainsKey(i))
aBuffers.Add(i, nhBuffers.buffers[i]); aBuffers.Add(i, nhBuffers.buffers[i]);
} }*/
} }
public void playSound(string sound, float gain = 1.0f, bool loop = false) public void playSound(string sound, float gain = 1.0f, bool loop = false)
{ {
// _player.position = this.Position.Value;
_player.position = this.Position; // _player.velocity = this.Velocity.Value;
_player.velocity = this.Velocity; // _player.play(aBuffers[sound], gain, loop);
_player.play(aBuffers[sound], gain, loop);
} }
private void syncSoundPosition() private void syncSoundPosition()
{ {
_player.setPosition(this.Position); // _player.setPosition(this.Position.Value);
_player.setVelocity(this.Velocity); // _player.setVelocity(this.Velocity.Value);
} }
public Boolean soundPlaying(){ public Boolean soundPlaying(){
return _player.state(); return false; //_player.state();
} }
} }

View File

@ -2,6 +2,7 @@
using org.budnhead.graphics.primitives; using org.budnhead.graphics.primitives;
using org.budnhead.graphics; using org.budnhead.graphics;
using org.budnhead.exceptions; using org.budnhead.exceptions;
using org.budnhead.tools;
using OpenTK; using OpenTK;
@ -17,7 +18,7 @@ namespace org.budnhead.core
:base(id) :base(id)
{ {
this.actorState = BallisticActorStates.FLYING; this.actorState = BallisticActorStates.FLYING;
this.Model3D = ModelManager.instance.findModel("ballistisch"); this.Model3D = ResourceLibrary.getResource<LoadedModel>("ballistisch");
for (int n=0;n < this.Model3D.vertexes.Length;n++){ 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); 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){ switch (actorState){
case BallisticActorStates.FLYING: case BallisticActorStates.FLYING:
Velocity += (Physics.Gravitation * timespan); Velocity.Value += (Physics.Gravitation * timespan);
Position += Velocity * timespan; Position.Value += Velocity.Value * timespan;
setHeading( Velocity, Physics.Gravitation); setHeading( Velocity.Value, Physics.Gravitation);
try 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!"); Console.WriteLine("BallisticActor hit ground!");
actorState = BallisticActorStates.HIT; actorState = BallisticActorStates.HIT;
playSound("HowHit"); playSound("HowHit");
@ -71,7 +72,7 @@ namespace org.budnhead.core
public void fire() public void fire()
{ {
playSound("HowFire"); //playSound("HowFire");
} }

View File

@ -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<T> : IDisposable,IBufferedValue
{
static List<IBufferedValue> bufferedValues = new List<IBufferedValue>();
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;
}
}
}

View File

@ -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);
}
}
}
}

View File

@ -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<SceneWindow>
sceneWindows = new List<SceneWindow>();
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<object>.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) );
}
}
}
}
}

View File

@ -73,8 +73,8 @@ namespace org.budnhead.core
.requires(intersectPlainCoeff(P,V,A,B,C,out coeff)) .requires(intersectPlainCoeff(P,V,A,B,C,out coeff))
.requires(coeff.Y >= 0) .requires(coeff.Y >= 0)
.requires(coeff.Z >= 0) .requires(coeff.Z >= 0)
.requires(coeff.Y <= 1) .requires(coeff.Y <= 1.00001f)
.requires(coeff.Z <= 1) .requires(coeff.Z <= 1.00001f)
.assigns(ref p, delegate { return P + (coeff.X * V); }) .assigns(ref p, delegate { return P + (coeff.X * V); })
.isSuccess(); .isSuccess();
} }
@ -89,9 +89,9 @@ namespace org.budnhead.core
.requires(intersectPlainCoeff(P,V,A,B,C,out coeff)) .requires(intersectPlainCoeff(P,V,A,B,C,out coeff))
.requires(coeff.Y >= 0) .requires(coeff.Y >= 0)
.requires(coeff.Z >= 0) .requires(coeff.Z >= 0)
.requires(coeff.Y <= 1) .requires(coeff.Y <= 1.00001f)
.requires(coeff.Z <= 1) .requires(coeff.Z <= 1.00001f)
.requires(coeff.Y + coeff.Z <= 1) .requires(coeff.Y + coeff.Z <= 1.00001f)
.assigns(ref p, delegate { return A + (coeff.Y * (B-A)) + (coeff.Z * (C-A)); }) .assigns(ref p, delegate { return A + (coeff.Y * (B-A)) + (coeff.Z * (C-A)); })
.isSuccess(); .isSuccess();
} }

View File

@ -2,55 +2,29 @@
using OpenTK.Graphics.OpenGL; 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(); internal static bool initialize(){
public static GlobalDefaults instance(){ ResourceLibrary.initializeResourceType(typeof(Shader), "shader/", "");
return _instance; ResourceLibrary.initializeResourceType(typeof(ShaderProgram), "shader/", ".program");
} ResourceLibrary.initializeResourceType(typeof(LoadedModel), "models/", ".obj");
private Shader defVertexShader, ResourceLibrary.cacheInstance("default.vshader",new Shader(OpenTK.Graphics.OpenGL.ShaderType.VertexShader, defVertexShaderSource));
defFragmentShader; ResourceLibrary.cacheInstance("default.fshader",new Shader(OpenTK.Graphics.OpenGL.ShaderType.FragmentShader, defFragmentShaderSource));
private ShaderProgram
defShaderProgram;
private GLSceneOrientation activeScene; ResourceLibrary.cacheInstance("default",new ShaderProgram("default.vshader","default.fshader"));
private GlobalDefaults(){ return true;
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; }
} }
private string defVertexShaderSource = @"#version 330
private static string defVertexShaderSource = @"#version 330
layout(location = 0) in vec3 iv_position; layout(location = 0) in vec3 iv_position;
layout(location = 1) in vec4 iv_color; 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 vec4 color;
in vec3 norm; in vec3 norm;
@ -119,7 +93,5 @@ void main()
"; ";
} }
} }

View File

@ -13,8 +13,8 @@ namespace org.budnhead.core
rows[2] = new Vector4(X.Z,Y.Z,Z.Z,W.Z); rows[2] = new Vector4(X.Z,Y.Z,Z.Z,W.Z);
c = new Vector3(); c = new Vector3();
Console.WriteLine("New Linear Equation System to solve:"); //Console.WriteLine("New Linear Equation System to solve:");
dumpLinearSystem(rows); //dumpLinearSystem(rows);
if (rows[0].Z == 0){ if (rows[0].Z == 0){
Vector4 t = rows[0]; Vector4 t = rows[0];
@ -34,7 +34,7 @@ namespace org.budnhead.core
rows[2] -= rows[0] * (rows[2].Z / rows[0].Z); rows[2] -= rows[0] * (rows[2].Z / rows[0].Z);
} }
dumpLinearSystem(rows); //dumpLinearSystem(rows);
if (rows[1].Y == 0){ if (rows[1].Y == 0){
Vector4 t = rows[1]; Vector4 t = rows[1];
@ -48,7 +48,7 @@ namespace org.budnhead.core
rows[2] -= rows[1] * (rows[2].Y / rows[1].Y); rows[2] -= rows[1] * (rows[2].Y / rows[1].Y);
} }
dumpLinearSystem(rows); //dumpLinearSystem(rows);
rows[2] /= rows[2].X; rows[2] /= rows[2].X;
c.X = rows[2].W; c.X = rows[2].W;
@ -65,8 +65,8 @@ namespace org.budnhead.core
rows[0] /= rows[0].Z; rows[0] /= rows[0].Z;
c.Z = rows[0].W; c.Z = rows[0].W;
dumpLinearSystem(rows); //dumpLinearSystem(rows);
Console.WriteLine("Solved to {0}",c); //Console.WriteLine("Solved to {0}",c);
return true; return true;
} }

View File

@ -9,11 +9,10 @@ using OpenTK.Graphics.OpenGL4;
using OpenTK; using OpenTK;
using org.hwo.contracts; using org.hwo.contracts;
using org.budnhead.core;
using org.budnhead.exceptions; using org.budnhead.exceptions;
using org.budnhead.graphics;
namespace org.budnhead.graphics namespace org.budnhead.core
{ {
public class SquaredMap : WorldObject public class SquaredMap : WorldObject
{ {
@ -197,7 +196,7 @@ namespace org.budnhead.graphics
public Vector2 toTileBorderless(Vector2 world){ public Vector2 toTileBorderless(Vector2 world){
Vector2 tile = world / edge; Vector2 tile = world / edge;
return tile; return new Vector2((int)tile.X,(int)tile.Y);
} }
public Vector2 toTile(Vector2 world){ public Vector2 toTile(Vector2 world){
@ -211,7 +210,7 @@ namespace org.budnhead.graphics
.requires(tile.Y < height) .requires(tile.Y < height)
.throws<OutOfWorldException>(); .throws<OutOfWorldException>();
return tile; return new Vector2((int)tile.X,(int)tile.Y);
} }
public Vector2 intersectTile(Vector3 P,Vector3 V){ public Vector2 intersectTile(Vector3 P,Vector3 V){
@ -225,57 +224,63 @@ namespace org.budnhead.graphics
Console.WriteLine("P: {0} V: {1}",P,V); 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) ); A = P + ( V * ( -P.Z / V.Z) );
Console.WriteLine("Lower Plane Intersection: {0}",A); Console.WriteLine("Lower Plane Intersection: {0}",A);
Console.WriteLine("Higher Plane Intersection (LIN): {0}",B);
B = P + ( V * ( (SquaredMap.maxHeight-P.Z) / V.Z) ); B = P + ( V * ( (SquaredMap.maxHeight-P.Z) / V.Z) );
Console.WriteLine("Higher Plane Intersection: {0}",B); 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); float steps = (step.X * step.Y) / 25.0f;
b = toTileBorderless(B.Xy); step /= steps;
min = Vector2.ComponentMax(Vector2.ComponentMin(a,b)-new Vector2(1,1),new Vector2()); int isteps = (int)steps;
max = Vector2.ComponentMin(Vector2.ComponentMax(a,b)+new Vector2(1,1),new Vector2(width,height));
Console.WriteLine("Checking Intersections: {0} -> {1}",min,max); Vector2 pos = start,
tile = toTileBorderless(pos);
for (int nx = (int)min.X; nx < max.X; nx++){ Console.WriteLine("Interpolation: {0} - {1} - {2}",start,step,finish);
for (int ny = (int)min.Y; ny < max.Y; ny++){
Vector3 isect = new Vector3();
//Console.WriteLine("Check Intersection: {0}/{1}",nx,ny);
for (int n=0;n<4;n++){ for (int n=0;n<=isteps;){
try { Console.WriteLine("IP RUN[{0}]: {1} Tile: {2}",n,pos,tile);
Model3D.Triangle t = model.triangles[tileIndex(nx,ny)]; if (new BooleanConditional()
if (Geometry.intersectTriangle( .requires( tile.X >= 0)
P, .requires( tile.Y >= 0)
V, .requires( tile.X < width)
t.VertexA, .requires( tile.Y < height)
t.VertexB, .isSuccess()
t.VertexC, ){
out isect Vector3 isect = new Vector3();
)){ for (int nt=0;nt<4;nt++){
return isect; 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(); throw new OutOfWorldException();
} }

View File

@ -20,15 +20,17 @@ namespace org.budnhead.core
return null; return null;
} }
public Vector3 Position{ get; set; } = new Vector3(); public readonly BufferedValueInstance<Vector3> Position = new BufferedValueInstance<Vector3>(new Vector3());
public Matrix4 Rotation { get; set; } = Matrix4.Identity; public readonly BufferedValueInstance<Matrix4> Rotation = new BufferedValueInstance<Matrix4>(Matrix4.Identity);
public Matrix4 Scale { get; set; } = Matrix4.Identity; public readonly BufferedValueInstance<Matrix4> Scale = new BufferedValueInstance<Matrix4>(Matrix4.Identity);
public Matrix4 Transformation { 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){ public void addChild(WorldObject wo){
if (!children.Contains(wo)){ if (!children.Contains(wo)){
children.Add(wo); children.Add(wo);
@ -44,7 +46,6 @@ namespace org.budnhead.core
public WorldObject[] Children{ public WorldObject[] Children{
get { return this.children.ToArray(); } get { return this.children.ToArray(); }
} }
} }
public class ObjectGroup : WorldObject { public class ObjectGroup : WorldObject {

View File

@ -34,7 +34,7 @@ namespace org.budnhead.graphics
buildMatrices(); buildMatrices();
} }
public void setViewport(int width, int height) override public void setViewport(int width, int height)
{ {
this.width = (float)width; this.width = (float)width;
this.height = (float)height; this.height = (float)height;
@ -54,7 +54,7 @@ namespace org.budnhead.graphics
aspect, aspect,
1.0f, 1.0f,
100000.0f 100000.0f
); );
} }
public Vector3 Position 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;
}
} }

View File

@ -4,6 +4,7 @@ using OpenTK.Graphics.OpenGL;
using OpenTK.Graphics; using OpenTK.Graphics;
using OpenTK; using OpenTK;
using org.budnhead.tools;
namespace org.budnhead.graphics namespace org.budnhead.graphics
{ {
@ -33,13 +34,13 @@ namespace org.budnhead.graphics
public GLObject(int vertexes) public GLObject(int vertexes)
{ {
shaderProgram = GlobalDefaults.instance().DefaultShaderProgram; shaderProgram = ResourceLibrary.getResource<ShaderProgram>("default");
init(vertexes); init(vertexes);
prepareGL(); prepareGL();
} }
public GLObject(){ public GLObject(){
shaderProgram = GlobalDefaults.instance().DefaultShaderProgram; shaderProgram = ResourceLibrary.getResource<ShaderProgram>("default");
init(0); init(0);
prepareGL(); prepareGL();
} }
@ -194,7 +195,7 @@ namespace org.budnhead.graphics
public void paint() public void paint()
{ {
paint(GlobalDefaults.instance().ActiveScene); paint(new GLCamera());
} }
public void paint(GLSceneOrientation scene) public void paint(GLSceneOrientation scene)

View File

@ -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 );
}
}
}
}

View File

@ -28,5 +28,16 @@ namespace org.budnhead.graphics
public Matrix4 mProjection(){ public Matrix4 mProjection(){
return this._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
);
}
} }
} }

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Drawing; using System.Drawing;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading;
using OpenTK.Graphics; using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL; using OpenTK.Graphics.OpenGL;
@ -8,13 +9,12 @@ using OpenTK;
using org.budnhead.core; using org.budnhead.core;
using org.budnhead.exceptions; using org.budnhead.exceptions;
using org.budnhead.graphics;
using org.budnhead.graphics.primitives; using org.budnhead.graphics.primitives;
namespace bnhdemo namespace org.budnhead.graphics
{ {
public class OpenGLWindow : GameWindow public class GLWindow : GameWindow
{ {
private Point mouseCapturePosition; private Point mouseCapturePosition;
private bool mouseCaptured; private bool mouseCaptured;
@ -25,15 +25,11 @@ namespace bnhdemo
private Vector3 lookAt; private Vector3 lookAt;
private float lookDistance; private float lookDistance;
private Cube cube,
c1, c2, c3;
private string titleMsg = "";
GLCamera sceneCamera; GLCamera sceneCamera;
GLScene scene; Scene scene;
public OpenGLWindow() public GLWindow()
:base(600, 600, :base(600, 600,
GraphicsMode.Default, GraphicsMode.Default,
"nhEngine", "nhEngine",
@ -44,37 +40,29 @@ namespace bnhdemo
{ {
VSync = VSyncMode.On; VSync = VSyncMode.On;
sceneCamera = new GLCamera(); sceneCamera = new GLCamera();
scene = new GLScene(sceneCamera); scene = new Scene(sceneCamera);
}
public Scene Scene {
get { return this.scene; }
} }
protected override void OnLoad(EventArgs e) protected override void OnLoad(EventArgs e)
{ {
base.OnLoad(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.DepthTest);
GL.Enable(EnableCap.Normalize); GL.Enable(EnableCap.Normalize);
GL.Enable(EnableCap.Blend); GL.Enable(EnableCap.Blend);
GL.BlendFunc(BlendingFactorSrc.SrcAlpha,BlendingFactorDest.OneMinusSrcAlpha); 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); lookAt = new Vector3(0,0,SquaredMap.maxHeight);
lookDistance = 2048; lookDistance = 2048;
arcUpDown = MathHelper.PiOver6; arcUpDown = MathHelper.PiOver6;
arcLeftRight = MathHelper.PiOver4; arcLeftRight = MathHelper.PiOver4;
sceneCamera.setFoV(MathHelper.PiOver2);
sceneCamera.setFoV(MathHelper.PiOver4);
setupCamera(); setupCamera();
scene.RootObject.addChild( cube );
scene.RootObject.addChild( c1 );
scene.RootObject.addChild( c2 );
scene.RootObject.addChild( c3 );
} }
protected override void OnResize(EventArgs e) protected override void OnResize(EventArgs e)
@ -85,32 +73,6 @@ namespace bnhdemo
sceneCamera.setViewport(ClientRectangle.Width, ClientRectangle.Height); 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(){ private void captureMouse(){
mouseCapturePosition = new Point(Mouse.X, Mouse.Y); mouseCapturePosition = new Point(Mouse.X, Mouse.Y);
mouseCaptured = true; mouseCaptured = true;
@ -141,7 +103,7 @@ namespace bnhdemo
{ {
switch (e.Button){ switch (e.Button){
case OpenTK.Input.MouseButton.Left: case OpenTK.Input.MouseButton.Left:
markMouse(e.X,e.Y); //markMouse(e.X,e.Y);
break; break;
case OpenTK.Input.MouseButton.Right: case OpenTK.Input.MouseButton.Right:
captureMouse(); captureMouse();
@ -211,7 +173,7 @@ namespace bnhdemo
break; break;
case OpenTK.Input.Key.Space: case OpenTK.Input.Key.Space:
fireBallistic(); //fireBallistic();
break; break;
case OpenTK.Input.Key.Number1: case OpenTK.Input.Key.Number1:
@ -234,7 +196,7 @@ namespace bnhdemo
} }
} }
/*
private void fireBallistic(){ private void fireBallistic(){
Console.WriteLine("Fire Ballistic..."); Console.WriteLine("Fire Ballistic...");
BallisticActor ba = new BallisticActor(0); BallisticActor ba = new BallisticActor(0);
@ -245,7 +207,7 @@ namespace bnhdemo
ba.Velocity.Normalize(); ba.Velocity.Normalize();
ba.Velocity *= 50; ba.Velocity *= 50;
} }
*/
public void rotateUpDown(float arc) public void rotateUpDown(float arc)
{ {
@ -289,10 +251,20 @@ namespace bnhdemo
sceneCamera.Position = pos; 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);
}
*/
} }
} }

View File

@ -22,6 +22,10 @@ namespace org.budnhead.graphics
load(new StreamReader(filename),scale); load(new StreamReader(filename),scale);
} }
public LoadedModel(Stream stream){
load(new StreamReader(stream),1.0f);
}
private void load(TextReader reader){ private void load(TextReader reader){
load(reader,1); load(reader,1);
} }

View File

@ -9,7 +9,7 @@ namespace org.budnhead.graphics {
public class Model3D { public class Model3D {
protected int vao, protected int vao = 0,
vbo, // Vertex Buffer vbo, // Vertex Buffer
cbo, // Color Buffer cbo, // Color Buffer
cbo2, // Second Color Buffer cbo2, // Second Color Buffer
@ -24,15 +24,14 @@ namespace org.budnhead.graphics {
public Triangle[] triangles = new Triangle[0]; public Triangle[] triangles = new Triangle[0];
public Model3D(){
protected Model3D(){
vao = GL.GenVertexArray();
nTriangles = 0; nTriangles = 0;
prepare(); prepare();
} }
protected void prepare(){ protected void prepare(){
vao = GL.GenVertexArray();
vbo = GL.GenBuffer(); vbo = GL.GenBuffer();
cbo = GL.GenBuffer(); cbo = GL.GenBuffer();
cbo2 = GL.GenBuffer(); cbo2 = GL.GenBuffer();
@ -110,6 +109,10 @@ namespace org.budnhead.graphics {
} }
public void rebind(){ public void rebind(){
if (vao != 0){
prepare();
}
bindVertexes(); bindVertexes();
bindNormals(); bindNormals();
bindColors(); bindColors();

View File

@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using org.budnhead.core; using org.budnhead.core;
using org.budnhead.tools;
namespace org.budnhead.graphics namespace org.budnhead.graphics
{ {

View File

@ -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<ShaderProgram>("default");
root = new ObjectGroup();
}
public Scene(GLSceneOrientation sceneOrientation)
{
shader = ResourceLibrary.getResource<ShaderProgram>("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 );
}
}
}
}

View File

@ -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<Viewport> viewports = new List<Viewport>();
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(){
}
}
}

View File

@ -4,6 +4,8 @@ using System.IO;
using OpenTK.Graphics.OpenGL; using OpenTK.Graphics.OpenGL;
using OpenTK; using OpenTK;
using org.budnhead.tools;
/** /**
* ShaderProgram Class * ShaderProgram Class
* *
@ -70,8 +72,8 @@ namespace org.budnhead.graphics
public ShaderProgram(String vertexShader, String fragmentShader) public ShaderProgram(String vertexShader, String fragmentShader)
{ {
init( init(
new Shader(ShaderType.VertexShader, vertexShader), ResourceLibrary.getResource<Shader>(vertexShader),
new Shader(ShaderType.FragmentShader, fragmentShader) ResourceLibrary.getResource<Shader>(fragmentShader)
); );
} }

View File

@ -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);
}
}
}
}

View File

@ -9,8 +9,8 @@ namespace org.budnhead.graphics.primitives
{ {
public Cube(Vector3 position, float width) public Cube(Vector3 position, float width)
{ {
Scale = Matrix4.CreateScale(width); Scale.Value = Matrix4.CreateScale(width);
Position = position; Position.Value = position;
} }
public override Model3D getModel3D() public override Model3D getModel3D()

View File

@ -50,18 +50,15 @@
<Compile Include="graphics\GLObject.cs" /> <Compile Include="graphics\GLObject.cs" />
<Compile Include="graphics\Shader.cs" /> <Compile Include="graphics\Shader.cs" />
<Compile Include="graphics\ShaderProgram.cs" /> <Compile Include="graphics\ShaderProgram.cs" />
<Compile Include="graphics\GlobalDefaults.cs" />
<Compile Include="graphics\primitives\Cube.cs" /> <Compile Include="graphics\primitives\Cube.cs" />
<Compile Include="graphics\primitives\Triangle.cs" /> <Compile Include="graphics\primitives\Triangle.cs" />
<Compile Include="graphics\GLSceneOrientation.cs" /> <Compile Include="graphics\GLSceneOrientation.cs" />
<Compile Include="graphics\GLModel.cs" /> <Compile Include="graphics\GLModel.cs" />
<Compile Include="graphics\GLScene.cs" /> <Compile Include="graphics\Scene.cs" />
<Compile Include="graphics\Model3D.cs" /> <Compile Include="graphics\Model3D.cs" />
<Compile Include="graphics\ModelManager.cs" /> <Compile Include="graphics\ModelManager.cs" />
<Compile Include="FileHelper.cs" />
<Compile Include="graphics\Texture.cs" /> <Compile Include="graphics\Texture.cs" />
<Compile Include="graphics\LoadedModel.cs" /> <Compile Include="graphics\LoadedModel.cs" />
<Compile Include="graphics\SquaredMap.cs" />
<Compile Include="exceptions\OutOfWorldException.cs" /> <Compile Include="exceptions\OutOfWorldException.cs" />
<Compile Include="audio\nhPlayer.cs" /> <Compile Include="audio\nhPlayer.cs" />
<Compile Include="audio\AudioDelegate.cs" /> <Compile Include="audio\AudioDelegate.cs" />
@ -77,6 +74,25 @@
<Compile Include="core\Physics.cs" /> <Compile Include="core\Physics.cs" />
<Compile Include="core\WorldObject.cs" /> <Compile Include="core\WorldObject.cs" />
<Compile Include="exceptions\BudNHeadException.cs" /> <Compile Include="exceptions\BudNHeadException.cs" />
<Compile Include="core\Engine.cs" />
<Compile Include="core\BufferedValue.cs" />
<Compile Include="graphics\GLWindow.cs" />
<Compile Include="core\SquaredMap.cs" />
<Compile Include="ui\Control.cs" />
<Compile Include="ui\Container.cs" />
<Compile Include="ui\events\UIEvent.cs" />
<Compile Include="ui\events\KeyPressedEvent.cs" />
<Compile Include="ui\ModifierKeys.cs" />
<Compile Include="core\ConsumerProducerLock.cs" />
<Compile Include="graphics\SceneWindow.cs" />
<Compile Include="tools\ResourceLibrary.cs" />
<Compile Include="tools\FileHelper.cs" />
<Compile Include="core\GlobalDefaults.cs" />
<Compile Include="tools\JobThreader.cs" />
<Compile Include="audio\streams\StreamSegment.cs" />
<Compile Include="audio\streams\AudioDomain.cs" />
<Compile Include="ui\SceneInScene.cs" />
<Compile Include="graphics\Viewport.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="packages.config" /> <None Include="packages.config" />
@ -159,6 +175,10 @@
</Folder> </Folder>
<Folder Include="exceptions\" /> <Folder Include="exceptions\" />
<Folder Include="core\" /> <Folder Include="core\" />
<Folder Include="ui\" />
<Folder Include="ui\events\" />
<Folder Include="tools\" />
<Folder Include="audio\streams\" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\org.hwo.contracts\org.hwo.contracts.csproj"> <ProjectReference Include="..\org.hwo.contracts\org.hwo.contracts.csproj">

View File

@ -1,7 +1,7 @@
using System; using System;
using System.IO; using System.IO;
namespace org.budnhead.core namespace org.budnhead.tools
{ {
public static class FileHelper public static class FileHelper
{ {

View File

@ -0,0 +1,84 @@
using System;
using System.Threading;
using System.Collections.Generic;
namespace org.budnhead.tools
{
public delegate T JobDelegate<T>();
public class JobThreader
{
Thread workerThread;
List<Job> queuedJobs;
public JobThreader()
{
workerThread = Thread.CurrentThread;
queuedJobs = new List<Job>();
}
public JobThreader(Thread workerThread){
this.workerThread = workerThread;
queuedJobs = new List<Job>();
}
public void execute(){
Monitor.Enter(queuedJobs);
foreach (Job j in queuedJobs){
j.execute();
}
queuedJobs.Clear();
Monitor.PulseAll(queuedJobs);
Monitor.Exit(queuedJobs);
}
public T execute<T>(JobDelegate<T> jobDelegate) where T : class{
if (workerThread.Equals(Thread.CurrentThread)){
return jobDelegate();
} else {
return Enqueue(jobDelegate);
}
}
private T Enqueue<T>(JobDelegate<T> jobDelegate) where T : class {
Job<T> job;
Monitor.Enter(queuedJobs);
job = new Job<T>(jobDelegate);
queuedJobs.Add(job);
Monitor.Wait(queuedJobs);
Monitor.Exit(queuedJobs);
return job.Result;
}
public abstract class Job{
public virtual void execute(){
}
}
public class Job<T> : Job{
T result;
JobDelegate<T> jobDelegate;
public Job(JobDelegate<T> jobDelegate){
this.jobDelegate = jobDelegate;
}
public override void execute()
{
this.result = this.jobDelegate();
}
public T Result {
get { return this.result; }
}
}
}
}

View File

@ -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<Type,Dictionary<string,object>>
resourceTypes = new Dictionary<Type, Dictionary<string, object>>();
static List<string>
resourcePaths = new List<string>(new string[]{"."});
static Dictionary<Type,string> prefixes = new Dictionary<Type, string>();
static Dictionary<Type,string> suffixes = new Dictionary<Type, string>();
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<T>(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<T>(string name,T instance){
if (!resourceTypes.ContainsKey(typeof(T))){
resourceTypes.Add(typeof(T),new Dictionary<string, object>());
}
resourceTypes[typeof(T)].Add(name,instance);
}
public static T getResource<T>(string name){
try {
return findLoadedInstance<T>(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));
}
}
}
}

View File

@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
namespace org.budnhead
{
public class Container : Control
{
private List<Control> children;
public Container()
{
this.children = new List<Control>();
}
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(); }
}
}
}

View File

@ -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(){
}
}
}

View File

@ -0,0 +1,8 @@
using System;
namespace org.budnhead
{
public enum ModifierKeys
{
NONE,SHIFT,CONTROL,COMMAND,WIN,CONTEXT
}
}

View File

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

View File

@ -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; }
}
}

View File

@ -0,0 +1,12 @@
using System;
namespace org.budnhead
{
public class UIEvent
{
public UIEvent()
{
}
}
}

View File

@ -41,13 +41,21 @@ namespace org.hwo.contracts
return this; return this;
} }
public Conditional<T> assigns<AT>(ref AT target,assignDelegate<AT> assigner){ public Conditional<T> assigns<AT>(ref AT target,assignDelegate<AT> assigner) {
if (success){ if (success){
target = assigner(); target = assigner();
} }
return this; return this;
} }
public Conditional<T> requiresValid<AT>(ref AT target,assignDelegate<AT> assigner){
if (success){
target = assigner();
success = target != null;
}
return this;
}
public bool isSuccess(){ public bool isSuccess(){
return this.success; return this.success;
} }