BizwareGL!

This commit is contained in:
zeromus 2014-01-27 00:02:21 +00:00
parent 157f092aa2
commit a2ba761ae1
78 changed files with 13008 additions and 1199 deletions

View File

@ -378,8 +378,10 @@
</Compile>
<Compile Include="CustomControls\Win32.cs" />
<Compile Include="DisplayManager\DisplayManager.cs" />
<Compile Include="DisplayManager\Filters\Hq2x.cs" />
<Compile Include="DisplayManager\Filters\Scanlines.cs" />
<Compile Include="DisplayManager\DisplaySurface.cs" />
<Compile Include="DisplayManager\IDisplayFilter.cs" />
<Compile Include="DisplayManager\OSDManager.cs" />
<Compile Include="DisplayManager\SwappableBitmapBufferSet.cs" />
<Compile Include="GlobalWin.cs" />
<Compile Include="Input\GamePad.cs" Condition=" '$(OS)' == 'Windows_NT' " />
<Compile Include="Input\GamePad360.cs" />
@ -1159,6 +1161,7 @@
<Compile Include="tools\ToolBox.Designer.cs">
<DependentUpon>ToolBox.cs</DependentUpon>
</Compile>
<EmbeddedResource Include="Resources\courier16px.fnt" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\BizHawk.Client.Common\BizHawk.Client.Common.csproj">
@ -1181,6 +1184,14 @@
<Project>{f51946ea-827f-4d82-b841-1f2f6d060312}</Project>
<Name>BizHawk.Emulation.DiscSystem</Name>
</ProjectReference>
<ProjectReference Include="..\Bizware\BizHawk.Bizware.BizwareGL.OpenTK\BizHawk.Bizware.BizwareGL.OpenTK.csproj">
<Project>{5160CFB1-5389-47C1-B7F6-8A0DC97641EE}</Project>
<Name>BizHawk.Bizware.BizwareGL.OpenTK</Name>
</ProjectReference>
<ProjectReference Include="..\Bizware\BizHawk.Bizware.BizwareGL\BizHawk.Bizware.BizwareGL.csproj">
<Project>{9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}</Project>
<Name>BizHawk.Bizware.BizwareGL</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="AboutBox.resx">
@ -1262,6 +1273,7 @@
<None Include="config\ControllerImages\GENController.png" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources\courier16px_0.png" />
<None Include="images\pcejin1.bmp" />
<None Include="images\watch.ico" />
<None Include="images\TurboFastForward.png" />
@ -1401,7 +1413,7 @@
</BootstrapperPackage>
</ItemGroup>
<ItemGroup>
<Folder Include="Resources\" />
<Folder Include="DisplayManager\Filters\" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.

View File

@ -9,634 +9,30 @@ using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
//using dx=SlimDX;
//using d3d=SlimDX.Direct3D9;
using BizHawk.Common;
using BizHawk.Emulation.Common;
using BizHawk.Client.Common;
using BizHawk.Bizware.BizwareGL;
namespace BizHawk.Client.EmuHawk
{
/// <summary>
/// encapsulates thread-safe concept of pending/current display surfaces, reusing buffers where matching
/// sizes are available and keeping them cleaned up when they dont seem like theyll need to be used anymore
/// </summary>
class SwappableDisplaySurfaceSet
{
DisplaySurface Pending, Current;
Queue<DisplaySurface> ReleasedSurfaces = new Queue<DisplaySurface>();
/// <summary>
/// retrieves a surface with the specified size, reusing an old buffer if available and clearing if requested
/// </summary>
public DisplaySurface AllocateSurface(int width, int height, bool needsClear = true)
{
for (; ; )
{
DisplaySurface trial;
lock (this)
{
if (ReleasedSurfaces.Count == 0) break;
trial = ReleasedSurfaces.Dequeue();
}
if (trial.Width == width && trial.Height == height)
{
if (needsClear) trial.Clear();
return trial;
}
trial.Dispose();
}
return new DisplaySurface(width, height);
}
/// <summary>
/// sets the provided buffer as pending. takes control of the supplied buffer
/// </summary>
public void SetPending(DisplaySurface newPending)
{
lock (this)
{
if (Pending != null) ReleasedSurfaces.Enqueue(Pending);
Pending = newPending;
}
}
public void ReleaseSurface(DisplaySurface surface)
{
lock (this) ReleasedSurfaces.Enqueue(surface);
}
/// <summary>
/// returns the current buffer, making the most recent pending buffer (if there is such) as the new current first.
/// </summary>
public DisplaySurface GetCurrent()
{
lock (this)
{
if (Pending != null)
{
if (Current != null) ReleasedSurfaces.Enqueue(Current);
Current = Pending;
Pending = null;
}
}
return Current;
}
}
public interface IDisplayFilter
{
/// <summary>
/// describes how this filter will respond to an input format
/// </summary>
DisplayFilterAnalysisReport Analyze(Size sourceSize);
/// <summary>
/// runs the filter
/// </summary>
DisplaySurface Execute(DisplaySurface surface);
}
public class DisplayFilterAnalysisReport
{
public bool Success;
public Size OutputSize;
}
interface IDisplayDriver
{
}
class Direct3DDisplayDriver : IDisplayDriver
{
}
public unsafe class DisplaySurface : IDisposable
{
Bitmap bmp;
BitmapData bmpdata;
int[] pixels;
public unsafe void Clear()
{
FromBitmap(false);
Util.Memset(PixelPtr, 0, Stride * Height);
}
public Bitmap PeekBitmap()
{
ToBitmap();
return bmp;
}
/// <summary>
/// returns a Graphics object used to render to this surface. be sure to dispose it!
/// </summary>
public Graphics GetGraphics()
{
ToBitmap();
return Graphics.FromImage(bmp);
}
public unsafe void ToBitmap(bool copy=true)
{
if (isBitmap) return;
isBitmap = true;
if (bmp == null)
{
bmp = new Bitmap(Width, Height, PixelFormat.Format32bppArgb);
}
if (copy)
{
bmpdata = bmp.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
int w = Width;
int h = Height;
int stride = bmpdata.Stride / 4;
int* bmpbuf = (int*)bmpdata.Scan0.ToPointer();
for (int y = 0, i = 0; y < h; y++)
for (int x = 0; x < w; x++)
bmpbuf[y * stride + x] = pixels[i++];
bmp.UnlockBits(bmpdata);
}
}
public bool IsBitmap { get { return isBitmap; } }
bool isBitmap = false;
public unsafe void FromBitmap(bool copy=true)
{
if (!isBitmap) return;
isBitmap = false;
if (copy)
{
bmpdata = bmp.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
int w = Width;
int h = Height;
int stride = bmpdata.Stride / 4;
int* bmpbuf = (int*)bmpdata.Scan0.ToPointer();
for (int y = 0, i = 0; y < h; y++)
for (int x = 0; x < w; x++)
pixels[i++] = bmpbuf[y * stride + x];
bmp.UnlockBits(bmpdata);
}
}
public static DisplaySurface DisplaySurfaceWrappingBitmap(Bitmap bmp)
{
DisplaySurface ret = new DisplaySurface();
ret.Width = bmp.Width;
ret.Height = bmp.Height;
ret.bmp = bmp;
ret.isBitmap = true;
return ret;
}
private DisplaySurface()
{
}
public DisplaySurface(int width, int height)
{
//can't create a bitmap with zero dimensions, so for now, just bump it up to one
if (width == 0) width = 1;
if (height == 0) height = 1;
Width = width;
Height = height;
pixels = new int[width * height];
LockPixels();
}
public int* PixelPtr { get { return (int*)ptr; } }
public IntPtr PixelIntPtr { get { return new IntPtr(ptr); } }
public int Stride { get { return Width*4; } }
public int OffsetOf(int x, int y) { return y * Stride + x*4; }
void* ptr;
GCHandle handle;
void LockPixels()
{
UnlockPixels();
handle = GCHandle.Alloc(pixels, GCHandleType.Pinned);
ptr = handle.AddrOfPinnedObject().ToPointer();
}
void UnlockPixels()
{
if(handle.IsAllocated) handle.Free();
}
/// <summary>
/// returns a new surface
/// </summary>
/// <param name="xpad"></param>
/// <param name="ypad"></param>
/// <returns></returns>
public DisplaySurface ToPaddedSurface(int xpad0, int ypad0, int xpad1, int ypad1)
{
int new_width = Width + xpad0 + xpad1;
int new_height = Height + ypad0 + ypad1;
DisplaySurface ret = new DisplaySurface(new_width, new_height);
int* dptr = ret.PixelPtr;
int* sptr = PixelPtr;
int dstride = ret.Stride / 4;
int sstride = Stride / 4;
for (int y = 0; y < Height; y++)
for (int x = 0; x < Width; x++)
{
dptr[(y + ypad0) * dstride + x + xpad0] = sptr[y * sstride + x];
}
return ret;
}
public int Width { get; private set; }
public int Height { get; private set; }
public void Dispose()
{
if (bmp != null)
bmp.Dispose();
bmp = null;
UnlockPixels();
}
//public unsafe int[] ToIntArray() { }
public void AcceptIntArray(int[] newpixels)
{
FromBitmap(false);
UnlockPixels();
pixels = newpixels;
LockPixels();
}
}
public class OSDManager
{
public string FPS { get; set; }
public string MT { get; set; }
public IBlitterFont MessageFont;
public IBlitterFont AlertFont;
public void Dispose()
{
}
public void Begin(IBlitter blitter)
{
MessageFont = blitter.GetFontType("MessageFont");
AlertFont = blitter.GetFontType("AlertFont");
}
public System.Drawing.Color FixedMessagesColor { get { return System.Drawing.Color.FromArgb(Global.Config.MessagesColor); } }
public System.Drawing.Color FixedAlertMessageColor { get { return System.Drawing.Color.FromArgb(Global.Config.AlertMessageColor); } }
public OSDManager()
{
}
private float GetX(IBlitter g, int x, int anchor, IBlitterFont font, string message)
{
var size = g.MeasureString(message, font);
//Rectangle rect = g.MeasureString(Sprite, message, new DrawTextFormat());
switch (anchor)
{
default:
case 0: //Top Left
case 2: //Bottom Left
return x;
case 1: //Top Right
case 3: //Bottom Right
return g.ClipBounds.Width - x - size.Width;
}
}
private float GetY(IBlitter g, int y, int anchor, IBlitterFont font, string message)
{
var size = g.MeasureString(message, font);
switch (anchor)
{
default:
case 0: //Top Left
case 1: //Top Right
return y;
case 2: //Bottom Left
case 3: //Bottom Right
return g.ClipBounds.Height - y - size.Height;
}
}
private string MakeFrameCounter()
{
if (Global.MovieSession.Movie.IsFinished)
{
var sb = new StringBuilder();
sb
.Append(Global.Emulator.Frame)
.Append('/')
.Append(Global.MovieSession.Movie.FrameCount)
.Append(" (Finished)");
return sb.ToString();
}
else if (Global.MovieSession.Movie.IsPlaying)
{
var sb = new StringBuilder();
sb
.Append(Global.Emulator.Frame)
.Append('/')
.Append(Global.MovieSession.Movie.FrameCount);
return sb.ToString();
}
else if (Global.MovieSession.Movie.IsRecording)
{
return Global.Emulator.Frame.ToString();
}
else
{
return Global.Emulator.Frame.ToString();
}
}
private string MakeLagCounter()
{
return Global.Emulator.LagCount.ToString();
}
private List<UIMessage> messages = new List<UIMessage>(5);
private List<UIDisplay> GUITextList = new List<UIDisplay>();
public void AddMessage(string message)
{
GlobalWin.DisplayManager.NeedsToPaint = true;
messages.Add(new UIMessage { Message = message, ExpireAt = DateTime.Now + TimeSpan.FromSeconds(2) });
}
public void AddGUIText(string message, int x, int y, bool alert, Color BackGround, Color ForeColor, int anchor)
{
GlobalWin.DisplayManager.NeedsToPaint = true;
GUITextList.Add(new UIDisplay { Message = message, X = x, Y = y, BackGround = BackGround, ForeColor = ForeColor, Alert = alert, Anchor = anchor });
}
public void ClearGUIText()
{
GlobalWin.DisplayManager.NeedsToPaint = true;
GUITextList.Clear();
}
public void DrawMessages(IBlitter g)
{
if (!Global.ClientControls["MaxTurbo"])
{
messages.RemoveAll(m => DateTime.Now > m.ExpireAt);
int line = 1;
if (Global.Config.StackOSDMessages)
{
for (int i = messages.Count - 1; i >= 0; i--, line++)
{
float x = GetX(g, Global.Config.DispMessagex, Global.Config.DispMessageanchor, MessageFont, messages[i].Message);
float y = GetY(g, Global.Config.DispMessagey, Global.Config.DispMessageanchor, MessageFont, messages[i].Message);
if (Global.Config.DispMessageanchor < 2)
{
y += ((line - 1) * 18);
}
else
{
y -= ((line - 1) * 18);
}
g.DrawString(messages[i].Message, MessageFont, Color.Black, x + 2, y + 2);
g.DrawString(messages[i].Message, MessageFont, FixedMessagesColor, x, y);
}
}
else
{
if (messages.Count > 0)
{
int i = messages.Count - 1;
float x = GetX(g, Global.Config.DispMessagex, Global.Config.DispMessageanchor, MessageFont, messages[i].Message);
float y = GetY(g, Global.Config.DispMessagey, Global.Config.DispMessageanchor, MessageFont, messages[i].Message);
if (Global.Config.DispMessageanchor < 2)
{
y += ((line - 1) * 18);
}
else
{
y -= ((line - 1) * 18);
}
g.DrawString(messages[i].Message, MessageFont, Color.Black, x + 2, y + 2);
g.DrawString(messages[i].Message, MessageFont, FixedMessagesColor, x, y);
}
}
for (int x = 0; x < GUITextList.Count; x++)
{
try
{
float posx = GetX(g, GUITextList[x].X, GUITextList[x].Anchor, MessageFont, GUITextList[x].Message);
float posy = GetY(g, GUITextList[x].Y, GUITextList[x].Anchor, MessageFont, GUITextList[x].Message);
g.DrawString(GUITextList[x].Message, MessageFont, GUITextList[x].BackGround, posx + 2, posy + 2);
//g.DrawString(GUITextList[x].Message, MessageFont, Color.Gray, posx + 1, posy + 1);
if (GUITextList[x].Alert)
g.DrawString(GUITextList[x].Message, MessageFont, FixedMessagesColor, posx, posy);
else
g.DrawString(GUITextList[x].Message, MessageFont, GUITextList[x].ForeColor, posx, posy);
}
catch (Exception)
{
return;
}
}
}
}
public string MakeInputDisplay()
{
StringBuilder s;
if (!Global.MovieSession.Movie.IsActive || Global.MovieSession.Movie.IsFinished)
{
s = new StringBuilder(Global.GetOutputControllersAsMnemonic());
}
else
{
s = new StringBuilder(Global.MovieSession.Movie.GetInput(Global.Emulator.Frame - 1));
}
s.Replace(".", " ").Replace("|", "").Replace(" 000, 000", " ");
return s.ToString();
}
public string MakeRerecordCount()
{
if (Global.MovieSession.Movie.IsActive)
{
return "Rerecord Count: " + Global.MovieSession.Movie.Header.Rerecords;
}
else
{
return String.Empty;
}
}
/// <summary>
/// Display all screen info objects like fps, frame counter, lag counter, and input display
/// </summary>
public void DrawScreenInfo(IBlitter g)
{
if (Global.Config.DisplayFrameCounter)
{
string message = MakeFrameCounter();
float x = GetX(g, Global.Config.DispFrameCx, Global.Config.DispFrameanchor, MessageFont, message);
float y = GetY(g, Global.Config.DispFrameCy, Global.Config.DispFrameanchor, MessageFont, message);
g.DrawString(message, MessageFont, Color.Black, x + 1, y + 1);
g.DrawString(message, MessageFont, Color.FromArgb(Global.Config.MessagesColor), x, y);
}
if (Global.Config.DisplayInput)
{
string input = MakeInputDisplay();
Color c;
float x = GetX(g, Global.Config.DispInpx, Global.Config.DispInpanchor, MessageFont, input);
float y = GetY(g, Global.Config.DispInpy, Global.Config.DispInpanchor, MessageFont, input);
if (Global.MovieSession.Movie.IsPlaying && !Global.MovieSession.Movie.IsRecording)
{
c = Color.FromArgb(Global.Config.MovieInput);
}
else
{
c = Color.FromArgb(Global.Config.MessagesColor);
}
g.DrawString(input, MessageFont, Color.Black, x+1,y+1);
g.DrawString(input, MessageFont, c, x,y);
}
if (Global.MovieSession.MultiTrack.IsActive)
{
float x = GetX(g, Global.Config.DispMultix, Global.Config.DispMultianchor, MessageFont, MT);
float y = GetY(g, Global.Config.DispMultiy, Global.Config.DispMultianchor, MessageFont, MT);
g.DrawString(MT, MessageFont, Color.Black,
x + 1, y + 1);
g.DrawString(MT, MessageFont, FixedMessagesColor,
x, y);
}
if (Global.Config.DisplayFPS && FPS != null)
{
float x = GetX(g, Global.Config.DispFPSx, Global.Config.DispFPSanchor, MessageFont, FPS);
float y = GetY(g, Global.Config.DispFPSy, Global.Config.DispFPSanchor, MessageFont, FPS);
g.DrawString(FPS, MessageFont, Color.Black, x + 1, y + 1);
g.DrawString(FPS, MessageFont, FixedMessagesColor, x, y);
}
if (Global.Config.DisplayLagCounter)
{
string counter = MakeLagCounter();
if (Global.Emulator.IsLagFrame)
{
float x = GetX(g, Global.Config.DispLagx, Global.Config.DispLaganchor, AlertFont, counter);
float y = GetY(g, Global.Config.DispLagy, Global.Config.DispLaganchor, AlertFont, counter);
g.DrawString(counter, AlertFont, Color.Black, x + 1, y + 1);
g.DrawString(counter, AlertFont, FixedAlertMessageColor, x, y);
}
else
{
float x = GetX(g, Global.Config.DispLagx, Global.Config.DispLaganchor, MessageFont, counter);
float y = GetY(g, Global.Config.DispLagy, Global.Config.DispLaganchor, MessageFont, counter);
g.DrawString(counter, MessageFont, Color.Black, x + 1, y + 1);
g.DrawString(counter, MessageFont, FixedMessagesColor, x , y );
}
}
if (Global.Config.DisplayRerecordCount)
{
string rerec = MakeRerecordCount();
float x = GetX(g, Global.Config.DispRecx, Global.Config.DispRecanchor, MessageFont, rerec);
float y = GetY(g, Global.Config.DispRecy, Global.Config.DispRecanchor, MessageFont, rerec);
g.DrawString(rerec, MessageFont, Color.Black, x + 1, y + 1);
g.DrawString(rerec, MessageFont, FixedMessagesColor, x, y);
}
if (Global.ClientControls["Autohold"] || Global.ClientControls["Autofire"])
{
StringBuilder disp = new StringBuilder("Held: ");
foreach (string s in Global.StickyXORAdapter.CurrentStickies)
{
disp.Append(s);
disp.Append(' ');
}
foreach (string s in Global.AutofireStickyXORAdapter.CurrentStickies)
{
disp.Append("Auto-");
disp.Append(s);
disp.Append(' ');
}
g.DrawString(disp.ToString(), MessageFont, Color.White, GetX(g, Global.Config.DispAutoholdx, Global.Config.DispAutoholdanchor, MessageFont,
disp.ToString()), GetY(g, Global.Config.DispAutoholdy, Global.Config.DispAutoholdanchor, MessageFont, disp.ToString()));
}
//TODO
//if (Global.MovieSession.Movie.IsPlaying)
//{
// //int r = (int)g.ClipBounds.Width;
// //Point[] p = { new Point(r - 20, 2),
// // new Point(r - 4, 12),
// // new Point(r - 20, 22) };
// //g.FillPolygon(new SolidBrush(Color.Red), p);
// //g.DrawPolygon(new Pen(new SolidBrush(Color.Pink)), p);
//}
//else if (Global.MovieSession.Movie.IsRecording)
//{
// //g.FillEllipse(new SolidBrush(Color.Red), new Rectangle((int)g.ClipBounds.Width - 22, 2, 20, 20));
// //g.DrawEllipse(new Pen(new SolidBrush(Color.Pink)), new Rectangle((int)g.ClipBounds.Width - 22, 2, 20, 20));
//}
if (Global.MovieSession.Movie.IsActive && Global.Config.DisplaySubtitles)
{
var subList = Global.MovieSession.Movie.Header.Subtitles.GetSubtitles(Global.Emulator.Frame).ToList();
for (int i = 0; i < subList.Count; i++)
{
g.DrawString(subList[i].Message, MessageFont, Color.Black, subList[i].X + 1, subList[i].Y + 1);
g.DrawString(subList[i].Message, MessageFont, Color.FromArgb((int)subList[i].Color), subList[i].X, subList[i].Y);
}
}
}
}
public class DisplayManager : IDisposable
{
public DisplayManager()
{
//have at least something here at the start
luaNativeSurfacePreOSD = new DisplaySurface(1, 1);
luaNativeSurfacePreOSD = new BitmapBuffer(1, 1);
}
readonly SwappableDisplaySurfaceSet sourceSurfaceSet = new SwappableDisplaySurfaceSet();
readonly SwappableBitmapBufferSet sourceSurfaceSet = new SwappableBitmapBufferSet();
public bool NeedsToPaint { get; set; }
@ -689,14 +85,16 @@ namespace BizHawk.Client.EmuHawk
//if (luaEmuSurface != null) complexComposite = true;
//if (luaSurface != null) complexComposite = true;
DisplaySurface surfaceToRender = filteredSurface;
BitmapBuffer surfaceToRender = filteredSurface;
if (surfaceToRender == null) surfaceToRender = currentSourceSurface;
renderPanel.Clear(Color.FromArgb(videoProvider.BackgroundColor));
renderPanel.Render(surfaceToRender);
//GL TODO - lua unhooked
if (luaEmuSurface != null)
{
renderPanel.RenderOverlay(luaEmuSurface);
renderPanel.RenderOverlay(luaEmuSurface);
}
RenderOSD((IBlitter)renderPanel);
@ -718,10 +116,10 @@ namespace BizHawk.Client.EmuHawk
Disposed = true;
}
DisplaySurface currentSourceSurface, filteredSurface;
BitmapBuffer currentSourceSurface, filteredSurface;
//the surface to use to render a lua layer at native resolution (under the OSD)
DisplaySurface luaNativeSurfacePreOSD;
BitmapBuffer luaNativeSurfacePreOSD;
SwappableDisplaySurfaceSet luaNativeSurfaceSet = new SwappableDisplaySurfaceSet();
@ -774,21 +172,22 @@ namespace BizHawk.Client.EmuHawk
IDisplayFilter filter = null;
switch (Global.Config.TargetDisplayFilter)
{
case 0:
//no filter
break;
case 1:
filter = new Hq2xBase_2xSai();
break;
case 2:
filter = new Hq2xBase_Super2xSai();
break;
case 3:
filter = new Hq2xBase_SuperEagle();
break;
case 4:
filter = new Scanlines2x();
break;
//TODO GL - filters removed
//case 0:
// //no filter
// break;
//case 1:
// filter = new Hq2xBase_2xSai();
// break;
//case 2:
// filter = new Hq2xBase_Super2xSai();
// break;
//case 3:
// filter = new Hq2xBase_SuperEagle();
// break;
//case 4:
// filter = new Scanlines2x();
// break;
}
if (filter == null)
@ -797,7 +196,7 @@ namespace BizHawk.Client.EmuHawk
filteredSurface = filter.Execute(currentSourceSurface);
}
SwappableDisplaySurfaceSet nativeDisplaySurfaceSet = new SwappableDisplaySurfaceSet();
SwappableBitmapBufferSet nativeDisplaySurfaceSet = new SwappableBitmapBufferSet();
//Thread displayThread;
}

View File

@ -0,0 +1,254 @@
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using BizHawk.Common;
using BizHawk.Client.Common;
namespace BizHawk.Client.EmuHawk
{
/// <summary>
/// encapsulates thread-safe concept of pending/current display surfaces, reusing buffers where matching
/// sizes are available and keeping them cleaned up when they dont seem like theyll need to be used anymore
/// </summary>
class SwappableDisplaySurfaceSet
{
DisplaySurface Pending, Current;
Queue<DisplaySurface> ReleasedSurfaces = new Queue<DisplaySurface>();
/// <summary>
/// retrieves a surface with the specified size, reusing an old buffer if available and clearing if requested
/// </summary>
public DisplaySurface AllocateSurface(int width, int height, bool needsClear = true)
{
for (; ; )
{
DisplaySurface trial;
lock (this)
{
if (ReleasedSurfaces.Count == 0) break;
trial = ReleasedSurfaces.Dequeue();
}
if (trial.Width == width && trial.Height == height)
{
if (needsClear) trial.Clear();
return trial;
}
trial.Dispose();
}
return new DisplaySurface(width, height);
}
/// <summary>
/// sets the provided buffer as pending. takes control of the supplied buffer
/// </summary>
public void SetPending(DisplaySurface newPending)
{
lock (this)
{
if (Pending != null) ReleasedSurfaces.Enqueue(Pending);
Pending = newPending;
}
}
public void ReleaseSurface(DisplaySurface surface)
{
lock (this) ReleasedSurfaces.Enqueue(surface);
}
/// <summary>
/// returns the current buffer, making the most recent pending buffer (if there is such) as the new current first.
/// </summary>
public DisplaySurface GetCurrent()
{
lock (this)
{
if (Pending != null)
{
if (Current != null) ReleasedSurfaces.Enqueue(Current);
Current = Pending;
Pending = null;
}
}
return Current;
}
}
public unsafe class DisplaySurface : IDisposable
{
Bitmap bmp;
BitmapData bmpdata;
int[] pixels;
public unsafe void Clear()
{
FromBitmap(false);
Util.Memset(PixelPtr, 0, Stride * Height);
}
public Bitmap PeekBitmap()
{
ToBitmap();
return bmp;
}
/// <summary>
/// returns a Graphics object used to render to this surface. be sure to dispose it!
/// </summary>
public Graphics GetGraphics()
{
ToBitmap();
return Graphics.FromImage(bmp);
}
public unsafe void ToBitmap(bool copy=true)
{
if (isBitmap) return;
isBitmap = true;
if (bmp == null)
{
bmp = new Bitmap(Width, Height, PixelFormat.Format32bppArgb);
}
if (copy)
{
bmpdata = bmp.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
int w = Width;
int h = Height;
int stride = bmpdata.Stride / 4;
int* bmpbuf = (int*)bmpdata.Scan0.ToPointer();
for (int y = 0, i = 0; y < h; y++)
for (int x = 0; x < w; x++)
bmpbuf[y * stride + x] = pixels[i++];
bmp.UnlockBits(bmpdata);
}
}
public bool IsBitmap { get { return isBitmap; } }
bool isBitmap = false;
public unsafe void FromBitmap(bool copy=true)
{
if (!isBitmap) return;
isBitmap = false;
if (copy)
{
bmpdata = bmp.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
int w = Width;
int h = Height;
int stride = bmpdata.Stride / 4;
int* bmpbuf = (int*)bmpdata.Scan0.ToPointer();
for (int y = 0, i = 0; y < h; y++)
for (int x = 0; x < w; x++)
pixels[i++] = bmpbuf[y * stride + x];
bmp.UnlockBits(bmpdata);
}
}
public static DisplaySurface DisplaySurfaceWrappingBitmap(Bitmap bmp)
{
DisplaySurface ret = new DisplaySurface();
ret.Width = bmp.Width;
ret.Height = bmp.Height;
ret.bmp = bmp;
ret.isBitmap = true;
return ret;
}
private DisplaySurface()
{
}
public DisplaySurface(int width, int height)
{
//can't create a bitmap with zero dimensions, so for now, just bump it up to one
if (width == 0) width = 1;
if (height == 0) height = 1;
Width = width;
Height = height;
pixels = new int[width * height];
LockPixels();
}
public int* PixelPtr { get { return (int*)ptr; } }
public IntPtr PixelIntPtr { get { return new IntPtr(ptr); } }
public int Stride { get { return Width*4; } }
public int OffsetOf(int x, int y) { return y * Stride + x*4; }
void* ptr;
GCHandle handle;
void LockPixels()
{
UnlockPixels();
handle = GCHandle.Alloc(pixels, GCHandleType.Pinned);
ptr = handle.AddrOfPinnedObject().ToPointer();
}
void UnlockPixels()
{
if(handle.IsAllocated) handle.Free();
}
/// <summary>
/// returns a new surface
/// </summary>
/// <param name="xpad"></param>
/// <param name="ypad"></param>
/// <returns></returns>
public DisplaySurface ToPaddedSurface(int xpad0, int ypad0, int xpad1, int ypad1)
{
int new_width = Width + xpad0 + xpad1;
int new_height = Height + ypad0 + ypad1;
DisplaySurface ret = new DisplaySurface(new_width, new_height);
int* dptr = ret.PixelPtr;
int* sptr = PixelPtr;
int dstride = ret.Stride / 4;
int sstride = Stride / 4;
for (int y = 0; y < Height; y++)
for (int x = 0; x < Width; x++)
{
dptr[(y + ypad0) * dstride + x + xpad0] = sptr[y * sstride + x];
}
return ret;
}
public int Width { get; private set; }
public int Height { get; private set; }
public void Dispose()
{
if (bmp != null)
bmp.Dispose();
bmp = null;
UnlockPixels();
}
//public unsafe int[] ToIntArray() { }
public void AcceptIntArray(int[] newpixels)
{
FromBitmap(false);
UnlockPixels();
pixels = newpixels;
LockPixels();
}
}
}

View File

@ -0,0 +1,20 @@
using System.Drawing;
using BizHawk.Bizware.BizwareGL;
namespace BizHawk.Client.EmuHawk
{
public interface IDisplayFilter
{
/// <summary>
/// describes how this filter will respond to an input format
/// </summary>
DisplayFilterAnalysisReport Analyze(Size sourceSize);
/// <summary>
/// runs the filter
/// </summary>
BitmapBuffer Execute(BitmapBuffer surface);
}
}

View File

@ -0,0 +1,356 @@
using System;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Collections.Generic;
using BizHawk.Client.Common;
using BizHawk.Bizware.BizwareGL;
namespace BizHawk.Client.EmuHawk
{
public class OSDManager
{
public string FPS { get; set; }
public string MT { get; set; }
public IBlitterFont MessageFont;
public IBlitterFont AlertFont;
public void Dispose()
{
}
public void Begin(IBlitter blitter)
{
MessageFont = blitter.GetFontType("MessageFont");
AlertFont = blitter.GetFontType("AlertFont");
}
public System.Drawing.Color FixedMessagesColor { get { return System.Drawing.Color.FromArgb(Global.Config.MessagesColor); } }
public System.Drawing.Color FixedAlertMessageColor { get { return System.Drawing.Color.FromArgb(Global.Config.AlertMessageColor); } }
public OSDManager()
{
}
private float GetX(IBlitter g, int x, int anchor, IBlitterFont font, string message)
{
var size = g.MeasureString(message, font);
//Rectangle rect = g.MeasureString(Sprite, message, new DrawTextFormat());
switch (anchor)
{
default:
case 0: //Top Left
case 2: //Bottom Left
return x;
case 1: //Top Right
case 3: //Bottom Right
return g.ClipBounds.Width - x - size.Width;
}
}
private float GetY(IBlitter g, int y, int anchor, IBlitterFont font, string message)
{
var size = g.MeasureString(message, font);
switch (anchor)
{
default:
case 0: //Top Left
case 1: //Top Right
return y;
case 2: //Bottom Left
case 3: //Bottom Right
return g.ClipBounds.Height - y - size.Height;
}
}
private string MakeFrameCounter()
{
if (Global.MovieSession.Movie.IsFinished)
{
var sb = new StringBuilder();
sb
.Append(Global.Emulator.Frame)
.Append('/')
.Append(Global.MovieSession.Movie.FrameCount)
.Append(" (Finished)");
return sb.ToString();
}
else if (Global.MovieSession.Movie.IsPlaying)
{
var sb = new StringBuilder();
sb
.Append(Global.Emulator.Frame)
.Append('/')
.Append(Global.MovieSession.Movie.FrameCount);
return sb.ToString();
}
else if (Global.MovieSession.Movie.IsRecording)
{
return Global.Emulator.Frame.ToString();
}
else
{
return Global.Emulator.Frame.ToString();
}
}
private string MakeLagCounter()
{
return Global.Emulator.LagCount.ToString();
}
private List<UIMessage> messages = new List<UIMessage>(5);
private List<UIDisplay> GUITextList = new List<UIDisplay>();
public void AddMessage(string message)
{
GlobalWin.DisplayManager.NeedsToPaint = true;
messages.Add(new UIMessage { Message = message, ExpireAt = DateTime.Now + TimeSpan.FromSeconds(2) });
}
public void AddGUIText(string message, int x, int y, bool alert, Color BackGround, Color ForeColor, int anchor)
{
GlobalWin.DisplayManager.NeedsToPaint = true;
GUITextList.Add(new UIDisplay { Message = message, X = x, Y = y, BackGround = BackGround, ForeColor = ForeColor, Alert = alert, Anchor = anchor });
}
public void ClearGUIText()
{
GlobalWin.DisplayManager.NeedsToPaint = true;
GUITextList.Clear();
}
public void DrawMessages(IBlitter g)
{
if (!Global.ClientControls["MaxTurbo"])
{
messages.RemoveAll(m => DateTime.Now > m.ExpireAt);
int line = 1;
if (Global.Config.StackOSDMessages)
{
for (int i = messages.Count - 1; i >= 0; i--, line++)
{
float x = GetX(g, Global.Config.DispMessagex, Global.Config.DispMessageanchor, MessageFont, messages[i].Message);
float y = GetY(g, Global.Config.DispMessagey, Global.Config.DispMessageanchor, MessageFont, messages[i].Message);
if (Global.Config.DispMessageanchor < 2)
{
y += ((line - 1) * 18);
}
else
{
y -= ((line - 1) * 18);
}
g.DrawString(messages[i].Message, MessageFont, Color.Black, x + 2, y + 2);
g.DrawString(messages[i].Message, MessageFont, FixedMessagesColor, x, y);
}
}
else
{
if (messages.Count > 0)
{
int i = messages.Count - 1;
float x = GetX(g, Global.Config.DispMessagex, Global.Config.DispMessageanchor, MessageFont, messages[i].Message);
float y = GetY(g, Global.Config.DispMessagey, Global.Config.DispMessageanchor, MessageFont, messages[i].Message);
if (Global.Config.DispMessageanchor < 2)
{
y += ((line - 1) * 18);
}
else
{
y -= ((line - 1) * 18);
}
g.DrawString(messages[i].Message, MessageFont, Color.Black, x + 2, y + 2);
g.DrawString(messages[i].Message, MessageFont, FixedMessagesColor, x, y);
}
}
for (int x = 0; x < GUITextList.Count; x++)
{
try
{
float posx = GetX(g, GUITextList[x].X, GUITextList[x].Anchor, MessageFont, GUITextList[x].Message);
float posy = GetY(g, GUITextList[x].Y, GUITextList[x].Anchor, MessageFont, GUITextList[x].Message);
g.DrawString(GUITextList[x].Message, MessageFont, GUITextList[x].BackGround, posx + 2, posy + 2);
//g.DrawString(GUITextList[x].Message, MessageFont, Color.Gray, posx + 1, posy + 1);
if (GUITextList[x].Alert)
g.DrawString(GUITextList[x].Message, MessageFont, FixedMessagesColor, posx, posy);
else
g.DrawString(GUITextList[x].Message, MessageFont, GUITextList[x].ForeColor, posx, posy);
}
catch (Exception)
{
return;
}
}
}
}
public string MakeInputDisplay()
{
StringBuilder s;
if (!Global.MovieSession.Movie.IsActive || Global.MovieSession.Movie.IsFinished)
{
s = new StringBuilder(Global.GetOutputControllersAsMnemonic());
}
else
{
s = new StringBuilder(Global.MovieSession.Movie.GetInput(Global.Emulator.Frame - 1));
}
s.Replace(".", " ").Replace("|", "").Replace(" 000, 000", " ");
return s.ToString();
}
public string MakeRerecordCount()
{
if (Global.MovieSession.Movie.IsActive)
{
return "Rerecord Count: " + Global.MovieSession.Movie.Header.Rerecords;
}
else
{
return String.Empty;
}
}
/// <summary>
/// Display all screen info objects like fps, frame counter, lag counter, and input display
/// </summary>
public void DrawScreenInfo(IBlitter g)
{
if (Global.Config.DisplayFrameCounter)
{
string message = MakeFrameCounter();
float x = GetX(g, Global.Config.DispFrameCx, Global.Config.DispFrameanchor, MessageFont, message);
float y = GetY(g, Global.Config.DispFrameCy, Global.Config.DispFrameanchor, MessageFont, message);
g.DrawString(message, MessageFont, Color.Black, x + 1, y + 1);
g.DrawString(message, MessageFont, Color.FromArgb(Global.Config.MessagesColor), x, y);
}
if (Global.Config.DisplayInput)
{
string input = MakeInputDisplay();
Color c;
float x = GetX(g, Global.Config.DispInpx, Global.Config.DispInpanchor, MessageFont, input);
float y = GetY(g, Global.Config.DispInpy, Global.Config.DispInpanchor, MessageFont, input);
if (Global.MovieSession.Movie.IsPlaying && !Global.MovieSession.Movie.IsRecording)
{
c = Color.FromArgb(Global.Config.MovieInput);
}
else
{
c = Color.FromArgb(Global.Config.MessagesColor);
}
g.DrawString(input, MessageFont, Color.Black, x + 1, y + 1);
g.DrawString(input, MessageFont, c, x, y);
}
if (Global.MovieSession.MultiTrack.IsActive)
{
float x = GetX(g, Global.Config.DispMultix, Global.Config.DispMultianchor, MessageFont, MT);
float y = GetY(g, Global.Config.DispMultiy, Global.Config.DispMultianchor, MessageFont, MT);
g.DrawString(MT, MessageFont, Color.Black,
x + 1, y + 1);
g.DrawString(MT, MessageFont, FixedMessagesColor,
x, y);
}
if (Global.Config.DisplayFPS && FPS != null)
{
float x = GetX(g, Global.Config.DispFPSx, Global.Config.DispFPSanchor, MessageFont, FPS);
float y = GetY(g, Global.Config.DispFPSy, Global.Config.DispFPSanchor, MessageFont, FPS);
g.DrawString(FPS, MessageFont, Color.Black, x + 1, y + 1);
g.DrawString(FPS, MessageFont, FixedMessagesColor, x, y);
}
if (Global.Config.DisplayLagCounter)
{
string counter = MakeLagCounter();
if (Global.Emulator.IsLagFrame)
{
float x = GetX(g, Global.Config.DispLagx, Global.Config.DispLaganchor, AlertFont, counter);
float y = GetY(g, Global.Config.DispLagy, Global.Config.DispLaganchor, AlertFont, counter);
g.DrawString(counter, AlertFont, Color.Black, x + 1, y + 1);
g.DrawString(counter, AlertFont, FixedAlertMessageColor, x, y);
}
else
{
float x = GetX(g, Global.Config.DispLagx, Global.Config.DispLaganchor, MessageFont, counter);
float y = GetY(g, Global.Config.DispLagy, Global.Config.DispLaganchor, MessageFont, counter);
g.DrawString(counter, MessageFont, Color.Black, x + 1, y + 1);
g.DrawString(counter, MessageFont, FixedMessagesColor, x, y);
}
}
if (Global.Config.DisplayRerecordCount)
{
string rerec = MakeRerecordCount();
float x = GetX(g, Global.Config.DispRecx, Global.Config.DispRecanchor, MessageFont, rerec);
float y = GetY(g, Global.Config.DispRecy, Global.Config.DispRecanchor, MessageFont, rerec);
g.DrawString(rerec, MessageFont, Color.Black, x + 1, y + 1);
g.DrawString(rerec, MessageFont, FixedMessagesColor, x, y);
}
if (Global.ClientControls["Autohold"] || Global.ClientControls["Autofire"])
{
StringBuilder disp = new StringBuilder("Held: ");
foreach (string s in Global.StickyXORAdapter.CurrentStickies)
{
disp.Append(s);
disp.Append(' ');
}
foreach (string s in Global.AutofireStickyXORAdapter.CurrentStickies)
{
disp.Append("Auto-");
disp.Append(s);
disp.Append(' ');
}
g.DrawString(disp.ToString(), MessageFont, Color.White, GetX(g, Global.Config.DispAutoholdx, Global.Config.DispAutoholdanchor, MessageFont,
disp.ToString()), GetY(g, Global.Config.DispAutoholdy, Global.Config.DispAutoholdanchor, MessageFont, disp.ToString()));
}
//TODO
//if (Global.MovieSession.Movie.IsPlaying)
//{
// //int r = (int)g.ClipBounds.Width;
// //Point[] p = { new Point(r - 20, 2),
// // new Point(r - 4, 12),
// // new Point(r - 20, 22) };
// //g.FillPolygon(new SolidBrush(Color.Red), p);
// //g.DrawPolygon(new Pen(new SolidBrush(Color.Pink)), p);
//}
//else if (Global.MovieSession.Movie.IsRecording)
//{
// //g.FillEllipse(new SolidBrush(Color.Red), new Rectangle((int)g.ClipBounds.Width - 22, 2, 20, 20));
// //g.DrawEllipse(new Pen(new SolidBrush(Color.Pink)), new Rectangle((int)g.ClipBounds.Width - 22, 2, 20, 20));
//}
if (Global.MovieSession.Movie.IsActive && Global.Config.DisplaySubtitles)
{
var subList = Global.MovieSession.Movie.Header.Subtitles.GetSubtitles(Global.Emulator.Frame).ToList();
for (int i = 0; i < subList.Count; i++)
{
g.DrawString(subList[i].Message, MessageFont, Color.Black, subList[i].X + 1, subList[i].Y + 1);
g.DrawString(subList[i].Message, MessageFont, Color.FromArgb((int)subList[i].Color), subList[i].X, subList[i].Y);
}
}
}
}
}

View File

@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;
using BizHawk.Bizware.BizwareGL;
namespace BizHawk.Client.EmuHawk
{
/// <summary>
/// encapsulates thread-safe concept of pending/current BitmapBuffer, reusing buffers where matching
/// sizes are available and keeping them cleaned up when they dont seem like theyll need to be used anymore
/// </summary>
class SwappableBitmapBufferSet
{
BitmapBuffer Pending, Current;
Queue<BitmapBuffer> ReleasedSurfaces = new Queue<BitmapBuffer>();
/// <summary>
/// retrieves a surface with the specified size, reusing an old buffer if available and clearing if requested
/// </summary>
public BitmapBuffer AllocateSurface(int width, int height, bool needsClear = true)
{
for (; ; )
{
BitmapBuffer trial;
lock (this)
{
if (ReleasedSurfaces.Count == 0) break;
trial = ReleasedSurfaces.Dequeue();
}
if (trial.Width == width && trial.Height == height)
{
if (needsClear) trial.ClearWithoutAlloc();
return trial;
}
trial.Dispose();
}
return new BitmapBuffer(width, height);
}
/// <summary>
/// sets the provided buffer as pending. takes control of the supplied buffer
/// </summary>
public void SetPending(BitmapBuffer newPending)
{
lock (this)
{
if (Pending != null) ReleasedSurfaces.Enqueue(Pending);
Pending = newPending;
}
}
public void ReleaseSurface(BitmapBuffer surface)
{
lock (this) ReleasedSurfaces.Enqueue(surface);
}
/// <summary>
/// returns the current buffer, making the most recent pending buffer (if there is such) as the new current first.
/// </summary>
public BitmapBuffer GetCurrent()
{
lock (this)
{
if (Pending != null)
{
if (Current != null) ReleasedSurfaces.Enqueue(Current);
Current = Pending;
Pending = null;
}
}
return Current;
}
}
}

View File

@ -911,8 +911,9 @@ namespace BizHawk.Client.EmuHawk
private void UseGDIMenuItem_Click(object sender, EventArgs e)
{
Global.Config.DisplayGDI ^= true;
SyncPresentationMode();
//TODO GL - this concept is gone
//Global.Config.DisplayGDI ^= true;
//SyncPresentationMode();
}
private void UseBilinearMenuItem_Click(object sender, EventArgs e)

View File

@ -93,8 +93,18 @@ namespace BizHawk.Client.EmuHawk
Database.LoadDatabase(Path.Combine(PathManager.GetExeDirectoryAbsolute(), "gamedb", "gamedb.txt"));
SyncPresentationMode();
//TODO GL - a lot of disorganized wiring-up here
var poop = new BizwareGLRenderPanel();
GlobalWin.RenderPanel = poop;
_renderTarget = poop.GraphicsControl;
poop.GraphicsControl.SetVsync(false);
Controls.Add(_renderTarget);
Controls.SetChildIndex(_renderTarget, 0);
_renderTarget.Dock = DockStyle.Fill;
_renderTarget.BackColor = Color.Black;
//TODO GL - move these event handlers somewhere less obnoxious line in the On* overrides
Load += (o, e) =>
{
AllowDrop = true;
@ -927,7 +937,6 @@ namespace BizHawk.Client.EmuHawk
private int _lastWidth = -1;
private int _lastHeight = -1;
private Control _renderTarget;
private RetainedViewportPanel _retainedPanel;
private readonly SaveSlotManager _stateSlots = new SaveSlotManager();
// AVI/WAV state
@ -961,9 +970,10 @@ namespace BizHawk.Client.EmuHawk
private readonly bool _autoCloseOnDump;
private int _lastOpenRomFilter;
// workaround for possible memory leak in SysdrawingRenderPanel
private RetainedViewportPanel _captureOsdRvp;
private SysdrawingRenderPanel _captureOsdSrp;
//TODO GL - this whole feature will have to be re-added
//// workaround for possible memory leak in SysdrawingRenderPanel
//private RetainedViewportPanel _captureOsdRvp;
//private SysdrawingRenderPanel _captureOsdSrp;
private object _syncSettingsHack;
@ -1331,70 +1341,69 @@ namespace BizHawk.Client.EmuHawk
}
}
private void SyncPresentationMode()
{
GlobalWin.DisplayManager.Suspend();
// private void SyncPresentationMode()
// {
// GlobalWin.DisplayManager.Suspend();
#if WINDOWS
bool gdi = Global.Config.DisplayGDI || GlobalWin.Direct3D == null;
#endif
if (_renderTarget != null)
{
_renderTarget.Dispose();
Controls.Remove(_renderTarget);
}
//#if WINDOWS
// bool gdi = Global.Config.DisplayGDI || GlobalWin.Direct3D == null;
//#endif
// if (_renderTarget != null)
// {
// _renderTarget.Dispose();
// Controls.Remove(_renderTarget);
// }
if (_retainedPanel != null)
{
_retainedPanel.Dispose();
}
// if (_retainedPanel != null)
// {
// _retainedPanel.Dispose();
// }
if (GlobalWin.RenderPanel != null)
{
GlobalWin.RenderPanel.Dispose();
}
// if (GlobalWin.RenderPanel != null)
// {
// GlobalWin.RenderPanel.Dispose();
// }
#if WINDOWS
if (gdi)
#endif
_renderTarget = _retainedPanel = new RetainedViewportPanel();
#if WINDOWS
else _renderTarget = new ViewportPanel();
#endif
Controls.Add(_renderTarget);
Controls.SetChildIndex(_renderTarget, 0);
//#if WINDOWS
// if (gdi)
//#endif
// _renderTarget = _retainedPanel = new RetainedViewportPanel();
//#if WINDOWS
// else _renderTarget = new ViewportPanel();
//#endif
// Controls.Add(_renderTarget);
// Controls.SetChildIndex(_renderTarget, 0);
_renderTarget.Dock = DockStyle.Fill;
_renderTarget.BackColor = Color.Black;
// _renderTarget.Dock = DockStyle.Fill;
// _renderTarget.BackColor = Color.Black;
#if WINDOWS
if (gdi)
{
#endif
GlobalWin.RenderPanel = new SysdrawingRenderPanel(_retainedPanel);
_retainedPanel.ActivateThreaded();
#if WINDOWS
}
else
{
try
{
var d3dPanel = new Direct3DRenderPanel(GlobalWin.Direct3D, _renderTarget);
d3dPanel.CreateDevice();
GlobalWin.RenderPanel = d3dPanel;
}
catch
{
Program.DisplayDirect3DError();
GlobalWin.Direct3D.Dispose();
GlobalWin.Direct3D = null;
SyncPresentationMode();
}
}
#endif
//#if WINDOWS
// if (gdi)
// {
//#endif
// GlobalWin.RenderPanel = new SysdrawingRenderPanel(_retainedPanel);
// _retainedPanel.ActivateThreaded();
//#if WINDOWS
// }
// else
// {
// try
// {
// var d3dPanel = new BizwareGLRenderPanel(_renderTarget);
// GlobalWin.RenderPanel = d3dPanel;
// }
// catch
// {
// Program.DisplayDirect3DError();
// GlobalWin.Direct3D.Dispose();
// GlobalWin.Direct3D = null;
// SyncPresentationMode();
// }
// }
//#endif
GlobalWin.DisplayManager.Resume();
}
// GlobalWin.DisplayManager.Resume();
// }
private void SyncThrottle()
{
@ -1862,24 +1871,26 @@ namespace BizHawk.Client.EmuHawk
Slot9StatusButton.BackColor = Global.Config.SaveSlot == 9 ? SystemColors.ControlDark : SystemColors.Control;
}
//TODO GL - this whole feature will have to be re-added
private Bitmap CaptureOSD() // sort of like MakeScreenShot(), but with OSD and LUA captured as well. slow and bad.
{
// this code captures the emu display with OSD and lua composited onto it.
// it's slow and a bit hackish; a better solution is to create a new
// "dummy render" class that implements IRenderer, IBlitter, and possibly
// IVideoProvider, and pass that to DisplayManager.UpdateSourceEx()
if (_captureOsdRvp == null)
{
_captureOsdRvp = new RetainedViewportPanel();
_captureOsdSrp = new SysdrawingRenderPanel(_captureOsdRvp);
}
// // this code captures the emu display with OSD and lua composited onto it.
// // it's slow and a bit hackish; a better solution is to create a new
// // "dummy render" class that implements IRenderer, IBlitter, and possibly
// // IVideoProvider, and pass that to DisplayManager.UpdateSourceEx()
// if (_captureOsdRvp == null)
// {
// _captureOsdRvp = new RetainedViewportPanel();
// _captureOsdSrp = new SysdrawingRenderPanel(_captureOsdRvp);
// }
// this size can be different for showing off stretching or filters
_captureOsdRvp.Width = Global.Emulator.VideoProvider.BufferWidth;
_captureOsdRvp.Height = Global.Emulator.VideoProvider.BufferHeight;
// // this size can be different for showing off stretching or filters
// _captureOsdRvp.Width = Global.Emulator.VideoProvider.BufferWidth;
// _captureOsdRvp.Height = Global.Emulator.VideoProvider.BufferHeight;
GlobalWin.DisplayManager.UpdateSourceEx(Global.Emulator.VideoProvider, _captureOsdSrp);
return (Bitmap)_captureOsdRvp.GetBitmap().Clone();
// GlobalWin.DisplayManager.UpdateSourceEx(Global.Emulator.VideoProvider, _captureOsdSrp);
// return (Bitmap)_captureOsdRvp.GetBitmap().Clone();
return null;
}
private void ShowConsole()

View File

@ -1,5 +1,6 @@
using System;
using System.Drawing;
using sd=System.Drawing;
using sysdrawingfont=System.Drawing.Font;
using sysdrawing2d=System.Drawing.Drawing2D;
using System.IO;
@ -12,381 +13,113 @@ using d3d9font=SlimDX.Direct3D9.Font;
#endif
using BizHawk.Client.Common;
using BizHawk.Bizware.BizwareGL;
namespace BizHawk.Client.EmuHawk
{
#if WINDOWS
public class ImageTexture : IDisposable
{
public Device GraphicsDevice;
public Texture Texture;
private int imageWidth;
public int ImageWidth { get { return imageWidth; } }
private int imageHeight;
public int ImageHeight { get { return imageHeight; } }
private int textureWidth;
public int TextureWidth { get { return textureWidth; } }
private int textureHeight;
public int TextureHeight { get { return textureHeight; } }
public ImageTexture(Device graphicsDevice)
{
GraphicsDevice = graphicsDevice;
}
public unsafe void SetImage(DisplaySurface surface, int width, int height)
{
//this function fails if the width and height are zero
if (width == 0 || height == 0) return;
bool needsRecreating = false;
//experiment:
//needsRecreating = true;
if (Texture == null)
{
needsRecreating = true;
}
else
{
if (imageWidth != width || imageHeight != height)
{
needsRecreating = true;
}
}
// If we need to recreate the texture, do so.
if (needsRecreating)
{
if (Texture != null)
{
Texture.Dispose();
Texture = null;
}
// Copy the width/height to member fields.
imageWidth = width;
imageHeight = height;
// Round up the width/height to the nearest power of two.
textureWidth = 32; textureHeight = 32;
while (textureWidth < imageWidth) textureWidth <<= 1;
while (textureHeight < imageHeight) textureHeight <<= 1;
// Create a new texture instance.
Texture = new Texture(GraphicsDevice, textureWidth, textureHeight, 1, Usage.None, Format.A8R8G8B8, Pool.Managed);
}
surface.FromBitmap();
// Copy the image data to the texture.
using (var Data = Texture.LockRectangle(0, LockFlags.None).Data)
{
if (imageWidth == textureWidth)
{
// Widths are the same, just dump the data across (easy!)
Data.WriteRange(surface.PixelIntPtr, imageWidth * imageHeight << 2);
}
else
{
// Widths are different, need a bit of additional magic here to make them fit:
long RowSeekOffset = (textureWidth - imageWidth) << 2;
for (int r = 0, s = 0; r < imageHeight; ++r, s += imageWidth)
{
IntPtr src = new IntPtr(((byte*)surface.PixelPtr + r*surface.Stride));
Data.WriteRange(src,imageWidth << 2);
Data.Seek(RowSeekOffset, SeekOrigin.Current);
}
}
Texture.UnlockRectangle(0);
}
}
private bool disposed;
public void Dispose()
{
if (!disposed)
{
disposed = true;
if (Texture != null)
Texture.Dispose();
Texture = null;
GC.SuppressFinalize(this);
}
}
}
#endif
public interface IRenderer : IDisposable
{
void FastRenderAndPresent(DisplaySurface surface);
void Render(DisplaySurface surface);
void RenderOverlay(DisplaySurface surface);
void Render(BitmapBuffer surface);
void Clear(Color color);
void Present();
bool Resized { get; set; }
Size NativeSize { get; }
/// <summary>
/// convert coordinates
/// convert coordinates. this is a dumb name
/// </summary>
/// <param name="p">desktop coordinates</param>
/// <returns>ivideoprovider coordinates</returns>
Point ScreenToScreen(Point p);
sd.Point ScreenToScreen(sd.Point p);
}
public class SysdrawingRenderPanel : IRenderer, IBlitter
//you might think it's cool to make this reusable for other windows, but it's probably a pipe dream. dont even try it. at least, refactor it into a simple render panel and some kind of NicePresentationWindow class
public class BizwareGLRenderPanel : IRenderer, IBlitter
{
private readonly sysdrawingfont MessageFont;
private readonly sysdrawingfont AlertFont;
private DisplaySurface tempBuffer;
private Graphics g;
private readonly SwappableDisplaySurfaceSet surfaceSet = new SwappableDisplaySurfaceSet();
public bool Resized { get; set; }
public void Dispose() { }
public void Render(DisplaySurface surface)
public void Dispose()
{
backingControl.ReleaseCallback = RetainedViewportPanelDisposeCallback;
lock (this)
tempBuffer = surfaceSet.AllocateSurface(backingControl.Width, backingControl.Height, false);
RenderInternal(surface);
//this hasnt been analyzed real well yet
Renderer.Dispose();
GraphicsControl.Dispose();
TheOneFont.Dispose();
if (LastSurfaceTexture != null)
LastSurfaceTexture.Dispose();
//gl shouldnt be disposed! it should be a global resource! probably managed elsewhere
}
class FontWrapper : IBlitterFont
{
public FontWrapper(sysdrawingfont font)
public FontWrapper(StringRenderer font)
{
this.font = font;
}
public readonly sysdrawingfont font;
public readonly StringRenderer font;
}
public Size NativeSize { get { return backingControl.ClientSize; } }
IBlitterFont IBlitter.GetFontType(string fontType)
public BizwareGLRenderPanel()
{
if (fontType == "MessageFont") return new FontWrapper(MessageFont);
if (fontType == "AlertFont") return new FontWrapper(AlertFont);
return null;
if(gl == null)
gl = new BizHawk.Bizware.BizwareGL.Drivers.OpenTK.IGL_TK();
GraphicsControl = gl.CreateGraphicsControl();
Renderer = new GuiRenderer(gl);
using (var xml = typeof(Program).Assembly.GetManifestResourceStream("BizHawk.Client.EmuHawk.Resources.courier16px.fnt"))
using (var tex = typeof(Program).Assembly.GetManifestResourceStream("BizHawk.Client.EmuHawk.Resources.courier16px_0.png"))
TheOneFont = new StringRenderer(gl,xml,tex);
}
void IBlitter.Open()
{
g = Graphics.FromImage(tempBuffer.PeekBitmap());
ClipBounds = new Rectangle(0, 0, NativeSize.Width, NativeSize.Height);
Renderer.Begin(GraphicsControl.Control.ClientSize.Width, GraphicsControl.Control.ClientSize.Height);
Renderer.SetBlendState(gl.BlendNormal);
ClipBounds = new sd.Rectangle(0, 0, NativeSize.Width, NativeSize.Height);
}
void IBlitter.Close()
{
g.Dispose();
void IBlitter.Close() {
Renderer.End();
}
IBlitterFont IBlitter.GetFontType(string fontType) { return new FontWrapper(TheOneFont); }
void IBlitter.DrawString(string s, IBlitterFont font, Color color, float x, float y)
{
using (var brush = new SolidBrush(color))
g.DrawString(s, ((FontWrapper)font).font, brush, x, y);
var stringRenderer = ((FontWrapper)font).font;
Renderer.SetModulateColor(color);
stringRenderer.RenderString(Renderer, x, y, s);
Renderer.SetModulateColorWhite();
}
SizeF IBlitter.MeasureString(string s, IBlitterFont _font)
SizeF IBlitter.MeasureString(string s, IBlitterFont font)
{
var font = ((FontWrapper)_font).font;
return g.MeasureString(s, font);
var stringRenderer = ((FontWrapper)font).font;
return stringRenderer.Measure(s);
}
public sd.Rectangle ClipBounds { get; set; }
StringRenderer TheOneFont;
public Bizware.BizwareGL.GraphicsControl GraphicsControl;
static Bizware.BizwareGL.IGL gl;
GuiRenderer Renderer;
Texture2d LastSurfaceTexture;
public bool Resized { get; set; }
public void Clear(Color color)
{
//todo
GraphicsControl.Begin();
}
public Rectangle ClipBounds { get; set; }
bool RetainedViewportPanelDisposeCallback(Bitmap bmp)
public sd.Point ScreenToScreen(sd.Point p)
{
lock (this)
{
DisplaySurface tempSurface = DisplaySurface.DisplaySurfaceWrappingBitmap(bmp);
surfaceSet.ReleaseSurface(tempSurface);
}
return false;
}
void RenderInternal(DisplaySurface surface, bool transparent = false)
{
using (var g = Graphics.FromImage(tempBuffer.PeekBitmap()))
{
g.PixelOffsetMode = sysdrawing2d.PixelOffsetMode.HighSpeed;
g.InterpolationMode = Global.Config.DispBlurry ? sysdrawing2d.InterpolationMode.Bilinear : sysdrawing2d.InterpolationMode.NearestNeighbor;
if (transparent) g.CompositingMode = sysdrawing2d.CompositingMode.SourceOver;
else g.CompositingMode = sysdrawing2d.CompositingMode.SourceCopy;
g.CompositingQuality = sysdrawing2d.CompositingQuality.HighSpeed;
if (backingControl.Width == surface.Width && backingControl.Height == surface.Height)
g.DrawImageUnscaled(surface.PeekBitmap(), 0, 0);
else
g.DrawImage(surface.PeekBitmap(), 0, 0, backingControl.Width, backingControl.Height);
}
if (!transparent)
{
lastsize = new Size(surface.Width, surface.Height);
}
}
public void FastRenderAndPresent(DisplaySurface surface)
{
backingControl.SetBitmap((Bitmap)surface.PeekBitmap().Clone());
}
public void RenderOverlay(DisplaySurface surface)
{
RenderInternal(surface, true);
}
public void Present()
{
backingControl.SetBitmap(tempBuffer.PeekBitmap());
tempBuffer = null;
}
public SysdrawingRenderPanel(RetainedViewportPanel control)
{
backingControl = control;
MessageFont = new sysdrawingfont("Courier", 14, FontStyle.Bold, GraphicsUnit.Pixel);
AlertFont = new sysdrawingfont("Courier", 14, FontStyle.Bold, GraphicsUnit.Pixel);
}
RetainedViewportPanel backingControl;
Size lastsize = new Size(256, 192);
public Point ScreenToScreen(Point p)
{
p = backingControl.PointToClient(p);
Point ret = new Point(p.X * lastsize.Width / backingControl.Width,
p.Y * lastsize.Height / backingControl.Height);
p = GraphicsControl.Control.PointToClient(p);
sd.Point ret = new sd.Point(p.X * sw / GraphicsControl.Control.Width,
p.Y * sh / GraphicsControl.Control.Height);
return ret;
}
}
public interface IBlitter
{
void Open();
void Close();
IBlitterFont GetFontType(string fontType);
void DrawString(string s, IBlitterFont font, Color color, float x, float y);
SizeF MeasureString(string s, IBlitterFont font);
Rectangle ClipBounds { get; set; }
}
public interface IBlitterFont { }
#if WINDOWS
public class Direct3DRenderPanel : IRenderer, IBlitter
{
public Color BackgroundColor { get; set; }
public bool Resized { get; set; }
public string FPS { get; set; }
public string MT { get; set; }
private readonly Direct3D d3d;
private Device _device;
private readonly Control backingControl;
public ImageTexture Texture;
private Sprite Sprite;
private d3d9font MessageFont;
private d3d9font AlertFont;
class FontWrapper : IBlitterFont
{
public FontWrapper(d3d9font font)
{
this.font = font;
}
public readonly d3d9font font;
}
void IBlitter.Open()
{
ClipBounds = new Rectangle(0, 0, NativeSize.Width, NativeSize.Height);
}
void IBlitter.Close() {}
private bool Vsync;
public Size NativeSize { get { return backingControl.ClientSize; } }
IBlitterFont IBlitter.GetFontType(string fontType)
{
if (fontType == "MessageFont") return new FontWrapper(MessageFont);
if (fontType == "AlertFont") return new FontWrapper(AlertFont);
return null;
}
Color4 col(Color c) { return new Color4(c.ToArgb()); }
void IBlitter.DrawString(string s, IBlitterFont font, Color color, float x, float y)
{
((FontWrapper)font).font.DrawString(null, s, (int)x + 1, (int)y + 1, col(color));
}
SizeF IBlitter.MeasureString(string s, IBlitterFont _font)
{
var font = ((FontWrapper)_font).font;
Rectangle r = font.MeasureString(null, s, DrawTextFormat.Left);
return new SizeF(r.Width, r.Height);
}
public Rectangle ClipBounds { get; set; }
public Direct3DRenderPanel(Direct3D direct3D, Control control)
{
d3d = direct3D;
backingControl = control;
control.MouseDoubleClick += (o, e) => HandleFullscreenToggle(o, e);
control.MouseClick += (o, e) => GlobalWin.MainForm.MainForm_MouseClick(o, e);
}
private void HandleFullscreenToggle(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
GlobalWin.MainForm.ToggleFullscreen();
}
private void DestroyDevice()
{
if (Texture != null)
{
Texture.Dispose();
Texture = null;
}
if (Sprite != null)
{
Sprite.Dispose();
Sprite = null;
}
if (_device != null)
{
_device.Dispose();
_device = null;
}
if (MessageFont != null)
{
MessageFont.Dispose();
MessageFont = null;
}
if (AlertFont != null)
{
AlertFont.Dispose();
AlertFont = null;
}
}
public Size NativeSize { get { return GraphicsControl.Control.ClientSize; } }
//the hell is this doing here? horrible
private bool VsyncRequested
{
get
@ -397,197 +130,103 @@ namespace BizHawk.Client.EmuHawk
}
}
public void CreateDevice()
{
DestroyDevice();
Vsync = VsyncRequested;
var pp = new PresentParameters
{
BackBufferWidth = Math.Max(1, backingControl.ClientSize.Width),
BackBufferHeight = Math.Max(1, backingControl.ClientSize.Height),
DeviceWindowHandle = backingControl.Handle,
PresentationInterval = Vsync ? PresentInterval.One : PresentInterval.Immediate
};
var flags = CreateFlags.SoftwareVertexProcessing;
if ((d3d.GetDeviceCaps(0, DeviceType.Hardware).DeviceCaps & DeviceCaps.HWTransformAndLight) != 0)
{
flags = CreateFlags.HardwareVertexProcessing;
}
_device = new Device(d3d, 0, DeviceType.Hardware, backingControl.Handle, flags, pp);
Sprite = new Sprite(_device);
Texture = new ImageTexture(_device);
MessageFont = new d3d9font(_device, 16, 0, FontWeight.Bold, 1, false, CharacterSet.Default, Precision.Default, FontQuality.Default, PitchAndFamily.Default | PitchAndFamily.DontCare, "Courier");
AlertFont = new d3d9font(_device, 16, 0, FontWeight.ExtraBold, 1, true, CharacterSet.Default, Precision.Default, FontQuality.Default, PitchAndFamily.Default | PitchAndFamily.DontCare, "Courier");
// NOTE: if you add ANY objects, like new fonts, textures, etc, to this method
// ALSO add dispose code in DestroyDevice() or you will be responsible for VRAM memory leaks.
}
public void Render()
{
if (_device == null || Resized || Vsync != VsyncRequested)
backingControl.Invoke(() => CreateDevice());
Resized = false;
_device.Clear(ClearFlags.Target, BackgroundColor, 1.0f, 0);
Present();
}
public void FastRenderAndPresent(DisplaySurface surface)
{
Render(surface);
Present();
}
public void RenderOverlay(DisplaySurface surface)
{
RenderWrapper(() => RenderExec(surface, true));
RenderExec(null, surface);
}
public void Render(DisplaySurface surface)
public void Render(BitmapBuffer surface)
{
RenderWrapper(() => RenderExec(surface, false));
RenderExec(surface,null);
}
public void RenderWrapper(Action todo)
private bool Vsync;
int sw=1, sh=1;
public void RenderExec(BitmapBuffer surface, DisplaySurface displaySurface)
{
try
if (Resized || Vsync != VsyncRequested)
{
todo();
}
catch (Direct3D9Exception)
{
// Wait until device is available or user gets annoyed and closes app
Result r;
// it can take a while for the device to be ready again, so avoid sound looping during the wait
if (GlobalWin.Sound != null) GlobalWin.Sound.StopSound();
do
{
r = _device.TestCooperativeLevel();
Thread.Sleep(100);
} while (r == ResultCode.DeviceLost);
if (GlobalWin.Sound != null) GlobalWin.Sound.StartSound();
// lets try recovery!
DestroyDevice();
backingControl.Invoke(() => CreateDevice());
todo();
}
}
void RenderPrep()
{
if (_device == null || Resized || Vsync != VsyncRequested)
backingControl.Invoke(() => CreateDevice());
Resized = false;
}
public void Clear(Color color)
{
_device.Clear(ClearFlags.Target, col(color), 0.0f, 0);
}
private void RenderExec(DisplaySurface surface, bool overlay)
{
RenderPrep();
if (surface == null)
{
Render();
return;
//recreate device
}
Texture.SetImage(surface, surface.Width, surface.Height);
if(!overlay) _device.Clear(ClearFlags.Target, BackgroundColor, 0.0f, 0);
// figure out scaling factor
float widthScale = (float)backingControl.Size.Width / surface.Width;
float heightScale = (float)backingControl.Size.Height / surface.Height;
float finalScale = Math.Min(widthScale, heightScale);
_device.BeginScene();
SpriteFlags flags = SpriteFlags.None;
if (overlay) flags |= SpriteFlags.AlphaBlend;
Sprite.Begin(flags);
if (Global.Config.DispBlurry)
bool overlay = false;
if(displaySurface != null)
{
_device.SetSamplerState(0, SamplerState.MagFilter, TextureFilter.Linear);
_device.SetSamplerState(0, SamplerState.MinFilter, TextureFilter.Linear);
overlay = true;
displaySurface.ToBitmap(false);
surface = new BitmapBuffer(displaySurface.PeekBitmap(), new BitmapLoadOptions());
}
if (sw != surface.Width || sh != surface.Height || LastSurfaceTexture == null)
{
LastSurfaceTexture = gl.LoadTexture(surface);
LastSurfaceTexture.SetFilterNearest();
}
else
{
_device.SetSamplerState(0, SamplerState.MagFilter, TextureFilter.Point);
_device.SetSamplerState(0, SamplerState.MinFilter, TextureFilter.Point);
gl.LoadTextureData(LastSurfaceTexture, surface);
}
Sprite.Transform = Matrix.Scaling(finalScale, finalScale, 0f);
Sprite.Draw(Texture.Texture, new Rectangle(0, 0, surface.Width, surface.Height), new Vector3(surface.Width / 2f, surface.Height / 2f, 0), new Vector3(backingControl.Size.Width / 2f / finalScale, backingControl.Size.Height / 2f / finalScale, 0), Color.White);
Sprite.End();
_device.EndScene();
sw = surface.Width;
sh = surface.Height;
Resized = false;
// figure out scaling factor
float vw = (float)GraphicsControl.Control.Width;
float vh = (float)GraphicsControl.Control.Height;
float widthScale = vw / surface.Width;
float heightScale = vh / surface.Height;
float finalScale = Math.Min(widthScale, heightScale);
float dx = (int)((vw - finalScale * surface.Width)/2);
float dy = (int)((vh - finalScale * surface.Height)/2);
GraphicsControl.Begin();
if (!overlay)
{
gl.ClearColor(Color.Black); //TODO set from background color
gl.Clear(ClearBufferMask.ColorBufferBit);
}
Renderer.Begin(GraphicsControl.Control.ClientSize.Width, GraphicsControl.Control.ClientSize.Height);
if (overlay)
Renderer.SetBlendState(gl.BlendNormal);
else Renderer.SetBlendState(gl.BlendNone);
Renderer.Modelview.Translate(dx, dy);
Renderer.Modelview.Scale(finalScale);
Renderer.Draw(LastSurfaceTexture);
Renderer.End();
GraphicsControl.End();
}
public void Present()
{
// Present() is the most likely place to get DeviceLost, so we need to wrap it
RenderWrapper(_Present);
GraphicsControl.Begin();
GraphicsControl.SwapBuffers();
GraphicsControl.End();
}
private readonly System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
private readonly long stopwatchthrottle = System.Diagnostics.Stopwatch.Frequency / 50;
private long stopwatchtmr;
private void _Present()
public void RenderOverlay(BitmapBuffer surface)
{
// according to the internet, D3DPRESENT_DONOTWAIT is not terribly reliable
// so instead we measure the time the present takes, and drop the next present call if it was too long
// this code isn't really very good
if (Global.Config.VSync && !Global.Config.VSyncThrottle)
{
if (stopwatchtmr > stopwatchthrottle)
{
stopwatchtmr = 0;
//Console.WriteLine('s');
}
else
{
stopwatch.Restart();
//Device.GetSwapChain(0).Present(SlimDX.Direct3D9.Present.DoNotWait);
_device.Present(SlimDX.Direct3D9.Present.None);
stopwatch.Stop();
stopwatchtmr += stopwatch.ElapsedTicks;
//Console.WriteLine('.');
stopwatchtmr -= stopwatchthrottle / 4;
}
}
else
_device.Present(SlimDX.Direct3D9.Present.None);
//TODO GL - draw transparent overlay
}
// not used anywhere?
//public static EventWaitHandle vsyncEvent = new EventWaitHandle(false, EventResetMode.AutoReset);
private bool disposed;
public void Dispose()
{
if (disposed == false)
{
disposed = true;
DestroyDevice();
}
}
public Point ScreenToScreen(Point p)
{
p = backingControl.PointToClient(p);
Point ret = new Point(p.X * Texture.ImageWidth / backingControl.Width,
p.Y * Texture.ImageHeight / backingControl.Height);
return ret;
}
}
#endif
public interface IBlitter
{
void Open();
void Close();
IBlitterFont GetFontType(string fontType);
void DrawString(string s, IBlitterFont font, Color color, float x, float y);
SizeF MeasureString(string s, IBlitterFont font);
sd.Rectangle ClipBounds { get; set; }
}
public interface IBlitterFont { }
class UIMessage
{

View File

@ -0,0 +1,55 @@
# AngelCode Bitmap Font Generator configuration file
fileVersion=1
# font settings
fontName=Courier
fontFile=
charSet=0
fontSize=16
aa=1
scaleH=100
useSmoothing=0
isBold=1
isItalic=0
useUnicode=1
disableBoxChars=1
outputInvalidCharGlyph=1
dontIncludeKerningPairs=0
useHinting=1
renderFromOutline=0
useClearType=1
# character alignment
paddingDown=0
paddingUp=0
paddingRight=0
paddingLeft=0
spacingHoriz=1
spacingVert=1
useFixedHeight=0
forceZero=0
# output file
outWidth=128
outHeight=256
outBitDepth=32
fontDescFormat=1
fourChnlPacked=0
textureFormat=png
textureCompression=0
alphaChnl=0
redChnl=4
greenChnl=4
blueChnl=4
invA=0
invR=0
invG=0
invB=0
# outline
outlineThickness=0
# selected chars
chars=32-127,129,141,143-144,157,160-255
# imported icon images

View File

@ -0,0 +1,208 @@
<?xml version="1.0"?>
<font>
<info face="Courier" size="16" bold="1" italic="0" charset="" unicode="1" stretchH="100" smooth="0" aa="1" padding="0,0,0,0" spacing="1,1" outline="0"/>
<common lineHeight="16" base="13" scaleW="128" scaleH="256" pages="1" packed="0" alphaChnl="0" redChnl="4" greenChnl="4" blueChnl="4"/>
<pages>
<page id="0" file="courier16px_0.png" />
</pages>
<chars count="198">
<char id="-1" x="126" y="73" width="1" height="1" xoffset="0" yoffset="0" xadvance="0" page="0" chnl="15" />
<char id="32" x="83" y="137" width="30" height="1" xoffset="-10" yoffset="15" xadvance="10" page="0" chnl="15" />
<char id="33" x="124" y="95" width="2" height="10" xoffset="4" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="34" x="15" y="137" width="5" height="4" xoffset="3" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="35" x="93" y="52" width="9" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="36" x="72" y="28" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="37" x="83" y="52" width="9" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="38" x="73" y="53" width="9" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="39" x="125" y="115" width="2" height="4" xoffset="4" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="40" x="61" y="28" width="4" height="13" xoffset="4" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="41" x="56" y="28" width="4" height="13" xoffset="3" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="42" x="106" y="124" width="8" height="5" xoffset="1" yoffset="5" xadvance="10" page="0" chnl="15" />
<char id="43" x="72" y="127" width="8" height="7" xoffset="1" yoffset="5" xadvance="10" page="0" chnl="15" />
<char id="44" x="38" y="135" width="5" height="3" xoffset="3" yoffset="11" xadvance="10" page="0" chnl="15" />
<char id="45" x="106" y="130" width="7" height="1" xoffset="2" yoffset="8" xadvance="10" page="0" chnl="15" />
<char id="46" x="49" y="135" width="3" height="2" xoffset="4" yoffset="11" xadvance="10" page="0" chnl="15" />
<char id="47" x="100" y="107" width="9" height="8" xoffset="1" yoffset="4" xadvance="10" page="0" chnl="15" />
<char id="48" x="52" y="97" width="7" height="10" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="49" x="58" y="108" width="6" height="10" xoffset="3" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="50" x="0" y="109" width="7" height="10" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="51" x="8" y="109" width="7" height="10" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="52" x="60" y="97" width="7" height="10" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="53" x="76" y="97" width="7" height="10" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="54" x="92" y="96" width="7" height="10" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="55" x="100" y="96" width="7" height="10" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="56" x="44" y="97" width="7" height="10" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="57" x="116" y="95" width="7" height="10" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="58" x="121" y="115" width="3" height="7" xoffset="4" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="59" x="7" y="120" width="5" height="8" xoffset="3" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="60" x="93" y="107" width="6" height="9" xoffset="2" yoffset="4" xadvance="10" page="0" chnl="15" />
<char id="61" x="30" y="136" width="7" height="3" xoffset="2" yoffset="7" xadvance="10" page="0" chnl="15" />
<char id="62" x="86" y="108" width="6" height="9" xoffset="2" yoffset="4" xadvance="10" page="0" chnl="15" />
<char id="63" x="84" y="97" width="7" height="10" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="64" x="90" y="28" width="9" height="11" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="65" x="11" y="53" width="10" height="10" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="66" x="27" y="75" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="67" x="36" y="75" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="68" x="45" y="75" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="69" x="54" y="75" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="70" x="63" y="75" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="71" x="0" y="65" width="9" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="72" x="0" y="54" width="10" height="10" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="73" x="51" y="108" width="6" height="10" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="74" x="20" y="64" width="9" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="75" x="30" y="64" width="9" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="76" x="72" y="75" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="77" x="107" y="40" width="10" height="10" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="78" x="19" y="42" width="10" height="10" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="79" x="81" y="75" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="80" x="40" y="64" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="81" x="81" y="28" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="82" x="53" y="53" width="9" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="83" x="90" y="74" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="84" x="41" y="42" width="10" height="10" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="85" x="22" y="53" width="10" height="10" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="86" x="63" y="42" width="10" height="10" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="87" x="74" y="41" width="10" height="10" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="88" x="85" y="41" width="10" height="10" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="89" x="96" y="40" width="10" height="10" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="90" x="99" y="74" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="91" x="51" y="28" width="4" height="13" xoffset="4" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="92" x="110" y="106" width="9" height="8" xoffset="1" yoffset="4" xadvance="10" page="0" chnl="15" />
<char id="93" x="123" y="14" width="4" height="13" xoffset="3" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="94" x="115" y="123" width="8" height="4" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="95" x="114" y="135" width="10" height="1" xoffset="0" yoffset="14" xadvance="10" page="0" chnl="15" />
<char id="96" x="53" y="135" width="3" height="2" xoffset="3" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="97" x="18" y="128" width="8" height="7" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="98" x="108" y="73" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="99" x="0" y="129" width="8" height="7" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="100" x="117" y="73" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="101" x="103" y="116" width="8" height="7" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="102" x="36" y="97" width="7" height="10" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="103" x="0" y="87" width="8" height="10" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="104" x="9" y="87" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="105" x="30" y="108" width="6" height="10" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="106" x="121" y="0" width="6" height="13" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="107" x="18" y="76" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="108" x="23" y="109" width="6" height="10" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="109" x="46" y="119" width="10" height="7" xoffset="0" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="110" x="76" y="118" width="8" height="7" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="111" x="63" y="127" width="8" height="7" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="112" x="18" y="87" width="8" height="10" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="113" x="27" y="86" width="8" height="10" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="114" x="57" y="119" width="9" height="7" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="115" x="9" y="129" width="8" height="7" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="116" x="68" y="108" width="8" height="9" xoffset="1" yoffset="4" xadvance="10" page="0" chnl="15" />
<char id="117" x="94" y="117" width="8" height="7" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="118" x="24" y="120" width="10" height="7" xoffset="0" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="119" x="35" y="119" width="10" height="7" xoffset="0" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="120" x="54" y="127" width="8" height="7" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="121" x="8" y="42" width="10" height="10" xoffset="0" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="122" x="27" y="128" width="8" height="7" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="123" x="9" y="28" width="6" height="13" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="124" x="66" y="28" width="2" height="13" xoffset="4" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="125" x="37" y="28" width="6" height="13" xoffset="3" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="126" x="21" y="136" width="8" height="3" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="127" x="123" y="51" width="4" height="10" xoffset="3" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="129" x="92" y="133" width="30" height="1" xoffset="-10" yoffset="15" xadvance="10" page="0" chnl="15" />
<char id="141" x="52" y="140" width="30" height="1" xoffset="-10" yoffset="15" xadvance="10" page="0" chnl="15" />
<char id="143" x="21" y="140" width="30" height="1" xoffset="-10" yoffset="15" xadvance="10" page="0" chnl="15" />
<char id="144" x="61" y="135" width="30" height="1" xoffset="-10" yoffset="15" xadvance="10" page="0" chnl="15" />
<char id="157" x="83" y="139" width="30" height="1" xoffset="-10" yoffset="15" xadvance="10" page="0" chnl="15" />
<char id="160" x="52" y="138" width="30" height="1" xoffset="-10" yoffset="15" xadvance="10" page="0" chnl="15" />
<char id="161" x="65" y="108" width="2" height="10" xoffset="4" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="162" x="0" y="42" width="7" height="11" xoffset="2" yoffset="4" xadvance="10" page="0" chnl="15" />
<char id="163" x="68" y="97" width="7" height="10" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="164" x="81" y="126" width="7" height="6" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="165" x="30" y="42" width="10" height="10" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="166" x="69" y="28" width="2" height="13" xoffset="4" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="167" x="110" y="28" width="8" height="11" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="168" x="100" y="135" width="5" height="1" xoffset="3" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="169" x="10" y="65" width="9" height="10" xoffset="1" yoffset="2" xadvance="10" page="0" chnl="15" />
<char id="170" x="120" y="106" width="7" height="8" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="171" x="67" y="119" width="8" height="7" xoffset="1" yoffset="5" xadvance="10" page="0" chnl="15" />
<char id="172" x="0" y="137" width="8" height="4" xoffset="1" yoffset="7" xadvance="10" page="0" chnl="15" />
<char id="173" x="92" y="135" width="7" height="1" xoffset="2" yoffset="8" xadvance="10" page="0" chnl="15" />
<char id="174" x="33" y="53" width="9" height="10" xoffset="1" yoffset="2" xadvance="10" page="0" chnl="15" />
<char id="175" x="81" y="133" width="10" height="1" xoffset="0" yoffset="1" xadvance="10" page="0" chnl="15" />
<char id="176" x="9" y="137" width="5" height="4" xoffset="3" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="177" x="77" y="108" width="8" height="9" xoffset="1" yoffset="4" xadvance="10" page="0" chnl="15" />
<char id="178" x="95" y="125" width="5" height="6" xoffset="3" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="179" x="89" y="126" width="5" height="6" xoffset="3" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="180" x="57" y="135" width="3" height="2" xoffset="4" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="181" x="100" y="28" width="9" height="11" xoffset="1" yoffset="5" xadvance="10" page="0" chnl="15" />
<char id="182" x="63" y="53" width="9" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="183" x="124" y="123" width="3" height="2" xoffset="4" yoffset="7" xadvance="10" page="0" chnl="15" />
<char id="184" x="44" y="135" width="4" height="3" xoffset="3" yoffset="13" xadvance="10" page="0" chnl="15" />
<char id="185" x="101" y="125" width="4" height="6" xoffset="3" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="186" x="0" y="120" width="6" height="8" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="187" x="85" y="118" width="8" height="7" xoffset="1" yoffset="5" xadvance="10" page="0" chnl="15" />
<char id="188" x="103" y="51" width="9" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="189" x="118" y="40" width="9" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="190" x="113" y="51" width="9" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="191" x="108" y="95" width="7" height="10" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="192" x="88" y="0" width="10" height="13" xoffset="0" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="193" x="11" y="0" width="10" height="13" xoffset="0" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="194" x="22" y="0" width="10" height="13" xoffset="0" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="195" x="22" y="14" width="10" height="13" xoffset="0" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="196" x="11" y="14" width="10" height="13" xoffset="0" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="197" x="0" y="14" width="10" height="13" xoffset="0" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="198" x="52" y="42" width="10" height="10" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="199" x="42" y="14" width="8" height="13" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="200" x="96" y="14" width="8" height="13" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="201" x="87" y="14" width="8" height="13" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="202" x="78" y="14" width="8" height="13" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="203" x="69" y="14" width="8" height="13" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="204" x="44" y="28" width="6" height="13" xoffset="2" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="205" x="23" y="28" width="6" height="13" xoffset="2" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="206" x="16" y="28" width="6" height="13" xoffset="2" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="207" x="30" y="28" width="6" height="13" xoffset="2" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="208" x="43" y="53" width="9" height="10" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="209" x="99" y="0" width="10" height="13" xoffset="0" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="210" x="60" y="14" width="8" height="13" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="211" x="51" y="14" width="8" height="13" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="212" x="0" y="28" width="8" height="13" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="213" x="114" y="14" width="8" height="13" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="214" x="105" y="14" width="8" height="13" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="215" x="112" y="115" width="8" height="7" xoffset="1" yoffset="5" xadvance="10" page="0" chnl="15" />
<char id="216" x="45" y="86" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="217" x="110" y="0" width="10" height="13" xoffset="0" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="218" x="0" y="0" width="10" height="13" xoffset="0" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="219" x="44" y="0" width="10" height="13" xoffset="0" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="220" x="77" y="0" width="10" height="13" xoffset="0" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="221" x="55" y="0" width="10" height="13" xoffset="0" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="222" x="54" y="86" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="223" x="63" y="86" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="224" x="72" y="86" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="225" x="81" y="86" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="226" x="90" y="85" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="227" x="99" y="85" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="228" x="108" y="84" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="229" x="119" y="28" width="8" height="11" xoffset="1" yoffset="2" xadvance="10" page="0" chnl="15" />
<char id="230" x="13" y="120" width="10" height="7" xoffset="0" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="231" x="117" y="84" width="8" height="10" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="232" x="36" y="86" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="233" x="0" y="98" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="234" x="9" y="98" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="235" x="18" y="98" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="236" x="44" y="108" width="6" height="10" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="237" x="37" y="108" width="6" height="10" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="238" x="16" y="109" width="6" height="10" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="239" x="121" y="62" width="6" height="10" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="240" x="27" y="97" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="241" x="49" y="64" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="242" x="58" y="64" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="243" x="67" y="64" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="244" x="76" y="64" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="245" x="85" y="63" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="246" x="94" y="63" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="247" x="36" y="127" width="8" height="7" xoffset="1" yoffset="5" xadvance="10" page="0" chnl="15" />
<char id="248" x="45" y="127" width="8" height="7" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="249" x="103" y="62" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="250" x="112" y="62" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="251" x="0" y="76" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="252" x="9" y="76" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="253" x="66" y="0" width="10" height="13" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="254" x="33" y="14" width="8" height="13" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="255" x="33" y="0" width="10" height="13" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
</chars>
</font>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -39,6 +39,7 @@ namespace BizHawk.Client.EmuHawk
public LuaTable GetMouse()
{
var buttons = _lua.NewTable();
//TODO - ZEROMUS - this could use a more sophisticated system, it's just a stopgap
var p = GlobalWin.RenderPanel.ScreenToScreen(Control.MousePosition);
buttons["X"] = p.X;
buttons["Y"] = p.Y;

View File

@ -41,7 +41,7 @@ namespace BizHawk.Client.EmuHawk
int defaultWidth; //For saving the default size of the dialog, so the user can restore if desired
int defaultHeight;
SwappableDisplaySurfaceSet surfaceSet = new SwappableDisplaySurfaceSet();
SwappableBitmapBufferSet surfaceSet = new SwappableBitmapBufferSet();
List<DisplayTypeItem> displayTypeItems = new List<DisplayTypeItem>();
public bool UpdateBefore { get { return false; } }

View File

@ -19,6 +19,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Emulation", "Emulation", "{
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BizHawk.Emulation.Cores", "BizHawk.Emulation.Cores\BizHawk.Emulation.Cores.csproj", "{197D4314-8A9F-49BA-977D-54ACEFAEB6BA}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Bizware", "Bizware", "{0540A9A6-977E-466D-8BD3-1D8590BD5282}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BizHawk.Bizware.BizwareGL", "Bizware\BizHawk.Bizware.BizwareGL\BizHawk.Bizware.BizwareGL.csproj", "{9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BizHawk.Bizware.BizwareGL.OpenTK", "Bizware\BizHawk.Bizware.BizwareGL.OpenTK\BizHawk.Bizware.BizwareGL.OpenTK.csproj", "{5160CFB1-5389-47C1-B7F6-8A0DC97641EE}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -115,6 +121,30 @@ Global
{197D4314-8A9F-49BA-977D-54ACEFAEB6BA}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{197D4314-8A9F-49BA-977D-54ACEFAEB6BA}.Release|Win32.ActiveCfg = Release|Any CPU
{197D4314-8A9F-49BA-977D-54ACEFAEB6BA}.Release|x86.ActiveCfg = Release|Any CPU
{9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}.Debug|Win32.ActiveCfg = Debug|Any CPU
{9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}.Debug|x86.ActiveCfg = Debug|Any CPU
{9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}.Release|Any CPU.Build.0 = Release|Any CPU
{9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}.Release|Win32.ActiveCfg = Release|Any CPU
{9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}.Release|x86.ActiveCfg = Release|Any CPU
{5160CFB1-5389-47C1-B7F6-8A0DC97641EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5160CFB1-5389-47C1-B7F6-8A0DC97641EE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5160CFB1-5389-47C1-B7F6-8A0DC97641EE}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{5160CFB1-5389-47C1-B7F6-8A0DC97641EE}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{5160CFB1-5389-47C1-B7F6-8A0DC97641EE}.Debug|Win32.ActiveCfg = Debug|Any CPU
{5160CFB1-5389-47C1-B7F6-8A0DC97641EE}.Debug|x86.ActiveCfg = Debug|Any CPU
{5160CFB1-5389-47C1-B7F6-8A0DC97641EE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5160CFB1-5389-47C1-B7F6-8A0DC97641EE}.Release|Any CPU.Build.0 = Release|Any CPU
{5160CFB1-5389-47C1-B7F6-8A0DC97641EE}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{5160CFB1-5389-47C1-B7F6-8A0DC97641EE}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{5160CFB1-5389-47C1-B7F6-8A0DC97641EE}.Release|Win32.ActiveCfg = Release|Any CPU
{5160CFB1-5389-47C1-B7F6-8A0DC97641EE}.Release|x86.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -126,6 +156,8 @@ Global
{E1A23168-B571-411C-B360-2229E7225E0E} = {3627C08B-3E43-4224-9DA4-40BD69495FBC}
{F51946EA-827F-4D82-B841-1F2F6D060312} = {3627C08B-3E43-4224-9DA4-40BD69495FBC}
{197D4314-8A9F-49BA-977D-54ACEFAEB6BA} = {3627C08B-3E43-4224-9DA4-40BD69495FBC}
{9F84A0B2-861E-4EF4-B89B-5E2A3F38A465} = {0540A9A6-977E-466D-8BD3-1D8590BD5282}
{5160CFB1-5389-47C1-B7F6-8A0DC97641EE} = {0540A9A6-977E-466D-8BD3-1D8590BD5282}
EndGlobalSection
GlobalSection(MonoDevelopProperties) = preSolution
StartupItem = BizHawk.Client.EmuHawk\BizHawk.Client.EmuHawk.csproj

View File

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{5160CFB1-5389-47C1-B7F6-8A0DC97641EE}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>BizHawk.Bizware.BizwareGL.OpenTK</RootNamespace>
<AssemblyName>BizHawk.Bizware.BizwareGL.OpenTK</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<Reference Include="OpenTK">
<HintPath>OpenTK\OpenTK.dll</HintPath>
</Reference>
<Reference Include="OpenTK.GLControl">
<HintPath>OpenTK\OpenTK.GLControl.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\BizHawk.Bizware.BizwareGL\BizHawk.Bizware.BizwareGL.csproj">
<Project>{9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}</Project>
<Name>BizHawk.Bizware.BizwareGL</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Compile Include="IGL_TK.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -0,0 +1,503 @@
//regarding binding and vertex arrays:
//http://stackoverflow.com/questions/8704801/glvertexattribpointer-clarification
//http://stackoverflow.com/questions/9536973/oes-vertex-array-object-and-client-state
//http://www.opengl.org/wiki/Vertex_Specification
//etc
//glBindAttribLocation (programID, 0, "vertexPosition_modelspace");
//for future reference: c# tesselators
//http://www.opentk.com/node/437 (AGG#, codes on Tao forums)
using System;
using System.Threading;
using System.IO;
using System.Collections.Generic;
using sd = System.Drawing;
using sdi = System.Drawing.Imaging;
using swf=System.Windows.Forms;
using BizHawk.Bizware.BizwareGL;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
namespace BizHawk.Bizware.BizwareGL.Drivers.OpenTK
{
/// <summary>
/// OpenTK implementation of the BizwareGL.IGL interface.
/// TODO - can we have more than one of these? could be dangerous. such dangerous things to be possibly reconsidered are marked with HAMNUTS
/// TODO - if we have any way of making contexts, we also need a way of freeing it, and then we can cleanup our dictionaries
/// </summary>
public class IGL_TK : IGL
{
static IGL_TK()
{
//make sure OpenTK initializes without getting wrecked on the SDL check and throwing an exception to annoy our MDA's
var toolkitOptions = global::OpenTK.ToolkitOptions.Default;
toolkitOptions.Backend = PlatformBackend.PreferNative;
global::OpenTK.Toolkit.Init(toolkitOptions);
//NOTE: this throws EGL exceptions anyway. I'm going to ignore it and whine about it later
}
public IGL_TK()
{
OffscreenNativeWindow = new NativeWindow();
OffscreenNativeWindow.ClientSize = new sd.Size(8, 8);
this.GraphicsContext = new GraphicsContext(GraphicsMode.Default, OffscreenNativeWindow.WindowInfo, 2, 0, GraphicsContextFlags.Default);
MakeDefaultCurrent();
this.GraphicsContext.LoadAll(); //this is important for reasons unknown
CreateRenderStates();
}
void IGL.Clear(ClearBufferMask mask)
{
GL.Clear((global::OpenTK.Graphics.OpenGL.ClearBufferMask)mask);
}
void IGL.ClearColor(sd.Color color)
{
GL.ClearColor(color);
}
class GLControlWrapper : GraphicsControl
{
//Note: In order to work around bugs in OpenTK which sometimes do things to a context without making that context active first...
//we are going to push and pop the context before doing stuff
public GLControlWrapper(IGL_TK owner)
{
Owner = owner;
}
IGL_TK Owner;
public override swf.Control Control { get { return MyControl; } }
public override void SetVsync(bool state)
{
//IGraphicsContext curr = global::OpenTK.Graphics.GraphicsContext.CurrentContext;
MyControl.MakeCurrent();
MyControl.VSync = state;
//Owner.MakeContextCurrent(curr, Owner.NativeWindowsForContexts[curr]);
}
public override void Begin()
{
Owner.MakeContextCurrent(MyControl.Context, MyControl.WindowInfo);
}
public override void End()
{
//this slows things down too much
//Owner.MakeDefaultCurrent();
}
public override void SwapBuffers()
{
//IGraphicsContext curr = global::OpenTK.Graphics.GraphicsContext.CurrentContext;
MyControl.MakeCurrent();
MyControl.SwapBuffers();
//Owner.MakeContextCurrent(curr, Owner.NativeWindowsForContexts[curr]);
}
public override void Dispose()
{
//TODO - what happens if this context was current?
MyControl.Dispose();
MyControl = null;
}
public GLControl MyControl;
}
GraphicsControl IGL.CreateGraphicsControl()
{
var glc = new GLControl(GraphicsMode.Default, 2, 0, GraphicsContextFlags.Default);
glc.CreateControl();
//now the control's context will be current. annoying! fix it.
MakeDefaultCurrent();
GLControlWrapper wrapper = new GLControlWrapper(this);
wrapper.MyControl = glc;
return wrapper;
}
IntPtr IGL.GenTexture() { return new IntPtr(GL.GenTexture()); }
void IGL.FreeTexture(IntPtr texHandle) { GL.DeleteTexture(texHandle.ToInt32()); }
IntPtr IGL.GetEmptyHandle() { return new IntPtr(0); }
IntPtr IGL.GetEmptyUniformHandle() { return new IntPtr(-1); }
Shader IGL.CreateFragmentShader(string source)
{
int sid = GL.CreateShader(ShaderType.FragmentShader);
CompileShaderSimple(sid,source);
return new Shader(this,new IntPtr(sid));
}
Shader IGL.CreateVertexShader(string source)
{
int sid = GL.CreateShader(ShaderType.VertexShader);
CompileShaderSimple(sid, source);
return new Shader(this, new IntPtr(sid));
}
void IGL.FreeShader(IntPtr shader) { GL.DeleteShader(shader.ToInt32()); }
class MyBlendState : IBlendState
{
public bool enabled;
public global::OpenTK.Graphics.OpenGL.BlendingFactorSrc colorSource;
public global::OpenTK.Graphics.OpenGL.BlendEquationMode colorEquation;
public global::OpenTK.Graphics.OpenGL.BlendingFactorDest colorDest;
public global::OpenTK.Graphics.OpenGL.BlendingFactorSrc alphaSource;
public global::OpenTK.Graphics.OpenGL.BlendEquationMode alphaEquation;
public global::OpenTK.Graphics.OpenGL.BlendingFactorDest alphaDest;
public MyBlendState(bool enabled, BlendingFactor colorSource, BlendEquationMode colorEquation, BlendingFactor colorDest,
BlendingFactor alphaSource, BlendEquationMode alphaEquation, BlendingFactor alphaDest)
{
this.enabled = enabled;
this.colorSource = (global::OpenTK.Graphics.OpenGL.BlendingFactorSrc)colorSource;
this.colorEquation = (global::OpenTK.Graphics.OpenGL.BlendEquationMode)colorEquation;
this.colorDest = (global::OpenTK.Graphics.OpenGL.BlendingFactorDest)colorDest;
this.alphaSource = (global::OpenTK.Graphics.OpenGL.BlendingFactorSrc)alphaSource;
this.alphaEquation = (global::OpenTK.Graphics.OpenGL.BlendEquationMode)alphaEquation;
this.alphaDest = (global::OpenTK.Graphics.OpenGL.BlendingFactorDest)alphaDest;
}
}
IBlendState IGL.CreateBlendState(BlendingFactor colorSource, BlendEquationMode colorEquation, BlendingFactor colorDest,
BlendingFactor alphaSource, BlendEquationMode alphaEquation, BlendingFactor alphaDest)
{
return new MyBlendState(true, colorSource, colorEquation, colorDest, alphaSource, alphaEquation, alphaDest);
}
void IGL.SetBlendState(IBlendState rsBlend)
{
var mybs = rsBlend as MyBlendState;
if (mybs.enabled)
{
GL.Enable(EnableCap.Blend);
GL.BlendEquationSeparate(mybs.colorEquation, mybs.alphaEquation);
GL.BlendFuncSeparate(mybs.colorSource, mybs.colorDest, mybs.alphaSource, mybs.alphaDest);
}
else GL.Disable(EnableCap.Blend);
}
IBlendState IGL.BlendNone { get { return _rsBlendNone; } }
IBlendState IGL.BlendNormal { get { return _rsBlendNormal; } }
Pipeline IGL.CreatePipeline(Shader vertexShader, Shader fragmentShader)
{
ErrorCode errcode;
int pid = GL.CreateProgram();
GL.AttachShader(pid, vertexShader.Id.ToInt32());
errcode = GL.GetError();
GL.AttachShader(pid, fragmentShader.Id.ToInt32());
errcode = GL.GetError();
GL.LinkProgram(pid);
errcode = GL.GetError();
int n;
GL.GetProgram(pid, GetProgramParameterName.LinkStatus, out n);
string result = GL.GetProgramInfoLog(pid);
if (result != "")
throw new InvalidOperationException("Error creating pipeline (program link step):\r\n\r\n" + result);
GL.ValidateProgram(pid);
errcode = GL.GetError();
result = GL.GetProgramInfoLog(pid);
if (result != "")
throw new InvalidOperationException("Error creating pipeline (program validate step):\r\n\r\n" + result);
//get all the uniforms
List<UniformInfo> uniforms = new List<UniformInfo>();
int nUniforms;
int nSamplers = 0;
GL.GetProgram(pid,GetProgramParameterName.ActiveUniforms,out nUniforms);
for (int i = 0; i < nUniforms; i++)
{
int size, length;
ActiveUniformType type;
var sbName = new System.Text.StringBuilder();
GL.GetActiveUniform(pid, i, 1024, out length, out size, out type, sbName);
string name = sbName.ToString();
int loc = GL.GetUniformLocation(pid, name);
var ui = new UniformInfo();
ui.Name = name;
ui.Handle = new IntPtr(loc);
//automatically assign sampler uniforms to texture units (and bind them)
bool isSampler = (type == ActiveUniformType.Sampler2D);
if (isSampler)
{
ui.SamplerIndex = nSamplers;
GL.Uniform1(loc, nSamplers);
nSamplers++;
}
uniforms.Add(ui);
}
return new Pipeline(this, new IntPtr(pid), uniforms);
}
VertexLayout IGL.CreateVertexLayout() { return new VertexLayout(this,new IntPtr(0)); }
void IGL.BindTexture2d(Texture2d tex)
{
GL.BindTexture(TextureTarget.Texture2D, tex.Id.ToInt32());
}
unsafe void IGL.BindVertexLayout(VertexLayout layout)
{
StatePendingVertexLayouts[CurrentContext] = layout;
}
unsafe void IGL.BindArrayData(void* pData)
{
MyBindArrayData(StatePendingVertexLayouts[CurrentContext], pData);
}
void IGL.DrawArrays(PrimitiveType mode, int first, int count)
{
GL.DrawArrays((global::OpenTK.Graphics.OpenGL.PrimitiveType)mode, first, count);
}
void IGL.BindPipeline(Pipeline pipeline)
{
GL.UseProgram(pipeline.Id.ToInt32());
}
unsafe void IGL.SetPipelineUniformMatrix(PipelineUniform uniform, Matrix mat, bool transpose)
{
GL.UniformMatrix4(uniform.Id.ToInt32(), 1, transpose, (float*)&mat);
}
unsafe void IGL.SetPipelineUniformMatrix(PipelineUniform uniform, ref Matrix mat, bool transpose)
{
fixed(Matrix* pMat = &mat)
GL.UniformMatrix4(uniform.Id.ToInt32(), 1, transpose, (float*)pMat);
}
void IGL.SetPipelineUniform(PipelineUniform uniform, Vector4 value)
{
GL.Uniform4(uniform.Id.ToInt32(), value.X, value.Y, value.Z, value.W);
}
void IGL.SetPipelineUniformSampler(PipelineUniform uniform, IntPtr texHandle)
{
//set the sampler index into the uniform first
GL.Uniform1(uniform.Id.ToInt32(), uniform.SamplerIndex);
//now bind the texture
GL.ActiveTexture((TextureUnit)((int)TextureUnit.Texture0 + uniform.SamplerIndex));
GL.BindTexture(TextureTarget.Texture2D, texHandle.ToInt32());
}
void IGL.TexParameter2d(TextureParameterName pname, int param)
{
GL.TexParameter(TextureTarget.Texture2D, (global::OpenTK.Graphics.OpenGL.TextureParameterName)pname, param);
}
Texture2d IGL.LoadTexture(sd.Bitmap bitmap)
{
using (var bmp = new BitmapBuffer(bitmap, new BitmapLoadOptions()))
return (this as IGL).LoadTexture(bmp);
}
Texture2d IGL.LoadTexture(Stream stream)
{
using(var bmp = new BitmapBuffer(stream,new BitmapLoadOptions()))
return (this as IGL).LoadTexture(bmp);
}
Texture2d IGL.CreateTexture(int width, int height)
{
IntPtr id = (this as IGL).GenTexture();
return new Texture2d(this, id, width, height);
}
void IGL.LoadTextureData(Texture2d tex, BitmapBuffer bmp)
{
sdi.BitmapData bmp_data = bmp.LockBits();
try
{
GL.BindTexture(TextureTarget.Texture2D, tex.Id.ToInt32());
GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, bmp.Width, bmp.Height, PixelFormat.Bgra, PixelType.UnsignedByte, bmp_data.Scan0);
}
finally
{
bmp.UnlockBits(bmp_data);
}
}
Texture2d IGL.LoadTexture(BitmapBuffer bmp)
{
Texture2d ret = null;
IntPtr id = (this as IGL).GenTexture();
try
{
ret = new Texture2d(this, id, bmp.Width, bmp.Height);
GL.BindTexture(TextureTarget.Texture2D, id.ToInt32());
//picking a color order that matches doesnt seem to help, any. maybe my driver is accelerating it, or maybe it isnt a big deal. but its something to study on another day
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, bmp.Width, bmp.Height, 0, PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero);
(this as IGL).LoadTextureData(ret, bmp);
}
catch
{
(this as IGL).FreeTexture(id);
throw;
}
//set default filtering.. its safest to do this always
ret.SetFilterNearest();
return ret;
}
Texture2d IGL.LoadTexture(string path)
{
using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
return (this as IGL).LoadTexture(fs);
}
Matrix IGL.CreateGuiProjectionMatrix(int w, int h)
{
Matrix ret = Matrix.Identity;
ret.M11 = 2.0f / (float)w;
ret.M22 = 2.0f / (float)h;
return ret;
}
Matrix IGL.CreateGuiViewMatrix(int w, int h)
{
Matrix ret = Matrix.Identity;
ret.M22 = -1.0f;
ret.M41 = -w * 0.5f; // -0.5f;
ret.M42 = h * 0.5f; // +0.5f;
return ret;
}
void IGL.SetViewport(int x, int y, int width, int height)
{
ErrorCode errcode;
GL.Viewport(x, y, width, height);
errcode = GL.GetError();
}
void IGL.SetViewport(swf.Control control)
{
ErrorCode errcode;
var r = control.ClientRectangle;
errcode = GL.GetError();
GL.Viewport(r.Left, r.Top, r.Width, r.Height);
}
//------------------
INativeWindow OffscreenNativeWindow;
IGraphicsContext GraphicsContext;
//---------------
//my utility methods
global::OpenTK.Graphics.IGraphicsContext CurrentContext { get { return global::OpenTK.Graphics.GraphicsContext.CurrentContext; } }
GLControl CastControl(swf.Control swfControl)
{
GLControl glc = swfControl as GLControl;
if (glc == null)
throw new ArgumentException("Argument isn't a control created by the IGL interface", "glControl");
return glc;
}
void CompileShaderSimple(int sid, string source)
{
GL.ShaderSource(sid, source);
ErrorCode errcode = GL.GetError();
GL.CompileShader(sid);
errcode = GL.GetError();
int n;
GL.GetShader(sid, ShaderParameter.CompileStatus, out n);
string result = GL.GetShaderInfoLog(sid);
if (result != "")
throw new InvalidOperationException("Error compiling shader:\r\n\r\n" + result);
//HAX???
GL.Enable(EnableCap.Texture2D);
//GL.PolygonMode(MaterialFace.Back, PolygonMode.Line); //??
//GL.PolygonMode(MaterialFace.Front, PolygonMode.Line); //??
}
Dictionary<IGraphicsContext, VertexLayout> StateCurrentVertexLayouts = new Dictionary<IGraphicsContext, VertexLayout>();
Dictionary<IGraphicsContext, VertexLayout> StatePendingVertexLayouts = new Dictionary<IGraphicsContext, VertexLayout>();
WorkingDictionary<IGraphicsContext, HashSet<int>> VertexAttribEnables = new WorkingDictionary<IGraphicsContext, HashSet<int>>();
void UnbindVertexAttributes()
{
//HAMNUTS:
//its not clear how many bindings we'll have to disable before we can enable the ones we need..
//so lets just disable the ones we remember we have bound
var currBindings = VertexAttribEnables[CurrentContext];
foreach (var index in currBindings)
GL.DisableVertexAttribArray(index);
currBindings.Clear();
}
unsafe void MyBindArrayData(VertexLayout layout, void* pData)
{
ErrorCode errcode;
UnbindVertexAttributes();
//HAMNUTS (continued)
var currBindings = VertexAttribEnables[CurrentContext];
StateCurrentVertexLayouts[CurrentContext] = StatePendingVertexLayouts[CurrentContext];
foreach (var kvp in layout.Items)
{
GL.VertexAttribPointer(kvp.Key, kvp.Value.Components, (VertexAttribPointerType)kvp.Value.AttribType, kvp.Value.Normalized, kvp.Value.Stride, new IntPtr(pData) + kvp.Value.Offset);
errcode = GL.GetError();
GL.EnableVertexAttribArray(kvp.Key);
errcode = GL.GetError();
currBindings.Add(kvp.Key);
}
}
void MakeDefaultCurrent()
{
MakeContextCurrent(this.GraphicsContext, OffscreenNativeWindow.WindowInfo);
}
void MakeContextCurrent(IGraphicsContext context, global::OpenTK.Platform.IWindowInfo windowInfo)
{
//TODO - if we're churning through contexts quickly, this will sort of be a memory leak, since they'll be memoized forever in here
//maybe make it a weakptr or something
//dont do anything if we're already current
IGraphicsContext currentForThread = null;
if (ThreadsForContexts.TryGetValue(Thread.CurrentThread, out currentForThread))
if (currentForThread == context)
return;
NativeWindowsForContexts[context] = windowInfo;
context.MakeCurrent(windowInfo);
ThreadsForContexts[Thread.CurrentThread] = context;
}
Dictionary<Thread, IGraphicsContext> ThreadsForContexts = new Dictionary<Thread, IGraphicsContext>();
Dictionary<IGraphicsContext, global::OpenTK.Platform.IWindowInfo> NativeWindowsForContexts = new Dictionary<IGraphicsContext, global::OpenTK.Platform.IWindowInfo>();
void CreateRenderStates()
{
_rsBlendNone = new MyBlendState(false, BlendingFactor.One, BlendEquationMode.FuncAdd, BlendingFactor.Zero, BlendingFactor.One, BlendEquationMode.FuncAdd, BlendingFactor.Zero);
_rsBlendNormal = new MyBlendState(true,
BlendingFactor.SrcAlpha, BlendEquationMode.FuncAdd, BlendingFactor.OneMinusSrcAlpha,
BlendingFactor.One, BlendEquationMode.FuncAdd, BlendingFactor.Zero);
}
MyBlendState _rsBlendNone, _rsBlendNormal;
} //class IGL_TK
}

View File

@ -0,0 +1,24 @@
namespace BizHawk.Bizware.BizwareGL
{
/// <summary>
/// Represents a piece of 2d art. Not as versatile as a texture.. could have come from an atlas. So it comes with a boatload of constraints
/// </summary>
public class Art
{
internal Art(ArtManager owner)
{
Owner = owner;
}
public ArtManager Owner { get; private set; }
public Texture2d BaseTexture { get; internal set; }
public float Width, Height;
public float u0, v0, u1, v1;
internal void Initialize()
{
//TBD
}
}
}

View File

@ -0,0 +1,165 @@
using System;
using System.IO;
using System.Collections.Generic;
namespace BizHawk.Bizware.BizwareGL
{
/// <summary>
/// Load resources through here, and they can be grouped together, for purposes of batching and whatnot.
/// You can't use any of the returned Art resources until calling Close on the ArtManager
/// </summary>
public class ArtManager : IDisposable
{
public ArtManager(IGL owner)
{
Owner = owner;
Open();
}
public void Dispose()
{
//todo
}
/// <summary>
/// Reopens this instance for further resource loading. Fails if it has been closed forever.
/// </summary>
public void Open()
{
AssertIsOpen(false);
if (IsClosedForever) throw new InvalidOperationException("ArtManager instance has been closed forever!");
IsOpened = true;
}
/// <summary>
/// Loads the given stream as an Art instance
/// </summary>
public Art LoadArt(Stream stream)
{
return LoadArtInternal(new BitmapBuffer(stream, new BitmapLoadOptions()));
}
/// <summary>
/// Loads the given path as an Art instance.
/// </summary>
public Art LoadArt(string path)
{
using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
return LoadArtInternal(new BitmapBuffer(path, new BitmapLoadOptions()));
}
Art LoadArtInternal(BitmapBuffer tex)
{
AssertIsOpen(true);
Art a = new Art(this);
ArtLooseTextureAssociation[a] = tex;
ManagedArts.Add(a);
return a;
}
/// <summary>
/// Closes this instance for for further resource loading. Will result in a texture atlasing operation.
/// If the close operation is forever, then internal backup copies of resources will be freed, but it can never be reopened.
/// This function may take some time to run, as it is
/// </summary>
public unsafe void Close(bool forever = true)
{
AssertIsOpen(true);
IsOpened = false;
IsClosedForever = forever;
//first, cleanup old stuff
foreach (var tex in ManagedTextures)
tex.Dispose();
ManagedTextures.Clear();
//prepare input for atlas process and perform atlas
//add 2 extra pixels for padding on all sides
List<TexAtlas.RectItem> atlasItems = new List<TexAtlas.RectItem>();
foreach (var kvp in ArtLooseTextureAssociation)
atlasItems.Add(new TexAtlas.RectItem(kvp.Value.Width+2, kvp.Value.Height+2, kvp));
var results = TexAtlas.PackAtlas(atlasItems);
//this isnt supported yet:
if (results.Atlases.Count > 1)
throw new InvalidOperationException("Art files too big for atlas");
//prepare the output buffer
BitmapBuffer bmpResult = new BitmapBuffer(results.Atlases[0].Size);
//for each item, copy it into the output buffer and set the tex parameters on them
for (int i = 0; i < atlasItems.Count; i++)
{
var item = results.Atlases[0].Items[i];
var artAndBitmap = (KeyValuePair<Art, BitmapBuffer>)item.Item;
var art = artAndBitmap.Key;
var bitmap = artAndBitmap.Value;
int w = bitmap.Width;
int h = bitmap.Height;
int dx = item.X + 1;
int dy = item.Y + 1;
for (int y = 0; y < h; y++)
for (int x = 0; x < w; x++)
{
int pixel = bitmap.GetPixel(x, y);
bmpResult.SetPixel(x+dx,y+dy,pixel);
}
var myDestBitmap = bmpResult;
float myDestWidth = (float)myDestBitmap.Width;
float myDestHeight = (float)myDestBitmap.Height;
art.u0 = dx / myDestWidth;
art.v0 = dy / myDestHeight;
art.u1 = (dx + w) / myDestWidth;
art.v1 = (dy + h) / myDestHeight;
art.Width = w;
art.Height = h;
}
//if we're closed forever, then forget all the original bitmaps
if (forever)
{
foreach (var kvp in ArtLooseTextureAssociation)
kvp.Value.Dispose();
ArtLooseTextureAssociation.Clear();
}
//create a physical texture
var texture = Owner.LoadTexture(bmpResult);
ManagedTextures.Add(texture);
//oops, we couldn't do this earlier.
foreach (var art in ManagedArts)
art.BaseTexture = texture;
}
/// <summary>
/// Throws an exception if the instance is not open
/// </summary>
private void AssertIsOpen(bool state) { if (IsOpened != state) throw new InvalidOperationException("ArtManager instance is not open!"); }
public IGL Owner { get; private set; }
public bool IsOpened { get; private set; }
public bool IsClosedForever { get; private set; }
/// <summary>
/// This is used to remember the original bitmap sources for art files. Once the ArtManager is closed forever, this will be purged
/// </summary>
Dictionary<Art, BitmapBuffer> ArtLooseTextureAssociation = new Dictionary<Art, BitmapBuffer>();
/// <summary>
/// Physical texture resources, which exist after this ArtManager has been closed
/// </summary>
List<Texture2d> ManagedTextures = new List<Texture2d>();
/// <summary>
/// All the Arts managed by this instance
/// </summary>
List<Art> ManagedArts = new List<Art>();
}
}

View File

@ -0,0 +1,444 @@
//TODO - introduce Trim for ArtManager
//TODO - add a small buffer reuse manager.. small images can be stored in larger buffers which we happen to have held. use a timer to wait to free it until some time has passed
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Text.RegularExpressions;
using System.Runtime.InteropServices;
using sd = System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Drawing;
using System.IO;
using System.Collections.Generic;
using System.Text;
namespace BizHawk.Bizware.BizwareGL
{
/// <summary>
/// a software-based bitmap, way easier (and faster) to use than .net's built-in bitmap.
/// Only supports a fixed rgba format
/// Even though this is IDisposable, you dont have to worry about disposing it normally (that's only for the Bitmap-mimicking)
/// But you know you can't resist.
/// </summary>
public unsafe class BitmapBuffer : IDisposable
{
public int Width, Height;
public int[] Pixels;
sd.Bitmap WrappedBitmap;
GCHandle CurrLockHandle;
BitmapData CurrLock;
public BitmapData LockBits() //TODO - add read/write semantic, for wraps
{
if(CurrLock != null)
throw new InvalidOperationException("BitmapBuffer can only be locked once!");
if (WrappedBitmap != null)
{
CurrLock = WrappedBitmap.LockBits(new sd.Rectangle(0, 0, Width, Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
return CurrLock;
}
CurrLockHandle = GCHandle.Alloc(Pixels, GCHandleType.Pinned);
CurrLock = new BitmapData();
CurrLock.Height = Height;
CurrLock.Width = Width;
CurrLock.Stride = Width * 4;
CurrLock.Scan0 = CurrLockHandle.AddrOfPinnedObject();
return CurrLock;
}
public void UnlockBits(BitmapData bmpd)
{
Debug.Assert(CurrLock == bmpd);
if (WrappedBitmap != null)
{
WrappedBitmap.UnlockBits(CurrLock);
CurrLock = null;
return;
}
CurrLockHandle.Free();
CurrLock = null;
}
public void Dispose()
{
if (CurrLock == null) return;
UnlockBits(CurrLock);
}
public int GetPixel(int x, int y) { return Pixels[Width * y + x]; }
public void SetPixel(int x, int y, int value) { Pixels[Width * y + x] = value; }
public Color GetPixelAsColor(int x, int y)
{
int c = Pixels[Width * y + x];
return Color.FromArgb(c);
}
/// <summary>
/// transforms tcol to 0,0,0,0
/// </summary>
public void Alphafy(int tcol)
{
for (int y = 0, idx = 0; y < Height; y++)
for (int x = 0; x < Width; x++, idx++)
{
if (Pixels[idx] == tcol)
Pixels[idx] = 0;
}
}
/// <summary>
/// copies this bitmap and trims out transparent pixels, returning the offset to the topleft pixel
/// </summary>
public BitmapBuffer Trim()
{
int x, y;
return Trim(out x, out y);
}
/// <summary>
/// copies this bitmap and trims out transparent pixels, returning the offset to the topleft pixel
/// </summary>
public BitmapBuffer Trim(out int xofs, out int yofs)
{
int minx = int.MaxValue;
int maxx = int.MinValue;
int miny = int.MaxValue;
int maxy = int.MinValue;
for (int y = 0; y < Height; y++)
for (int x = 0; x < Width; x++)
{
int pixel = GetPixel(x, y);
int a = (pixel >> 24) & 0xFF;
if (a != 0)
{
minx = Math.Min(minx, x);
maxx = Math.Max(maxx, x);
miny = Math.Min(miny, y);
maxy = Math.Max(maxy, y);
}
}
if (minx == int.MaxValue || maxx == int.MinValue || miny == int.MaxValue || minx == int.MinValue)
{
xofs = yofs = 0;
return new BitmapBuffer(0, 0);
}
int w = maxx - minx + 1;
int h = maxy - miny + 1;
BitmapBuffer bbRet = new BitmapBuffer(w, h);
for (int y = 0; y < h; y++)
for (int x = 0; x < w; x++)
{
bbRet.SetPixel(x, y, GetPixel(x + minx, y + miny));
}
xofs = minx;
yofs = miny;
return bbRet;
}
/// <summary>
/// increases dimensions of this bitmap to the next higher power of 2
/// </summary>
public void Pad()
{
int widthRound = nexthigher(Width);
int heightRound = nexthigher(Height);
if (widthRound == Width && heightRound == Height) return;
int[] NewPixels = new int[heightRound * widthRound];
for (int y = 0, sptr = 0, dptr = 0; y < Height; y++)
{
for (int x = 0; x < Width; x++)
NewPixels[dptr++] = Pixels[sptr++];
dptr += (widthRound - Width);
}
Pixels = NewPixels;
Width = widthRound;
Height = heightRound;
}
/// <summary>
/// Creates a BitmapBuffer image from the specified filename
/// </summary>
public BitmapBuffer(string fname, BitmapLoadOptions options)
{
using (var fs = new FileStream(fname, FileMode.Open, FileAccess.Read, FileShare.Read))
LoadInternal(fs, null, options);
}
/// <summary>
/// loads an image from the specified stream
/// </summary>
public BitmapBuffer(Stream stream, BitmapLoadOptions options)
{
LoadInternal(stream, null, options);
}
/// <summary>
/// Initializes the BitmapBuffer from a System.Drawing.Bitmap
/// </summary>
public BitmapBuffer(sd.Bitmap bitmap, BitmapLoadOptions options)
{
if (options.AllowWrap && bitmap.PixelFormat == PixelFormat.Format32bppArgb)
{
Width = bitmap.Width;
Height = bitmap.Height;
WrappedBitmap = bitmap;
}
else LoadInternal(null, bitmap, options);
}
void LoadInternal(Stream stream, sd.Bitmap bitmap, BitmapLoadOptions options)
{
bool cleanup = options.CleanupAlpha0;
bool needsPad = true;
var colorKey24bpp = options.ColorKey24bpp;
using (Bitmap loadedBmp = bitmap == null ? new Bitmap(stream) : null) //sneaky!
{
Bitmap bmp = loadedBmp;
if (bmp == null)
bmp = bitmap;
//if we have a 24bpp image and a colorkey callback, the callback can choose a colorkey color and we'll use that
if (bmp.PixelFormat == PixelFormat.Format24bppRgb && colorKey24bpp != null)
{
int colorKey = colorKey24bpp(bmp);
int w = bmp.Width;
int h = bmp.Height;
InitSize(w, h);
BitmapData bmpdata = bmp.LockBits(new sd.Rectangle(0, 0, w, h), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
Color[] palette = bmp.Palette.Entries;
int* ptr = (int*)bmpdata.Scan0.ToPointer();
int stride = bmpdata.Stride;
fixed (int* pPtr = &Pixels[0])
{
for (int idx = 0, y = 0; y < h; y++)
for (int x = 0; x < w; x++)
{
int srcPixel = ptr[idx];
if (srcPixel == colorKey)
srcPixel = 0;
pPtr[idx++] = srcPixel;
}
}
bmp.UnlockBits(bmpdata);
}
if (bmp.PixelFormat == PixelFormat.Format8bppIndexed || bmp.PixelFormat == PixelFormat.Format4bppIndexed)
{
int w = bmp.Width;
int h = bmp.Height;
InitSize(w, h);
BitmapData bmpdata = bmp.LockBits(new sd.Rectangle(0, 0, w, h), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed);
Color[] palette = bmp.Palette.Entries;
byte* ptr = (byte*)bmpdata.Scan0.ToPointer();
int stride = bmpdata.Stride;
fixed (int* pPtr = &Pixels[0])
{
for (int idx = 0, y = 0; y < h; y++)
for (int x = 0; x < w; x++)
{
int srcPixel = ptr[idx];
if (srcPixel != 0)
{
int color = palette[srcPixel].ToArgb();
//make transparent pixels turn into black to avoid filtering issues and other annoying issues with stray junk in transparent pixels.
//(yes, we can have palette entries with transparency in them (PNGs support this, annoyingly))
if (cleanup)
{
if ((color & 0xFF000000) == 0) color = 0;
pPtr[idx] = color;
}
}
idx++;
}
}
bmp.UnlockBits(bmpdata);
}
else
{
//dump the supplied bitmap into our pixels array
int width = bmp.Width;
int height = bmp.Height;
InitSize(width, height);
BitmapData bmpdata = bmp.LockBits(new sd.Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
int* ptr = (int*)bmpdata.Scan0.ToInt32();
int stride = bmpdata.Stride / 4;
LoadFrom(width, stride, height, (byte*)ptr, options);
bmp.UnlockBits(bmpdata);
needsPad = false;
}
}
if (needsPad && options.Pad)
Pad();
}
/// <summary>
/// Loads the BitmapBuffer from a source buffer, which is expected to be the right pixel format
/// </summary>
public unsafe void LoadFrom(int width, int stride, int height, byte* data, BitmapLoadOptions options)
{
bool cleanup = options.CleanupAlpha0;
Width = width;
Height = height;
Pixels = new int[width * height];
fixed (int* pPtr = &Pixels[0])
{
for (int idx = 0, y = 0; y < Height; y++)
for (int x = 0; x < Width; x++)
{
int src = y * stride + x;
int srcVal = ((int*)data)[src];
//make transparent pixels turn into black to avoid filtering issues and other annoying issues with stray junk in transparent pixels
if (cleanup)
{
if ((srcVal & 0xFF000000) == 0) srcVal = 0;
pPtr[idx++] = srcVal;
}
}
}
if (options.Pad)
Pad();
}
/// <summary>
/// premultiplies a color
/// </summary>
public static int PremultiplyColor(int srcVal)
{
int b = (srcVal >> 0) & 0xFF;
int g = (srcVal >> 8) & 0xFF;
int r = (srcVal >> 16) & 0xFF;
int a = (srcVal >> 24) & 0xFF;
r = (r * a) >> 8;
g = (g * a) >> 8;
b = (b * a) >> 8;
srcVal = b | (g << 8) | (r << 16) | (a << 24);
return srcVal;
}
/// <summary>
/// initializes an empty BitmapBuffer, cleared to all 0
/// </summary>
public BitmapBuffer(int width, int height)
{
InitSize(width, height);
}
public BitmapBuffer() { }
/// <summary>
/// clears this instance to (0,0,0,0) -- without allocating a new array (to avoid GC churn)
/// </summary>
public unsafe void ClearWithoutAlloc()
{
//http://techmikael.blogspot.com/2009/12/filling-array-with-default-value.html
//this guy says its faster
int size = Width * Height;
byte fillValue = 0;
ulong fillValueLong = 0;
fixed (int* ptr = &Pixels[0])
{
ulong* dest = (ulong*)ptr;
int length = size;
while (length >= 8)
{
*dest = fillValueLong;
dest++;
length -= 8;
}
byte* bDest = (byte*)dest;
for (byte i = 0; i < length; i++)
{
*bDest = fillValue;
bDest++;
}
}
}
/// <summary>
/// just a temporary measure while refactoring emuhawk
/// </summary>
public void AcceptIntArray(int[] arr)
{
//should these be copied?
Pixels = arr;
}
/// <summary>
/// initializes an empty BitmapBuffer, cleared to all 0
/// </summary>
public BitmapBuffer(Size size)
{
InitSize(size.Width, size.Height);
}
void InitSize(int width, int height)
{
Pixels = new int[width * height];
Width = width;
Height = height;
}
/// <summary>
/// returns the next higher power of 2 than the provided value, for rounding up POW2 textures.
/// </summary>
int nexthigher(int k)
{
k--;
for (int i = 1; i < 32; i <<= 1)
k = k | k >> i;
int candidate = k + 1;
return candidate;
}
/// <summary>
/// Dumps this BitmapBuffer to a System.Drawing.Bitmap
/// </summary>
public unsafe Bitmap ToSysdrawingBitmap()
{
Bitmap bmp = new Bitmap(Width, Height, PixelFormat.Format32bppArgb);
var bmpdata = bmp.LockBits(new sd.Rectangle(0, 0, Width, Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
int* ptr = (int*)bmpdata.Scan0.ToPointer();
int stride = bmpdata.Stride;
fixed (int* pPtr = &Pixels[0])
{
for (int idx = 0, y = 0; y < Height; y++)
for (int x = 0; x < Width; x++)
{
int srcPixel = pPtr[idx];
ptr[idx] = srcPixel;
idx++;
}
}
bmp.UnlockBits(bmpdata);
return bmp;
}
}
}

View File

@ -0,0 +1,42 @@
using System;
using System.Drawing;
using System.Text;
namespace BizHawk.Bizware.BizwareGL
{
public class BitmapLoadOptions
{
/// <summary>
/// A callback to be issued when a 24bpp image is detected, which will allow you to return a colorkey
/// </summary>
public Func<Bitmap, int> ColorKey24bpp;
/// <summary>
/// Specifies whether palette entry 0 (if there is a palette) shall represent transparent (Alpha=0)
/// </summary>
public bool TransparentPalette0 = true;
/// <summary>
/// Specifies whether (r,g,b,0) pixels shall be turned into (0,0,0,0).
/// This is useful for cleaning up junk which you might not know you had littering purely transparent areas, which can mess up a lot of stuff during rendering.
/// </summary>
public bool CleanupAlpha0 = true;
/// <summary>
/// Applies the Premultiply post-process (not supported yet; and anyway it could be done as it loads for a little speedup, in many cases)
/// </summary>
public bool Premultiply = false;
/// <summary>
/// Applies Pad() post-process
/// </summary>
public bool Pad = false;
/// <summary>
/// Allows the BitmapBuffer to wrap a System.Drawing.Bitmap, if one is provided for loading.
/// This System.Drawing.Bitmap must be 32bpp and these other options may be valid (since this approach is designed for quickly getting things into textures)
/// Ownership of the bitmap remains with the user.
/// </summary>
public bool AllowWrap = true;
}
}

View File

@ -0,0 +1,104 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>BizHawk.Bizware.BizwareGL</RootNamespace>
<AssemblyName>BizHawk.Bizware.BizwareGL</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="BitmapBuffer.cs" />
<Compile Include="BitmapLoadOptions.cs" />
<Compile Include="Borrowed\BitmapFontParser\BitmapFont.cs" />
<Compile Include="Borrowed\BitmapFontParser\BitmapFontLoader.cs" />
<Compile Include="Borrowed\BitmapFontParser\Character.cs" />
<Compile Include="Borrowed\BitmapFontParser\Kerning.cs" />
<Compile Include="Borrowed\BitmapFontParser\Padding.cs" />
<Compile Include="Borrowed\BitmapFontParser\Page.cs" />
<Compile Include="GraphicsControl.cs" />
<Compile Include="Enums.cs" />
<Compile Include="GuiRenderer.cs" />
<Compile Include="IGL.cs" />
<Compile Include="ArtManager.cs" />
<Compile Include="MatrixStack.cs" />
<Compile Include="Pipeline.cs" />
<Compile Include="PipelineUniform.cs" />
<Compile Include="RenderStates.cs" />
<Compile Include="Shader.cs" />
<Compile Include="StringRenderer.cs" />
<Compile Include="TexAtlas.cs" />
<Compile Include="Art.cs" />
<Compile Include="Texture2d.cs" />
<Compile Include="Types\BoundingBox.cs" />
<Compile Include="Types\BoundingFrustum.cs" />
<Compile Include="Types\BoundingSphere.cs" />
<Compile Include="Types\Enums.cs" />
<Compile Include="Types\MathHelper.cs" />
<Compile Include="Types\Matrix.cs" />
<Compile Include="Types\Plane.cs" />
<Compile Include="Types\PlaneHelper.cs" />
<Compile Include="Types\Point.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Types\Quaternion.cs" />
<Compile Include="Types\Ray.cs" />
<Compile Include="Types\Rectangle.cs" />
<Compile Include="Types\Vector2.cs" />
<Compile Include="Types\Vector3.cs" />
<Compile Include="Types\Vector4.cs" />
<Compile Include="UniformInfo.cs" />
<Compile Include="VertexLayout.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="Docs\Readme.txt" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -0,0 +1,184 @@
//public domain assumed from cyotek.com
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
namespace Cyotek.Drawing.BitmapFont
{
public class BitmapFont : IEnumerable<Character>
{
#region  Public Member Declarations
public const int NoMaxWidth = -1;
#endregion  Public Member Declarations
#region  Public Constructors
public BitmapFont()
{ }
#endregion  Public Constructors
#region  Public Methods
public IEnumerator<Character> GetEnumerator()
{
foreach (KeyValuePair<char, Character> pair in this.Characters)
yield return pair.Value;
}
public int GetKerning(char previous, char current)
{
Kerning key;
int result;
key = new Kerning(previous, current, 0);
if (!this.Kernings.TryGetValue(key, out result))
result = 0;
return result;
}
public Size MeasureFont(string text)
{
return this.MeasureFont(text, BitmapFont.NoMaxWidth);
}
public Size MeasureFont(string text, double maxWidth)
{
char previousCharacter;
string normalizedText;
int currentLineWidth;
int currentLineHeight;
int blockWidth;
int blockHeight;
List<int> lineHeights;
previousCharacter = ' ';
normalizedText = this.NormalizeLineBreaks(text);
currentLineWidth = 0;
currentLineHeight = this.LineHeight;
blockWidth = 0;
blockHeight = 0;
lineHeights = new List<int>();
foreach (char character in normalizedText)
{
switch (character)
{
case '\n':
lineHeights.Add(currentLineHeight);
blockWidth = Math.Max(blockWidth, currentLineWidth);
currentLineWidth = 0;
currentLineHeight = this.LineHeight;
break;
default:
Character data;
int width;
data = this[character];
width = data.XAdvance + this.GetKerning(previousCharacter, character);
if (maxWidth != BitmapFont.NoMaxWidth && currentLineWidth + width >= maxWidth)
{
lineHeights.Add(currentLineHeight);
blockWidth = Math.Max(blockWidth, currentLineWidth);
currentLineWidth = 0;
currentLineHeight = this.LineHeight;
}
currentLineWidth += width;
currentLineHeight = Math.Max(currentLineHeight, data.Bounds.Height + data.Offset.Y);
previousCharacter = character;
break;
}
}
// finish off the current line if required
if (currentLineHeight != 0)
lineHeights.Add(currentLineHeight);
// reduce any lines other than the last back to the base
for (int i = 0; i < lineHeights.Count - 1; i++)
lineHeights[i] = this.LineHeight;
// calculate the final block height
foreach (int lineHeight in lineHeights)
blockHeight += lineHeight;
return new Size(Math.Max(currentLineWidth, blockWidth), blockHeight);
}
public string NormalizeLineBreaks(string s)
{
return s.Replace("\r\n", "\n").Replace("\r", "\n");
}
#endregion  Public Methods
#region  Public Properties
public int AlphaChannel { get; set; }
public int BaseHeight { get; set; }
public int BlueChannel { get; set; }
public bool Bold { get; set; }
public IDictionary<char, Character> Characters { get; set; }
public string Charset { get; set; }
public string FamilyName { get; set; }
public int FontSize { get; set; }
public int GreenChannel { get; set; }
public bool Italic { get; set; }
public IDictionary<Kerning, int> Kernings { get; set; }
public int LineHeight { get; set; }
public int OutlineSize { get; set; }
public bool Packed { get; set; }
public Padding Padding { get; set; }
public Page[] Pages { get; set; }
public int RedChannel { get; set; }
public bool Smoothed { get; set; }
public Point Spacing { get; set; }
public int StretchedHeight { get; set; }
public int SuperSampling { get; set; }
public Size TextureSize { get; set; }
public Character this[char character]
{ get { return this.Characters[character]; } }
public bool Unicode { get; set; }
#endregion  Public Properties
#region  Private Methods
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
#endregion  Private Methods
}
}

View File

@ -0,0 +1,457 @@
//public domain assumed from cyotek.com
using System;
using System.Reflection;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Xml;
namespace Cyotek.Drawing.BitmapFont
{
// Parsing class for bitmap fonts generated by AngelCode BMFont
// http://www.angelcode.com/products/bmfont/
public static class BitmapFontLoader
{
#region  Public Class Methods
///// <summary>
///// Loads a bitmap font from a file, attempting to auto detect the file type
///// </summary>
///// <param name="fileName">Name of the file to load.</param>
///// <returns></returns>
//public static BitmapFont LoadFontFromFile(string fileName)
//{
// BitmapFont result;
// if (string.IsNullOrEmpty(fileName))
// throw new ArgumentNullException("fileName", "File name not specified");
// else if (!File.Exists(fileName))
// throw new FileNotFoundException(string.Format("Cannot find file '{0}'", fileName), fileName);
// using (FileStream file = File.OpenRead(fileName))
// {
// using (TextReader reader = new StreamReader(file))
// {
// string line;
// line = reader.ReadLine();
// if (line.StartsWith("info "))
// result = BitmapFontLoader.LoadFontFromTextFile(fileName);
// else if (line.StartsWith("<?xml"))
// result = BitmapFontLoader.LoadFontFromXmlFile(fileName);
// else
// throw new InvalidDataException("Unknown file format.");
// }
// }
// return result;
//}
/// <summary>
/// Loads a bitmap font from a text file.
/// </summary>
/// <param name="fileName">Name of the file to load.</param>
/// <returns></returns>
public static BitmapFont LoadFontFromTextFile(string fileName)
{
BitmapFont font;
IDictionary<int, Page> pageData;
IDictionary<Kerning, int> kerningDictionary;
IDictionary<char, Character> charDictionary;
string resourcePath;
string[] lines;
if (string.IsNullOrEmpty(fileName))
throw new ArgumentNullException("fileName", "File name not specified");
else if (!File.Exists(fileName))
throw new FileNotFoundException(string.Format("Cannot find file '{0}'", fileName), fileName);
pageData = new SortedDictionary<int, Page>();
kerningDictionary = new Dictionary<Kerning, int>();
charDictionary = new Dictionary<char, Character>();
font = new BitmapFont();
resourcePath = Path.GetDirectoryName(fileName);
lines = File.ReadAllLines(fileName);
foreach (string line in lines)
{
string[] parts;
parts = BitmapFontLoader.Split(line, ' ');
if (parts.Length != 0)
{
switch (parts[0])
{
case "info":
font.FamilyName = BitmapFontLoader.GetNamedString(parts, "face");
font.FontSize = BitmapFontLoader.GetNamedInt(parts, "size");
font.Bold = BitmapFontLoader.GetNamedBool(parts, "bold");
font.Italic = BitmapFontLoader.GetNamedBool(parts, "italic");
font.Charset = BitmapFontLoader.GetNamedString(parts, "charset");
font.Unicode = BitmapFontLoader.GetNamedBool(parts, "unicode");
font.StretchedHeight = BitmapFontLoader.GetNamedInt(parts, "stretchH");
font.Smoothed = BitmapFontLoader.GetNamedBool(parts, "smooth");
font.SuperSampling = BitmapFontLoader.GetNamedInt(parts, "aa");
font.Padding = BitmapFontLoader.ParsePadding(BitmapFontLoader.GetNamedString(parts, "padding"));
font.Spacing = BitmapFontLoader.ParsePoint(BitmapFontLoader.GetNamedString(parts, "spacing"));
font.OutlineSize = BitmapFontLoader.GetNamedInt(parts, "outline");
break;
case "common":
font.LineHeight = BitmapFontLoader.GetNamedInt(parts, "lineHeight");
font.BaseHeight = BitmapFontLoader.GetNamedInt(parts, "base");
font.TextureSize = new Size
(
BitmapFontLoader.GetNamedInt(parts, "scaleW"),
BitmapFontLoader.GetNamedInt(parts, "scaleH")
);
font.Packed = BitmapFontLoader.GetNamedBool(parts, "packed");
font.AlphaChannel = BitmapFontLoader.GetNamedInt(parts, "alphaChnl");
font.RedChannel = BitmapFontLoader.GetNamedInt(parts, "redChnl");
font.GreenChannel = BitmapFontLoader.GetNamedInt(parts, "greenChnl");
font.BlueChannel = BitmapFontLoader.GetNamedInt(parts, "blueChnl");
break;
case "page":
int id;
string name;
string textureId;
id = BitmapFontLoader.GetNamedInt(parts, "id");
name = BitmapFontLoader.GetNamedString(parts, "file");
textureId = Path.GetFileNameWithoutExtension(name);
pageData.Add(id, new Page(id, Path.Combine(resourcePath, name)));
break;
case "char":
Character charData;
charData = new Character
{
Char = (char)BitmapFontLoader.GetNamedInt(parts, "id"),
Bounds = new Rectangle
(
BitmapFontLoader.GetNamedInt(parts, "x"),
BitmapFontLoader.GetNamedInt(parts, "y"),
BitmapFontLoader.GetNamedInt(parts, "width"),
BitmapFontLoader.GetNamedInt(parts, "height")
),
Offset = new Point
(
BitmapFontLoader.GetNamedInt(parts, "xoffset"),
BitmapFontLoader.GetNamedInt(parts, "yoffset")
),
XAdvance = BitmapFontLoader.GetNamedInt(parts, "xadvance"),
TexturePage = BitmapFontLoader.GetNamedInt(parts, "page"),
Channel = BitmapFontLoader.GetNamedInt(parts, "chnl")
};
charDictionary.Add(charData.Char, charData);
break;
case "kerning":
Kerning key;
key = new Kerning((char)BitmapFontLoader.GetNamedInt(parts, "first"), (char)BitmapFontLoader.GetNamedInt(parts, "second"), GetNamedInt(parts, "amount"));
if (!kerningDictionary.ContainsKey(key))
kerningDictionary.Add(key, key.Amount);
break;
}
}
}
font.Pages = BitmapFontLoader.ToArray(pageData.Values);
font.Characters = charDictionary;
font.Kernings = kerningDictionary;
return font;
}
/// <summary>
/// Loads a bitmap font from an XML file.
/// </summary>
/// <param name="fileName">Name of the file to load.</param>
/// <returns></returns>
public static BitmapFont LoadFontFromXmlFile(Stream stream)
{
XmlDocument document;
BitmapFont font;
IDictionary<int, Page> pageData;
IDictionary<Kerning, int> kerningDictionary;
IDictionary<char, Character> charDictionary;
XmlNode root;
XmlNode properties;
document = new XmlDocument();
pageData = new SortedDictionary<int, Page>();
kerningDictionary = new Dictionary<Kerning, int>();
charDictionary = new Dictionary<char, Character>();
font = new BitmapFont();
document.Load(stream);
root = document.DocumentElement;
// load the basic attributes
properties = root.SelectSingleNode("info");
font.FamilyName = properties.Attributes["face"].Value;
font.FontSize = Convert.ToInt32(properties.Attributes["size"].Value);
font.Bold = Convert.ToInt32(properties.Attributes["bold"].Value) != 0;
font.Italic = Convert.ToInt32(properties.Attributes["italic"].Value) != 0;
font.Unicode = Convert.ToInt32(properties.Attributes["unicode"].Value) != 0;
font.StretchedHeight = Convert.ToInt32(properties.Attributes["stretchH"].Value);
font.Charset = properties.Attributes["charset"].Value;
font.Smoothed = Convert.ToInt32(properties.Attributes["smooth"].Value) != 0;
font.SuperSampling = Convert.ToInt32(properties.Attributes["aa"].Value);
font.Padding = BitmapFontLoader.ParsePadding(properties.Attributes["padding"].Value);
font.Spacing = BitmapFontLoader.ParsePoint(properties.Attributes["spacing"].Value);
font.OutlineSize = Convert.ToInt32(properties.Attributes["outline"].Value);
// common attributes
properties = root.SelectSingleNode("common");
font.BaseHeight = Convert.ToInt32(properties.Attributes["lineHeight"].Value);
font.LineHeight = Convert.ToInt32(properties.Attributes["base"].Value);
font.TextureSize = new Size
(
Convert.ToInt32(properties.Attributes["scaleW"].Value),
Convert.ToInt32(properties.Attributes["scaleH"].Value)
);
font.Packed = Convert.ToInt32(properties.Attributes["packed"].Value) != 0;
font.AlphaChannel = Convert.ToInt32(properties.Attributes["alphaChnl"].Value);
font.RedChannel = Convert.ToInt32(properties.Attributes["redChnl"].Value);
font.GreenChannel = Convert.ToInt32(properties.Attributes["greenChnl"].Value);
font.BlueChannel = Convert.ToInt32(properties.Attributes["blueChnl"].Value);
// load texture information
foreach (XmlNode node in root.SelectNodes("pages/page"))
{
Page page;
page = new Page();
page.Id = Convert.ToInt32(node.Attributes["id"].Value);
page.FileName = node.Attributes["file"].Value;
pageData.Add(page.Id, page);
}
font.Pages = BitmapFontLoader.ToArray(pageData.Values);
// load character information
foreach (XmlNode node in root.SelectNodes("chars/char"))
{
Character character;
character = new Character();
character.Char = (char)Convert.ToInt32(node.Attributes["id"].Value);
character.Bounds = new Rectangle
(
Convert.ToInt32(node.Attributes["x"].Value),
Convert.ToInt32(node.Attributes["y"].Value),
Convert.ToInt32(node.Attributes["width"].Value),
Convert.ToInt32(node.Attributes["height"].Value)
);
character.Offset = new Point
(
Convert.ToInt32(node.Attributes["xoffset"].Value),
Convert.ToInt32(node.Attributes["yoffset"].Value)
);
character.XAdvance = Convert.ToInt32(node.Attributes["xadvance"].Value);
character.TexturePage = Convert.ToInt32(node.Attributes["page"].Value);
character.Channel = Convert.ToInt32(node.Attributes["chnl"].Value);
charDictionary.Add(character.Char, character);
}
font.Characters = charDictionary;
// loading kerning information
foreach (XmlNode node in root.SelectNodes("kernings/kerning"))
{
Kerning key;
key = new Kerning((char)Convert.ToInt32(node.Attributes["first"].Value), (char)Convert.ToInt32(node.Attributes["second"].Value), Convert.ToInt32(node.Attributes["amount"].Value));
if (!kerningDictionary.ContainsKey(key))
kerningDictionary.Add(key, key.Amount);
}
font.Kernings = kerningDictionary;
return font;
}
#endregion  Public Class Methods
#region  Private Class Methods
/// <summary>
/// Returns a boolean from an array of name/value pairs.
/// </summary>
/// <param name="parts">The array of parts.</param>
/// <param name="name">The name of the value to return.</param>
/// <returns></returns>
private static bool GetNamedBool(string[] parts, string name)
{
return BitmapFontLoader.GetNamedInt(parts, name) != 0;
}
/// <summary>
/// Returns an integer from an array of name/value pairs.
/// </summary>
/// <param name="parts">The array of parts.</param>
/// <param name="name">The name of the value to return.</param>
/// <returns></returns>
private static int GetNamedInt(string[] parts, string name)
{
return Convert.ToInt32(BitmapFontLoader.GetNamedString(parts, name));
}
/// <summary>
/// Returns a string from an array of name/value pairs.
/// </summary>
/// <param name="parts">The array of parts.</param>
/// <param name="name">The name of the value to return.</param>
/// <returns></returns>
private static string GetNamedString(string[] parts, string name)
{
string result;
result = string.Empty;
name = name.ToLowerInvariant();
foreach (string part in parts)
{
int nameEndIndex;
nameEndIndex = part.IndexOf("=");
if (nameEndIndex != -1)
{
string namePart;
string valuePart;
namePart = part.Substring(0, nameEndIndex).ToLowerInvariant();
valuePart = part.Substring(nameEndIndex + 1);
if (namePart == name)
{
if (valuePart.StartsWith("\"") && valuePart.EndsWith("\""))
valuePart = valuePart.Substring(1, valuePart.Length - 2);
result = valuePart;
break;
}
}
}
return result;
}
/// <summary>
/// Creates a Padding object from a string representation
/// </summary>
/// <param name="s">The string.</param>
/// <returns></returns>
private static Padding ParsePadding(string s)
{
string[] parts;
parts = s.Split(',');
return new Padding()
{
Left = Convert.ToInt32(parts[3].Trim()),
Top = Convert.ToInt32(parts[0].Trim()),
Right = Convert.ToInt32(parts[1].Trim()),
Bottom = Convert.ToInt32(parts[2].Trim())
};
}
/// <summary>
/// Creates a Point object from a string representation
/// </summary>
/// <param name="s">The string.</param>
/// <returns></returns>
private static Point ParsePoint(string s)
{
string[] parts;
parts = s.Split(',');
return new Point()
{
X = Convert.ToInt32(parts[0].Trim()),
Y = Convert.ToInt32(parts[1].Trim())
};
}
/// <summary>
/// Splits the specified string using a given delimiter, ignoring any instances of the delimiter as part of a quoted string.
/// </summary>
/// <param name="s">The string to split.</param>
/// <param name="delimiter">The delimiter.</param>
/// <returns></returns>
private static string[] Split(string s, char delimiter)
{
string[] results;
if (s.Contains("\""))
{
List<string> parts;
int partStart;
partStart = -1;
parts = new List<string>();
do
{
int partEnd;
int quoteStart;
int quoteEnd;
bool hasQuotes;
quoteStart = s.IndexOf("\"", partStart + 1);
quoteEnd = s.IndexOf("\"", quoteStart + 1);
partEnd = s.IndexOf(delimiter, partStart + 1);
if (partEnd == -1)
partEnd = s.Length;
hasQuotes = quoteStart != -1 && partEnd > quoteStart && partEnd < quoteEnd;
if (hasQuotes)
partEnd = s.IndexOf(delimiter, quoteEnd + 1);
parts.Add(s.Substring(partStart + 1, partEnd - partStart - 1));
if (hasQuotes)
partStart = partEnd - 1;
partStart = s.IndexOf(delimiter, partStart + 1);
} while (partStart != -1);
results = parts.ToArray();
}
else
results = s.Split(new char[] { delimiter }, StringSplitOptions.RemoveEmptyEntries);
return results;
}
/// <summary>
/// Converts the given collection into an array
/// </summary>
/// <typeparam name="T">Type of the items in the array</typeparam>
/// <param name="values">The values.</param>
/// <returns></returns>
private static T[] ToArray<T>(ICollection<T> values)
{
T[] result;
// avoid a forced .NET 3 dependency just for one call to Linq
result = new T[values.Count];
values.CopyTo(result, 0);
return result;
}
#endregion  Private Class Methods
}
}

View File

@ -0,0 +1,34 @@
//public domain assumed from cyotek.com
using System.Drawing;
namespace Cyotek.Drawing.BitmapFont
{
public struct Character
{
#region  Public Methods
public override string ToString()
{
return this.Char.ToString();
}
#endregion  Public Methods
#region  Public Properties
public int Channel { get; set; }
public Rectangle Bounds { get; set; }
public Point Offset { get; set; }
public char Char { get; set; }
public int TexturePage { get; set; }
public int XAdvance { get; set; }
#endregion  Public Properties
}
}

View File

@ -0,0 +1,38 @@
//public domain assumed from cyotek.com
namespace Cyotek.Drawing.BitmapFont
{
public struct Kerning
{
#region  Public Constructors
public Kerning(char firstCharacter, char secondCharacter, int amount)
: this()
{
this.FirstCharacter = firstCharacter;
this.SecondCharacter = secondCharacter;
this.Amount = amount;
}
#endregion  Public Constructors
#region  Public Methods
public override string ToString()
{
return string.Format("{0} to {1} = {2}", this.FirstCharacter, this.SecondCharacter, this.Amount);
}
#endregion  Public Methods
#region  Public Properties
public char FirstCharacter { get; set; }
public char SecondCharacter { get; set; }
public int Amount { get; set; }
#endregion  Public Properties
}
}

View File

@ -0,0 +1,41 @@
//public domain assumed from cyotek.com
namespace Cyotek.Drawing.BitmapFont
{
public struct Padding
{
#region  Public Constructors
public Padding(int left, int top, int right, int bottom)
: this()
{
this.Top = top;
this.Left = left;
this.Right = right;
this.Bottom = bottom;
}
#endregion  Public Constructors
#region  Public Methods
public override string ToString()
{
return string.Format("{0}, {1}, {2}, {3}", this.Left, this.Top, this.Right, this.Bottom);
}
#endregion  Public Methods
#region  Public Properties
public int Top { get; set; }
public int Left { get; set; }
public int Right { get; set; }
public int Bottom { get; set; }
#endregion  Public Properties
}
}

View File

@ -0,0 +1,37 @@
//public domain assumed from cyotek.com
using System.IO;
namespace Cyotek.Drawing.BitmapFont
{
public struct Page
{
#region  Public Constructors
public Page(int id, string fileName)
: this()
{
this.FileName = fileName;
this.Id = id;
}
#endregion  Public Constructors
#region  Public Methods
public override string ToString()
{
return string.Format("{0} ({1})", this.Id, Path.GetFileName(this.FileName));
}
#endregion  Public Methods
#region  Public Properties
public string FileName { get; set; }
public int Id { get; set; }
#endregion  Public Properties
}
}

View File

@ -0,0 +1,4 @@
BitmapFontParser
http://cyotek.com/blog/angelcode-bitmap-font-parsing-using-csharp
License not stated. I'm content with calling it public domain. As future work, the code could be replaced easily, so I dont consider this a big deal. It's most trivial code.
It loads fonts created by http://www.angelcode.com/products/bmfont/

View File

@ -0,0 +1,573 @@
using System;
namespace BizHawk.Bizware.BizwareGL
{
// Summary:
// Used in GL.BlendFunc, GL.BlendFuncSeparate
public enum BlendingFactor
{
// Summary:
// Original was GL_ZERO = 0
Zero = 0,
//
// Summary:
// Original was GL_ONE = 1
One = 1,
//
// Summary:
// Original was GL_SRC_COLOR = 0x0300
SrcColor = 768,
//
// Summary:
// Original was GL_ONE_MINUS_SRC_COLOR = 0x0301
OneMinusSrcColor = 769,
//
// Summary:
// Original was GL_SRC_ALPHA = 0x0302
SrcAlpha = 770,
//
// Summary:
// Original was GL_ONE_MINUS_SRC_ALPHA = 0x0303
OneMinusSrcAlpha = 771,
//
// Summary:
// Original was GL_DST_ALPHA = 0x0304
DstAlpha = 772,
//
// Summary:
// Original was GL_ONE_MINUS_DST_ALPHA = 0x0305
OneMinusDstAlpha = 773,
//
// Summary:
// Original was GL_DST_COLOR = 0x0306
DstColor = 774,
//
// Summary:
// Original was GL_ONE_MINUS_DST_COLOR = 0x0307
OneMinusDstColor = 775,
//
// Summary:
// Original was GL_SRC_ALPHA_SATURATE = 0x0308
SrcAlphaSaturate = 776,
//
// Summary:
// Original was GL_CONSTANT_COLOR_EXT = 0x8001
ConstantColorExt = 32769,
//
// Summary:
// Original was GL_CONSTANT_COLOR = 0x8001
ConstantColor = 32769,
//
// Summary:
// Original was GL_ONE_MINUS_CONSTANT_COLOR = 0x8002
OneMinusConstantColor = 32770,
//
// Summary:
// Original was GL_ONE_MINUS_CONSTANT_COLOR_EXT = 0x8002
OneMinusConstantColorExt = 32770,
//
// Summary:
// Original was GL_CONSTANT_ALPHA = 0x8003
ConstantAlpha = 32771,
//
// Summary:
// Original was GL_CONSTANT_ALPHA_EXT = 0x8003
ConstantAlphaExt = 32771,
//
// Summary:
// Original was GL_ONE_MINUS_CONSTANT_ALPHA_EXT = 0x8004
OneMinusConstantAlphaExt = 32772,
//
// Summary:
// Original was GL_ONE_MINUS_CONSTANT_ALPHA = 0x8004
OneMinusConstantAlpha = 32772,
//
// Summary:
// Original was GL_SRC1_ALPHA = 0x8589
Src1Alpha = 34185,
//
// Summary:
// Original was GL_SRC1_COLOR = 0x88F9
Src1Color = 35065,
//
// Summary:
// Original was GL_ONE_MINUS_SRC1_COLOR = 0x88FA
OneMinusSrc1Color = 35066,
//
// Summary:
// Original was GL_ONE_MINUS_SRC1_ALPHA = 0x88FB
OneMinusSrc1Alpha = 35067,
}
// Summary:
// Used in GL.Arb.BlendEquation, GL.BlendEquation and 2 other functions
public enum BlendEquationMode
{
// Summary:
// Original was GL_FUNC_ADD = 0x8006
FuncAdd = 32774,
//
// Summary:
// Original was GL_MIN = 0x8007
Min = 32775,
//
// Summary:
// Original was GL_MAX = 0x8008
Max = 32776,
//
// Summary:
// Original was GL_FUNC_SUBTRACT = 0x800A
FuncSubtract = 32778,
//
// Summary:
// Original was GL_FUNC_REVERSE_SUBTRACT = 0x800B
FuncReverseSubtract = 32779,
}
// Summary:
// Used in GL.BlitFramebuffer, GL.Clear and 1 other function
[Flags]
public enum ClearBufferMask
{
// Summary:
// Original was GL_NONE = 0
None = 0,
//
// Summary:
// Original was GL_DEPTH_BUFFER_BIT = 0x00000100
DepthBufferBit = 256,
//
// Summary:
// Original was GL_ACCUM_BUFFER_BIT = 0x00000200
AccumBufferBit = 512,
//
// Summary:
// Original was GL_STENCIL_BUFFER_BIT = 0x00000400
StencilBufferBit = 1024,
//
// Summary:
// Original was GL_COLOR_BUFFER_BIT = 0x00004000
ColorBufferBit = 16384,
//
// Summary:
// Original was GL_COVERAGE_BUFFER_BIT_NV = 0x00008000
CoverageBufferBitNv = 32768,
}
// Summary:
// Used in GL.TexParameter, GL.TexParameterI and 5 other functions
public enum TextureParameterName
{
// Summary:
// Original was GL_TEXTURE_BORDER_COLOR = 0x1004
TextureBorderColor = 4100,
//
// Summary:
// Original was GL_TEXTURE_MAG_FILTER = 0x2800
TextureMagFilter = 10240,
//
// Summary:
// Original was GL_TEXTURE_MIN_FILTER = 0x2801
TextureMinFilter = 10241,
//
// Summary:
// Original was GL_TEXTURE_WRAP_S = 0x2802
TextureWrapS = 10242,
//
// Summary:
// Original was GL_TEXTURE_WRAP_T = 0x2803
TextureWrapT = 10243,
//
// Summary:
// Original was GL_TEXTURE_PRIORITY = 0x8066
TexturePriority = 32870,
//
// Summary:
// Original was GL_TEXTURE_PRIORITY_EXT = 0x8066
TexturePriorityExt = 32870,
//
// Summary:
// Original was GL_TEXTURE_DEPTH = 0x8071
TextureDepth = 32881,
//
// Summary:
// Original was GL_TEXTURE_WRAP_R_EXT = 0x8072
TextureWrapRExt = 32882,
//
// Summary:
// Original was GL_TEXTURE_WRAP_R_OES = 0x8072
TextureWrapROes = 32882,
//
// Summary:
// Original was GL_TEXTURE_WRAP_R = 0x8072
TextureWrapR = 32882,
//
// Summary:
// Original was GL_DETAIL_TEXTURE_LEVEL_SGIS = 0x809A
DetailTextureLevelSgis = 32922,
//
// Summary:
// Original was GL_DETAIL_TEXTURE_MODE_SGIS = 0x809B
DetailTextureModeSgis = 32923,
//
// Summary:
// Original was GL_TEXTURE_COMPARE_FAIL_VALUE = 0x80BF
TextureCompareFailValue = 32959,
//
// Summary:
// Original was GL_SHADOW_AMBIENT_SGIX = 0x80BF
ShadowAmbientSgix = 32959,
//
// Summary:
// Original was GL_DUAL_TEXTURE_SELECT_SGIS = 0x8124
DualTextureSelectSgis = 33060,
//
// Summary:
// Original was GL_QUAD_TEXTURE_SELECT_SGIS = 0x8125
QuadTextureSelectSgis = 33061,
//
// Summary:
// Original was GL_CLAMP_TO_BORDER = 0x812D
ClampToBorder = 33069,
//
// Summary:
// Original was GL_CLAMP_TO_EDGE = 0x812F
ClampToEdge = 33071,
//
// Summary:
// Original was GL_TEXTURE_WRAP_Q_SGIS = 0x8137
TextureWrapQSgis = 33079,
//
// Summary:
// Original was GL_TEXTURE_MIN_LOD = 0x813A
TextureMinLod = 33082,
//
// Summary:
// Original was GL_TEXTURE_MAX_LOD = 0x813B
TextureMaxLod = 33083,
//
// Summary:
// Original was GL_TEXTURE_BASE_LEVEL = 0x813C
TextureBaseLevel = 33084,
//
// Summary:
// Original was GL_TEXTURE_MAX_LEVEL = 0x813D
TextureMaxLevel = 33085,
//
// Summary:
// Original was GL_TEXTURE_CLIPMAP_CENTER_SGIX = 0x8171
TextureClipmapCenterSgix = 33137,
//
// Summary:
// Original was GL_TEXTURE_CLIPMAP_FRAME_SGIX = 0x8172
TextureClipmapFrameSgix = 33138,
//
// Summary:
// Original was GL_TEXTURE_CLIPMAP_OFFSET_SGIX = 0x8173
TextureClipmapOffsetSgix = 33139,
//
// Summary:
// Original was GL_TEXTURE_CLIPMAP_VIRTUAL_DEPTH_SGIX = 0x8174
TextureClipmapVirtualDepthSgix = 33140,
//
// Summary:
// Original was GL_TEXTURE_CLIPMAP_LOD_OFFSET_SGIX = 0x8175
TextureClipmapLodOffsetSgix = 33141,
//
// Summary:
// Original was GL_TEXTURE_CLIPMAP_DEPTH_SGIX = 0x8176
TextureClipmapDepthSgix = 33142,
//
// Summary:
// Original was GL_POST_TEXTURE_FILTER_BIAS_SGIX = 0x8179
PostTextureFilterBiasSgix = 33145,
//
// Summary:
// Original was GL_POST_TEXTURE_FILTER_SCALE_SGIX = 0x817A
PostTextureFilterScaleSgix = 33146,
//
// Summary:
// Original was GL_TEXTURE_LOD_BIAS_S_SGIX = 0x818E
TextureLodBiasSSgix = 33166,
//
// Summary:
// Original was GL_TEXTURE_LOD_BIAS_T_SGIX = 0x818F
TextureLodBiasTSgix = 33167,
//
// Summary:
// Original was GL_TEXTURE_LOD_BIAS_R_SGIX = 0x8190
TextureLodBiasRSgix = 33168,
//
// Summary:
// Original was GL_GENERATE_MIPMAP = 0x8191
GenerateMipmap = 33169,
//
// Summary:
// Original was GL_GENERATE_MIPMAP_SGIS = 0x8191
GenerateMipmapSgis = 33169,
//
// Summary:
// Original was GL_TEXTURE_COMPARE_SGIX = 0x819A
TextureCompareSgix = 33178,
//
// Summary:
// Original was GL_TEXTURE_MAX_CLAMP_S_SGIX = 0x8369
TextureMaxClampSSgix = 33641,
//
// Summary:
// Original was GL_TEXTURE_MAX_CLAMP_T_SGIX = 0x836A
TextureMaxClampTSgix = 33642,
//
// Summary:
// Original was GL_TEXTURE_MAX_CLAMP_R_SGIX = 0x836B
TextureMaxClampRSgix = 33643,
//
// Summary:
// Original was GL_TEXTURE_LOD_BIAS = 0x8501
TextureLodBias = 34049,
//
// Summary:
// Original was GL_DEPTH_TEXTURE_MODE = 0x884B
DepthTextureMode = 34891,
//
// Summary:
// Original was GL_TEXTURE_COMPARE_MODE = 0x884C
TextureCompareMode = 34892,
//
// Summary:
// Original was GL_TEXTURE_COMPARE_FUNC = 0x884D
TextureCompareFunc = 34893,
//
// Summary:
// Original was GL_TEXTURE_SWIZZLE_R = 0x8E42
TextureSwizzleR = 36418,
//
// Summary:
// Original was GL_TEXTURE_SWIZZLE_G = 0x8E43
TextureSwizzleG = 36419,
//
// Summary:
// Original was GL_TEXTURE_SWIZZLE_B = 0x8E44
TextureSwizzleB = 36420,
//
// Summary:
// Original was GL_TEXTURE_SWIZZLE_A = 0x8E45
TextureSwizzleA = 36421,
//
// Summary:
// Original was GL_TEXTURE_SWIZZLE_RGBA = 0x8E46
TextureSwizzleRgba = 36422,
}
// Summary:
// Not used directly.
public enum TextureMinFilter
{
// Summary:
// Original was GL_NEAREST = 0x2600
Nearest = 9728,
//
// Summary:
// Original was GL_LINEAR = 0x2601
Linear = 9729,
//
// Summary:
// Original was GL_NEAREST_MIPMAP_NEAREST = 0x2700
NearestMipmapNearest = 9984,
//
// Summary:
// Original was GL_LINEAR_MIPMAP_NEAREST = 0x2701
LinearMipmapNearest = 9985,
//
// Summary:
// Original was GL_NEAREST_MIPMAP_LINEAR = 0x2702
NearestMipmapLinear = 9986,
//
// Summary:
// Original was GL_LINEAR_MIPMAP_LINEAR = 0x2703
LinearMipmapLinear = 9987,
//
// Summary:
// Original was GL_FILTER4_SGIS = 0x8146
Filter4Sgis = 33094,
//
// Summary:
// Original was GL_LINEAR_CLIPMAP_LINEAR_SGIX = 0x8170
LinearClipmapLinearSgix = 33136,
//
// Summary:
// Original was GL_PIXEL_TEX_GEN_Q_CEILING_SGIX = 0x8184
PixelTexGenQCeilingSgix = 33156,
//
// Summary:
// Original was GL_PIXEL_TEX_GEN_Q_ROUND_SGIX = 0x8185
PixelTexGenQRoundSgix = 33157,
//
// Summary:
// Original was GL_PIXEL_TEX_GEN_Q_FLOOR_SGIX = 0x8186
PixelTexGenQFloorSgix = 33158,
//
// Summary:
// Original was GL_NEAREST_CLIPMAP_NEAREST_SGIX = 0x844D
NearestClipmapNearestSgix = 33869,
//
// Summary:
// Original was GL_NEAREST_CLIPMAP_LINEAR_SGIX = 0x844E
NearestClipmapLinearSgix = 33870,
//
// Summary:
// Original was GL_LINEAR_CLIPMAP_NEAREST_SGIX = 0x844F
LinearClipmapNearestSgix = 33871,
}
// Summary:
// Not used directly.
public enum TextureMagFilter
{
// Summary:
// Original was GL_NEAREST = 0x2600
Nearest = 9728,
//
// Summary:
// Original was GL_LINEAR = 0x2601
Linear = 9729,
//
// Summary:
// Original was GL_LINEAR_DETAIL_SGIS = 0x8097
LinearDetailSgis = 32919,
//
// Summary:
// Original was GL_LINEAR_DETAIL_ALPHA_SGIS = 0x8098
LinearDetailAlphaSgis = 32920,
//
// Summary:
// Original was GL_LINEAR_DETAIL_COLOR_SGIS = 0x8099
LinearDetailColorSgis = 32921,
//
// Summary:
// Original was GL_LINEAR_SHARPEN_SGIS = 0x80AD
LinearSharpenSgis = 32941,
//
// Summary:
// Original was GL_LINEAR_SHARPEN_ALPHA_SGIS = 0x80AE
LinearSharpenAlphaSgis = 32942,
//
// Summary:
// Original was GL_LINEAR_SHARPEN_COLOR_SGIS = 0x80AF
LinearSharpenColorSgis = 32943,
//
// Summary:
// Original was GL_FILTER4_SGIS = 0x8146
Filter4Sgis = 33094,
//
// Summary:
// Original was GL_PIXEL_TEX_GEN_Q_CEILING_SGIX = 0x8184
PixelTexGenQCeilingSgix = 33156,
//
// Summary:
// Original was GL_PIXEL_TEX_GEN_Q_ROUND_SGIX = 0x8185
PixelTexGenQRoundSgix = 33157,
//
// Summary:
// Original was GL_PIXEL_TEX_GEN_Q_FLOOR_SGIX = 0x8186
PixelTexGenQFloorSgix = 33158,
}
public enum VertexAttributeType
{
// Summary:
// Original was GL_BYTE = 0x1400
Byte = 5120,
//
// Summary:
// Original was GL_UNSIGNED_BYTE = 0x1401
UnsignedByte = 5121,
//
// Summary:
// Original was GL_SHORT = 0x1402
Short = 5122,
//
// Summary:
// Original was GL_UNSIGNED_SHORT = 0x1403
UnsignedShort = 5123,
//
// Summary:
// Original was GL_INT = 0x1404
Int = 5124,
//
// Summary:
// Original was GL_UNSIGNED_INT = 0x1405
UnsignedInt = 5125,
//
// Summary:
// Original was GL_FLOAT = 0x1406
Float = 5126,
//
// Summary:
// Original was GL_DOUBLE = 0x140A
Double = 5130,
//
// Summary:
// Original was GL_HALF_FLOAT = 0x140B
HalfFloat = 5131,
//
// Summary:
// Original was GL_FIXED = 0x140C
Fixed = 5132,
//
// Summary:
// Original was GL_UNSIGNED_INT_2_10_10_10_REV = 0x8368
UnsignedInt2101010Rev = 33640,
//
// Summary:
// Original was GL_INT_2_10_10_10_REV = 0x8D9F
Int2101010Rev = 36255,
}
// Summary:
// Used in GL.Apple.DrawElementArray, GL.Apple.DrawRangeElementArray and 38
// other functions
public enum PrimitiveType
{
// Summary:
// Original was GL_POINTS = 0x0000
Points = 0,
//
// Summary:
// Original was GL_LINES = 0x0001
Lines = 1,
//
// Summary:
// Original was GL_LINE_LOOP = 0x0002
LineLoop = 2,
//
// Summary:
// Original was GL_LINE_STRIP = 0x0003
LineStrip = 3,
//
// Summary:
// Original was GL_TRIANGLES = 0x0004
Triangles = 4,
//
// Summary:
// Original was GL_TRIANGLE_STRIP = 0x0005
TriangleStrip = 5,
//
// Summary:
// Original was GL_TRIANGLE_FAN = 0x0006
TriangleFan = 6,
//
// Summary:
// Original was GL_QUADS = 0x0007
Quads = 7,
//
// Summary:
// Original was GL_QUAD_STRIP = 0x0008
QuadStrip = 8,
//
// Summary:
// Original was GL_POLYGON = 0x0009
Polygon = 9,
}
}

View File

@ -0,0 +1,42 @@
using System;
using swf = System.Windows.Forms;
namespace BizHawk.Bizware.BizwareGL
{
/// <summary>
/// Represents
/// </summary>
public abstract class GraphicsControl : IDisposable
{
/// <summary>
/// Gets the control that this interface is wrapping
/// </summary>
public abstract swf.Control Control { get; }
public static implicit operator swf.Control(GraphicsControl ctrl) { return ctrl.Control; }
/// <summary>
/// Sets whether presentation operations on this control will vsync
/// </summary>
public abstract void SetVsync(bool state);
/// <summary>
/// Swaps the buffers for this control
/// </summary>
public abstract void SwapBuffers();
/// <summary>
/// Makes this control current for rendering operations.
/// Note that at this time, the window size shouldnt change until End() or else something bad might happen
/// Please be aware that this might change the rendering context, meaning that some things you set without calling BeginControl/EndControl might not be affected
/// </summary>
public abstract void Begin();
/// <summary>
/// Ends rendering on the specified control.
/// </summary>
public abstract void End();
public abstract void Dispose();
}
}

View File

@ -0,0 +1,305 @@
//http://stackoverflow.com/questions/6893302/decode-rgb-value-to-single-float-without-bit-shift-in-glsl
using System;
using sd=System.Drawing;
namespace BizHawk.Bizware.BizwareGL
{
/// <summary>
/// A simple renderer useful for rendering GUI stuff.
/// When doing GUI rendering, run everything through here (if you need a GL feature not done through here, run it through here first)
/// Call Begin, then draw, then End, and dont use other Renderers or GL calls in the meantime, unless you know what youre doing.
/// This can perform batching (well.. maybe not yet), which is occasionally necessary for drawing large quantities of things.
/// </summary>
public class GuiRenderer : IDisposable
{
public GuiRenderer(IGL owner)
{
Owner = owner;
VertexLayout = owner.CreateVertexLayout();
VertexLayout.DefineVertexAttribute(0, 2, BizwareGL.VertexAttributeType.Float, false, 16, 0);
VertexLayout.DefineVertexAttribute(1, 2, BizwareGL.VertexAttributeType.Float, false, 16, 8);
VertexLayout.Close();
_Projection = new MatrixStack();
_Modelview = new MatrixStack();
var vs = Owner.CreateVertexShader(DefaultVertexShader);
var ps = Owner.CreateFragmentShader(DefaultPixelShader);
CurrPipeline = DefaultPipeline = Owner.CreatePipeline(vs, ps);
}
public void Dispose()
{
VertexLayout.Dispose();
VertexLayout = null;
DefaultPipeline.Dispose();
DefaultPipeline = null;
}
/// <summary>
/// Sets the pipeline for this GuiRenderer to use. We won't keep possession of it.
/// This pipeline must work in certain ways, which can be discerned by inspecting the built-in one
/// </summary>
public void SetPipeline(Pipeline pipeline)
{
if (IsActive)
throw new InvalidOperationException("Can't change pipeline while renderer is running!");
Flush();
CurrPipeline = pipeline;
}
/// <summary>
/// Restores the pipeline to the default
/// </summary>
public void SetDefaultPipeline()
{
SetPipeline(DefaultPipeline);
}
public void SetModulateColorWhite()
{
SetModulateColor(sd.Color.White);
}
public void SetModulateColor(sd.Color color)
{
Flush();
CurrPipeline["uModulateColor"].Set(new Vector4(color.R / 255.0f, color.G / 255.0f, color.B / 255.0f, color.A / 255.0f));
}
public void SetBlendState(IBlendState rsBlend)
{
Flush();
Owner.SetBlendState(rsBlend);
}
MatrixStack _Projection, _Modelview;
public MatrixStack Projection
{
get { return _Projection; }
set
{
_Projection = value;
_Projection.IsDirty = true;
}
}
public MatrixStack Modelview
{
get { return _Modelview; }
set
{
_Modelview = value;
_Modelview.IsDirty = true;
}
}
/// <summary>
/// begin rendering, initializing viewport and projections to the given dimensions
/// </summary>
public void Begin(int width, int height)
{
Begin();
Projection = Owner.CreateGuiProjectionMatrix(width, height);
Modelview = Owner.CreateGuiViewMatrix(width, height);
Owner.SetViewport(0, 0, width, height);
}
/// <summary>
/// Begins rendering
/// </summary>
public void Begin()
{
//uhhmmm I want to throw an exception if its already active, but its annoying.
if(CurrPipeline == null)
throw new InvalidOperationException("Pipeline hasn't been set!");
IsActive = true;
Owner.BindVertexLayout(VertexLayout);
Owner.BindPipeline(CurrPipeline);
//clear state cache
sTexture = null;
Modelview.Clear();
Projection.Clear();
SetModulateColorWhite();
}
/// <summary>
/// Use this, if you must do something sneaky to openGL without this GuiRenderer knowing.
/// It might be faster than End and Beginning again, and certainly prettier
/// </summary>
public void Flush()
{
//no batching, nothing to do here yet
}
/// <summary>
/// Ends rendering
/// </summary>
public void End()
{
if (!IsActive)
throw new InvalidOperationException("GuiRenderer is not active!");
IsActive = false;
}
/// <summary>
/// Draws a subrectangle from the provided texture. For advanced users only
/// </summary>
public void DrawSubrect(Texture2d tex, float x, float y, float w, float h, float u0, float v0, float u1, float v1)
{
DrawSubrectInternal(tex, x, y, w, h, u0, v0, u1, v1);
}
/// <summary>
/// draws the specified Art resource
/// </summary>
public void Draw(Art art) { DrawInternal(art, 0, 0, art.Width, art.Height, false, false); }
/// <summary>
/// draws the specified Art resource with the specified offset. This could be tricky if youve applied other rotate or scale transforms first.
/// </summary>
public void Draw(Art art, float x, float y) { DrawInternal(art, x, y, art.Width, art.Height, false, false); }
/// <summary>
/// draws the specified Art resource with the specified offset, with the specified size. This could be tricky if youve applied other rotate or scale transforms first.
/// </summary>
public void Draw(Art art, float x, float y, float width, float height) { DrawInternal(art, x, y, width, height, false, false); }
/// <summary>
/// draws the specified Art resource with the specified offset. This could be tricky if youve applied other rotate or scale transforms first.
/// </summary>
public void Draw(Art art, Vector2 pos) { DrawInternal(art, pos.X, pos.Y, art.Width, art.Height, false, false); }
/// <summary>
/// draws the specified texture2d resource.
/// </summary>
public void Draw(Texture2d tex) { DrawInternal(tex, 0, 0, tex.Width, tex.Height); }
/// <summary>
/// draws the specified Art resource with the given flip flags
/// </summary>
public void DrawFlipped(Art art, bool xflip, bool yflip) { DrawInternal(art, 0, 0, art.Width, art.Height, xflip, yflip); }
unsafe void DrawInternal(Texture2d tex, float x, float y, float w, float h)
{
Art art = new Art(null);
art.Width = w;
art.Height = h;
art.u0 = art.v0 = 0;
art.u1 = art.v1 = 1;
art.BaseTexture = tex;
DrawInternal(art,x,y,w,h,false,false);
}
unsafe void DrawInternal(Art art, float x, float y, float w, float h, bool fx, bool fy)
{
float u0,v0,u1,v1;
if(fx) { u0 = art.u1; u1 = art.u0; }
else { u0 = art.u0; u1 = art.u1; }
if(fy) { v0 = art.v1; v1 = art.v0; }
else { v0 = art.v0; v1 = art.v1; }
float[] data = new float[16] {
x,y, u0,v0,
x+art.Width,y, u1,v0,
x,y+art.Height, u0,v1,
x+art.Width,y+art.Height, u1,v1
};
Texture2d tex = art.BaseTexture;
if(sTexture != tex)
CurrPipeline["uSampler0"].Set(sTexture = tex);
if (_Projection.IsDirty)
{
CurrPipeline["um44Projection"].Set(ref _Projection.Top);
_Projection.IsDirty = false;
}
if (_Modelview.IsDirty)
{
CurrPipeline["um44Modelview"].Set(ref _Modelview.Top);
_Modelview.IsDirty = false;
}
fixed (float* pData = &data[0])
{
Owner.BindArrayData(pData);
Owner.DrawArrays(PrimitiveType.TriangleStrip, 0, 4);
}
}
unsafe void DrawSubrectInternal(Texture2d tex, float x, float y, float w, float h, float u0, float v0, float u1, float v1)
{
float[] data = new float[16] {
x,y, u0,v0,
x+w,y, u1,v0,
x,y+h, u0,v1,
x+w,y+h, u1,v1
};
if (sTexture != tex)
CurrPipeline["uSampler0"].Set(sTexture = tex);
if (_Projection.IsDirty)
{
CurrPipeline["um44Projection"].Set(ref _Projection.Top);
_Projection.IsDirty = false;
}
if (_Modelview.IsDirty)
{
CurrPipeline["um44Modelview"].Set(ref _Modelview.Top);
_Modelview.IsDirty = false;
}
fixed (float* pData = &data[0])
{
Owner.BindArrayData(pData);
Owner.DrawArrays(PrimitiveType.TriangleStrip, 0, 4);
}
}
public bool IsActive { get; private set; }
public IGL Owner { get; private set; }
VertexLayout VertexLayout;
Pipeline CurrPipeline, DefaultPipeline;
//state cache
Texture2d sTexture;
public readonly string DefaultVertexShader = @"
uniform mat4 um44Modelview, um44Projection;
attribute vec2 aPosition;
attribute vec2 aTexcoord;
varying vec2 vTexcoord0;
void main()
{
vec4 temp = vec4(aPosition,0,1);
gl_Position = um44Projection * (um44Modelview * temp);
vTexcoord0 = aTexcoord;
}";
public readonly string DefaultPixelShader = @"
uniform sampler2D uSampler0;
uniform vec4 uModulateColor;
varying vec2 vTexcoord0;
void main()
{
vec4 temp = texture2D(uSampler0,vTexcoord0);
temp *= uModulateColor;
gl_FragColor = temp;
}";
}
}

View File

@ -0,0 +1,204 @@
using System;
using System.IO;
using sd=System.Drawing;
using swf=System.Windows.Forms;
namespace BizHawk.Bizware.BizwareGL
{
/// <summary>
/// This is a wrapper over hopefully any OpenGL bindings..
/// And possibly, quite possibly, Direct3d.. even though none of your shaders would work. (could use nvidia CG, native dlls in necessary since this would only be for windows)
/// TODO - This really needs to be split up into an internal and a user interface. so many of the functions are made to support the smart wrappers
/// Maybe make a method that returns an interface used for advanced methods (and IGL_TK could implement that as well and just "return this:")
/// </summary>
public interface IGL
{
/// <summary>
/// Returns an a control optimized for drawing onto the screen.
/// </summary>
GraphicsControl CreateGraphicsControl();
/// <summary>
/// Clears the specified buffer parts
/// </summary>
/// <param name="mask"></param>
void Clear(ClearBufferMask mask);
/// <summary>
/// Sets the current clear color
/// </summary>
void ClearColor(sd.Color color);
/// <summary>
/// generates a texture handle
/// </summary>
IntPtr GenTexture();
/// <summary>
/// returns an empty handle
/// </summary>
IntPtr GetEmptyHandle();
/// <summary>
/// returns an empty uniform handle
/// </summary>
IntPtr GetEmptyUniformHandle();
/// <summary>
/// compile a fragment shader. This is the simplified method. A more complex method may be added later which will accept multiple sources and preprocessor definitions independently
/// </summary>
Shader CreateFragmentShader(string source);
/// <summary>
/// compile a vertex shader. This is the simplified method. A more complex method may be added later which will accept multiple sources and preprocessor definitions independently
/// </summary>
Shader CreateVertexShader(string source);
/// <summary>
/// Creates a complete pipeline from the provided vertex and fragment shader handles
/// </summary>
Pipeline CreatePipeline(Shader vertexShader, Shader fragmentShader);
/// <summary>
/// Binds this pipeline as the current used for rendering
/// </summary>
void BindPipeline(Pipeline pipeline);
/// <summary>
/// Sets a uniform sampler to use use the provided texture handle
/// </summary>
void SetPipelineUniformSampler(PipelineUniform uniform, IntPtr texHandle);
/// <summary>
/// Sets a uniform value
/// </summary>
void SetPipelineUniformMatrix(PipelineUniform uniform, Matrix mat, bool transpose);
/// <summary>
/// Sets a uniform value
/// </summary>
void SetPipelineUniformMatrix(PipelineUniform uniform, ref Matrix mat, bool transpose);
/// <summary>
/// sets a uniform value
/// </summary>
void SetPipelineUniform(PipelineUniform uniform, Vector4 value);
/// <summary>
/// Binds this VertexLayout for use in rendering (in OpenGL's case, by glVertexAttribPointer calls)
/// </summary>
void BindVertexLayout(VertexLayout layout);
/// <summary>
/// Binds array data for use with the currently-bound VertexLayout
/// </summary>
unsafe void BindArrayData(void* pData);
/// <summary>
/// Draws based on the currently set VertexLayout and ArrayData
/// </summary>
void DrawArrays(PrimitiveType mode, int first, int count);
/// <summary>
/// Frees the provided shader handle
/// </summary>
void FreeShader(IntPtr shader);
/// <summary>
/// frees the provided texture handle
/// </summary>
void FreeTexture(IntPtr texHandle);
/// <summary>
/// Binds this texture as the current texture2d target for parameter-specification
/// </summary>
/// <param name="texture"></param>
void BindTexture2d(Texture2d texture);
/// <summary>
/// Sets a 2d texture parameter
/// </summary>
void TexParameter2d(TextureParameterName pname, int param);
/// <summary>
/// creates a vertex layout resource
/// </summary>
VertexLayout CreateVertexLayout();
/// <summary>
/// Creates a blending state object
/// </summary>
IBlendState CreateBlendState(BlendingFactor colorSource, BlendEquationMode colorEquation, BlendingFactor colorDest,
BlendingFactor alphaSource, BlendEquationMode alphaEquation, BlendingFactor alphaDest);
/// <summary>
/// retrieves a blend state for opaque rendering
/// Alpha values are copied from the source fragment.
/// </summary>
IBlendState BlendNone { get; }
/// <summary>
/// retrieves a blend state for normal (non-premultiplied) alpha blending.
/// Alpha values are copied from the source fragment.
/// </summary>
IBlendState BlendNormal { get; }
/// <summary>
/// Sets the current blending state object
/// </summary>
void SetBlendState(IBlendState rsBlend);
/// <summary>
/// Creates a texture with the specified dimensions
/// TODO - pass in specifications somehow
/// </summary>
Texture2d CreateTexture(int width, int height);
/// <summary>
/// Loads the texture with new data. This isnt supposed to be especially versatile, it just blasts a bitmap buffer into the texture
/// </summary>
void LoadTextureData(Texture2d tex, BitmapBuffer bmp);
/// <summary>
/// Loads a texture from disk
/// </summary>
Texture2d LoadTexture(string path);
/// <summary>
/// Loads a texture from the stream
/// </summary>
Texture2d LoadTexture(Stream stream);
/// <summary>
/// Loads a texture from the BitmapBuffer
/// </summary>
Texture2d LoadTexture(BitmapBuffer buffer);
/// <summary>
/// Loads a texture from the System.Drawing.Bitmap
/// </summary>
Texture2d LoadTexture(sd.Bitmap bitmap);
/// <summary>
/// sets the viewport according to the provided specifications
/// </summary>
void SetViewport(int x, int y, int width, int height);
/// <summary>
/// sets the viewport according to the client area of the provided control
/// </summary>
void SetViewport(swf.Control control);
/// <summary>
/// generates a proper 2d othographic projection for the given destination size, suitable for use in a GUI
/// </summary>
Matrix CreateGuiProjectionMatrix(int w, int h);
/// <summary>
/// generates a proper view transform for a standard 2d ortho projection, including half-pixel jitter if necessary and
/// re-establishing of a normal 2d graphics top-left origin. suitable for use in a GUI
/// </summary>
Matrix CreateGuiViewMatrix(int w, int h);
}
}

View File

@ -0,0 +1,77 @@
using System;
using System.Collections.Generic;
namespace BizHawk.Bizware.BizwareGL
{
public class MatrixStack
{
public MatrixStack()
{
LoadIdentity();
IsDirty = false;
}
public static implicit operator Matrix(MatrixStack ms) { return ms.Top; }
public static implicit operator MatrixStack(Matrix m) { return new MatrixStack(m); }
public MatrixStack(Matrix matrix) { LoadMatrix(matrix); }
public bool IsDirty;
Stack<Matrix> stack = new Stack<Matrix>();
/// <summary>
/// This is made public for performance reasons, to avoid lame copies of the matrix when necessary. Don't mess it up!
/// </summary>
public Matrix Top;
/// <summary>
/// Resets the matrix stack to an empty identity matrix stack
/// </summary>
public void Clear()
{
stack.Clear();
LoadIdentity();
IsDirty = true;
}
/// <summary>
/// Clears the matrix stack and loads the specified value
/// </summary>
public void Clear(Matrix value)
{
stack.Clear();
Top = value;
IsDirty = true;
}
public void LoadMatrix(Matrix value) { Top = value; IsDirty = true; }
public void LoadIdentity() { Top = Matrix.Identity; IsDirty = true; }
public void Pop() { Top = stack.Pop(); IsDirty = true; }
public void Push() { stack.Push(Top); IsDirty = true; }
public void RotateAxis(Vector3 axisRotation, float angle) { Top = Matrix.CreateFromAxisAngle(axisRotation, angle) * Top; IsDirty = true; }
public void Scale(Vector3 scale) { Top = Matrix.CreateScale(scale) * Top; IsDirty = true; }
public void Scale(Vector2 scale) { Top = Matrix.CreateScale(scale.X, scale.Y, 1) * Top; IsDirty = true; }
public void Scale(float x, float y, float z) { Top = Matrix.CreateScale(x, y, z) * Top; IsDirty = true; }
public void Scale(float ratio) { Scale(ratio, ratio, ratio); IsDirty = true; }
public void Scale(float x, float y) { Scale(x, y, 1); IsDirty = true; }
public void RotateAxis(float x, float y, float z, float degrees) { MultiplyMatrix(Matrix.CreateFromAxisAngle(new Vector3(x, y, z), degrees)); IsDirty = true; }
public void RotateY(float degrees) { MultiplyMatrix(Matrix.CreateRotationY(degrees)); IsDirty = true; }
public void RotateX(float degrees) { MultiplyMatrix(Matrix.CreateRotationX(degrees)); IsDirty = true; }
public void RotateZ(float degrees) { MultiplyMatrix(Matrix.CreateRotationZ(degrees)); IsDirty = true; }
public void Translate(Vector2 v) { Translate(v.X, v.Y, 0); IsDirty = true; }
public void Translate(Vector3 trans) { Top = Matrix.CreateTranslation(trans) * Top; IsDirty = true; }
public void Translate(float x, float y, float z) { Top = Matrix.CreateTranslation(x, y, z) * Top; IsDirty = true; }
public void Translate(float x, float y) { Translate(x, y, 0); IsDirty = true; }
public void Translate(Point pt) { Translate(pt.X, pt.Y, 0); IsDirty = true; }
public void MultiplyMatrix(MatrixStack ms) { MultiplyMatrix(ms.Top); IsDirty = true; }
public void MultiplyMatrix(Matrix value) { Top = value * Top; IsDirty = true; }
}
}

View File

@ -0,0 +1,81 @@
using System;
using System.Collections.Generic;
namespace BizHawk.Bizware.BizwareGL
{
public class Pipeline : IDisposable
{
public Pipeline(IGL owner, IntPtr id, IEnumerable<UniformInfo> uniforms)
{
Owner = owner;
Id = id;
//create the uniforms from the info list we got
UniformsDictionary = new SpecialWorkingDictionary(this);
foreach(var ui in uniforms)
{
UniformsDictionary[ui.Name] = new PipelineUniform(this, ui);
}
}
/// <summary>
/// Allows us to create PipelineUniforms on the fly, in case a non-existing one has been requested.
/// GLSL will optimize out unused uniforms, and we wont have a record of it in the uniforms population loop
/// </summary>
class SpecialWorkingDictionary : Dictionary<string, PipelineUniform>
{
public SpecialWorkingDictionary(Pipeline owner)
{
Owner = owner;
}
Pipeline Owner;
public new PipelineUniform this[string key]
{
get
{
PipelineUniform temp;
if (!TryGetValue(key, out temp))
{
var ui = new UniformInfo();
ui.Handle = Owner.Owner.GetEmptyUniformHandle();
temp = this[key] = new PipelineUniform(Owner,ui);
}
return temp;
}
internal set
{
base[key] = value;
}
}
}
SpecialWorkingDictionary UniformsDictionary;
IDictionary<string, PipelineUniform> Uniforms { get { return UniformsDictionary; } }
public PipelineUniform this[string key]
{
get { return UniformsDictionary[key]; }
}
public IGL Owner { get; private set; }
public IntPtr Id { get; private set; }
///// <summary>
///// Makes the pipeline current
///// </summary>
//public void BindData()
//{
// Owner.BindPipeline(this);
//}
public void Dispose()
{
//todo
}
}
}

View File

@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
namespace BizHawk.Bizware.BizwareGL
{
public class PipelineUniform
{
internal PipelineUniform(Pipeline owner, UniformInfo info)
{
Owner = owner;
Id = info.Handle;
SamplerIndex = info.SamplerIndex;
}
public Pipeline Owner { get; private set; }
public IntPtr Id { get; private set; }
public int SamplerIndex { get; private set; }
public void Set(Matrix mat, bool transpose = false)
{
Owner.Owner.SetPipelineUniformMatrix(this, mat, transpose);
}
public void Set(Vector4 vec, bool transpose = false)
{
Owner.Owner.SetPipelineUniform(this, vec);
}
public void Set(ref Matrix mat, bool transpose = false)
{
Owner.Owner.SetPipelineUniformMatrix(this, ref mat, transpose);
}
public void Set(Texture2d tex)
{
Owner.Owner.SetPipelineUniformSampler(this, tex.Id);
}
}
}

View File

@ -0,0 +1,7 @@
using System;
using System.Collections.Generic;
namespace BizHawk.Bizware.BizwareGL
{
public interface IBlendState { }
}

View File

@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
namespace BizHawk.Bizware.BizwareGL
{
/// <summary>
/// Just a lifecycle-managed wrapper around shader handles
/// </summary>
public class Shader : IDisposable
{
public Shader(IGL owner, IntPtr id)
{
Owner = owner;
Id = id;
}
public IGL Owner { get; private set; }
public IntPtr Id { get; private set; }
public bool Disposed { get; private set; }
public void Dispose()
{
if (Disposed) return;
Disposed = true;
Owner.FreeShader(Id);
Id = Owner.GetEmptyHandle();
}
}
}

View File

@ -0,0 +1,80 @@
//http://www.angelcode.com/products/bmfont/
//http://cyotek.com/blog/angelcode-bitmap-font-parsing-using-csharp
using System;
using sd=System.Drawing;
using System.Collections.Generic;
using System.IO;
namespace BizHawk.Bizware.BizwareGL
{
public class StringRenderer : IDisposable
{
public StringRenderer(IGL owner, Stream xml, params Stream[] textures)
{
Owner = owner;
FontInfo = Cyotek.Drawing.BitmapFont.BitmapFontLoader.LoadFontFromXmlFile(xml);
//load textures
for(int i=0;i<FontInfo.Pages.Length;i++)
{
TexturePages.Add(owner.LoadTexture(textures[i]));
}
}
public void Dispose()
{
foreach (var tex in TexturePages)
tex.Dispose();
TexturePages = null;
}
public sd.SizeF Measure(string str)
{
float x = 0;
int len = str.Length;
for (int i = 0; i < len; i++)
{
Cyotek.Drawing.BitmapFont.Character c;
if (!FontInfo.Characters.TryGetValue(str[i], out c))
c = FontInfo.Characters[unchecked((char)-1)];
x += c.XAdvance;
}
return new sd.SizeF(x, FontInfo.LineHeight);
}
public void RenderString(GuiRenderer renderer, float x, float y, string str)
{
int len = str.Length;
for (int i = 0; i < len; i++)
{
Cyotek.Drawing.BitmapFont.Character c;
if (!FontInfo.Characters.TryGetValue(str[i], out c))
c = FontInfo.Characters[unchecked((char)-1)];
//calculate texcoords (we shouldve already had this cached, but im speedcoding now)
Texture2d tex = TexturePages[c.TexturePage];
float w = tex.Width;
float h = tex.Height;
float u0 = c.Bounds.Left / w;
float v0 = c.Bounds.Top / h;
float u1 = c.Bounds.Right / w;
float v1 = c.Bounds.Bottom / h;
float gx = x + c.Offset.X;
float gy = y + c.Offset.Y;
renderer.DrawSubrect(tex, gx, gy, c.Bounds.Width, c.Bounds.Height, u0, v0, u1, v1);
x += c.XAdvance;
}
}
public IGL Owner { get; private set; }
Cyotek.Drawing.BitmapFont.BitmapFont FontInfo;
List<Texture2d> TexturePages = new List<Texture2d>();
}
}

View File

@ -0,0 +1,325 @@
using System;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using System.Drawing;
namespace BizHawk.Bizware.BizwareGL
{
public class TexAtlas
{
public class RectItem
{
public RectItem(int width, int height, object item)
{
Width = width;
Height = height;
Item = item;
}
public int X, Y;
public int Width, Height;
public int TexIndex;
public object Item;
}
class TryFitParam
{
public TryFitParam(int _w, int _h) { this.w = _w; this.h = _h; }
public int w, h;
public bool ok = true;
public RectangleBinPack rbp = new RectangleBinPack();
public List<RectangleBinPack.Node> nodes = new List<RectangleBinPack.Node>();
}
public class PackedAtlasResults
{
public class SingleAtlas
{
public Size Size;
public List<RectItem> Items;
}
public List<SingleAtlas> Atlases = new List<SingleAtlas>();
}
public static int MaxSizeBits = 16;
/// <summary>
/// packs the supplied RectItems into an atlas. Modifies the RectItems with x/y values of location in new atlas.
/// </summary>
public static PackedAtlasResults PackAtlas(IEnumerable<RectItem> items)
{
PackedAtlasResults ret = new PackedAtlasResults();
ret.Atlases.Add(new PackedAtlasResults.SingleAtlas());
//initially, we'll try all the items; none remain
List<RectItem> currentItems = new List<RectItem>(items);
List<RectItem> remainItems = new List<RectItem>();
RETRY:
//this is where the texture size range is determined.
//we run this every time we make an atlas, in case we want to variably control the maximum texture output size.
//ALSO - we accumulate data in there, so we need to refresh it each time. ... lame.
List<TryFitParam> todoSizes = new List<TryFitParam>();
for (int i = 3; i <= MaxSizeBits; i++)
{
for (int j = 3; j <= MaxSizeBits; j++)
{
int w = 1 << i;
int h = 1 << j;
TryFitParam tfp = new TryFitParam(w, h);
todoSizes.Add(tfp);
}
}
//run the packing algorithm on each potential size
Parallel.ForEach(todoSizes, (param) =>
{
var rbp = new RectangleBinPack();
rbp.Init(16384, 16384);
param.rbp.Init(param.w, param.h);
foreach (var ri in currentItems)
{
RectangleBinPack.Node node = param.rbp.Insert(ri.Width, ri.Height);
if (node == null)
{
param.ok = false;
}
else
{
node.ri = ri;
param.nodes.Add(node);
}
}
});
//find the best fit among the potential sizes that worked
long best = long.MaxValue;
TryFitParam tfpFinal = null;
foreach (TryFitParam tfp in todoSizes)
{
if (tfp.ok)
{
long area = (long)tfp.w * (long)tfp.h;
long perimeter = (long)tfp.w + (long)tfp.h;
if (area < best)
{
best = area;
tfpFinal = tfp;
}
else if (area == best)
{
//try to minimize perimeter (to create squares, which are nicer to look at)
if (tfpFinal == null)
{ }
else if (perimeter < tfpFinal.w + tfpFinal.h)
{
best = area;
tfpFinal = tfp;
}
}
}
}
//did we find any fit?
if (best == long.MaxValue)
{
//nope - move an item to the remaining list and try again
remainItems.Add(currentItems[currentItems.Count - 1]);
currentItems.RemoveAt(currentItems.Count - 1);
goto RETRY;
}
//we found a fit. setup this atlas in the result and drop the items into it
var atlas = ret.Atlases[ret.Atlases.Count - 1];
atlas.Size.Width = tfpFinal.w;
atlas.Size.Height = tfpFinal.h;
atlas.Items = new List<RectItem>(items);
foreach (var item in currentItems)
{
object o = item.Item;
var node = tfpFinal.nodes.Find((x) => x.ri == item);
item.X = node.x;
item.Y = node.y;
item.TexIndex = ret.Atlases.Count - 1;
}
//if we have any items left, we've got to run this again
if (remainItems.Count > 0)
{
//move all remaining items into the clear list
currentItems.Clear();
currentItems.AddRange(remainItems);
remainItems.Clear();
ret.Atlases.Add(new PackedAtlasResults.SingleAtlas());
goto RETRY;
}
if (ret.Atlases.Count > 1)
Console.WriteLine("Created animset with >1 texture ({0} textures)", ret.Atlases.Count);
return ret;
}
//original file: RectangleBinPack.cpp
//author: Jukka Jylänki
class RectangleBinPack
{
/** A node of a binary tree. Each node represents a rectangular area of the texture
we surface. Internal nodes store rectangles of used data, whereas leaf nodes track
rectangles of free space. All the rectangles stored in the tree are disjoint. */
public class Node
{
// Left and right child. We don't really distinguish which is which, so these could
// as well be child1 and child2.
public Node left;
public Node right;
// The top-left coordinate of the rectangle.
public int x;
public int y;
// The dimension of the rectangle.
public int width;
public int height;
public RectItem ri;
};
/// Starts a new packing process to a bin of the given dimension.
public void Init(int width, int height)
{
binWidth = width;
binHeight = height;
root = new Node();
root.left = root.right = null;
root.x = root.y = 0;
root.width = width;
root.height = height;
}
/// Inserts a new rectangle of the given size into the bin.
/** Running time is linear to the number of rectangles that have been already packed.
@return A pointer to the node that stores the newly added rectangle, or 0
if it didn't fit. */
public Node Insert(int width, int height)
{
return Insert(root, width, height);
}
/// Computes the ratio of used surface area.
float Occupancy()
{
int totalSurfaceArea = binWidth * binHeight;
int usedSurfaceArea = UsedSurfaceArea(root);
return (float)usedSurfaceArea / totalSurfaceArea;
}
private Node root;
// The total size of the bin we started with.
private int binWidth;
private int binHeight;
/// @return The surface area used by the subtree rooted at node.
private int UsedSurfaceArea(Node node)
{
if (node.left != null || node.right != null)
{
int usedSurfaceArea = node.width * node.height;
if (node.left != null)
usedSurfaceArea += UsedSurfaceArea(node.left);
if (node.right != null)
usedSurfaceArea += UsedSurfaceArea(node.right);
return usedSurfaceArea;
}
// This is a leaf node, it doesn't constitute to the total surface area.
return 0;
}
/// Inserts a new rectangle in the subtree rooted at the given node.
private Node Insert(Node node, int width, int height)
{
// If this node is an internal node, try both leaves for possible space.
// (The rectangle in an internal node stores used space, the leaves store free space)
if (node.left != null || node.right != null)
{
if (node.left != null)
{
Node newNode = Insert(node.left, width, height);
if (newNode != null)
return newNode;
}
if (node.right != null)
{
Node newNode = Insert(node.right, width, height);
if (newNode != null)
return newNode;
}
return null; // Didn't fit into either subtree!
}
// This node is a leaf, but can we fit the new rectangle here?
if (width > node.width || height > node.height)
return null; // Too bad, no space.
// The new cell will fit, split the remaining space along the shorter axis,
// that is probably more optimal.
int w = node.width - width;
int h = node.height - height;
node.left = new Node();
node.right = new Node();
if (w <= h) // Split the remaining space in horizontal direction.
{
node.left.x = node.x + width;
node.left.y = node.y;
node.left.width = w;
node.left.height = height;
node.right.x = node.x;
node.right.y = node.y + height;
node.right.width = node.width;
node.right.height = h;
}
else // Split the remaining space in vertical direction.
{
node.left.x = node.x;
node.left.y = node.y + height;
node.left.width = width;
node.left.height = h;
node.right.x = node.x + width;
node.right.y = node.y;
node.right.width = w;
node.right.height = node.height;
}
// Note that as a result of the above, it can happen that node.left or node.right
// is now a degenerate (zero area) rectangle. No need to do anything about it,
// like remove the nodes as "unnecessary" since they need to exist as children of
// this node (this node can't be a leaf anymore).
// This node is now a non-leaf, so shrink its area - it now denotes
// *occupied* space instead of free space. Its children spawn the resulting
// area of free space.
node.width = width;
node.height = height;
return node;
}
};
}
}

View File

@ -0,0 +1,82 @@
using System;
namespace BizHawk.Bizware.BizwareGL
{
/// <summary>
/// A full-scale 2D texture, with mip levels and everything.
/// In OpenGL tradition, this encapsulates the sampler state, as well, which is equal parts annoying and convenient
/// </summary>
public class Texture2d : IDisposable
{
//not sure if I need this idea.
//public class Maker
//{
// public Maker(Texture2d tex)
// {
// MyTexture = tex;
// }
// public void SetWidth(int width)
// {
// MyTexture.Width = width;
// }
// public void SetHeight(int width)
// {
// MyTexture.Height = height;
// }
// Texture2d MyTexture;
//}
public void Dispose()
{
Owner.FreeTexture(Id);
Id = Owner.GetEmptyHandle();
}
public Texture2d(IGL owner, IntPtr id, int width, int height)
{
Owner = owner;
Id = id;
Width = width;
Height = height;
}
public void LoadFrom(BitmapBuffer buffer)
{
}
public void SetMinFilter(TextureMinFilter minFilter)
{
Owner.BindTexture2d(this);
Owner.TexParameter2d(TextureParameterName.TextureMinFilter, (int)minFilter);
}
public void SetMagFilter(TextureMagFilter magFilter)
{
Owner.BindTexture2d(this);
Owner.TexParameter2d(TextureParameterName.TextureMagFilter, (int)magFilter);
}
public void SetFilterLinear()
{
SetMinFilter(TextureMinFilter.Linear);
SetMagFilter(TextureMagFilter.Linear);
}
public void SetFilterNearest()
{
SetMinFilter(TextureMinFilter.Nearest);
SetMagFilter(TextureMagFilter.Nearest);
}
public IGL Owner { get; private set; }
public IntPtr Id { get; private set; }
//note.. it is commonly helpful to have these as floats, since we're more often using them for rendering than for raster logic
public float Width { get; private set; }
public float Height { get; private set; }
public int IntWidth { get { return (int)Width; } }
public int IntHeight { get { return (int)Height; } }
}
}

View File

@ -0,0 +1,426 @@
#region License
/*
MIT License
Copyright © 2006 The Mono.Xna Team
All rights reserved.
Authors:
Olivier Dufour (Duff)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#endregion License
using System;
using System.Collections.Generic;
using System.ComponentModel;
namespace BizHawk.Bizware.BizwareGL
{
public struct BoundingBox : IEquatable<BoundingBox>
{
#region Public Fields
public Vector3 Min;
public Vector3 Max;
public const int CornerCount = 8;
#endregion Public Fields
#region Public Constructors
public BoundingBox(Vector3 min, Vector3 max)
{
this.Min = min;
this.Max = max;
}
#endregion Public Constructors
#region Public Methods
public ContainmentType Contains(BoundingBox box)
{
//test if all corner is in the same side of a face by just checking min and max
if (box.Max.X < Min.X
|| box.Min.X > Max.X
|| box.Max.Y < Min.Y
|| box.Min.Y > Max.Y
|| box.Max.Z < Min.Z
|| box.Min.Z > Max.Z)
return ContainmentType.Disjoint;
if (box.Min.X >= Min.X
&& box.Max.X <= Max.X
&& box.Min.Y >= Min.Y
&& box.Max.Y <= Max.Y
&& box.Min.Z >= Min.Z
&& box.Max.Z <= Max.Z)
return ContainmentType.Contains;
return ContainmentType.Intersects;
}
public void Contains(ref BoundingBox box, out ContainmentType result)
{
result = Contains(box);
}
public ContainmentType Contains(BoundingFrustum frustum)
{
//TODO: bad done here need a fix.
//Because question is not frustum contain box but reverse and this is not the same
int i;
ContainmentType contained;
Vector3[] corners = frustum.GetCorners();
// First we check if frustum is in box
for (i = 0; i < corners.Length; i++)
{
this.Contains(ref corners[i], out contained);
if (contained == ContainmentType.Disjoint)
break;
}
if (i == corners.Length) // This means we checked all the corners and they were all contain or instersect
return ContainmentType.Contains;
if (i != 0) // if i is not equal to zero, we can fastpath and say that this box intersects
return ContainmentType.Intersects;
// If we get here, it means the first (and only) point we checked was actually contained in the frustum.
// So we assume that all other points will also be contained. If one of the points is disjoint, we can
// exit immediately saying that the result is Intersects
i++;
for (; i < corners.Length; i++)
{
this.Contains(ref corners[i], out contained);
if (contained != ContainmentType.Contains)
return ContainmentType.Intersects;
}
// If we get here, then we know all the points were actually contained, therefore result is Contains
return ContainmentType.Contains;
}
public ContainmentType Contains(BoundingSphere sphere)
{
if (sphere.Center.X - Min.X > sphere.Radius
&& sphere.Center.Y - Min.Y > sphere.Radius
&& sphere.Center.Z - Min.Z > sphere.Radius
&& Max.X - sphere.Center.X > sphere.Radius
&& Max.Y - sphere.Center.Y > sphere.Radius
&& Max.Z - sphere.Center.Z > sphere.Radius)
return ContainmentType.Contains;
double dmin = 0;
if (sphere.Center.X - Min.X <= sphere.Radius)
dmin += (sphere.Center.X - Min.X) * (sphere.Center.X - Min.X);
else if (Max.X - sphere.Center.X <= sphere.Radius)
dmin += (sphere.Center.X - Max.X) * (sphere.Center.X - Max.X);
if (sphere.Center.Y - Min.Y <= sphere.Radius)
dmin += (sphere.Center.Y - Min.Y) * (sphere.Center.Y - Min.Y);
else if (Max.Y - sphere.Center.Y <= sphere.Radius)
dmin += (sphere.Center.Y - Max.Y) * (sphere.Center.Y - Max.Y);
if (sphere.Center.Z - Min.Z <= sphere.Radius)
dmin += (sphere.Center.Z - Min.Z) * (sphere.Center.Z - Min.Z);
else if (Max.Z - sphere.Center.Z <= sphere.Radius)
dmin += (sphere.Center.Z - Max.Z) * (sphere.Center.Z - Max.Z);
if (dmin <= sphere.Radius * sphere.Radius)
return ContainmentType.Intersects;
return ContainmentType.Disjoint;
}
public void Contains(ref BoundingSphere sphere, out ContainmentType result)
{
result = this.Contains(sphere);
}
public ContainmentType Contains(Vector3 point)
{
ContainmentType result;
this.Contains(ref point, out result);
return result;
}
public void Contains(ref Vector3 point, out ContainmentType result)
{
//first we get if point is out of box
if (point.X < this.Min.X
|| point.X > this.Max.X
|| point.Y < this.Min.Y
|| point.Y > this.Max.Y
|| point.Z < this.Min.Z
|| point.Z > this.Max.Z)
{
result = ContainmentType.Disjoint;
}//or if point is on box because coordonate of point is lesser or equal
else if (point.X == this.Min.X
|| point.X == this.Max.X
|| point.Y == this.Min.Y
|| point.Y == this.Max.Y
|| point.Z == this.Min.Z
|| point.Z == this.Max.Z)
result = ContainmentType.Intersects;
else
result = ContainmentType.Contains;
}
public static BoundingBox CreateFromPoints(IEnumerable<Vector3> points)
{
if (points == null)
throw new ArgumentNullException();
// TODO: Just check that Count > 0
bool empty = true;
Vector3 vector2 = new Vector3(float.MaxValue);
Vector3 vector1 = new Vector3(float.MinValue);
foreach (Vector3 vector3 in points)
{
vector2 = Vector3.Min(vector2, vector3);
vector1 = Vector3.Max(vector1, vector3);
empty = false;
}
if (empty)
throw new ArgumentException();
return new BoundingBox(vector2, vector1);
}
public static BoundingBox CreateFromSphere(BoundingSphere sphere)
{
Vector3 vector1 = new Vector3(sphere.Radius);
return new BoundingBox(sphere.Center - vector1, sphere.Center + vector1);
}
public static void CreateFromSphere(ref BoundingSphere sphere, out BoundingBox result)
{
result = BoundingBox.CreateFromSphere(sphere);
}
public static BoundingBox CreateMerged(BoundingBox original, BoundingBox additional)
{
return new BoundingBox(
Vector3.Min(original.Min, additional.Min), Vector3.Max(original.Max, additional.Max));
}
public static void CreateMerged(ref BoundingBox original, ref BoundingBox additional, out BoundingBox result)
{
result = BoundingBox.CreateMerged(original, additional);
}
public bool Equals(BoundingBox other)
{
return (this.Min == other.Min) && (this.Max == other.Max);
}
public override bool Equals(object obj)
{
return (obj is BoundingBox) ? this.Equals((BoundingBox)obj) : false;
}
public Vector3[] GetCorners()
{
return new Vector3[] {
new Vector3(this.Min.X, this.Max.Y, this.Max.Z),
new Vector3(this.Max.X, this.Max.Y, this.Max.Z),
new Vector3(this.Max.X, this.Min.Y, this.Max.Z),
new Vector3(this.Min.X, this.Min.Y, this.Max.Z),
new Vector3(this.Min.X, this.Max.Y, this.Min.Z),
new Vector3(this.Max.X, this.Max.Y, this.Min.Z),
new Vector3(this.Max.X, this.Min.Y, this.Min.Z),
new Vector3(this.Min.X, this.Min.Y, this.Min.Z)
};
}
public void GetCorners(Vector3[] corners)
{
if (corners == null)
{
throw new ArgumentNullException("corners");
}
if (corners.Length < 8)
{
throw new ArgumentOutOfRangeException("corners", "Not Enought Corners");
}
corners[0].X = this.Min.X;
corners[0].Y = this.Max.Y;
corners[0].Z = this.Max.Z;
corners[1].X = this.Max.X;
corners[1].Y = this.Max.Y;
corners[1].Z = this.Max.Z;
corners[2].X = this.Max.X;
corners[2].Y = this.Min.Y;
corners[2].Z = this.Max.Z;
corners[3].X = this.Min.X;
corners[3].Y = this.Min.Y;
corners[3].Z = this.Max.Z;
corners[4].X = this.Min.X;
corners[4].Y = this.Max.Y;
corners[4].Z = this.Min.Z;
corners[5].X = this.Max.X;
corners[5].Y = this.Max.Y;
corners[5].Z = this.Min.Z;
corners[6].X = this.Max.X;
corners[6].Y = this.Min.Y;
corners[6].Z = this.Min.Z;
corners[7].X = this.Min.X;
corners[7].Y = this.Min.Y;
corners[7].Z = this.Min.Z;
}
public override int GetHashCode()
{
return this.Min.GetHashCode() + this.Max.GetHashCode();
}
public bool Intersects(BoundingBox box)
{
bool result;
Intersects(ref box, out result);
return result;
}
public void Intersects(ref BoundingBox box, out bool result)
{
if ((this.Max.X >= box.Min.X) && (this.Min.X <= box.Max.X))
{
if ((this.Max.Y < box.Min.Y) || (this.Min.Y > box.Max.Y))
{
result = false;
return;
}
result = (this.Max.Z >= box.Min.Z) && (this.Min.Z <= box.Max.Z);
return;
}
result = false;
return;
}
public bool Intersects(BoundingFrustum frustum)
{
return frustum.Intersects(this);
}
public bool Intersects(BoundingSphere sphere)
{
if (sphere.Center.X - Min.X > sphere.Radius
&& sphere.Center.Y - Min.Y > sphere.Radius
&& sphere.Center.Z - Min.Z > sphere.Radius
&& Max.X - sphere.Center.X > sphere.Radius
&& Max.Y - sphere.Center.Y > sphere.Radius
&& Max.Z - sphere.Center.Z > sphere.Radius)
return true;
double dmin = 0;
if (sphere.Center.X - Min.X <= sphere.Radius)
dmin += (sphere.Center.X - Min.X) * (sphere.Center.X - Min.X);
else if (Max.X - sphere.Center.X <= sphere.Radius)
dmin += (sphere.Center.X - Max.X) * (sphere.Center.X - Max.X);
if (sphere.Center.Y - Min.Y <= sphere.Radius)
dmin += (sphere.Center.Y - Min.Y) * (sphere.Center.Y - Min.Y);
else if (Max.Y - sphere.Center.Y <= sphere.Radius)
dmin += (sphere.Center.Y - Max.Y) * (sphere.Center.Y - Max.Y);
if (sphere.Center.Z - Min.Z <= sphere.Radius)
dmin += (sphere.Center.Z - Min.Z) * (sphere.Center.Z - Min.Z);
else if (Max.Z - sphere.Center.Z <= sphere.Radius)
dmin += (sphere.Center.Z - Max.Z) * (sphere.Center.Z - Max.Z);
if (dmin <= sphere.Radius * sphere.Radius)
return true;
return false;
}
public void Intersects(ref BoundingSphere sphere, out bool result)
{
result = Intersects(sphere);
}
public PlaneIntersectionType Intersects(Plane plane)
{
//check all corner side of plane
Vector3[] corners = this.GetCorners();
float lastdistance = Vector3.Dot(plane.Normal, corners[0]) + plane.D;
for (int i = 1; i < corners.Length; i++)
{
float distance = Vector3.Dot(plane.Normal, corners[i]) + plane.D;
if ((distance <= 0.0f && lastdistance > 0.0f) || (distance >= 0.0f && lastdistance < 0.0f))
return PlaneIntersectionType.Intersecting;
lastdistance = distance;
}
if (lastdistance > 0.0f)
return PlaneIntersectionType.Front;
return PlaneIntersectionType.Back;
}
public void Intersects(ref Plane plane, out PlaneIntersectionType result)
{
result = Intersects(plane);
}
public Nullable<float> Intersects(Ray ray)
{
return ray.Intersects(this);
}
public void Intersects(ref Ray ray, out Nullable<float> result)
{
result = Intersects(ray);
}
public static bool operator ==(BoundingBox a, BoundingBox b)
{
return a.Equals(b);
}
public static bool operator !=(BoundingBox a, BoundingBox b)
{
return !a.Equals(b);
}
public override string ToString()
{
return string.Format("{{Min:{0} Max:{1}}}", this.Min.ToString(), this.Max.ToString());
}
#endregion Public Methods
}
}

View File

@ -0,0 +1,513 @@
#region License
/*
MIT License
Copyright © 2006 The Mono.Xna Team
All rights reserved.
Authors:
Olivier Dufour (Duff)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#endregion License
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Text;
namespace BizHawk.Bizware.BizwareGL
{
[Serializable, TypeConverter(typeof(ExpandableObjectConverter))]
public class BoundingFrustum : IEquatable<BoundingFrustum>
{
#region Private Fields
private Matrix matrix;
private Plane bottom;
private Plane far;
private Plane left;
private Plane right;
private Plane near;
private Plane top;
private Vector3[] corners;
#endregion Private Fields
#region Public Fields
public const int CornerCount = 8;
#endregion
#region Public Constructors
public BoundingFrustum(Matrix value)
{
this.matrix = value;
CreatePlanes();
CreateCorners();
}
#endregion Public Constructors
#region Public Properties
public Plane Bottom
{
get { return this.bottom; }
}
public Plane Far
{
get { return this.far; }
}
public Plane Left
{
get { return this.left; }
}
public Matrix Matrix
{
get { return this.matrix; }
set
{
this.matrix = value;
this.CreatePlanes(); // FIXME: The odds are the planes will be used a lot more often than the matrix
this.CreateCorners(); // is updated, so this should help performance. I hope ;)
}
}
public Plane Near
{
get { return this.near; }
}
public Plane Right
{
get { return this.right; }
}
public Plane Top
{
get { return this.top; }
}
#endregion Public Properties
#region Public Methods
public static bool operator ==(BoundingFrustum a, BoundingFrustum b)
{
if (object.Equals(a, null))
return (object.Equals(b, null));
if (object.Equals(b, null))
return (object.Equals(a, null));
return a.matrix == (b.matrix);
}
public static bool operator !=(BoundingFrustum a, BoundingFrustum b)
{
return !(a == b);
}
public ContainmentType Contains(BoundingBox box)
{
ContainmentType result;
this.Contains(ref box, out result);
return result;
}
public void GetCorners(Vector3[] corners)
{
throw new NotImplementedException();
}
public void Contains(ref BoundingBox box, out ContainmentType result)
{
// FIXME: Is this a bug?
// If the bounding box is of W * D * H = 0, then return disjoint
if (box.Min == box.Max)
{
result = ContainmentType.Disjoint;
return;
}
int i;
ContainmentType contained;
Vector3[] corners = box.GetCorners();
// First we assume completely disjoint. So if we find a point that is contained, we break out of this loop
for (i = 0; i < corners.Length; i++)
{
this.Contains(ref corners[i], out contained);
if (contained != ContainmentType.Disjoint)
break;
}
if (i == corners.Length) // This means we checked all the corners and they were all disjoint
{
result = ContainmentType.Disjoint;
return;
}
if (i != 0) // if i is not equal to zero, we can fastpath and say that this box intersects
{ // because we know at least one point is outside and one is inside.
result = ContainmentType.Intersects;
return;
}
// If we get here, it means the first (and only) point we checked was actually contained in the frustum.
// So we assume that all other points will also be contained. If one of the points is disjoint, we can
// exit immediately saying that the result is Intersects
i++;
for (; i < corners.Length; i++)
{
this.Contains(ref corners[i], out contained);
if (contained != ContainmentType.Contains)
{
result = ContainmentType.Intersects;
return;
}
}
// If we get here, then we know all the points were actually contained, therefore result is Contains
result = ContainmentType.Contains;
return;
}
// TODO: Implement this
public ContainmentType Contains(BoundingFrustum frustum)
{
if (this == frustum) // We check to see if the two frustums are equal
return ContainmentType.Contains;// If they are, there's no need to go any further.
throw new NotImplementedException();
}
public ContainmentType Contains(BoundingSphere sphere)
{
ContainmentType result;
this.Contains(ref sphere, out result);
return result;
}
public void Contains(ref BoundingSphere sphere, out ContainmentType result)
{
float val;
ContainmentType contained;
// We first check if the sphere is inside the frustum
this.Contains(ref sphere.Center, out contained);
// The sphere is inside. Now we need to check if it's fully contained or not
// So we see if the perpendicular distance to each plane is less than or equal to the sphere's radius.
// If the perpendicular distance is less, just return Intersects.
if (contained == ContainmentType.Contains)
{
val = PlaneHelper.PerpendicularDistance(ref sphere.Center, ref this.bottom);
if (val < sphere.Radius)
{
result = ContainmentType.Intersects;
return;
}
val = PlaneHelper.PerpendicularDistance(ref sphere.Center, ref this.far);
if (val < sphere.Radius)
{
result = ContainmentType.Intersects;
return;
}
val = PlaneHelper.PerpendicularDistance(ref sphere.Center, ref this.left);
if (val < sphere.Radius)
{
result = ContainmentType.Intersects;
return;
}
val = PlaneHelper.PerpendicularDistance(ref sphere.Center, ref this.near);
if (val < sphere.Radius)
{
result = ContainmentType.Intersects;
return;
}
val = PlaneHelper.PerpendicularDistance(ref sphere.Center, ref this.right);
if (val < sphere.Radius)
{
result = ContainmentType.Intersects;
return;
}
val = PlaneHelper.PerpendicularDistance(ref sphere.Center, ref this.top);
if (val < sphere.Radius)
{
result = ContainmentType.Intersects;
return;
}
// If we get here, the sphere is fully contained
result = ContainmentType.Contains;
return;
}
//duff idea : test if all corner is in same side of a plane if yes and outside it is disjoint else intersect
// issue is that we can have some times when really close aabb
// If we're here, the the sphere's centre was outside of the frustum. This makes things hard :(
// We can't use perpendicular distance anymore. I'm not sure how to code this.
throw new NotImplementedException();
}
public ContainmentType Contains(Vector3 point)
{
ContainmentType result;
this.Contains(ref point, out result);
return result;
}
public void Contains(ref Vector3 point, out ContainmentType result)
{
float val;
// If a point is on the POSITIVE side of the plane, then the point is not contained within the frustum
// Check the top
val = PlaneHelper.ClassifyPoint(ref point, ref this.top);
if (val > 0)
{
result = ContainmentType.Disjoint;
return;
}
// Check the bottom
val = PlaneHelper.ClassifyPoint(ref point, ref this.bottom);
if (val > 0)
{
result = ContainmentType.Disjoint;
return;
}
// Check the left
val = PlaneHelper.ClassifyPoint(ref point, ref this.left);
if (val > 0)
{
result = ContainmentType.Disjoint;
return;
}
// Check the right
val = PlaneHelper.ClassifyPoint(ref point, ref this.right);
if (val > 0)
{
result = ContainmentType.Disjoint;
return;
}
// Check the near
val = PlaneHelper.ClassifyPoint(ref point, ref this.near);
if (val > 0)
{
result = ContainmentType.Disjoint;
return;
}
// Check the far
val = PlaneHelper.ClassifyPoint(ref point, ref this.far);
if (val > 0)
{
result = ContainmentType.Disjoint;
return;
}
// If we get here, it means that the point was on the correct side of each plane to be
// contained. Therefore this point is contained
result = ContainmentType.Contains;
}
public bool Equals(BoundingFrustum other)
{
return (this == other);
}
public override bool Equals(object obj)
{
BoundingFrustum f = obj as BoundingFrustum;
return (object.Equals(f, null)) ? false : (this == f);
}
public Vector3[] GetCorners()
{
return corners;
}
public override int GetHashCode()
{
return this.matrix.GetHashCode();
}
public bool Intersects(BoundingBox box)
{
throw new NotImplementedException();
}
public void Intersects(ref BoundingBox box, out bool result)
{
throw new NotImplementedException();
}
public bool Intersects(BoundingFrustum frustum)
{
throw new NotImplementedException();
}
public bool Intersects(BoundingSphere sphere)
{
throw new NotImplementedException();
}
public void Intersects(ref BoundingSphere sphere, out bool result)
{
throw new NotImplementedException();
}
public PlaneIntersectionType Intersects(Plane plane)
{
throw new NotImplementedException();
}
public void Intersects(ref Plane plane, out PlaneIntersectionType result)
{
throw new NotImplementedException();
}
public Nullable<float> Intersects(Ray ray)
{
throw new NotImplementedException();
}
public void Intersects(ref Ray ray, out Nullable<float> result)
{
throw new NotImplementedException();
}
public override string ToString()
{
StringBuilder sb = new StringBuilder(256);
sb.Append("{Near:");
sb.Append(this.near.ToString());
sb.Append(" Far:");
sb.Append(this.far.ToString());
sb.Append(" Left:");
sb.Append(this.left.ToString());
sb.Append(" Right:");
sb.Append(this.right.ToString());
sb.Append(" Top:");
sb.Append(this.top.ToString());
sb.Append(" Bottom:");
sb.Append(this.bottom.ToString());
sb.Append("}");
return sb.ToString();
}
#endregion Public Methods
#region Private Methods
private void CreateCorners()
{
this.corners = new Vector3[8];
this.corners[0] = IntersectionPoint(ref this.near, ref this.left, ref this.top);
this.corners[1] = IntersectionPoint(ref this.near, ref this.right, ref this.top);
this.corners[2] = IntersectionPoint(ref this.near, ref this.right, ref this.bottom);
this.corners[3] = IntersectionPoint(ref this.near, ref this.left, ref this.bottom);
this.corners[4] = IntersectionPoint(ref this.far, ref this.left, ref this.top);
this.corners[5] = IntersectionPoint(ref this.far, ref this.right, ref this.top);
this.corners[6] = IntersectionPoint(ref this.far, ref this.right, ref this.bottom);
this.corners[7] = IntersectionPoint(ref this.far, ref this.left, ref this.bottom);
}
private void CreatePlanes()
{
// Pre-calculate the different planes needed
this.left = new Plane(-this.matrix.M14 - this.matrix.M11, -this.matrix.M24 - this.matrix.M21,
-this.matrix.M34 - this.matrix.M31, -this.matrix.M44 - this.matrix.M41);
this.right = new Plane(this.matrix.M11 - this.matrix.M14, this.matrix.M21 - this.matrix.M24,
this.matrix.M31 - this.matrix.M34, this.matrix.M41 - this.matrix.M44);
this.top = new Plane(this.matrix.M12 - this.matrix.M14, this.matrix.M22 - this.matrix.M24,
this.matrix.M32 - this.matrix.M34, this.matrix.M42 - this.matrix.M44);
this.bottom = new Plane(-this.matrix.M14 - this.matrix.M12, -this.matrix.M24 - this.matrix.M22,
-this.matrix.M34 - this.matrix.M32, -this.matrix.M44 - this.matrix.M42);
this.near = new Plane(-this.matrix.M13, -this.matrix.M23, -this.matrix.M33, -this.matrix.M43);
this.far = new Plane(this.matrix.M13 - this.matrix.M14, this.matrix.M23 - this.matrix.M24,
this.matrix.M33 - this.matrix.M34, this.matrix.M43 - this.matrix.M44);
this.NormalizePlane(ref this.left);
this.NormalizePlane(ref this.right);
this.NormalizePlane(ref this.top);
this.NormalizePlane(ref this.bottom);
this.NormalizePlane(ref this.near);
this.NormalizePlane(ref this.far);
}
private static Vector3 IntersectionPoint(ref Plane a, ref Plane b, ref Plane c)
{
// Formula used
// d1 ( N2 * N3 ) + d2 ( N3 * N1 ) + d3 ( N1 * N2 )
//P = -------------------------------------------------------------------------
// N1 . ( N2 * N3 )
//
// Note: N refers to the normal, d refers to the displacement. '.' means dot product. '*' means cross product
Vector3 v1, v2, v3;
float f = -Vector3.Dot(a.Normal, Vector3.Cross(b.Normal, c.Normal));
v1 = (a.D * (Vector3.Cross(b.Normal, c.Normal)));
v2 = (b.D * (Vector3.Cross(c.Normal, a.Normal)));
v3 = (c.D * (Vector3.Cross(a.Normal, b.Normal)));
Vector3 vec = new Vector3(v1.X + v2.X + v3.X, v1.Y + v2.Y + v3.Y, v1.Z + v2.Z + v3.Z);
return vec / f;
}
private void NormalizePlane(ref Plane p)
{
float factor = 1f / p.Normal.Length();
p.Normal.X *= factor;
p.Normal.Y *= factor;
p.Normal.Z *= factor;
p.D *= factor;
}
#endregion
}
}

View File

@ -0,0 +1,363 @@
#region License
/*
MIT License
Copyright © 2006 The Mono.Xna Team
All rights reserved.
Authors:
Olivier Dufour (Duff)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#endregion License
using System;
using System.Collections.Generic;
using System.Globalization;
using System.ComponentModel;
namespace BizHawk.Bizware.BizwareGL
{
public struct BoundingSphere : IEquatable<BoundingSphere>
{
#region Public Fields
public Vector3 Center;
public float Radius;
#endregion Public Fields
#region Constructors
public BoundingSphere(Vector3 center, float radius)
{
this.Center = center;
this.Radius = radius;
}
#endregion Constructors
#region Public Methods
public BoundingSphere Transform(Matrix matrix)
{
BoundingSphere sphere = new BoundingSphere();
sphere.Center = Vector3.Transform(this.Center, matrix);
sphere.Radius = this.Radius * ((float)Math.Sqrt((double)Math.Max(((matrix.M11 * matrix.M11) + (matrix.M12 * matrix.M12)) + (matrix.M13 * matrix.M13), Math.Max(((matrix.M21 * matrix.M21) + (matrix.M22 * matrix.M22)) + (matrix.M23 * matrix.M23), ((matrix.M31 * matrix.M31) + (matrix.M32 * matrix.M32)) + (matrix.M33 * matrix.M33)))));
return sphere;
}
public void Transform(ref Matrix matrix, out BoundingSphere result)
{
result.Center = Vector3.Transform(this.Center, matrix);
result.Radius = this.Radius * ((float)Math.Sqrt((double)Math.Max(((matrix.M11 * matrix.M11) + (matrix.M12 * matrix.M12)) + (matrix.M13 * matrix.M13), Math.Max(((matrix.M21 * matrix.M21) + (matrix.M22 * matrix.M22)) + (matrix.M23 * matrix.M23), ((matrix.M31 * matrix.M31) + (matrix.M32 * matrix.M32)) + (matrix.M33 * matrix.M33)))));
}
public ContainmentType Contains(BoundingBox box)
{
//check if all corner is in sphere
bool inside = true;
foreach (Vector3 corner in box.GetCorners())
{
if (this.Contains(corner) == ContainmentType.Disjoint)
{
inside = false;
break;
}
}
if (inside)
return ContainmentType.Contains;
//check if the distance from sphere center to cube face < radius
double dmin = 0;
if (Center.X < box.Min.X)
dmin += (Center.X - box.Min.X) * (Center.X - box.Min.X);
else if (Center.X > box.Max.X)
dmin += (Center.X - box.Max.X) * (Center.X - box.Max.X);
if (Center.Y < box.Min.Y)
dmin += (Center.Y - box.Min.Y) * (Center.Y - box.Min.Y);
else if (Center.Y > box.Max.Y)
dmin += (Center.Y - box.Max.Y) * (Center.Y - box.Max.Y);
if (Center.Z < box.Min.Z)
dmin += (Center.Z - box.Min.Z) * (Center.Z - box.Min.Z);
else if (Center.Z > box.Max.Z)
dmin += (Center.Z - box.Max.Z) * (Center.Z - box.Max.Z);
if (dmin <= Radius * Radius)
return ContainmentType.Intersects;
//else disjoint
return ContainmentType.Disjoint;
}
public void Contains(ref BoundingBox box, out ContainmentType result)
{
result = this.Contains(box);
}
public ContainmentType Contains(BoundingFrustum frustum)
{
//check if all corner is in sphere
bool inside = true;
Vector3[] corners = frustum.GetCorners();
foreach (Vector3 corner in corners)
{
if (this.Contains(corner) == ContainmentType.Disjoint)
{
inside = false;
break;
}
}
if (inside)
return ContainmentType.Contains;
//check if the distance from sphere center to frustrum face < radius
double dmin = 0;
//TODO : calcul dmin
if (dmin <= Radius * Radius)
return ContainmentType.Intersects;
//else disjoint
return ContainmentType.Disjoint;
}
public ContainmentType Contains(BoundingSphere sphere)
{
float val = Vector3.Distance(sphere.Center, Center);
if (val > sphere.Radius + Radius)
return ContainmentType.Disjoint;
else if (val <= Radius - sphere.Radius)
return ContainmentType.Contains;
else
return ContainmentType.Intersects;
}
public void Contains(ref BoundingSphere sphere, out ContainmentType result)
{
result = Contains(sphere);
}
public ContainmentType Contains(Vector3 point)
{
float distance = Vector3.Distance(point, Center);
if (distance > this.Radius)
return ContainmentType.Disjoint;
else if (distance < this.Radius)
return ContainmentType.Contains;
return ContainmentType.Intersects;
}
public void Contains(ref Vector3 point, out ContainmentType result)
{
result = Contains(point);
}
public static BoundingSphere CreateFromBoundingBox(BoundingBox box)
{
// Find the center of the box.
Vector3 center = new Vector3((box.Min.X + box.Max.X) / 2.0f,
(box.Min.Y + box.Max.Y) / 2.0f,
(box.Min.Z + box.Max.Z) / 2.0f);
// Find the distance between the center and one of the corners of the box.
float radius = Vector3.Distance(center, box.Max);
return new BoundingSphere(center, radius);
}
public static void CreateFromBoundingBox(ref BoundingBox box, out BoundingSphere result)
{
result = CreateFromBoundingBox(box);
}
public static BoundingSphere CreateFromFrustum(BoundingFrustum frustum)
{
return BoundingSphere.CreateFromPoints(frustum.GetCorners());
}
public static BoundingSphere CreateFromPoints(IEnumerable<Vector3> points)
{
if (points == null)
throw new ArgumentNullException("points");
float radius = 0;
Vector3 center = new Vector3();
// First, we'll find the center of gravity for the point 'cloud'.
int num_points = 0; // The number of points (there MUST be a better way to get this instead of counting the number of points one by one?)
foreach (Vector3 v in points)
{
center += v; // If we actually knew the number of points, we'd get better accuracy by adding v / num_points.
++num_points;
}
center /= (float)num_points;
// Calculate the radius of the needed sphere (it equals the distance between the center and the point further away).
foreach (Vector3 v in points)
{
float distance = ((Vector3)(v - center)).Length();
if (distance > radius)
radius = distance;
}
return new BoundingSphere(center, radius);
}
public static BoundingSphere CreateMerged(BoundingSphere original, BoundingSphere additional)
{
Vector3 ocenterToaCenter = Vector3.Subtract(additional.Center, original.Center);
float distance = ocenterToaCenter.Length();
if (distance <= original.Radius + additional.Radius)//intersect
{
if (distance <= original.Radius - additional.Radius)//original contain additional
return original;
if (distance <= additional.Radius - original.Radius)//additional contain original
return additional;
}
//else find center of new sphere and radius
float leftRadius = Math.Max(original.Radius - distance, additional.Radius);
float Rightradius = Math.Max(original.Radius + distance, additional.Radius);
ocenterToaCenter = ocenterToaCenter + (((leftRadius - Rightradius) / (2 * ocenterToaCenter.Length())) * ocenterToaCenter);//oCenterToResultCenter
BoundingSphere result = new BoundingSphere();
result.Center = original.Center + ocenterToaCenter;
result.Radius = (leftRadius + Rightradius) / 2;
return result;
}
public static void CreateMerged(ref BoundingSphere original, ref BoundingSphere additional, out BoundingSphere result)
{
result = BoundingSphere.CreateMerged(original, additional);
}
public bool Equals(BoundingSphere other)
{
return this.Center == other.Center && this.Radius == other.Radius;
}
public override bool Equals(object obj)
{
if (obj is BoundingSphere)
return this.Equals((BoundingSphere)obj);
return false;
}
public override int GetHashCode()
{
return this.Center.GetHashCode() + this.Radius.GetHashCode();
}
public bool Intersects(BoundingBox box)
{
return box.Intersects(this);
}
public void Intersects(ref BoundingBox box, out bool result)
{
result = Intersects(box);
}
public bool Intersects(BoundingFrustum frustum)
{
if (frustum == null)
throw new NullReferenceException();
throw new NotImplementedException();
}
public bool Intersects(BoundingSphere sphere)
{
float val = Vector3.Distance(sphere.Center, Center);
if (val > sphere.Radius + Radius)
return false;
return true;
}
public void Intersects(ref BoundingSphere sphere, out bool result)
{
result = Intersects(sphere);
}
public PlaneIntersectionType Intersects(Plane plane)
{
float distance = Vector3.Dot(plane.Normal, this.Center) + plane.D;
if (distance > this.Radius)
return PlaneIntersectionType.Front;
if (distance < -this.Radius)
return PlaneIntersectionType.Back;
//else it intersect
return PlaneIntersectionType.Intersecting;
}
public void Intersects(ref Plane plane, out PlaneIntersectionType result)
{
result = Intersects(plane);
}
public Nullable<float> Intersects(Ray ray)
{
return ray.Intersects(this);
}
public void Intersects(ref Ray ray, out Nullable<float> result)
{
result = Intersects(ray);
}
public static bool operator == (BoundingSphere a, BoundingSphere b)
{
return a.Equals(b);
}
public static bool operator != (BoundingSphere a, BoundingSphere b)
{
return !a.Equals(b);
}
public override string ToString()
{
return string.Format(CultureInfo.CurrentCulture, "{{Center:{0} Radius:{1}}}", this.Center.ToString(), this.Radius.ToString());
}
#endregion Public Methods
}
}

View File

@ -0,0 +1,76 @@
#region License
/*
MIT License
Copyright © 2006 - 2007 The Mono.Xna Team
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#endregion License
using System;
namespace BizHawk.Bizware.BizwareGL
{
public enum CurveLoopType
{
Constant,
Cycle,
CycleOffset,
Oscillate,
Linear
}
public enum CurveContinuity
{
Smooth,
Step
}
public enum CurveTangent
{
Flat,
Linear,
Smooth
}
public enum TargetPlatform
{
Unknown,
Windows,
Xbox360,
Zune
}
public enum PlaneIntersectionType
{
Front,
Back,
Intersecting
}
public enum ContainmentType
{
Disjoint,
Contains,
Intersects
}
}

View File

@ -0,0 +1,150 @@
#region License
/*
MIT License
Copyright © 2006 The Mono.Xna Team
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#endregion License
using System;
using System.Collections.Generic;
using System.Text;
namespace BizHawk.Bizware.BizwareGL
{
public static class MathHelper
{
public const float E = (float)Math.E;
public const float Log10E = 0.4342945f;
public const float Log2E = 1.442695f;
public const float Pi = (float)Math.PI;
public const float PiOver2 = (float)(Math.PI / 2.0);
public const float PiOver4 = (float)(Math.PI / 4.0);
public const float TwoPi = (float)(Math.PI * 2.0);
public static float Barycentric(float value1, float value2, float value3, float amount1, float amount2)
{
return value1 + (value2 - value1) * amount1 + (value3 - value1) * amount2;
}
public static float CatmullRom(float value1, float value2, float value3, float value4, float amount)
{
// Using formula from http://www.mvps.org/directx/articles/catmull/
// Internally using doubles not to lose precission
double amountSquared = amount * amount;
double amountCubed = amountSquared * amount;
return (float)(0.5f * (2.0f * value2 +
(value3 - value1) * amount +
(2.0f * value1 - 5.0f * value2 + 4.0f * value3 - value4) * amountSquared +
(3.0f * value2 - value1 - 3.0f * value3 + value4) * amountCubed));
}
public static float Clamp(float value, float min, float max)
{
return value > max ? max : (value < min ? min : value);
}
public static float Distance(float value1, float value2)
{
return Math.Abs(value1 - value2);
}
public static float Hermite(float value1, float tangent1, float value2, float tangent2, float amount)
{
// All transformed to double not to lose precission
// Otherwise, for high numbers of param:amount the result is NaN instead of Infinity
double v1 = value1, v2 = value2, t1 = tangent1, t2 = tangent2, s = amount, result;
double sCubed = s * s * s;
double sSquared = s * s;
if (amount == 0f)
result = value1;
else if (amount == 1f)
result = value2;
else
result = (2.0f * v1 - 2.0f * v2 + t2 + t1) * sCubed +
(3.0f * v2 - 3.0f * v1 - 2.0f * t1 - t2) * sSquared +
t1 * s +
v1;
return (float)result;
}
public static float Lerp(float value1, float value2, float amount)
{
return value1 + (value2 - value1) * amount;
}
public static float Max(float value1, float value2)
{
return Math.Max(value1, value2);
}
public static float Min(float value1, float value2)
{
return Math.Min(value1, value2);
}
public static float SmoothStep(float value1, float value2, float amount)
{
// It is expected that 0 < amount < 1
// If amount < 0, return value1
// If amount > 1, return value2
float result = MathHelper.Clamp(amount, 0f, 1f);
result = MathHelper.Hermite(value1, 0f, value2, 0f, result);
return result;
}
public static float ToDegrees(float radians)
{
// This method uses double precission internally,
// though it returns single float
// Factor = 180 / pi
return (float)(radians * 57.295779513082320876798154814105);
}
public static float ToRadians(float degrees)
{
// This method uses double precission internally,
// though it returns single float
// Factor = pi / 180
return (float)(degrees * 0.017453292519943295769236907684886);
}
public static float WrapAngle(float angle)
{
angle = (float)Math.IEEERemainder((double)angle, 6.2831854820251465); //2xPi precission is double
if (angle <= -3.141593f)
{
angle += 6.283185f;
return angle;
}
if (angle > 3.141593f)
{
angle -= 6.283185f;
}
return angle;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,212 @@
#region License
/*
MIT License
Copyright © 2006 The Mono.Xna Team
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#endregion License
using System;
using System.ComponentModel;
namespace BizHawk.Bizware.BizwareGL
{
[Serializable]
public struct Plane : IEquatable<Plane>
{
#region Public Fields
public float D;
public Vector3 Normal;
#endregion Public Fields
#region Constructors
public Plane(Vector4 value)
: this(new Vector3(value.X, value.Y, value.Z), value.W)
{
}
public Plane(Vector3 normal, float d)
{
Normal = normal;
D = d;
}
public Plane(Vector3 a, Vector3 b, Vector3 c)
{
Vector3 ab = b - a;
Vector3 ac = c - a;
Vector3 cross = Vector3.Cross(ab, ac);
Normal = Vector3.Normalize(cross);
D = -(Vector3.Dot(cross, a));
}
public Plane(float a, float b, float c, float d)
: this(new Vector3(a, b, c), d)
{
}
#endregion Constructors
#region Public Methods
public float Dot(Vector4 value)
{
return ((((this.Normal.X * value.X) + (this.Normal.Y * value.Y)) + (this.Normal.Z * value.Z)) + (this.D * value.W));
}
public void Dot(ref Vector4 value, out float result)
{
result = (((this.Normal.X * value.X) + (this.Normal.Y * value.Y)) + (this.Normal.Z * value.Z)) + (this.D * value.W);
}
public float DotCoordinate(Vector3 value)
{
return ((((this.Normal.X * value.X) + (this.Normal.Y * value.Y)) + (this.Normal.Z * value.Z)) + this.D);
}
public void DotCoordinate(ref Vector3 value, out float result)
{
result = (((this.Normal.X * value.X) + (this.Normal.Y * value.Y)) + (this.Normal.Z * value.Z)) + this.D;
}
public float DotNormal(Vector3 value)
{
return (((this.Normal.X * value.X) + (this.Normal.Y * value.Y)) + (this.Normal.Z * value.Z));
}
public void DotNormal(ref Vector3 value, out float result)
{
result = ((this.Normal.X * value.X) + (this.Normal.Y * value.Y)) + (this.Normal.Z * value.Z);
}
public static void Transform(ref Plane plane, ref Quaternion rotation, out Plane result)
{
throw new NotImplementedException();
}
public static void Transform(ref Plane plane, ref Matrix matrix, out Plane result)
{
throw new NotImplementedException();
}
public static Plane Transform(Plane plane, Quaternion rotation)
{
throw new NotImplementedException();
}
public static Plane Transform(Plane plane, Matrix matrix)
{
throw new NotImplementedException();
}
public void Normalize()
{
float factor;
Vector3 normal = Normal;
Normal = Vector3.Normalize(Normal);
factor = (float)Math.Sqrt(Normal.X * Normal.X + Normal.Y * Normal.Y + Normal.Z * Normal.Z) /
(float)Math.Sqrt(normal.X * normal.X + normal.Y * normal.Y + normal.Z * normal.Z);
D = D * factor;
}
public static Plane Normalize(Plane value)
{
Plane ret;
Normalize(ref value, out ret);
return ret;
}
public static void Normalize(ref Plane value, out Plane result)
{
float factor;
result.Normal = Vector3.Normalize(value.Normal);
factor = (float)Math.Sqrt(result.Normal.X * result.Normal.X + result.Normal.Y * result.Normal.Y + result.Normal.Z * result.Normal.Z) /
(float)Math.Sqrt(value.Normal.X * value.Normal.X + value.Normal.Y * value.Normal.Y + value.Normal.Z * value.Normal.Z);
result.D = value.D * factor;
}
public static bool operator !=(Plane plane1, Plane plane2)
{
return !plane1.Equals(plane2);
}
public static bool operator ==(Plane plane1, Plane plane2)
{
return plane1.Equals(plane2);
}
public override bool Equals(object other)
{
return (other is Plane) ? this.Equals((Plane)other) : false;
}
public bool Equals(Plane other)
{
return ((Normal == other.Normal) && (D == other.D));
}
public override int GetHashCode()
{
return Normal.GetHashCode() ^ D.GetHashCode();
}
public PlaneIntersectionType Intersects(BoundingBox box)
{
return box.Intersects(this);
}
public void Intersects(ref BoundingBox box, out PlaneIntersectionType result)
{
result = Intersects(box);
}
public PlaneIntersectionType Intersects(BoundingFrustum frustum)
{
return frustum.Intersects(this);
}
public PlaneIntersectionType Intersects(BoundingSphere sphere)
{
return sphere.Intersects(this);
}
public void Intersects(ref BoundingSphere sphere, out PlaneIntersectionType result)
{
result = Intersects(sphere);
}
public override string ToString()
{
return string.Format("{{Normal:{0} D:{1}}}", Normal, D);
}
#endregion
}
}

View File

@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace BizHawk.Bizware.BizwareGL
{
internal class PlaneHelper
{
/// <summary>
/// Returns a value indicating what side (positive/negative) of a plane a point is
/// </summary>
/// <param name="point">The point to check with</param>
/// <param name="plane">The plane to check against</param>
/// <returns>Greater than zero if on the positive side, less than zero if on the negative size, 0 otherwise</returns>
public static float ClassifyPoint(ref Vector3 point, ref Plane plane)
{
return point.X * plane.Normal.X + point.Y * plane.Normal.Y + point.Z * plane.Normal.Z + plane.D;
}
/// <summary>
/// Returns the perpendicular distance from a point to a plane
/// </summary>
/// <param name="point">The point to check</param>
/// <param name="plane">The place to check</param>
/// <returns>The perpendicular distance from the point to the plane</returns>
public static float PerpendicularDistance(ref Vector3 point, ref Plane plane)
{
// dist = (ax + by + cz + d) / sqrt(a*a + b*b + c*c)
return (float)Math.Abs((plane.Normal.X * point.X + plane.Normal.Y * point.Y + plane.Normal.Z * point.Z)
/ Math.Sqrt(plane.Normal.X * plane.Normal.X + plane.Normal.Y * plane.Normal.Y + plane.Normal.Z * plane.Normal.Z));
}
}
}

View File

@ -0,0 +1,119 @@
#region License
/*
MIT License
Copyright © 2006 The Mono.Xna Team
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#endregion License
using System;
using System.ComponentModel;
namespace BizHawk.Bizware.BizwareGL
{
[Serializable]
public struct Point : IEquatable<Point>
{
#region Private Fields
private static Point zeroPoint = new Point();
#endregion Private Fields
#region Public Fields
public int X;
public int Y;
#endregion Public Fields
#region Properties
public static Point Zero
{
get { return zeroPoint; }
}
#endregion Properties
#region Constructors
/// <summary>
/// Makes new Point with integer accurate
/// </summary>
/// <param name="x">
/// A <see cref="System.Int32"/>
/// </param>
/// <param name="y">
/// A <see cref="System.Int32"/>
/// </param>
public Point(int x, int y)
{
this.X = x;
this.Y = y;
}
#endregion Constructors
#region Public methods
public static bool operator ==(Point a, Point b)
{
return a.Equals(b);
}
public static bool operator !=(Point a, Point b)
{
return !a.Equals(b);
}
public bool Equals(Point other)
{
return ((X == other.X) && (Y == other.Y));
}
public override bool Equals(object obj)
{
return (obj is Point) ? Equals((Point)obj) : false;
}
public override int GetHashCode()
{
return X ^ Y;
}
public override string ToString()
{
return string.Format("{{X:{0} Y:{1}}}", X, Y);
}
#endregion
}
}

View File

@ -0,0 +1,687 @@
#region License
/*
MIT License
Copyright © 2006 The Mono.Xna Team
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#endregion License
using System;
using System.ComponentModel;
using System.Text;
namespace BizHawk.Bizware.BizwareGL
{
[Serializable]
public struct Quaternion : IEquatable<Quaternion>
{
public float X;
public float Y;
public float Z;
public float W;
static Quaternion identity = new Quaternion(0, 0, 0, 1);
public Quaternion(float x, float y, float z, float w)
{
this.X = x;
this.Y = y;
this.Z = z;
this.W = w;
}
public Quaternion(Vector3 vectorPart, float scalarPart)
{
this.X = vectorPart.X;
this.Y = vectorPart.Y;
this.Z = vectorPart.Z;
this.W = scalarPart;
}
public static Quaternion Identity
{
get{ return identity; }
}
public static Quaternion Add(Quaternion quaternion1, Quaternion quaternion2)
{
quaternion1.X += quaternion2.X;
quaternion1.Y += quaternion2.Y;
quaternion1.Z += quaternion2.Z;
quaternion1.W += quaternion2.W;
return quaternion1;
}
public static void Add(ref Quaternion quaternion1, ref Quaternion quaternion2, out Quaternion result)
{
result.W = quaternion1.W + quaternion2.W;
result.X = quaternion1.X + quaternion2.X;
result.Y = quaternion1.Y + quaternion2.Y;
result.Z = quaternion1.Z + quaternion2.Z;
}
public static Quaternion Concatenate(Quaternion value1, Quaternion value2)
{
Quaternion quaternion;
quaternion.X = ((value2.X * value1.W) + (value1.X * value2.W)) + (value2.Y * value1.Z) - (value2.Z * value1.Y);
quaternion.Y = ((value2.Y * value1.W) + (value1.Y * value2.W)) + (value2.Z * value1.X) - (value2.X * value1.Z);
quaternion.Z = ((value2.Z * value1.W) + (value1.Z * value2.W)) + (value2.X * value1.Y) - (value2.Y * value1.X);
quaternion.W = (value2.W * value1.W) - ((value2.X * value1.X) + (value2.Y * value1.Y)) + (value2.Z * value1.Z);
return quaternion;
}
public void Conjugate()
{
this.X = -this.X;
this.Y = -this.Y;
this.Z = -this.Z;
}
public static Quaternion Conjugate(Quaternion value)
{
Quaternion quaternion;
quaternion.X = -value.X;
quaternion.Y = -value.Y;
quaternion.Z = -value.Z;
quaternion.W = value.W;
return quaternion;
}
public static void Conjugate(ref Quaternion value, out Quaternion result)
{
result.X = -value.X;
result.Y = -value.Y;
result.Z = -value.Z;
result.W = value.W;
}
public static void Concatenate(ref Quaternion value1, ref Quaternion value2, out Quaternion result)
{
result.X = ((value2.X * value1.W) + (value1.X * value2.W)) + (value2.Y * value1.Z) - (value2.Z * value1.Y);
result.Y = ((value2.Y * value1.W) + (value1.Y * value2.W)) + (value2.Z * value1.X) - (value2.X * value1.Z);
result.Z = ((value2.Z * value1.W) + (value1.Z * value2.W)) + (value2.X * value1.Y) - (value2.Y * value1.X);
result.W = (value2.W * value1.W) - ((value2.X * value1.X) + (value2.Y * value1.Y)) + (value2.Z * value1.Z);
}
public static Quaternion CreateFromYawPitchRoll(float yaw, float pitch, float roll)
{
Quaternion quaternion;
quaternion.X = (((float)Math.Cos((double)(yaw * 0.5f)) * (float)Math.Sin((double)(pitch * 0.5f))) * (float)Math.Cos((double)(roll * 0.5f))) + (((float)Math.Sin((double)(yaw * 0.5f)) * (float)Math.Cos((double)(pitch * 0.5f))) * (float)Math.Sin((double)(roll * 0.5f)));
quaternion.Y = (((float)Math.Sin((double)(yaw * 0.5f)) * (float)Math.Cos((double)(pitch * 0.5f))) * (float)Math.Cos((double)(roll * 0.5f))) - (((float)Math.Cos((double)(yaw * 0.5f)) * (float)Math.Sin((double)(pitch * 0.5f))) * (float)Math.Sin((double)(roll * 0.5f)));
quaternion.Z = (((float)Math.Cos((double)(yaw * 0.5f)) * (float)Math.Cos((double)(pitch * 0.5f))) * (float)Math.Sin((double)(roll * 0.5f))) - (((float)Math.Sin((double)(yaw * 0.5f)) * (float)Math.Sin((double)(pitch * 0.5f))) * (float)Math.Cos((double)(roll * 0.5f)));
quaternion.W = (((float)Math.Cos((double)(yaw * 0.5f)) * (float)Math.Cos((double)(pitch * 0.5f))) * (float)Math.Cos((double)(roll * 0.5f))) + (((float)Math.Sin((double)(yaw * 0.5f)) * (float)Math.Sin((double)(pitch * 0.5f))) * (float)Math.Sin((double)(roll * 0.5f)));
return quaternion;
}
public static void CreateFromYawPitchRoll(float yaw, float pitch, float roll, out Quaternion result)
{
result.X = (((float)Math.Cos((double)(yaw * 0.5f)) * (float)Math.Sin((double)(pitch * 0.5f))) * (float)Math.Cos((double)(roll * 0.5f))) + (((float)Math.Sin((double)(yaw * 0.5f)) * (float)Math.Cos((double)(pitch * 0.5f))) * (float)Math.Sin((double)(roll * 0.5f)));
result.Y = (((float)Math.Sin((double)(yaw * 0.5f)) * (float)Math.Cos((double)(pitch * 0.5f))) * (float)Math.Cos((double)(roll * 0.5f))) - (((float)Math.Cos((double)(yaw * 0.5f)) * (float)Math.Sin((double)(pitch * 0.5f))) * (float)Math.Sin((double)(roll * 0.5f)));
result.Z = (((float)Math.Cos((double)(yaw * 0.5f)) * (float)Math.Cos((double)(pitch * 0.5f))) * (float)Math.Sin((double)(roll * 0.5f))) - (((float)Math.Sin((double)(yaw * 0.5f)) * (float)Math.Sin((double)(pitch * 0.5f))) * (float)Math.Cos((double)(roll * 0.5f)));
result.W = (((float)Math.Cos((double)(yaw * 0.5f)) * (float)Math.Cos((double)(pitch * 0.5f))) * (float)Math.Cos((double)(roll * 0.5f))) + (((float)Math.Sin((double)(yaw * 0.5f)) * (float)Math.Sin((double)(pitch * 0.5f))) * (float)Math.Sin((double)(roll * 0.5f)));
}
public static Quaternion CreateFromAxisAngle(Vector3 axis, float angle)
{
float sin_a = (float)Math.Sin(angle / 2.0f);
return new Quaternion(axis.X * sin_a,axis.Y * sin_a,axis.Z * sin_a,(float)Math.Cos(angle / 2.0f));
}
public static void CreateFromAxisAngle(ref Vector3 axis, float angle, out Quaternion result)
{
float sin_a = (float)Math.Sin(angle / 2.0f);
result.X = axis.X * sin_a;
result.Y = axis.Y * sin_a;
result.Z = axis.Z * sin_a;
result.W = (float)Math.Cos(angle / 2.0f);
}
public static Quaternion CreateFromRotationMatrix(Matrix matrix)
{
Quaternion result;
if ((matrix.M11 + matrix.M22 + matrix.M33) > 0.0F)
{
float M1 = (float)System.Math.Sqrt((double)(matrix.M11 + matrix.M22 + matrix.M33 + 1.0F));
result.W = M1 * 0.5F;
M1 = 0.5F / M1;
result.X = (matrix.M23 - matrix.M32) * M1;
result.Y = (matrix.M31 - matrix.M13) * M1;
result.Z = (matrix.M12 - matrix.M21) * M1;
return result;
}
if ((matrix.M11 >= matrix.M22) && (matrix.M11 >= matrix.M33))
{
float M2 = (float)System.Math.Sqrt((double)(1.0F + matrix.M11 - matrix.M22 - matrix.M33));
float M3 = 0.5F / M2;
result.X = 0.5F * M2;
result.Y = (matrix.M12 + matrix.M21) * M3;
result.Z = (matrix.M13 + matrix.M31) * M3;
result.W = (matrix.M23 - matrix.M32) * M3;
return result;
}
if (matrix.M22 > matrix.M33)
{
float M4 = (float)System.Math.Sqrt((double)(1.0F + matrix.M22 - matrix.M11 - matrix.M33));
float M5 = 0.5F / M4;
result.X = (matrix.M21 + matrix.M12) * M5;
result.Y = 0.5F * M4;
result.Z = (matrix.M32 + matrix.M23) * M5;
result.W = (matrix.M31 - matrix.M13) * M5;
return result;
}
float M6 = (float)System.Math.Sqrt((double)(1.0F + matrix.M33 - matrix.M11 - matrix.M22));
float M7 = 0.5F / M6;
result.X = (matrix.M31 + matrix.M13) * M7;
result.Y = (matrix.M32 + matrix.M23) * M7;
result.Z = 0.5F * M6;
result.W = (matrix.M12 - matrix.M21) * M7;
return result;
}
public static void CreateFromRotationMatrix(ref Matrix matrix, out Quaternion result)
{
if ((matrix.M11 + matrix.M22 + matrix.M33) > 0.0F)
{
float M1 = (float)System.Math.Sqrt((double)(matrix.M11 + matrix.M22 + matrix.M33 + 1.0F));
result.W = M1 * 0.5F;
M1 = 0.5F / M1;
result.X = (matrix.M23 - matrix.M32) * M1;
result.Y = (matrix.M31 - matrix.M13) * M1;
result.Z = (matrix.M12 - matrix.M21) * M1;
return;
}
if ((matrix.M11 >= matrix.M22) && (matrix.M11 >= matrix.M33))
{
float M2 = (float)System.Math.Sqrt((double)(1.0F + matrix.M11 - matrix.M22 - matrix.M33));
float M3 = 0.5F / M2;
result.X = 0.5F * M2;
result.Y = (matrix.M12 + matrix.M21) * M3;
result.Z = (matrix.M13 + matrix.M31) * M3;
result.W = (matrix.M23 - matrix.M32) * M3;
return;
}
if (matrix.M22 > matrix.M33)
{
float M4 = (float)System.Math.Sqrt((double)(1.0F + matrix.M22 - matrix.M11 - matrix.M33));
float M5 = 0.5F / M4;
result.X = (matrix.M21 + matrix.M12) * M5;
result.Y = 0.5F * M4;
result.Z = (matrix.M32 + matrix.M23) * M5;
result.W = (matrix.M31 - matrix.M13) * M5;
return;
}
float M6 = (float)System.Math.Sqrt((double)(1.0F + matrix.M33 - matrix.M11 - matrix.M22));
float M7 = 0.5F / M6;
result.X = (matrix.M31 + matrix.M13) * M7;
result.Y = (matrix.M32 + matrix.M23) * M7;
result.Z = 0.5F * M6;
result.W = (matrix.M12 - matrix.M21) * M7;
}
public static Quaternion Divide(Quaternion quaternion1, Quaternion quaternion2)
{
Quaternion result;
float w5 = 1.0F / ((quaternion2.X * quaternion2.X) + (quaternion2.Y * quaternion2.Y) + (quaternion2.Z * quaternion2.Z) + (quaternion2.W * quaternion2.W));
float w4 = -quaternion2.X * w5;
float w3 = -quaternion2.Y * w5;
float w2 = -quaternion2.Z * w5;
float w1 = quaternion2.W * w5;
result.X = (quaternion1.X * w1) + (w4 * quaternion1.W) + ((quaternion1.Y * w2) - (quaternion1.Z * w3));
result.Y = (quaternion1.Y * w1) + (w3 * quaternion1.W) + ((quaternion1.Z * w4) - (quaternion1.X * w2));
result.Z = (quaternion1.Z * w1) + (w2 * quaternion1.W) + ((quaternion1.X * w3) - (quaternion1.Y * w4));
result.W = (quaternion1.W * quaternion2.W * w5) - ((quaternion1.X * w4) + (quaternion1.Y * w3) + (quaternion1.Z * w2));
return result;
}
public static void Divide(ref Quaternion quaternion1, ref Quaternion quaternion2, out Quaternion result)
{
float w5 = 1.0F / ((quaternion2.X * quaternion2.X) + (quaternion2.Y * quaternion2.Y) + (quaternion2.Z * quaternion2.Z) + (quaternion2.W * quaternion2.W));
float w4 = -quaternion2.X * w5;
float w3 = -quaternion2.Y * w5;
float w2 = -quaternion2.Z * w5;
float w1 = quaternion2.W * w5;
result.X = (quaternion1.X * w1) + (w4 * quaternion1.W) + ((quaternion1.Y * w2) - (quaternion1.Z * w3));
result.Y = (quaternion1.Y * w1) + (w3 * quaternion1.W) + ((quaternion1.Z * w4) - (quaternion1.X * w2));
result.Z = (quaternion1.Z * w1) + (w2 * quaternion1.W) + ((quaternion1.X * w3) - (quaternion1.Y * w4));
result.W = (quaternion1.W * quaternion2.W * w5) - ((quaternion1.X * w4) + (quaternion1.Y * w3) + (quaternion1.Z * w2));
}
public static float Dot(Quaternion quaternion1, Quaternion quaternion2)
{
return (quaternion1.X * quaternion2.X) + (quaternion1.Y * quaternion2.Y) + (quaternion1.Z * quaternion2.Z) + (quaternion1.W * quaternion2.W);
}
public static void Dot(ref Quaternion quaternion1, ref Quaternion quaternion2, out float result)
{
result = (quaternion1.X * quaternion2.X) + (quaternion1.Y * quaternion2.Y) + (quaternion1.Z * quaternion2.Z) + (quaternion1.W * quaternion2.W);
}
public override bool Equals(object obj)
{
return (obj is Quaternion) ? this == (Quaternion)obj : false;
}
public bool Equals(Quaternion other)
{
if ((X == other.X) && (Y == other.Y) && (Z == other.Z))
return W == other.W;
return false;
}
public override int GetHashCode()
{
return X.GetHashCode() + Y.GetHashCode() + Z.GetHashCode() + W.GetHashCode();
}
public static Quaternion Inverse(Quaternion quaternion)
{
Quaternion result;
float m1 = 1.0F / ((quaternion.X * quaternion.X) + (quaternion.Y * quaternion.Y) + (quaternion.Z * quaternion.Z) + (quaternion.W * quaternion.W));
result.X = -quaternion.X * m1;
result.Y = -quaternion.Y * m1;
result.Z = -quaternion.Z * m1;
result.W = quaternion.W * m1;
return result;
}
public static void Inverse(ref Quaternion quaternion, out Quaternion result)
{
float m1 = 1.0F / ((quaternion.X * quaternion.X) + (quaternion.Y * quaternion.Y) + (quaternion.Z * quaternion.Z) + (quaternion.W * quaternion.W));
result.X = -quaternion.X * m1;
result.Y = -quaternion.Y * m1;
result.Z = -quaternion.Z * m1;
result.W = quaternion.W * m1;
}
public float Length()
{
return (float)System.Math.Sqrt((double)((X * X) + (Y * Y) + (Z * Z) + (W * W)));
}
public float LengthSquared()
{
return (X * X) + (Y * Y) + (Z * Z) + (W * W);
}
public static Quaternion Lerp(Quaternion quaternion1, Quaternion quaternion2, float amount)
{
Quaternion result;
float f2 = 1.0F - amount;
if (((quaternion1.X * quaternion2.X) + (quaternion1.Y * quaternion2.Y) + (quaternion1.Z * quaternion2.Z) + (quaternion1.W * quaternion2.W)) >= 0.0F)
{
result.X = (f2 * quaternion1.X) + (amount * quaternion2.X);
result.Y = (f2 * quaternion1.Y) + (amount * quaternion2.Y);
result.Z = (f2 * quaternion1.Z) + (amount * quaternion2.Z);
result.W = (f2 * quaternion1.W) + (amount * quaternion2.W);
}
else
{
result.X = (f2 * quaternion1.X) - (amount * quaternion2.X);
result.Y = (f2 * quaternion1.Y) - (amount * quaternion2.Y);
result.Z = (f2 * quaternion1.Z) - (amount * quaternion2.Z);
result.W = (f2 * quaternion1.W) - (amount * quaternion2.W);
}
float f4 = (result.X * result.X) + (result.Y * result.Y) + (result.Z * result.Z) + (result.W * result.W);
float f3 = 1.0F / (float)System.Math.Sqrt((double)f4);
result.X *= f3;
result.Y *= f3;
result.Z *= f3;
result.W *= f3;
return result;
}
public static void Lerp(ref Quaternion quaternion1, ref Quaternion quaternion2, float amount, out Quaternion result)
{
float m2 = 1.0F - amount;
if (((quaternion1.X * quaternion2.X) + (quaternion1.Y * quaternion2.Y) + (quaternion1.Z * quaternion2.Z) + (quaternion1.W * quaternion2.W)) >= 0.0F)
{
result.X = (m2 * quaternion1.X) + (amount * quaternion2.X);
result.Y = (m2 * quaternion1.Y) + (amount * quaternion2.Y);
result.Z = (m2 * quaternion1.Z) + (amount * quaternion2.Z);
result.W = (m2 * quaternion1.W) + (amount * quaternion2.W);
}
else
{
result.X = (m2 * quaternion1.X) - (amount * quaternion2.X);
result.Y = (m2 * quaternion1.Y) - (amount * quaternion2.Y);
result.Z = (m2 * quaternion1.Z) - (amount * quaternion2.Z);
result.W = (m2 * quaternion1.W) - (amount * quaternion2.W);
}
float m4 = (result.X * result.X) + (result.Y * result.Y) + (result.Z * result.Z) + (result.W * result.W);
float m3 = 1.0F / (float)System.Math.Sqrt((double)m4);
result.X *= m3;
result.Y *= m3;
result.Z *= m3;
result.W *= m3;
}
public static Quaternion Slerp(Quaternion quaternion1, Quaternion quaternion2, float amount)
{
Quaternion result;
float q2, q3;
float q4 = (quaternion1.X * quaternion2.X) + (quaternion1.Y * quaternion2.Y) + (quaternion1.Z * quaternion2.Z) + (quaternion1.W * quaternion2.W);
bool flag = false;
if (q4 < 0.0F)
{
flag = true;
q4 = -q4;
}
if (q4 > 0.999999F)
{
q3 = 1.0F - amount;
q2 = flag ? -amount : amount;
}
else
{
float q5 = (float)System.Math.Acos((double)q4);
float q6 = (float)(1.0 / System.Math.Sin((double)q5));
q3 = (float)System.Math.Sin((double)((1.0F - amount) * q5)) * q6;
q2 = flag ? (float)-System.Math.Sin((double)(amount * q5)) * q6 : (float)System.Math.Sin((double)(amount * q5)) * q6;
}
result.X = (q3 * quaternion1.X) + (q2 * quaternion2.X);
result.Y = (q3 * quaternion1.Y) + (q2 * quaternion2.Y);
result.Z = (q3 * quaternion1.Z) + (q2 * quaternion2.Z);
result.W = (q3 * quaternion1.W) + (q2 * quaternion2.W);
return result;
}
public static void Slerp(ref Quaternion quaternion1, ref Quaternion quaternion2, float amount, out Quaternion result)
{
float q2, q3;
float q4 = (quaternion1.X * quaternion2.X) + (quaternion1.Y * quaternion2.Y) + (quaternion1.Z * quaternion2.Z) + (quaternion1.W * quaternion2.W);
bool flag = false;
if (q4 < 0.0F)
{
flag = true;
q4 = -q4;
}
if (q4 > 0.999999F)
{
q3 = 1.0F - amount;
q2 = flag ? -amount : amount;
}
else
{
float q5 = (float)System.Math.Acos((double)q4);
float q6 = (float)(1.0 / System.Math.Sin((double)q5));
q3 = (float)System.Math.Sin((double)((1.0F - amount) * q5)) * q6;
q2 = flag ? (float)-System.Math.Sin((double)(amount * q5)) * q6 : (float)System.Math.Sin((double)(amount * q5)) * q6;
}
result.X = (q3 * quaternion1.X) + (q2 * quaternion2.X);
result.Y = (q3 * quaternion1.Y) + (q2 * quaternion2.Y);
result.Z = (q3 * quaternion1.Z) + (q2 * quaternion2.Z);
result.W = (q3 * quaternion1.W) + (q2 * quaternion2.W);
}
public static Quaternion Subtract(Quaternion quaternion1, Quaternion quaternion2)
{
quaternion1.X -= quaternion2.X;
quaternion1.Y -= quaternion2.Y;
quaternion1.Z -= quaternion2.Z;
quaternion1.W -= quaternion2.W;
return quaternion1;
}
public static void Subtract(ref Quaternion quaternion1, ref Quaternion quaternion2, out Quaternion result)
{
result.X = quaternion1.X - quaternion2.X;
result.Y = quaternion1.Y - quaternion2.Y;
result.Z = quaternion1.Z - quaternion2.Z;
result.W = quaternion1.W - quaternion2.W;
}
public static Quaternion Multiply(Quaternion quaternion1, Quaternion quaternion2)
{
Quaternion result;
float f12 = (quaternion1.Y * quaternion2.Z) - (quaternion1.Z * quaternion2.Y);
float f11 = (quaternion1.Z * quaternion2.X) - (quaternion1.X * quaternion2.Z);
float f10 = (quaternion1.X * quaternion2.Y) - (quaternion1.Y * quaternion2.X);
float f9 = (quaternion1.X * quaternion2.X) + (quaternion1.Y * quaternion2.Y) + (quaternion1.Z * quaternion2.Z);
result.X = (quaternion1.X * quaternion2.W) + (quaternion2.X * quaternion1.W) + f12;
result.Y = (quaternion1.Y * quaternion2.W) + (quaternion2.Y * quaternion1.W) + f11;
result.Z = (quaternion1.Z * quaternion2.W) + (quaternion2.Z * quaternion1.W) + f10;
result.W = (quaternion1.W * quaternion2.W) - f9;
return result;
}
public static Quaternion Multiply(Quaternion quaternion1, float scaleFactor)
{
quaternion1.X *= scaleFactor;
quaternion1.Y *= scaleFactor;
quaternion1.Z *= scaleFactor;
quaternion1.W *= scaleFactor;
return quaternion1;
}
public static void Multiply(ref Quaternion quaternion1, float scaleFactor, out Quaternion result)
{
result.X = quaternion1.X * scaleFactor;
result.Y = quaternion1.Y * scaleFactor;
result.Z = quaternion1.Z * scaleFactor;
result.W = quaternion1.W * scaleFactor;
}
public static void Multiply(ref Quaternion quaternion1, ref Quaternion quaternion2, out Quaternion result)
{
float f12 = (quaternion1.Y * quaternion2.Z) - (quaternion1.Z * quaternion2.Y);
float f11 = (quaternion1.Z * quaternion2.X) - (quaternion1.X * quaternion2.Z);
float f10 = (quaternion1.X * quaternion2.Y) - (quaternion1.Y * quaternion2.X);
float f9 = (quaternion1.X * quaternion2.X) + (quaternion1.Y * quaternion2.Y) + (quaternion1.Z * quaternion2.Z);
result.X = (quaternion1.X * quaternion2.W) + (quaternion2.X * quaternion1.W) + f12;
result.Y = (quaternion1.Y * quaternion2.W) + (quaternion2.Y * quaternion1.W) + f11;
result.Z = (quaternion1.Z * quaternion2.W) + (quaternion2.Z * quaternion1.W) + f10;
result.W = (quaternion1.W * quaternion2.W) - f9;
}
public static Quaternion Negate(Quaternion quaternion)
{
Quaternion result;
result.X = -quaternion.X;
result.Y = -quaternion.Y;
result.Z = -quaternion.Z;
result.W = -quaternion.W;
return result;
}
public static void Negate(ref Quaternion quaternion, out Quaternion result)
{
result.X = -quaternion.X;
result.Y = -quaternion.Y;
result.Z = -quaternion.Z;
result.W = -quaternion.W;
}
public void Normalize()
{
float f1 = 1.0F / (float)System.Math.Sqrt((double)((this.X * this.X) + (this.Y * this.Y) + (this.Z * this.Z) + (this.W * this.W)));
this.X *= f1;
this.Y *= f1;
this.Z *= f1;
this.W *= f1;
}
public static Quaternion Normalize(Quaternion quaternion)
{
Quaternion result;
float f1 = 1.0F / (float)System.Math.Sqrt((double)((quaternion.X * quaternion.X) + (quaternion.Y * quaternion.Y) + (quaternion.Z * quaternion.Z) + (quaternion.W * quaternion.W)));
result.X = quaternion.X * f1;
result.Y = quaternion.Y * f1;
result.Z = quaternion.Z * f1;
result.W = quaternion.W * f1;
return result;
}
public static void Normalize(ref Quaternion quaternion, out Quaternion result)
{
float f1 = 1.0F / (float)System.Math.Sqrt((double)((quaternion.X * quaternion.X) + (quaternion.Y * quaternion.Y) + (quaternion.Z * quaternion.Z) + (quaternion.W * quaternion.W)));
result.X = quaternion.X * f1;
result.Y = quaternion.Y * f1;
result.Z = quaternion.Z * f1;
result.W = quaternion.W * f1;
}
public static Quaternion operator +(Quaternion quaternion1, Quaternion quaternion2)
{
quaternion1.X += quaternion2.X;
quaternion1.Y += quaternion2.Y;
quaternion1.Z += quaternion2.Z;
quaternion1.W += quaternion2.W;
return quaternion1;
}
public static Quaternion operator /(Quaternion quaternion1, Quaternion quaternion2)
{
Quaternion result;
float w5 = 1.0F / ((quaternion2.X * quaternion2.X) + (quaternion2.Y * quaternion2.Y) + (quaternion2.Z * quaternion2.Z) + (quaternion2.W * quaternion2.W));
float w4 = -quaternion2.X * w5;
float w3 = -quaternion2.Y * w5;
float w2 = -quaternion2.Z * w5;
float w1 = quaternion2.W * w5;
result.X = (quaternion1.X * w1) + (w4 * quaternion1.W) + ((quaternion1.Y * w2) - (quaternion1.Z * w3));
result.Y = (quaternion1.Y * w1) + (w3 * quaternion1.W) + ((quaternion1.Z * w4) - (quaternion1.X * w2));
result.Z = (quaternion1.Z * w1) + (w2 * quaternion1.W) + ((quaternion1.X * w3) - (quaternion1.Y * w4));
result.W = (quaternion1.W * quaternion2.W * w5) - ((quaternion1.X * w4) + (quaternion1.Y * w3) + (quaternion1.Z * w2));
return result;
}
public static bool operator ==(Quaternion quaternion1, Quaternion quaternion2)
{
return quaternion1.X == quaternion2.X
&& quaternion1.Y == quaternion2.Y
&& quaternion1.Z == quaternion2.Z
&& quaternion1.W == quaternion2.W;
}
public static bool operator !=(Quaternion quaternion1, Quaternion quaternion2)
{
return quaternion1.X != quaternion2.X
|| quaternion1.Y != quaternion2.Y
|| quaternion1.Z != quaternion2.Z
|| quaternion1.W != quaternion2.W;
}
public static Quaternion operator *(Quaternion quaternion1, Quaternion quaternion2)
{
Quaternion result;
float f12 = (quaternion1.Y * quaternion2.Z) - (quaternion1.Z * quaternion2.Y);
float f11 = (quaternion1.Z * quaternion2.X) - (quaternion1.X * quaternion2.Z);
float f10 = (quaternion1.X * quaternion2.Y) - (quaternion1.Y * quaternion2.X);
float f9 = (quaternion1.X * quaternion2.X) + (quaternion1.Y * quaternion2.Y) + (quaternion1.Z * quaternion2.Z);
result.X = (quaternion1.X * quaternion2.W) + (quaternion2.X * quaternion1.W) + f12;
result.Y = (quaternion1.Y * quaternion2.W) + (quaternion2.Y * quaternion1.W) + f11;
result.Z = (quaternion1.Z * quaternion2.W) + (quaternion2.Z * quaternion1.W) + f10;
result.W = (quaternion1.W * quaternion2.W) - f9;
return result;
}
public static Quaternion operator *(Quaternion quaternion1, float scaleFactor)
{
quaternion1.X *= scaleFactor;
quaternion1.Y *= scaleFactor;
quaternion1.Z *= scaleFactor;
quaternion1.W *= scaleFactor;
return quaternion1;
}
public static Quaternion operator -(Quaternion quaternion1, Quaternion quaternion2)
{
quaternion1.X -= quaternion2.X;
quaternion1.Y -= quaternion2.Y;
quaternion1.Z -= quaternion2.Z;
quaternion1.W -= quaternion2.W;
return quaternion1;
}
public static Quaternion operator -(Quaternion quaternion)
{
quaternion.X = -quaternion.X;
quaternion.Y = -quaternion.Y;
quaternion.Z = -quaternion.Z;
quaternion.W = -quaternion.W;
return quaternion;
}
public override string ToString()
{
StringBuilder sb = new StringBuilder(32);
sb.Append("{X:");
sb.Append(this.X);
sb.Append(" Y:");
sb.Append(this.Y);
sb.Append(" Z:");
sb.Append(this.Z);
sb.Append(" W:");
sb.Append(this.W);
sb.Append("}");
return sb.ToString();
}
}
}

View File

@ -0,0 +1,233 @@
#region License
/*
MIT License
Copyright © 2006 The Mono.Xna Team
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#endregion License
using System;
using System.ComponentModel;
namespace BizHawk.Bizware.BizwareGL
{
[Serializable]
public struct Ray : IEquatable<Ray>
{
#region Public Fields
public Vector3 Direction;
public Vector3 Position;
#endregion
#region Public Constructors
public Ray(Vector3 position, Vector3 direction)
{
this.Position = position;
this.Direction = direction;
}
#endregion
#region Public Methods
public override bool Equals(object obj)
{
return (obj is Ray) ? this.Equals((Ray)obj) : false;
}
public bool Equals(Ray other)
{
return this.Position.Equals(other.Position) && this.Direction.Equals(other.Direction);
}
public override int GetHashCode()
{
return Position.GetHashCode() ^ Direction.GetHashCode();
}
public float? Intersects(BoundingBox box)
{
//first test if start in box
if (Position.X >= box.Min.X
&& Position.X <= box.Max.X
&& Position.Y >= box.Min.Y
&& Position.Y <= box.Max.Y
&& Position.Z >= box.Min.Z
&& Position.Z <= box.Max.Z)
return 0.0f;// here we concidere cube is full and origine is in cube so intersect at origine
//Second we check each face
Vector3 maxT = new Vector3(-1.0f);
//Vector3 minT = new Vector3(-1.0f);
//calcul intersection with each faces
if (Position.X < box.Min.X && Direction.X != 0.0f)
maxT.X = (box.Min.X - Position.X) / Direction.X;
else if (Position.X > box.Max.X && Direction.X != 0.0f)
maxT.X = (box.Max.X - Position.X) / Direction.X;
if (Position.Y < box.Min.Y && Direction.Y != 0.0f)
maxT.Y = (box.Min.Y - Position.Y) / Direction.Y;
else if (Position.Y > box.Max.Y && Direction.Y != 0.0f)
maxT.Y = (box.Max.Y - Position.Y) / Direction.Y;
if (Position.Z < box.Min.Z && Direction.Z != 0.0f)
maxT.Z = (box.Min.Z - Position.Z) / Direction.Z;
else if (Position.Z > box.Max.Z && Direction.Z != 0.0f)
maxT.Z = (box.Max.Z - Position.Z) / Direction.Z;
//get the maximum maxT
if (maxT.X > maxT.Y && maxT.X > maxT.Z)
{
if (maxT.X < 0.0f)
return null;// ray go on opposite of face
//coordonate of hit point of face of cube
float coord = Position.Z + maxT.X * Direction.Z;
// if hit point coord ( intersect face with ray) is out of other plane coord it miss
if (coord < box.Min.Z || coord > box.Max.Z)
return null;
coord = Position.Y + maxT.X * Direction.Y;
if (coord < box.Min.Y || coord > box.Max.Y)
return null;
return maxT.X;
}
if (maxT.Y > maxT.X && maxT.Y > maxT.Z)
{
if (maxT.Y < 0.0f)
return null;// ray go on opposite of face
//coordonate of hit point of face of cube
float coord = Position.Z + maxT.Y * Direction.Z;
// if hit point coord ( intersect face with ray) is out of other plane coord it miss
if (coord < box.Min.Z || coord > box.Max.Z)
return null;
coord = Position.X + maxT.Y * Direction.X;
if (coord < box.Min.X || coord > box.Max.X)
return null;
return maxT.Y;
}
else //Z
{
if (maxT.Z < 0.0f)
return null;// ray go on opposite of face
//coordonate of hit point of face of cube
float coord = Position.X + maxT.Z * Direction.X;
// if hit point coord ( intersect face with ray) is out of other plane coord it miss
if (coord < box.Min.X || coord > box.Max.X)
return null;
coord = Position.Y + maxT.Z * Direction.Y;
if (coord < box.Min.Y || coord > box.Max.Y)
return null;
return maxT.Z;
}
}
public void Intersects(ref BoundingBox box, out float? result)
{
result = Intersects(box);
}
public float? Intersects(BoundingFrustum frustum)
{
throw new NotImplementedException();
}
public float? Intersects(BoundingSphere sphere)
{
float? result;
Intersects(ref sphere, out result);
return result;
}
public float? Intersects(Plane plane)
{
throw new NotImplementedException();
}
public void Intersects(ref Plane plane, out float? result)
{
throw new NotImplementedException();
}
public void Intersects(ref BoundingSphere sphere, out float? result)
{
// Find the vector between where the ray starts the the sphere's centre
Vector3 difference = sphere.Center - this.Position;
float differenceLengthSquared = difference.LengthSquared();
float sphereRadiusSquared = sphere.Radius * sphere.Radius;
float distanceAlongRay;
// If the distance between the ray start and the sphere's centre is less than
// the radius of the sphere, it means we've intersected. N.B. checking the LengthSquared is faster.
if (differenceLengthSquared < sphereRadiusSquared)
{
result = 0.0f;
return;
}
Vector3.Dot(ref this.Direction, ref difference, out distanceAlongRay);
// If the ray is pointing away from the sphere then we don't ever intersect
if (distanceAlongRay < 0)
{
result = null;
return;
}
// Next we kinda use Pythagoras to check if we are within the bounds of the sphere
// if x = radius of sphere
// if y = distance between ray position and sphere centre
// if z = the distance we've travelled along the ray
// if x^2 + z^2 - y^2 < 0, we do not intersect
float dist = sphereRadiusSquared + distanceAlongRay * distanceAlongRay - differenceLengthSquared;
result = (dist < 0) ? null : distanceAlongRay - (float?)Math.Sqrt(dist);
}
public static bool operator !=(Ray a, Ray b)
{
return !a.Equals(b);
}
public static bool operator ==(Ray a, Ray b)
{
return a.Equals(b);
}
public override string ToString()
{
return string.Format("{{Position:{0} Direction:{1}}}", Position.ToString(), Direction.ToString());
}
#endregion
}
}

View File

@ -0,0 +1,312 @@
#region License
/*
MIT License
Copyright © 2006 The Mono.Xna Team
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#endregion License
using System;
using System.Globalization;
using System.ComponentModel;
namespace BizHawk.Bizware.BizwareGL
{
public struct Rectangle : IEquatable<Rectangle>
{
#region Private Fields
private static Rectangle emptyRectangle = new Rectangle();
#endregion Private Fields
#region Public Fields
public int X;
public int Y;
public int Width;
public int Height;
#endregion Public Fields
#region Public Properties
public Point Center
{
get
{
return new Point(this.X + (this.Width / 2), this.Y + (this.Height / 2));
}
}
public Point Location
{
get
{
return new Point(this.X, this.Y);
}
set
{
this.X = value.X;
this.Y = value.Y;
}
}
public bool IsEmpty
{
get
{
return ((((this.Width == 0) && (this.Height == 0)) && (this.X == 0)) && (this.Y == 0));
}
}
public static Rectangle Empty
{
get { return emptyRectangle; }
}
public int Left
{
get { return this.X; }
}
public int Right
{
get { return (this.X + this.Width); }
}
public int Top
{
get { return this.Y; }
}
public int Bottom
{
get { return (this.Y + this.Height); }
}
#endregion Public Properties
#region Constructors
public Rectangle(int x, int y, int width, int height)
{
this.X = x;
this.Y = y;
this.Width = width;
this.Height = height;
}
#endregion Constructors
#region Public Methods
public static Rectangle Union(Rectangle value1, Rectangle value2)
{
throw new NotImplementedException();
}
public static void Union(ref Rectangle value1, ref Rectangle value2, out Rectangle result)
{
throw new NotImplementedException();
}
public static Rectangle Intersect(Rectangle value1, Rectangle value2)
{
throw new NotImplementedException();
}
public void Intersects(ref Rectangle value, out bool result)
{
result = (((value.X < (this.X + this.Width)) && (this.X < (value.X + value.Width))) && (value.Y < (this.Y + this.Height))) && (this.Y < (value.Y + value.Height));
}
public bool Contains(Point value)
{
return ((((this.X <= value.X) && (value.X < (this.X + this.Width))) && (this.Y <= value.Y)) && (value.Y < (this.Y + this.Height)));
}
public bool Contains(Rectangle value)
{
return ((((this.X <= value.X) && ((value.X + value.Width) <= (this.X + this.Width))) && (this.Y <= value.Y)) && ((value.Y + value.Height) <= (this.Y + this.Height)));
}
public void Contains(ref Rectangle value, out bool result)
{
result = (((this.X <= value.X) && ((value.X + value.Width) <= (this.X + this.Width))) && (this.Y <= value.Y)) && ((value.Y + value.Height) <= (this.Y + this.Height));
}
public bool Contains(int x, int y)
{
return ((((this.X <= x) && (x < (this.X + this.Width))) && (this.Y <= y)) && (y < (this.Y + this.Height)));
}
public void Contains(ref Point value, out bool result)
{
result = (((this.X <= value.X) && (value.X < (this.X + this.Width))) && (this.Y <= value.Y)) && (value.Y < (this.Y + this.Height));
}
public static void Intersect(ref Rectangle value1, ref Rectangle value2, out Rectangle result)
{
throw new NotImplementedException();
}
public static bool operator ==(Rectangle a, Rectangle b)
{
return ((a.X == b.X) && (a.Y == b.Y) && (a.Width == b.Width) && (a.Height == b.Height));
}
public static bool operator !=(Rectangle a, Rectangle b)
{
return !(a == b);
}
/// <summary>
/// Moves Rectangle for both Point values.
/// </summary>
/// <param name="offset">
/// A <see cref="Point"/>
/// </param>
public void Offset(Point offset)
{
X += offset.X;
Y += offset.Y;
}
/// <summary>
/// Moves rectangle for both values.
/// </summary>
/// <param name="offsetX">
/// A <see cref="System.Int32"/>
/// </param>
/// <param name="offsetY">
/// A <see cref="System.Int32"/>
/// </param>
public void Offset(int offsetX, int offsetY)
{
X += offsetX;
Y += offsetY;
}
/// <summary>
/// Grows the Rectangle. Down right point is in the same position.
/// </summary>
/// <param name="horizontalValue">
/// A <see cref="System.Int32"/>
/// </param>
/// <param name="verticalValue">
/// A <see cref="System.Int32"/>
/// </param>
public void Inflate(int horizontalValue, int verticalValue)
{
X -= horizontalValue;
Y -= verticalValue;
Width += horizontalValue * 2;
Height += verticalValue * 2;
}
/// <summary>
/// It checks if two rectangle intersects.
/// </summary>
/// <param name="rect">
/// A <see cref="Rectangle"/>
/// </param>
/// <returns>
/// A <see cref="System.Boolean"/>
/// </returns>
public bool Intersects(Rectangle rect)
{
if(this.X <= rect.X)
{
if((this.X + this.Width) > rect.X)
{
if(this.Y < rect.Y)
{
if((this.Y + this.Height) > rect.Y)
return true;
}
else
{
if((rect.Y + rect.Height) > this.Y)
return true;
}
}
}
else
{
if((rect.X + rect.Width) > this.X)
{
if(this.Y < rect.Y)
{
if((this.Y + this.Height) > rect.Y)
return true;
}
else
{
if((rect.Y + rect.Height) > this.Y)
return true;
}
}
}
return false;
}
public bool Equals(Rectangle other)
{
return this == other;
}
/// <summary>
/// Returns true if recangles are same
/// </summary>
/// <param name="obj">
/// A <see cref="System.Object"/>
/// </param>
/// <returns>
/// A <see cref="System.Boolean"/>
/// </returns>
public override bool Equals(object obj)
{
return (obj is Rectangle) ? this == ((Rectangle)obj) : false;
}
public override string ToString()
{
return string.Format("{{X:{0} Y:{1} Width:{2} Height:{3}}}", X, Y, Width, Height);
}
public override int GetHashCode()
{
return (this.X ^ this.Y ^ this.Width ^ this.Height);
}
#endregion Public Methods
}
}

View File

@ -0,0 +1,368 @@
//
// System.Drawing.Size.cs
//
// Author:
// Mike Kestner (mkestner@speakeasy.net)
//
// Copyright (C) 2001 Mike Kestner
// Copyright (C) 2004 Novell, Inc. http://www.novell.com
//
//The MIT license:
//
// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Runtime.Serialization;
using System.Runtime.InteropServices;
using System.ComponentModel;
namespace BizHawk.Bizware.BizwareGL
{
[Serializable]
[ComVisible(true)]
public struct Size
{
// Private Height and width fields.
private int width, height;
// -----------------------
// Public Shared Members
// -----------------------
/// <summary>
/// Empty Shared Field
/// </summary>
///
/// <remarks>
/// An uninitialized Size Structure.
/// </remarks>
public static readonly Size Empty;
/// <summary>
/// Ceiling Shared Method
/// </summary>
///
/// <remarks>
/// Produces a Size structure from a SizeF structure by
/// taking the ceiling of the Width and Height properties.
/// </remarks>
public static Size Ceiling(SizeF value)
{
int w, h;
checked
{
w = (int)Math.Ceiling(value.Width);
h = (int)Math.Ceiling(value.Height);
}
return new Size(w, h);
}
/// <summary>
/// Round Shared Method
/// </summary>
///
/// <remarks>
/// Produces a Size structure from a SizeF structure by
/// rounding the Width and Height properties.
/// </remarks>
public static Size Round(SizeF value)
{
int w, h;
checked
{
w = (int)Math.Round(value.Width);
h = (int)Math.Round(value.Height);
}
return new Size(w, h);
}
/// <summary>
/// Truncate Shared Method
/// </summary>
///
/// <remarks>
/// Produces a Size structure from a SizeF structure by
/// truncating the Width and Height properties.
/// </remarks>
public static Size Truncate(SizeF value)
{
int w, h;
checked
{
w = (int)value.Width;
h = (int)value.Height;
}
return new Size(w, h);
}
/// <summary>
/// Addition Operator
/// </summary>
///
/// <remarks>
/// Addition of two Size structures.
/// </remarks>
public static Size operator +(Size sz1, Size sz2)
{
return new Size(sz1.Width + sz2.Width,
sz1.Height + sz2.Height);
}
/// <summary>
/// Equality Operator
/// </summary>
///
/// <remarks>
/// Compares two Size objects. The return value is
/// based on the equivalence of the Width and Height
/// properties of the two Sizes.
/// </remarks>
public static bool operator ==(Size sz1, Size sz2)
{
return ((sz1.Width == sz2.Width) &&
(sz1.Height == sz2.Height));
}
/// <summary>
/// Inequality Operator
/// </summary>
///
/// <remarks>
/// Compares two Size objects. The return value is
/// based on the equivalence of the Width and Height
/// properties of the two Sizes.
/// </remarks>
public static bool operator !=(Size sz1, Size sz2)
{
return ((sz1.Width != sz2.Width) ||
(sz1.Height != sz2.Height));
}
/// <summary>
/// Subtraction Operator
/// </summary>
///
/// <remarks>
/// Subtracts two Size structures.
/// </remarks>
public static Size operator -(Size sz1, Size sz2)
{
return new Size(sz1.Width - sz2.Width,
sz1.Height - sz2.Height);
}
/// <summary>
/// Size to Point Conversion
/// </summary>
///
/// <remarks>
/// Returns a Point based on the dimensions of a given
/// Size. Requires explicit cast.
/// </remarks>
public static explicit operator Point(Size size)
{
return new Point(size.Width, size.Height);
}
/// <summary>
/// Size to SizeF Conversion
/// </summary>
///
/// <remarks>
/// Creates a SizeF based on the dimensions of a given
/// Size. No explicit cast is required.
/// </remarks>
public static implicit operator SizeF(Size p)
{
return new SizeF(p.Width, p.Height);
}
// -----------------------
// Public Constructors
// -----------------------
/// <summary>
/// Size Constructor
/// </summary>
///
/// <remarks>
/// Creates a Size from a Point value.
/// </remarks>
public Size(Point pt)
{
width = pt.X;
height = pt.Y;
}
/// <summary>
/// Size Constructor
/// </summary>
///
/// <remarks>
/// Creates a Size from specified dimensions.
/// </remarks>
public Size(int width, int height)
{
this.width = width;
this.height = height;
}
// -----------------------
// Public Instance Members
// -----------------------
/// <summary>
/// IsEmpty Property
/// </summary>
///
/// <remarks>
/// Indicates if both Width and Height are zero.
/// </remarks>
[Browsable(false)]
public bool IsEmpty
{
get
{
return ((width == 0) && (height == 0));
}
}
/// <summary>
/// Width Property
/// </summary>
///
/// <remarks>
/// The Width coordinate of the Size.
/// </remarks>
public int Width
{
get
{
return width;
}
set
{
width = value;
}
}
/// <summary>
/// Height Property
/// </summary>
///
/// <remarks>
/// The Height coordinate of the Size.
/// </remarks>
public int Height
{
get
{
return height;
}
set
{
height = value;
}
}
/// <summary>
/// Equals Method
/// </summary>
///
/// <remarks>
/// Checks equivalence of this Size and another object.
/// </remarks>
public override bool Equals(object obj)
{
if (!(obj is Size))
return false;
return (this == (Size)obj);
}
/// <summary>
/// GetHashCode Method
/// </summary>
///
/// <remarks>
/// Calculates a hashing value.
/// </remarks>
public override int GetHashCode()
{
return width ^ height;
}
/// <summary>
/// ToString Method
/// </summary>
///
/// <remarks>
/// Formats the Size as a string in coordinate notation.
/// </remarks>
public override string ToString()
{
return String.Format("{{Width={0}, Height={1}}}", width, height);
}
#if NET_2_0
public static Size Add (Size sz1, Size sz2)
{
return new Size (sz1.Width + sz2.Width,
sz1.Height + sz2.Height);
}
public static Size Subtract (Size sz1, Size sz2)
{
return new Size (sz1.Width - sz2.Width,
sz1.Height - sz2.Height);
}
#endif
}
}

View File

@ -0,0 +1,599 @@
#region License
/*
MIT License
Copyright © 2006 The Mono.Xna Team
All rights reserved.
Authors
* Alan McGovern
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#endregion License
using System;
using System.ComponentModel;
using System.Text;
using System.Runtime.InteropServices;
namespace BizHawk.Bizware.BizwareGL
{
[Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct Vector2 : IEquatable<Vector2>
{
#region Private Fields
private static Vector2 zeroVector = new Vector2(0f, 0f);
private static Vector2 unitVector = new Vector2(1f, 1f);
private static Vector2 unitXVector = new Vector2(1f, 0f);
private static Vector2 unitYVector = new Vector2(0f, 1f);
#endregion Private Fields
#region Public Fields
public float X;
public float Y;
#endregion Public Fields
#region Properties
public static Vector2 Zero
{
get { return zeroVector; }
}
public static Vector2 One
{
get { return unitVector; }
}
public static Vector2 UnitX
{
get { return unitXVector; }
}
public static Vector2 UnitY
{
get { return unitYVector; }
}
#endregion Properties
#region Constructors
/// <summary>
/// Constructor foe standard 2D vector.
/// </summary>
/// <param name="x">
/// A <see cref="System.Single"/>
/// </param>
/// <param name="y">
/// A <see cref="System.Single"/>
/// </param>
public Vector2(float x, float y)
{
this.X = x;
this.Y = y;
}
/// <summary>
/// Constructor for "square" vector.
/// </summary>
/// <param name="value">
/// A <see cref="System.Single"/>
/// </param>
public Vector2(float value)
{
this.X = value;
this.Y = value;
}
#endregion Constructors
#region Public Methods
public static void Reflect(ref Vector2 vector, ref Vector2 normal, out Vector2 result)
{
float dot = Dot(vector, normal);
result.X = vector.X - ((2f * dot) * normal.X);
result.Y = vector.Y - ((2f * dot) * normal.Y);
}
public static Vector2 Reflect(Vector2 vector, Vector2 normal)
{
Vector2 result;
Reflect(ref vector, ref normal, out result);
return result;
}
public static Vector2 Add(Vector2 value1, Vector2 value2)
{
value1.X += value2.X;
value1.Y += value2.Y;
return value1;
}
public static void Add(ref Vector2 value1, ref Vector2 value2, out Vector2 result)
{
result.X = value1.X + value2.X;
result.Y = value1.Y + value2.Y;
}
public static Vector2 Barycentric(Vector2 value1, Vector2 value2, Vector2 value3, float amount1, float amount2)
{
return new Vector2(
MathHelper.Barycentric(value1.X, value2.X, value3.X, amount1, amount2),
MathHelper.Barycentric(value1.Y, value2.Y, value3.Y, amount1, amount2));
}
public static void Barycentric(ref Vector2 value1, ref Vector2 value2, ref Vector2 value3, float amount1, float amount2, out Vector2 result)
{
result = new Vector2(
MathHelper.Barycentric(value1.X, value2.X, value3.X, amount1, amount2),
MathHelper.Barycentric(value1.Y, value2.Y, value3.Y, amount1, amount2));
}
public static Vector2 CatmullRom(Vector2 value1, Vector2 value2, Vector2 value3, Vector2 value4, float amount)
{
return new Vector2(
MathHelper.CatmullRom(value1.X, value2.X, value3.X, value4.X, amount),
MathHelper.CatmullRom(value1.Y, value2.Y, value3.Y, value4.Y, amount));
}
public static void CatmullRom(ref Vector2 value1, ref Vector2 value2, ref Vector2 value3, ref Vector2 value4, float amount, out Vector2 result)
{
result = new Vector2(
MathHelper.CatmullRom(value1.X, value2.X, value3.X, value4.X, amount),
MathHelper.CatmullRom(value1.Y, value2.Y, value3.Y, value4.Y, amount));
}
public static Vector2 Clamp(Vector2 value1, Vector2 min, Vector2 max)
{
return new Vector2(
MathHelper.Clamp(value1.X, min.X, max.X),
MathHelper.Clamp(value1.Y, min.Y, max.Y));
}
public static void Clamp(ref Vector2 value1, ref Vector2 min, ref Vector2 max, out Vector2 result)
{
result = new Vector2(
MathHelper.Clamp(value1.X, min.X, max.X),
MathHelper.Clamp(value1.Y, min.Y, max.Y));
}
/// <summary>
/// Returns float precison distanve between two vectors
/// </summary>
/// <param name="value1">
/// A <see cref="Vector2"/>
/// </param>
/// <param name="value2">
/// A <see cref="Vector2"/>
/// </param>
/// <returns>
/// A <see cref="System.Single"/>
/// </returns>
public static float Distance(Vector2 value1, Vector2 value2)
{
return (float)Math.Sqrt((value1.X - value2.X) * (value1.X - value2.X) + (value1.Y - value2.Y) * (value1.Y - value2.Y));
}
public static void Distance(ref Vector2 value1, ref Vector2 value2, out float result)
{
result = (float)Math.Sqrt((value1.X - value2.X) * (value1.X - value2.X) + (value1.Y - value2.Y) * (value1.Y - value2.Y));
}
public static float DistanceSquared(Vector2 value1, Vector2 value2)
{
return (value1.X - value2.X) * (value1.X - value2.X) + (value1.Y - value2.Y) * (value1.Y - value2.Y);
}
public static void DistanceSquared(ref Vector2 value1, ref Vector2 value2, out float result)
{
result = (value1.X - value2.X) * (value1.X - value2.X) + (value1.Y - value2.Y) * (value1.Y - value2.Y);
}
/// <summary>
/// Devide first vector with the secund vector
/// </summary>
/// <param name="value1">
/// A <see cref="Vector2"/>
/// </param>
/// <param name="value2">
/// A <see cref="Vector2"/>
/// </param>
/// <returns>
/// A <see cref="Vector2"/>
/// </returns>
public static Vector2 Divide(Vector2 value1, Vector2 value2)
{
value1.X /= value2.X;
value1.Y /= value2.Y;
return value1;
}
public static void Divide(ref Vector2 value1, ref Vector2 value2, out Vector2 result)
{
result.X = value1.X / value2.X;
result.Y = value1.Y / value2.Y;
}
public static Vector2 Divide(Vector2 value1, float divider)
{
float factor = 1.0f / divider;
value1.X *= factor;
value1.Y *= factor;
return value1;
}
public static void Divide(ref Vector2 value1, float divider, out Vector2 result)
{
float factor = 1.0f / divider;
result.X = value1.X * factor;
result.Y = value1.Y * factor;
}
public static float Dot(Vector2 value1, Vector2 value2)
{
return value1.X * value2.X + value1.Y * value2.Y;
}
public static void Dot(ref Vector2 value1, ref Vector2 value2, out float result)
{
result = value1.X * value2.X + value1.Y * value2.Y;
}
public override bool Equals(object obj)
{
return (obj is Vector2) ? this == ((Vector2)obj) : false;
}
public bool Equals(Vector2 other)
{
return this == other;
}
public override int GetHashCode()
{
return (int)(this.X + this.Y);
}
public static Vector2 Hermite(Vector2 value1, Vector2 tangent1, Vector2 value2, Vector2 tangent2, float amount)
{
value1.X = MathHelper.Hermite(value1.X, tangent1.X, value2.X, tangent2.X, amount);
value1.Y = MathHelper.Hermite(value1.Y, tangent1.Y, value2.Y, tangent2.Y, amount);
return value1;
}
public static void Hermite(ref Vector2 value1, ref Vector2 tangent1, ref Vector2 value2, ref Vector2 tangent2, float amount, out Vector2 result)
{
result.X = MathHelper.Hermite(value1.X, tangent1.X, value2.X, tangent2.X, amount);
result.Y = MathHelper.Hermite(value1.Y, tangent1.Y, value2.Y, tangent2.Y, amount);
}
public float Length()
{
return (float)Math.Sqrt((double)(X * X + Y * Y));
}
public float LengthSquared()
{
return X * X + Y * Y;
}
public static Vector2 Lerp(Vector2 value1, Vector2 value2, float amount)
{
return new Vector2(
MathHelper.Lerp(value1.X, value2.X, amount),
MathHelper.Lerp(value1.Y, value2.Y, amount));
}
public static void Lerp(ref Vector2 value1, ref Vector2 value2, float amount, out Vector2 result)
{
result = new Vector2(
MathHelper.Lerp(value1.X, value2.X, amount),
MathHelper.Lerp(value1.Y, value2.Y, amount));
}
public static Vector2 Max(Vector2 value1, Vector2 value2)
{
return new Vector2(
MathHelper.Max(value1.X, value2.X),
MathHelper.Max(value1.Y, value2.Y));
}
public static void Max(ref Vector2 value1, ref Vector2 value2, out Vector2 result)
{
result = new Vector2(
MathHelper.Max(value1.X, value2.X),
MathHelper.Max(value1.Y, value2.Y));
}
public static Vector2 Min(Vector2 value1, Vector2 value2)
{
return new Vector2(
MathHelper.Min(value1.X, value2.X),
MathHelper.Min(value1.Y, value2.Y));
}
public static void Min(ref Vector2 value1, ref Vector2 value2, out Vector2 result)
{
result = new Vector2(
MathHelper.Min(value1.X, value2.X),
MathHelper.Min(value1.Y, value2.Y));
}
public static Vector2 Multiply(Vector2 value1, Vector2 value2)
{
value1.X *= value2.X;
value1.Y *= value2.Y;
return value1;
}
public static Vector2 Multiply(Vector2 value1, float scaleFactor)
{
value1.X *= scaleFactor;
value1.Y *= scaleFactor;
return value1;
}
public static void Multiply(ref Vector2 value1, float scaleFactor, out Vector2 result)
{
result.X = value1.X * scaleFactor;
result.Y = value1.Y * scaleFactor;
}
public static void Multiply(ref Vector2 value1, ref Vector2 value2, out Vector2 result)
{
result.X = value1.X * value2.X;
result.Y = value1.Y * value2.Y;
}
public static Vector2 Negate(Vector2 value)
{
value.X = -value.X;
value.Y = -value.Y;
return value;
}
public static void Negate(ref Vector2 value, out Vector2 result)
{
result.X = -value.X;
result.Y = -value.Y;
}
public void Normalize()
{
float factor = 1f / (float)Math.Sqrt((double)(X * X + Y * Y));
X *= factor;
Y *= factor;
}
public static Vector2 Normalize(Vector2 value)
{
float factor = 1f / (float)Math.Sqrt((double)(value.X * value.X + value.Y * value.Y));
value.X *= factor;
value.Y *= factor;
return value;
}
public static void Normalize(ref Vector2 value, out Vector2 result)
{
float factor = 1f / (float)Math.Sqrt((double)(value.X * value.X + value.Y * value.Y));
result.X = value.X * factor;
result.Y = value.Y * factor;
}
public static Vector2 SmoothStep(Vector2 value1, Vector2 value2, float amount)
{
return new Vector2(
MathHelper.SmoothStep(value1.X, value2.X, amount),
MathHelper.SmoothStep(value1.Y, value2.Y, amount));
}
public static void SmoothStep(ref Vector2 value1, ref Vector2 value2, float amount, out Vector2 result)
{
result = new Vector2(
MathHelper.SmoothStep(value1.X, value2.X, amount),
MathHelper.SmoothStep(value1.Y, value2.Y, amount));
}
public static Vector2 Subtract(Vector2 value1, Vector2 value2)
{
value1.X -= value2.X;
value1.Y -= value2.Y;
return value1;
}
public static void Subtract(ref Vector2 value1, ref Vector2 value2, out Vector2 result)
{
result.X = value1.X - value2.X;
result.Y = value1.Y - value2.Y;
}
public static Vector2 Transform(Vector2 position, Matrix matrix)
{
Transform(ref position, ref matrix, out position);
return position;
}
public static void Transform(ref Vector2 position, ref Matrix matrix, out Vector2 result)
{
result = new Vector2((position.X * matrix.M11) + (position.Y * matrix.M21) + matrix.M41,
(position.X * matrix.M12) + (position.Y * matrix.M22) + matrix.M42);
}
public static Vector2 Transform(Vector2 value, Quaternion rotation)
{
throw new NotImplementedException();
}
public static void Transform(ref Vector2 value, ref Quaternion rotation, out Vector2 result)
{
throw new NotImplementedException();
}
public static void Transform(Vector2[] sourceArray, ref Matrix matrix, Vector2[] destinationArray)
{
throw new NotImplementedException();
}
public static void Transform(Vector2[] sourceArray, ref Quaternion rotation, Vector2[] destinationArray)
{
throw new NotImplementedException();
}
public static void Transform(Vector2[] sourceArray, int sourceIndex, ref Matrix matrix, Vector2[] destinationArray, int destinationIndex, int length)
{
throw new NotImplementedException();
}
public static void Transform(Vector2[] sourceArray, int sourceIndex, ref Quaternion rotation, Vector2[] destinationArray, int destinationIndex, int length)
{
throw new NotImplementedException();
}
public static Vector2 TransformNormal(Vector2 normal, Matrix matrix)
{
Vector2.TransformNormal(ref normal, ref matrix, out normal);
return normal;
}
public static void TransformNormal(ref Vector2 normal, ref Matrix matrix, out Vector2 result)
{
result = new Vector2((normal.X * matrix.M11) + (normal.Y * matrix.M21),
(normal.X * matrix.M12) + (normal.Y * matrix.M22));
}
public static void TransformNormal(Vector2[] sourceArray, ref Matrix matrix, Vector2[] destinationArray)
{
throw new NotImplementedException();
}
public static void TransformNormal(Vector2[] sourceArray, int sourceIndex, ref Matrix matrix, Vector2[] destinationArray, int destinationIndex, int length)
{
throw new NotImplementedException();
}
public override string ToString()
{
StringBuilder sb = new StringBuilder(24);
sb.Append("{X:");
sb.Append(this.X);
sb.Append(" Y:");
sb.Append(this.Y);
sb.Append("}");
return sb.ToString();
}
#endregion Public Methods
#region Operators
public static Vector2 operator -(Vector2 value)
{
value.X = -value.X;
value.Y = -value.Y;
return value;
}
public static bool operator ==(Vector2 value1, Vector2 value2)
{
return value1.X == value2.X && value1.Y == value2.Y;
}
public static bool operator !=(Vector2 value1, Vector2 value2)
{
return value1.X != value2.X || value1.Y != value2.Y;
}
public static Vector2 operator +(Vector2 value1, Vector2 value2)
{
value1.X += value2.X;
value1.Y += value2.Y;
return value1;
}
public static Vector2 operator -(Vector2 value1, Vector2 value2)
{
value1.X -= value2.X;
value1.Y -= value2.Y;
return value1;
}
public static Vector2 operator *(Vector2 value1, Vector2 value2)
{
value1.X *= value2.X;
value1.Y *= value2.Y;
return value1;
}
public static Vector2 operator *(Vector2 value, float scaleFactor)
{
value.X *= scaleFactor;
value.Y *= scaleFactor;
return value;
}
public static Vector2 operator *(float scaleFactor, Vector2 value)
{
value.X *= scaleFactor;
value.Y *= scaleFactor;
return value;
}
public static Vector2 operator /(Vector2 value1, Vector2 value2)
{
value1.X /= value2.X;
value1.Y /= value2.Y;
return value1;
}
public static Vector2 operator /(Vector2 value1, float divider)
{
float factor = 1 / divider;
value1.X *= factor;
value1.Y *= factor;
return value1;
}
#endregion Operators
}
}

View File

@ -0,0 +1,679 @@
#region License
/*
MIT License
Copyright © 2006 The Mono.Xna Team
All rights reserved.
Authors:
* Alan McGovern
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#endregion License
using System;
using System.ComponentModel;
using System.Text;
using System.Runtime.InteropServices;
namespace BizHawk.Bizware.BizwareGL
{
[Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct Vector3 : IEquatable<Vector3>
{
#region Private Fields
private static Vector3 zero = new Vector3(0f, 0f, 0f);
private static Vector3 one = new Vector3(1f, 1f, 1f);
private static Vector3 unitX = new Vector3(1f, 0f, 0f);
private static Vector3 unitY = new Vector3(0f, 1f, 0f);
private static Vector3 unitZ = new Vector3(0f, 0f, 1f);
private static Vector3 up = new Vector3(0f, 1f, 0f);
private static Vector3 down = new Vector3(0f, -1f, 0f);
private static Vector3 right = new Vector3(1f, 0f, 0f);
private static Vector3 left = new Vector3(-1f, 0f, 0f);
private static Vector3 forward = new Vector3(0f, 0f, -1f);
private static Vector3 backward = new Vector3(0f, 0f, 1f);
#endregion Private Fields
#region Public Fields
public float X;
public float Y;
public float Z;
#endregion Public Fields
#region Properties
public static Vector3 Zero
{
get { return zero; }
}
public static Vector3 One
{
get { return one; }
}
public static Vector3 UnitX
{
get { return unitX; }
}
public static Vector3 UnitY
{
get { return unitY; }
}
public static Vector3 UnitZ
{
get { return unitZ; }
}
public static Vector3 Up
{
get { return up; }
}
public static Vector3 Down
{
get { return down; }
}
public static Vector3 Right
{
get { return right; }
}
public static Vector3 Left
{
get { return left; }
}
public static Vector3 Forward
{
get { return forward; }
}
public static Vector3 Backward
{
get { return backward; }
}
#endregion Properties
#region Constructors
public Vector3(float x, float y, float z)
{
this.X = x;
this.Y = y;
this.Z = z;
}
public Vector3(float value)
{
this.X = value;
this.Y = value;
this.Z = value;
}
public Vector3(Vector2 value, float z)
{
this.X = value.X;
this.Y = value.Y;
this.Z = z;
}
#endregion Constructors
#region Public Methods
public static Vector3 Add(Vector3 value1, Vector3 value2)
{
value1.X += value2.X;
value1.Y += value2.Y;
value1.Z += value2.Z;
return value1;
}
public static void Add(ref Vector3 value1, ref Vector3 value2, out Vector3 result)
{
result.X = value1.X + value2.X;
result.Y = value1.Y + value2.Y;
result.Z = value1.Z + value2.Z;
}
public static Vector3 Barycentric(Vector3 value1, Vector3 value2, Vector3 value3, float amount1, float amount2)
{
return new Vector3(
MathHelper.Barycentric(value1.X, value2.X, value3.X, amount1, amount2),
MathHelper.Barycentric(value1.Y, value2.Y, value3.Y, amount1, amount2),
MathHelper.Barycentric(value1.Z, value2.Z, value3.Z, amount1, amount2));
}
public static void Barycentric(ref Vector3 value1, ref Vector3 value2, ref Vector3 value3, float amount1, float amount2, out Vector3 result)
{
result = new Vector3(
MathHelper.Barycentric(value1.X, value2.X, value3.X, amount1, amount2),
MathHelper.Barycentric(value1.Y, value2.Y, value3.Y, amount1, amount2),
MathHelper.Barycentric(value1.Z, value2.Z, value3.Z, amount1, amount2));
}
public static Vector3 CatmullRom(Vector3 value1, Vector3 value2, Vector3 value3, Vector3 value4, float amount)
{
return new Vector3(
MathHelper.CatmullRom(value1.X, value2.X, value3.X, value4.X, amount),
MathHelper.CatmullRom(value1.Y, value2.Y, value3.Y, value4.Y, amount),
MathHelper.CatmullRom(value1.Z, value2.Z, value3.Z, value4.Z, amount));
}
public static void CatmullRom(ref Vector3 value1, ref Vector3 value2, ref Vector3 value3, ref Vector3 value4, float amount, out Vector3 result)
{
result = new Vector3(
MathHelper.CatmullRom(value1.X, value2.X, value3.X, value4.X, amount),
MathHelper.CatmullRom(value1.Y, value2.Y, value3.Y, value4.Y, amount),
MathHelper.CatmullRom(value1.Z, value2.Z, value3.Z, value4.Z, amount));
}
public static Vector3 Clamp(Vector3 value1, Vector3 min, Vector3 max)
{
return new Vector3(
MathHelper.Clamp(value1.X, min.X, max.X),
MathHelper.Clamp(value1.Y, min.Y, max.Y),
MathHelper.Clamp(value1.Z, min.Z, max.Z));
}
public static void Clamp(ref Vector3 value1, ref Vector3 min, ref Vector3 max, out Vector3 result)
{
result = new Vector3(
MathHelper.Clamp(value1.X, min.X, max.X),
MathHelper.Clamp(value1.Y, min.Y, max.Y),
MathHelper.Clamp(value1.Z, min.Z, max.Z));
}
public static Vector3 Cross(Vector3 vector1, Vector3 vector2)
{
Vector3 result;
result.X = vector1.Y * vector2.Z - vector2.Y * vector1.Z;
result.Y = vector2.X * vector1.Z - vector1.X * vector2.Z;
result.Z = vector1.X * vector2.Y - vector2.X * vector1.Y;
return result;
}
public static void Cross(ref Vector3 vector1, ref Vector3 vector2, out Vector3 result)
{
result.X = vector1.Y * vector2.Z - vector2.Y * vector1.Z;
result.Y = vector2.X * vector1.Z - vector1.X * vector2.Z;
result.Z = vector1.X * vector2.Y - vector2.X * vector1.Y;
}
public static float Distance(Vector3 value1, Vector3 value2)
{
return (float)Math.Sqrt((value1.X - value2.X) * (value1.X - value2.X) +
(value1.Y - value2.Y) * (value1.Y - value2.Y) +
(value1.Z - value2.Z) * (value1.Z - value2.Z));
}
public static void Distance(ref Vector3 value1, ref Vector3 value2, out float result)
{
result = (float)Math.Sqrt((value1.X - value2.X) * (value1.X - value2.X) +
(value1.Y - value2.Y) * (value1.Y - value2.Y) +
(value1.Z - value2.Z) * (value1.Z - value2.Z));
}
public static float DistanceSquared(Vector3 value1, Vector3 value2)
{
return (value1.X - value2.X) * (value1.X - value2.X) +
(value1.Y - value2.Y) * (value1.Y - value2.Y) +
(value1.Z - value2.Z) * (value1.Z - value2.Z); ;
}
public static void DistanceSquared(ref Vector3 value1, ref Vector3 value2, out float result)
{
result = (value1.X - value2.X) * (value1.X - value2.X) +
(value1.Y - value2.Y) * (value1.Y - value2.Y) +
(value1.Z - value2.Z) * (value1.Z - value2.Z);
}
public static Vector3 Divide(Vector3 value1, Vector3 value2)
{
value1.X /= value2.X;
value1.Y /= value2.Y;
value1.Z /= value2.Z;
return value1;
}
public static Vector3 Divide(Vector3 value1, float value2)
{
float factor = 1.0f / value2;
value1.X *= factor;
value1.Y *= factor;
value1.Z *= factor;
return value1;
}
public static void Divide(ref Vector3 value1, float divisor, out Vector3 result)
{
float factor = 1.0f / divisor;
result.X = value1.X * factor;
result.Y = value1.Y * factor;
result.Z = value1.Z * factor;
}
public static void Divide(ref Vector3 value1, ref Vector3 value2, out Vector3 result)
{
result.X = value1.X / value2.X;
result.Y = value1.Y / value2.Y;
result.Z = value1.Z / value2.Z;
}
public static float Dot(Vector3 vector1, Vector3 vector2)
{
return vector1.X * vector2.X + vector1.Y * vector2.Y + vector1.Z * vector2.Z;
}
public static void Dot(ref Vector3 vector1, ref Vector3 vector2, out float result)
{
result = vector1.X * vector2.X + vector1.Y * vector2.Y + vector1.Z * vector2.Z;
}
public override bool Equals(object obj)
{
return (obj is Vector3) ? this == (Vector3)obj : false;
}
public bool Equals(Vector3 other)
{
return this == other;
}
public override int GetHashCode()
{
return (int)(this.X + this.Y + this.Z);
}
public static Vector3 Hermite(Vector3 value1, Vector3 tangent1, Vector3 value2, Vector3 tangent2, float amount)
{
value1.X = MathHelper.Hermite(value1.X, tangent1.X, value2.X, tangent2.X, amount);
value1.Y = MathHelper.Hermite(value1.Y, tangent1.Y, value2.Y, tangent2.Y, amount);
value1.Z = MathHelper.Hermite(value1.Z, tangent1.Z, value2.Z, tangent2.Z, amount);
return value1;
}
public static void Hermite(ref Vector3 value1, ref Vector3 tangent1, ref Vector3 value2, ref Vector3 tangent2, float amount, out Vector3 result)
{
result.X = MathHelper.Hermite(value1.X, tangent1.X, value2.X, tangent2.X, amount);
result.Y = MathHelper.Hermite(value1.Y, tangent1.Y, value2.Y, tangent2.Y, amount);
result.Z = MathHelper.Hermite(value1.Z, tangent1.Z, value2.Z, tangent2.Z, amount);
}
public float Length()
{
return (float)Math.Sqrt((double)(X * X + Y * Y + Z * Z));
}
public float LengthSquared()
{
return X * X + Y * Y + Z * Z;
}
public static Vector3 Lerp(Vector3 value1, Vector3 value2, float amount)
{
return new Vector3(
MathHelper.Lerp(value1.X, value2.X, amount),
MathHelper.Lerp(value1.Y, value2.Y, amount),
MathHelper.Lerp(value1.Z, value2.Z, amount));
}
public static void Lerp(ref Vector3 value1, ref Vector3 value2, float amount, out Vector3 result)
{
result = new Vector3(
MathHelper.Lerp(value1.X, value2.X, amount),
MathHelper.Lerp(value1.Y, value2.Y, amount),
MathHelper.Lerp(value1.Z, value2.Z, amount));
}
public static Vector3 Max(Vector3 value1, Vector3 value2)
{
return new Vector3(
MathHelper.Max(value1.X, value2.X),
MathHelper.Max(value1.Y, value2.Y),
MathHelper.Max(value1.Z, value2.Z));
}
public static void Max(ref Vector3 value1, ref Vector3 value2, out Vector3 result)
{
result = new Vector3(
MathHelper.Max(value1.X, value2.X),
MathHelper.Max(value1.Y, value2.Y),
MathHelper.Max(value1.Z, value2.Z));
}
public static Vector3 Min(Vector3 value1, Vector3 value2)
{
return new Vector3(
MathHelper.Min(value1.X, value2.X),
MathHelper.Min(value1.Y, value2.Y),
MathHelper.Min(value1.Z, value2.Z));
}
public static void Min(ref Vector3 value1, ref Vector3 value2, out Vector3 result)
{
result = new Vector3(
MathHelper.Min(value1.X, value2.X),
MathHelper.Min(value1.Y, value2.Y),
MathHelper.Min(value1.Z, value2.Z));
}
public static Vector3 Multiply(Vector3 value1, Vector3 value2)
{
value1.X *= value2.X;
value1.Y *= value2.Y;
value1.Z *= value2.Z;
return value1;
}
public static Vector3 Multiply(Vector3 value1, float scaleFactor)
{
value1.X *= scaleFactor;
value1.Y *= scaleFactor;
value1.Z *= scaleFactor;
return value1;
}
public static void Multiply(ref Vector3 value1, float scaleFactor, out Vector3 result)
{
result.X = value1.X * scaleFactor;
result.Y = value1.Y * scaleFactor;
result.Z = value1.Z * scaleFactor;
}
public static void Multiply(ref Vector3 value1, ref Vector3 value2, out Vector3 result)
{
result.X = value1.X * value2.X;
result.Y = value1.Y * value2.Y;
result.Z = value1.Z * value2.Z;
}
public static Vector3 Negate(Vector3 value)
{
value.X = -value.X;
value.Y = -value.Y;
value.Z = -value.Z;
return value;
}
public static void Negate(ref Vector3 value, out Vector3 result)
{
result.X = -value.X;
result.Y = -value.Y;
result.Z = -value.Z;
}
public void Normalize()
{
float factor = 1f / (float)Math.Sqrt((double)(X * X + Y * Y + Z * Z));
X *= factor;
Y *= factor;
Z *= factor;
}
public static Vector3 Normalize(Vector3 value)
{
float factor = 1f / (float)Math.Sqrt((double)(value.X * value.X + value.Y * value.Y + value.Z * value.Z));
value.X *= factor;
value.Y *= factor;
value.Z *= factor;
return value;
}
public static void Normalize(ref Vector3 value, out Vector3 result)
{
float factor = 1f / (float)Math.Sqrt((double)(value.X * value.X + value.Y * value.Y + value.Z * value.Z));
result.X = value.X * factor;
result.Y = value.Y * factor;
result.Z = value.Z * factor;
}
public static Vector3 Reflect(Vector3 vector, Vector3 normal)
{
float dotTimesTwo = 2f * Dot(vector, normal);
vector.X = vector.X - dotTimesTwo * normal.X;
vector.Y = vector.Y - dotTimesTwo * normal.Y;
vector.Z = vector.Z - dotTimesTwo * normal.Z;
return vector;
}
public static void Reflect(ref Vector3 vector, ref Vector3 normal, out Vector3 result)
{
float dotTimesTwo = 2f * Dot(vector, normal);
result.X = vector.X - dotTimesTwo * normal.X;
result.Y = vector.Y - dotTimesTwo * normal.Y;
result.Z = vector.Z - dotTimesTwo * normal.Z;
}
public static Vector3 SmoothStep(Vector3 value1, Vector3 value2, float amount)
{
return new Vector3(
MathHelper.SmoothStep(value1.X, value2.X, amount),
MathHelper.SmoothStep(value1.Y, value2.Y, amount),
MathHelper.SmoothStep(value1.Z, value2.Z, amount));
}
public static void SmoothStep(ref Vector3 value1, ref Vector3 value2, float amount, out Vector3 result)
{
result = new Vector3(
MathHelper.SmoothStep(value1.X, value2.X, amount),
MathHelper.SmoothStep(value1.Y, value2.Y, amount),
MathHelper.SmoothStep(value1.Z, value2.Z, amount));
}
public static Vector3 Subtract(Vector3 value1, Vector3 value2)
{
value1.X -= value2.X;
value1.Y -= value2.Y;
value1.Z -= value2.Z;
return value1;
}
public static void Subtract(ref Vector3 value1, ref Vector3 value2, out Vector3 result)
{
result.X = value1.X - value2.X;
result.Y = value1.Y - value2.Y;
result.Z = value1.Z - value2.Z;
}
public override string ToString()
{
StringBuilder sb = new StringBuilder(32);
sb.Append("{X:");
sb.Append(this.X);
sb.Append(" Y:");
sb.Append(this.Y);
sb.Append(" Z:");
sb.Append(this.Z);
sb.Append("}");
return sb.ToString();
}
public static Vector3 Transform(Vector3 position, Matrix matrix)
{
Transform(ref position, ref matrix, out position);
return position;
}
public static void Transform(ref Vector3 position, ref Matrix matrix, out Vector3 result)
{
result = new Vector3((position.X * matrix.M11) + (position.Y * matrix.M21) + (position.Z * matrix.M31) + matrix.M41,
(position.X * matrix.M12) + (position.Y * matrix.M22) + (position.Z * matrix.M32) + matrix.M42,
(position.X * matrix.M13) + (position.Y * matrix.M23) + (position.Z * matrix.M33) + matrix.M43);
}
public static Vector3 Transform(Vector3 value, Quaternion rotation)
{
throw new NotImplementedException();
}
public static void Transform(Vector3[] sourceArray, ref Matrix matrix, Vector3[] destinationArray)
{
throw new NotImplementedException();
}
public static void Transform(Vector3[] sourceArray, ref Quaternion rotation, Vector3[] destinationArray)
{
throw new NotImplementedException();
}
public static void Transform(Vector3[] sourceArray, int sourceIndex, ref Matrix matrix, Vector3[] destinationArray, int destinationIndex, int length)
{
throw new NotImplementedException();
}
public static void Transform(Vector3[] sourceArray, int sourceIndex, ref Quaternion rotation, Vector3[] destinationArray, int destinationIndex, int length)
{
throw new NotImplementedException();
}
public static void Transform(ref Vector3 value, ref Quaternion rotation, out Vector3 result)
{
throw new NotImplementedException();
}
public static void TransformNormal(Vector3[] sourceArray, ref Matrix matrix, Vector3[] destinationArray)
{
throw new NotImplementedException();
}
public static void TransformNormal(Vector3[] sourceArray, int sourceIndex, ref Matrix matrix, Vector3[] destinationArray, int destinationIndex, int length)
{
throw new NotImplementedException();
}
public static Vector3 TransformNormal(Vector3 normal, Matrix matrix)
{
TransformNormal(ref normal, ref matrix, out normal);
return normal;
}
public static void TransformNormal(ref Vector3 normal, ref Matrix matrix, out Vector3 result)
{
result = new Vector3((normal.X * matrix.M11) + (normal.Y * matrix.M21) + (normal.Z * matrix.M31),
(normal.X * matrix.M12) + (normal.Y * matrix.M22) + (normal.Z * matrix.M32),
(normal.X * matrix.M13) + (normal.Y * matrix.M23) + (normal.Z * matrix.M33));
}
#endregion Public methods
#region Operators
public static bool operator ==(Vector3 value1, Vector3 value2)
{
return value1.X == value2.X
&& value1.Y == value2.Y
&& value1.Z == value2.Z;
}
public static bool operator !=(Vector3 value1, Vector3 value2)
{
return value1.X != value2.X
|| value1.Y != value2.Y
|| value1.Z != value2.Z;
}
public static Vector3 operator +(Vector3 value1, Vector3 value2)
{
value1.X += value2.X;
value1.Y += value2.Y;
value1.Z += value2.Z;
return value1;
}
public static Vector3 operator -(Vector3 value)
{
value = new Vector3(-value.X, -value.Y, -value.Z);
return value;
}
public static Vector3 operator -(Vector3 value1, Vector3 value2)
{
value1.X -= value2.X;
value1.Y -= value2.Y;
value1.Z -= value2.Z;
return value1;
}
public static Vector3 operator *(Vector3 value1, Vector3 value2)
{
value1.X *= value2.X;
value1.Y *= value2.Y;
value1.Z *= value2.Z;
return value1;
}
public static Vector3 operator *(Vector3 value, float scaleFactor)
{
value.X *= scaleFactor;
value.Y *= scaleFactor;
value.Z *= scaleFactor;
return value;
}
public static Vector3 operator *(float scaleFactor, Vector3 value)
{
value.X *= scaleFactor;
value.Y *= scaleFactor;
value.Z *= scaleFactor;
return value;
}
public static Vector3 operator /(Vector3 value1, Vector3 value2)
{
value1.X /= value2.X;
value1.Y /= value2.Y;
value1.Z /= value2.Z;
return value1;
}
public static Vector3 operator /(Vector3 value, float divider)
{
float factor = 1 / divider;
value.X *= factor;
value.Y *= factor;
value.Z *= factor;
return value;
}
#endregion
}
}

View File

@ -0,0 +1,709 @@
#region License
/*
MIT License
Copyright © 2006 The Mono.Xna Team
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#endregion License
using System;
using System.ComponentModel;
using System.Text;
using System.Runtime.InteropServices;
namespace BizHawk.Bizware.BizwareGL
{
[Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct Vector4 : IEquatable<Vector4>
{
#region Private Fields
private static Vector4 zeroVector = new Vector4();
private static Vector4 unitVector = new Vector4(1f, 1f, 1f, 1f);
private static Vector4 unitXVector = new Vector4(1f, 0f, 0f, 0f);
private static Vector4 unitYVector = new Vector4(0f, 1f, 0f, 0f);
private static Vector4 unitZVector = new Vector4(0f, 0f, 1f, 0f);
private static Vector4 unitWVector = new Vector4(0f, 0f, 0f, 1f);
#endregion Private Fields
#region Public Fields
public float X;
public float Y;
public float Z;
public float W;
#endregion Public Fields
#region Properties
public static Vector4 Zero
{
get { return zeroVector; }
}
public static Vector4 One
{
get { return unitVector; }
}
public static Vector4 UnitX
{
get { return unitXVector; }
}
public static Vector4 UnitY
{
get { return unitYVector; }
}
public static Vector4 UnitZ
{
get { return unitZVector; }
}
public static Vector4 UnitW
{
get { return unitWVector; }
}
#endregion Properties
#region Constructors
public Vector4(float x, float y, float z, float w)
{
this.X = x;
this.Y = y;
this.Z = z;
this.W = w;
}
public Vector4(Vector2 value, float z, float w)
{
this.X = value.X;
this.Y = value.Y;
this.Z = z;
this.W = w;
}
public Vector4(Vector3 value, float w)
{
this.X = value.X;
this.Y = value.Y;
this.Z = value.Z;
this.W = w;
}
public Vector4(float value)
{
this.X = value;
this.Y = value;
this.Z = value;
this.W = value;
}
#endregion
#region Public Methods
public static Vector4 Add(Vector4 value1, Vector4 value2)
{
value1.W += value2.W;
value1.X += value2.X;
value1.Y += value2.Y;
value1.Z += value2.Z;
return value1;
}
public static void Add(ref Vector4 value1, ref Vector4 value2, out Vector4 result)
{
result.W = value1.W + value2.W;
result.X = value1.X + value2.X;
result.Y = value1.Y + value2.Y;
result.Z = value1.Z + value2.Z;
}
public static Vector4 Barycentric(Vector4 value1, Vector4 value2, Vector4 value3, float amount1, float amount2)
{
return new Vector4(
MathHelper.Barycentric(value1.X, value2.X, value3.X, amount1, amount2),
MathHelper.Barycentric(value1.Y, value2.Y, value3.Y, amount1, amount2),
MathHelper.Barycentric(value1.Z, value2.Z, value3.Z, amount1, amount2),
MathHelper.Barycentric(value1.W, value2.W, value3.W, amount1, amount2));
}
public static void Barycentric(ref Vector4 value1, ref Vector4 value2, ref Vector4 value3, float amount1, float amount2, out Vector4 result)
{
result = new Vector4(
MathHelper.Barycentric(value1.X, value2.X, value3.X, amount1, amount2),
MathHelper.Barycentric(value1.Y, value2.Y, value3.Y, amount1, amount2),
MathHelper.Barycentric(value1.Z, value2.Z, value3.Z, amount1, amount2),
MathHelper.Barycentric(value1.W, value2.W, value3.W, amount1, amount2));
}
public static Vector4 CatmullRom(Vector4 value1, Vector4 value2, Vector4 value3, Vector4 value4, float amount)
{
return new Vector4(
MathHelper.CatmullRom(value1.X, value2.X, value3.X, value4.X, amount),
MathHelper.CatmullRom(value1.Y, value2.Y, value3.Y, value4.Y, amount),
MathHelper.CatmullRom(value1.Z, value2.Z, value3.Z, value4.Z, amount),
MathHelper.CatmullRom(value1.W, value2.W, value3.W, value4.W, amount));
}
public static void CatmullRom(ref Vector4 value1, ref Vector4 value2, ref Vector4 value3, ref Vector4 value4, float amount, out Vector4 result)
{
result = new Vector4(
MathHelper.CatmullRom(value1.X, value2.X, value3.X, value4.X, amount),
MathHelper.CatmullRom(value1.Y, value2.Y, value3.Y, value4.Y, amount),
MathHelper.CatmullRom(value1.Z, value2.Z, value3.Z, value4.Z, amount),
MathHelper.CatmullRom(value1.W, value2.W, value3.W, value4.W, amount));
}
public static Vector4 Clamp(Vector4 value1, Vector4 min, Vector4 max)
{
return new Vector4(
MathHelper.Clamp(value1.X, min.X, max.X),
MathHelper.Clamp(value1.Y, min.Y, max.Y),
MathHelper.Clamp(value1.Z, min.Z, max.Z),
MathHelper.Clamp(value1.W, min.W, max.W));
}
public static void Clamp(ref Vector4 value1, ref Vector4 min, ref Vector4 max, out Vector4 result)
{
result = new Vector4(
MathHelper.Clamp(value1.X, min.X, max.X),
MathHelper.Clamp(value1.Y, min.Y, max.Y),
MathHelper.Clamp(value1.Z, min.Z, max.Z),
MathHelper.Clamp(value1.W, min.W, max.W));
}
public static float Distance(Vector4 value1, Vector4 value2)
{
return (float)Math.Sqrt((value1.W - value2.W) * (value1.W - value2.W) +
(value1.X - value2.X) * (value1.X - value2.X) +
(value1.Y - value2.Y) * (value1.Y - value2.Y) +
(value1.Z - value2.Z) * (value1.Z - value2.Z));
}
public static void Distance(ref Vector4 value1, ref Vector4 value2, out float result)
{
result = (float)Math.Sqrt((value1.W - value2.W) * (value1.W - value2.W) +
(value1.X - value2.X) * (value1.X - value2.X) +
(value1.Y - value2.Y) * (value1.Y - value2.Y) +
(value1.Z - value2.Z) * (value1.Z - value2.Z));
}
public static float DistanceSquared(Vector4 value1, Vector4 value2)
{
return (value1.W - value2.W) * (value1.W - value2.W) +
(value1.X - value2.X) * (value1.X - value2.X) +
(value1.Y - value2.Y) * (value1.Y - value2.Y) +
(value1.Z - value2.Z) * (value1.Z - value2.Z);
}
public static void DistanceSquared(ref Vector4 value1, ref Vector4 value2, out float result)
{
result = (value1.W - value2.W) * (value1.W - value2.W) +
(value1.X - value2.X) * (value1.X - value2.X) +
(value1.Y - value2.Y) * (value1.Y - value2.Y) +
(value1.Z - value2.Z) * (value1.Z - value2.Z);
}
public static Vector4 Divide(Vector4 value1, Vector4 value2)
{
value1.W /= value2.W;
value1.X /= value2.X;
value1.Y /= value2.Y;
value1.Z /= value2.Z;
return value1;
}
public static Vector4 Divide(Vector4 value1, float divider)
{
float factor = 1f / divider;
value1.W *= factor;
value1.X *= factor;
value1.Y *= factor;
value1.Z *= factor;
return value1;
}
public static void Divide(ref Vector4 value1, float divider, out Vector4 result)
{
float factor = 1f / divider;
result.W = value1.W * factor;
result.X = value1.X * factor;
result.Y = value1.Y * factor;
result.Z = value1.Z * factor;
}
public static void Divide(ref Vector4 value1, ref Vector4 value2, out Vector4 result)
{
result.W = value1.W / value2.W;
result.X = value1.X / value2.X;
result.Y = value1.Y / value2.Y;
result.Z = value1.Z / value2.Z;
}
public static float Dot(Vector4 vector1, Vector4 vector2)
{
return vector1.X * vector2.X + vector1.Y * vector2.Y + vector1.Z * vector2.Z + vector1.W * vector2.W;
}
public static void Dot(ref Vector4 vector1, ref Vector4 vector2, out float result)
{
result = vector1.X * vector2.X + vector1.Y * vector2.Y + vector1.Z * vector2.Z + vector1.W * vector2.W;
}
public override bool Equals(object obj)
{
return (obj is Vector4) ? this == (Vector4)obj : false;
}
public bool Equals(Vector4 other)
{
return this.W == other.W
&& this.X == other.X
&& this.Y == other.Y
&& this.Z == other.Z;
}
public override int GetHashCode()
{
return (int)(this.W + this.X + this.Y + this.Y);
}
public static Vector4 Hermite(Vector4 value1, Vector4 tangent1, Vector4 value2, Vector4 tangent2, float amount)
{
value1.W = MathHelper.Hermite(value1.W, tangent1.W, value2.W, tangent2.W, amount);
value1.X = MathHelper.Hermite(value1.X, tangent1.X, value2.X, tangent2.X, amount);
value1.Y = MathHelper.Hermite(value1.Y, tangent1.Y, value2.Y, tangent2.Y, amount);
value1.Z = MathHelper.Hermite(value1.Z, tangent1.Z, value2.Z, tangent2.Z, amount);
return value1;
}
public static void Hermite(ref Vector4 value1, ref Vector4 tangent1, ref Vector4 value2, ref Vector4 tangent2, float amount, out Vector4 result)
{
result.W = MathHelper.Hermite(value1.W, tangent1.W, value2.W, tangent2.W, amount);
result.X = MathHelper.Hermite(value1.X, tangent1.X, value2.X, tangent2.X, amount);
result.Y = MathHelper.Hermite(value1.Y, tangent1.Y, value2.Y, tangent2.Y, amount);
result.Z = MathHelper.Hermite(value1.Z, tangent1.Z, value2.Z, tangent2.Z, amount);
}
public float Length()
{
return (float)Math.Sqrt((double)(X * X + Y * Y + Z * Z + W * W));
}
public float LengthSquared()
{
return X * X + Y * Y + Z * Z + W * W;
}
public static Vector4 Lerp(Vector4 value1, Vector4 value2, float amount)
{
return new Vector4(
MathHelper.Lerp(value1.X, value2.X, amount),
MathHelper.Lerp(value1.Y, value2.Y, amount),
MathHelper.Lerp(value1.Z, value2.Z, amount),
MathHelper.Lerp(value1.W, value2.W, amount));
}
public static void Lerp(ref Vector4 value1, ref Vector4 value2, float amount, out Vector4 result)
{
result = new Vector4(
MathHelper.Lerp(value1.X, value2.X, amount),
MathHelper.Lerp(value1.Y, value2.Y, amount),
MathHelper.Lerp(value1.Z, value2.Z, amount),
MathHelper.Lerp(value1.W, value2.W, amount));
}
public static Vector4 Max(Vector4 value1, Vector4 value2)
{
return new Vector4(
MathHelper.Max(value1.X, value2.X),
MathHelper.Max(value1.Y, value2.Y),
MathHelper.Max(value1.Z, value2.Z),
MathHelper.Max(value1.W, value2.W));
}
public static void Max(ref Vector4 value1, ref Vector4 value2, out Vector4 result)
{
result = new Vector4(
MathHelper.Max(value1.X, value2.X),
MathHelper.Max(value1.Y, value2.Y),
MathHelper.Max(value1.Z, value2.Z),
MathHelper.Max(value1.W, value2.W));
}
public static Vector4 Min(Vector4 value1, Vector4 value2)
{
return new Vector4(
MathHelper.Min(value1.X, value2.X),
MathHelper.Min(value1.Y, value2.Y),
MathHelper.Min(value1.Z, value2.Z),
MathHelper.Min(value1.W, value2.W));
}
public static void Min(ref Vector4 value1, ref Vector4 value2, out Vector4 result)
{
result = new Vector4(
MathHelper.Min(value1.X, value2.X),
MathHelper.Min(value1.Y, value2.Y),
MathHelper.Min(value1.Z, value2.Z),
MathHelper.Min(value1.W, value2.W));
}
public static Vector4 Multiply(Vector4 value1, Vector4 value2)
{
value1.W *= value2.W;
value1.X *= value2.X;
value1.Y *= value2.Y;
value1.Z *= value2.Z;
return value1;
}
public static Vector4 Multiply(Vector4 value1, float scaleFactor)
{
value1.W *= scaleFactor;
value1.X *= scaleFactor;
value1.Y *= scaleFactor;
value1.Z *= scaleFactor;
return value1;
}
public static void Multiply(ref Vector4 value1, float scaleFactor, out Vector4 result)
{
result.W = value1.W * scaleFactor;
result.X = value1.X * scaleFactor;
result.Y = value1.Y * scaleFactor;
result.Z = value1.Z * scaleFactor;
}
public static void Multiply(ref Vector4 value1, ref Vector4 value2, out Vector4 result)
{
result.W = value1.W * value2.W;
result.X = value1.X * value2.X;
result.Y = value1.Y * value2.Y;
result.Z = value1.Z * value2.Z;
}
public static Vector4 Negate(Vector4 value)
{
value.X = -value.X;
value.Y = -value.Y;
value.Z = -value.Z;
value.W = -value.W;
return value;
}
public static void Negate(ref Vector4 value, out Vector4 result)
{
result.X = -value.X;
result.Y = -value.Y;
result.Z = -value.Z;
result.W = -value.W;
}
public void Normalize()
{
float factor = 1f / (float)Math.Sqrt((double)(X * X + Y * Y + Z * Z + W * W));
W = W * factor;
X = X * factor;
Y = Y * factor;
Z = Z * factor;
}
public static Vector4 Normalize(Vector4 vector)
{
float factor = 1f / (float)Math.Sqrt((double)(vector.X * vector.X + vector.Y * vector.Y + vector.Z * vector.Z + vector.W * vector.W));
vector.W = vector.W * factor;
vector.X = vector.X * factor;
vector.Y = vector.Y * factor;
vector.Z = vector.Z * factor;
return vector;
}
public static void Normalize(ref Vector4 vector, out Vector4 result)
{
float factor = 1f / (float)Math.Sqrt((double)(vector.X * vector.X + vector.Y * vector.Y + vector.Z * vector.Z + vector.W * vector.W));
result.W = vector.W * factor;
result.X = vector.X * factor;
result.Y = vector.Y * factor;
result.Z = vector.Z * factor;
}
public static Vector4 SmoothStep(Vector4 value1, Vector4 value2, float amount)
{
return new Vector4(
MathHelper.SmoothStep(value1.X, value2.X, amount),
MathHelper.SmoothStep(value1.Y, value2.Y, amount),
MathHelper.SmoothStep(value1.Z, value2.Z, amount),
MathHelper.SmoothStep(value1.W, value2.W, amount));
}
public static void SmoothStep(ref Vector4 value1, ref Vector4 value2, float amount, out Vector4 result)
{
result = new Vector4(
MathHelper.SmoothStep(value1.X, value2.X, amount),
MathHelper.SmoothStep(value1.Y, value2.Y, amount),
MathHelper.SmoothStep(value1.Z, value2.Z, amount),
MathHelper.SmoothStep(value1.W, value2.W, amount));
}
public static Vector4 Subtract(Vector4 value1, Vector4 value2)
{
value1.W -= value2.W;
value1.X -= value2.X;
value1.Y -= value2.Y;
value1.Z -= value2.Z;
return value1;
}
public static void Subtract(ref Vector4 value1, ref Vector4 value2, out Vector4 result)
{
result.W = value1.W - value2.W;
result.X = value1.X - value2.X;
result.Y = value1.Y - value2.Y;
result.Z = value1.Z - value2.Z;
}
public static Vector4 Transform(Vector2 position, Matrix matrix)
{
Vector4 result;
Transform(ref position, ref matrix, out result);
return result;
}
public static Vector4 Transform(Vector2 value, Quaternion rotation)
{
throw new NotImplementedException();
}
public static Vector4 Transform(Vector3 value, Quaternion rotation)
{
throw new NotImplementedException();
}
public static Vector4 Transform(Vector4 value, Quaternion rotation)
{
throw new NotImplementedException();
}
public static void Transform(ref Vector2 value, ref Quaternion rotation, out Vector4 result)
{
throw new NotImplementedException();
}
public static void Transform(ref Vector3 value, ref Quaternion rotation, out Vector4 result)
{
throw new NotImplementedException();
}
public static void Transform(ref Vector4 value, ref Quaternion rotation, out Vector4 result)
{
throw new NotImplementedException();
}
public static void Transform(Vector4[] sourceArray, ref Quaternion rotation, Vector4[] destinationArray)
{
throw new NotImplementedException();
}
public static void Transform(Vector4[] sourceArray, ref Matrix matrix, Vector4[] destinationArray)
{
throw new NotImplementedException();
}
public static void Transform(Vector4[] sourceArray, int sourceIndex, ref Matrix matrix, Vector4[] destinationArray, int destinationIndex, int length)
{
throw new NotImplementedException();
}
public static void Transform(Vector4[] sourceArray, int sourceIndex, ref Quaternion rotation, Vector4[] destinationArray, int destinationIndex, int length)
{
throw new NotImplementedException();
}
public static Vector4 Transform(Vector3 position, Matrix matrix)
{
Vector4 result;
Transform(ref position, ref matrix, out result);
return result;
}
public static Vector4 Transform(Vector4 vector, Matrix matrix)
{
Transform(ref vector, ref matrix, out vector);
return vector;
}
public static void Transform(ref Vector2 position, ref Matrix matrix, out Vector4 result)
{
result = new Vector4((position.X * matrix.M11) + (position.Y * matrix.M21) + matrix.M41,
(position.X * matrix.M12) + (position.Y * matrix.M22) + matrix.M42,
(position.X * matrix.M13) + (position.Y * matrix.M23) + matrix.M43,
(position.X * matrix.M14) + (position.Y * matrix.M24) + matrix.M44);
}
public static void Transform(ref Vector3 position, ref Matrix matrix, out Vector4 result)
{
result = new Vector4((position.X * matrix.M11) + (position.Y * matrix.M21) + (position.Z * matrix.M31) + matrix.M41,
(position.X * matrix.M12) + (position.Y * matrix.M22) + (position.Z * matrix.M32) + matrix.M42,
(position.X * matrix.M13) + (position.Y * matrix.M23) + (position.Z * matrix.M33) + matrix.M43,
(position.X * matrix.M14) + (position.Y * matrix.M24) + (position.Z * matrix.M34) + matrix.M44);
}
public static void Transform(ref Vector4 vector, ref Matrix matrix, out Vector4 result)
{
result = new Vector4((vector.X * matrix.M11) + (vector.Y * matrix.M21) + (vector.Z * matrix.M31) + (vector.W * matrix.M41),
(vector.X * matrix.M12) + (vector.Y * matrix.M22) + (vector.Z * matrix.M32) + (vector.W * matrix.M42),
(vector.X * matrix.M13) + (vector.Y * matrix.M23) + (vector.Z * matrix.M33) + (vector.W * matrix.M43),
(vector.X * matrix.M14) + (vector.Y * matrix.M24) + (vector.Z * matrix.M34) + (vector.W * matrix.M44));
}
public override string ToString()
{
StringBuilder sb = new StringBuilder(32);
sb.Append("{X:");
sb.Append(this.X);
sb.Append(" Y:");
sb.Append(this.Y);
sb.Append(" Z:");
sb.Append(this.Z);
sb.Append(" W:");
sb.Append(this.W);
sb.Append("}");
return sb.ToString();
}
#endregion Public Methods
#region Operators
public static Vector4 operator -(Vector4 value)
{
value.X = -value.X;
value.Y = -value.Y;
value.Z = -value.Z;
value.W = -value.W;
return value;
}
public static bool operator ==(Vector4 value1, Vector4 value2)
{
return value1.W == value2.W
&& value1.X == value2.X
&& value1.Y == value2.Y
&& value1.Z == value2.Z;
}
public static bool operator !=(Vector4 value1, Vector4 value2)
{
return value1.W != value2.W
|| value1.X != value2.X
|| value1.Y != value2.Y
|| value1.Z != value2.Z;
}
public static Vector4 operator +(Vector4 value1, Vector4 value2)
{
value1.W += value2.W;
value1.X += value2.X;
value1.Y += value2.Y;
value1.Z += value2.Z;
return value1;
}
public static Vector4 operator -(Vector4 value1, Vector4 value2)
{
value1.W -= value2.W;
value1.X -= value2.X;
value1.Y -= value2.Y;
value1.Z -= value2.Z;
return value1;
}
public static Vector4 operator *(Vector4 value1, Vector4 value2)
{
value1.W *= value2.W;
value1.X *= value2.X;
value1.Y *= value2.Y;
value1.Z *= value2.Z;
return value1;
}
public static Vector4 operator *(Vector4 value1, float scaleFactor)
{
value1.W *= scaleFactor;
value1.X *= scaleFactor;
value1.Y *= scaleFactor;
value1.Z *= scaleFactor;
return value1;
}
public static Vector4 operator *(float scaleFactor, Vector4 value1)
{
value1.W *= scaleFactor;
value1.X *= scaleFactor;
value1.Y *= scaleFactor;
value1.Z *= scaleFactor;
return value1;
}
public static Vector4 operator /(Vector4 value1, Vector4 value2)
{
value1.W /= value2.W;
value1.X /= value2.X;
value1.Y /= value2.Y;
value1.Z /= value2.Z;
return value1;
}
public static Vector4 operator /(Vector4 value1, float divider)
{
float factor = 1f / divider;
value1.W *= factor;
value1.X *= factor;
value1.Y *= factor;
value1.Z *= factor;
return value1;
}
#endregion Operators
}
}

View File

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
namespace BizHawk.Bizware.BizwareGL
{
public class UniformInfo
{
public IntPtr Handle;
public string Name;
public int SamplerIndex;
}
}

View File

@ -0,0 +1,99 @@
using System;
using System.Collections.Generic;
namespace BizHawk.Bizware.BizwareGL
{
//TEMP until its in bizhawk main
public class WorkingDictionary<K, V> : Dictionary<K, V> where V : new()
{
public new V this[K key]
{
get
{
V temp;
if (!TryGetValue(key, out temp))
{
temp = this[key] = new V();
}
return temp;
}
set
{
base[key] = value;
}
}
public WorkingDictionary() { }
}
public class VertexLayout : IDisposable
{
//TODO - could refactor to use vertex array objects? check opengl profile requirements (answer: 3.0. dont want to do this.)
public VertexLayout(IGL owner, IntPtr id)
{
Owner = owner;
Id = id;
Items = new MyDictionary();
}
public void Dispose()
{
//nothing to do yet..
}
public void Bind()
{
Owner.BindVertexLayout(this);
}
public void DefineVertexAttribute(int index, int components, VertexAttributeType attribType, bool normalized, int stride, int offset=0)
{
if (Closed)
throw new InvalidOperationException("Type is Closed and is now immutable.");
Items[index] = new LayoutItem { Components = components, AttribType = attribType, Normalized = normalized, Stride = stride, Offset = offset };
}
/// <summary>
/// finishes this VertexLayout and renders it immutable
/// </summary>
public void Close()
{
Closed = true;
}
public class LayoutItem
{
public int Components { get; internal set; }
public VertexAttributeType AttribType { get; internal set; }
public bool Normalized { get; internal set; }
public int Stride { get; internal set; }
public int Offset { get; internal set; }
}
public class MyDictionary : WorkingDictionary<int, LayoutItem>
{
public new LayoutItem this[int key]
{
get
{
return base[key];
}
internal set
{
base[key] = value;
}
}
}
public MyDictionary Items { get; private set; }
bool Closed = false;
public IGL Owner { get; private set; }
public IntPtr Id { get; private set; }
}
}

View File

@ -0,0 +1,99 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{B9925307-6A8F-4CD0-8EFB-0617FF0AE5AD}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>BizHawk.Bizware.Test</RootNamespace>
<AssemblyName>BizHawk.Bizware.Test</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="TestForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="TestForm.Designer.cs">
<DependentUpon>TestForm.cs</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\BizHawk.Bizware.BizwareGL.OpenTK\BizHawk.Bizware.BizwareGL.OpenTK.csproj">
<Project>{5160CFB1-5389-47C1-B7F6-8A0DC97641EE}</Project>
<Name>BizHawk.Bizware.BizwareGL.OpenTK</Name>
</ProjectReference>
<ProjectReference Include="..\BizHawk.Bizware.BizwareGL\BizHawk.Bizware.BizwareGL.csproj">
<Project>{9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}</Project>
<Name>BizHawk.Bizware.BizwareGL</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="TestForm.resx">
<DependentUpon>TestForm.cs</DependentUpon>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="TestImages\flame1.jpg" />
<EmbeddedResource Include="TestImages\flame2.jpg" />
<EmbeddedResource Include="TestImages\flame3.jpg" />
<EmbeddedResource Include="TestImages\flame4.jpg" />
<EmbeddedResource Include="TestImages\flame5.jpg" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="TestImages\courier16px.fnt" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="TestImages\courier16px_0.png" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="TestImages\smile.png" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -0,0 +1,83 @@
using System;
using System.Drawing;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BizHawk.Bizware.BizwareGL;
namespace BizHawk.Bizware.Test
{
class Program
{
static unsafe void Main(string[] args)
{
BizHawk.Bizware.BizwareGL.IGL igl = new BizHawk.Bizware.BizwareGL.Drivers.OpenTK.IGL_TK();
List<Art> testArts = new List<Art>();
ArtManager am = new ArtManager(igl);
foreach (var name in typeof(Program).Assembly.GetManifestResourceNames())
if (name.Contains("flame"))
testArts.Add(am.LoadArt(typeof(Program).Assembly.GetManifestResourceStream(name)));
var smile = am.LoadArt(typeof(Program).Assembly.GetManifestResourceStream("BizHawk.Bizware.Test.TestImages.smile.png"));
am.Close(true);
StringRenderer sr;
using (var xml = typeof(Program).Assembly.GetManifestResourceStream("BizHawk.Bizware.Test.TestImages.courier16px.fnt"))
using (var tex = typeof(Program).Assembly.GetManifestResourceStream("BizHawk.Bizware.Test.TestImages.courier16px_0.png"))
sr = new StringRenderer(igl, xml, tex);
GuiRenderer gr = new GuiRenderer(igl);
TestForm tf = new TestForm();
GraphicsControl c = igl.CreateGraphicsControl();
tf.Controls.Add(c);
c.Control.Dock = System.Windows.Forms.DockStyle.Fill;
tf.FormClosing += (object sender, System.Windows.Forms.FormClosingEventArgs e) =>
{
tf.Controls.Remove(c);
c.Dispose();
c = null;
};
tf.Show();
c.SetVsync(false);
DateTime start = DateTime.Now;
int wobble = 0;
for (; ; )
{
if (c == null) break;
c.Begin();
igl.ClearColor(Color.Red);
igl.Clear(BizwareGL.ClearBufferMask.ColorBufferBit);
int frame = (int)((DateTime.Now - start).TotalSeconds) % testArts.Count;
gr.Begin(c.Control.ClientSize.Width, c.Control.ClientSize.Height);
sr.RenderString(gr, 0, 0, "60 fps");
gr.Modelview.Translate((float)Math.Sin(wobble / 360.0f) * 50, 0);
gr.Modelview.Translate(100, 100);
gr.Modelview.Push();
gr.Modelview.Translate(testArts[frame].Width, 0);
gr.Modelview.Scale(-1, 1);
wobble++;
gr.SetModulateColor(Color.Yellow);
gr.DrawFlipped(testArts[frame], true, false);
gr.SetModulateColorWhite();
gr.Modelview.Pop();
gr.SetBlendState(igl.BlendNormal);
gr.Draw(smile);
gr.End();
c.SwapBuffers();
c.End();
System.Windows.Forms.Application.DoEvents();
}
}
}
}

View File

@ -0,0 +1,48 @@
namespace BizHawk.Bizware.Test
{
partial class TestForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.SuspendLayout();
//
// TestForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(292, 273);
this.Name = "TestForm";
this.Text = "TestForm";
this.ResumeLayout(false);
}
#endregion
}
}

View File

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace BizHawk.Bizware.Test
{
public partial class TestForm : Form
{
public TestForm()
{
InitializeComponent();
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,208 @@
<?xml version="1.0"?>
<font>
<info face="Courier" size="16" bold="1" italic="0" charset="" unicode="1" stretchH="100" smooth="0" aa="1" padding="0,0,0,0" spacing="1,1" outline="0"/>
<common lineHeight="16" base="13" scaleW="128" scaleH="256" pages="1" packed="0" alphaChnl="0" redChnl="4" greenChnl="4" blueChnl="4"/>
<pages>
<page id="0" file="courier16px_0.png" />
</pages>
<chars count="198">
<char id="-1" x="126" y="73" width="1" height="1" xoffset="0" yoffset="0" xadvance="0" page="0" chnl="15" />
<char id="32" x="83" y="137" width="30" height="1" xoffset="-10" yoffset="15" xadvance="10" page="0" chnl="15" />
<char id="33" x="124" y="95" width="2" height="10" xoffset="4" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="34" x="15" y="137" width="5" height="4" xoffset="3" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="35" x="93" y="52" width="9" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="36" x="72" y="28" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="37" x="83" y="52" width="9" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="38" x="73" y="53" width="9" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="39" x="125" y="115" width="2" height="4" xoffset="4" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="40" x="61" y="28" width="4" height="13" xoffset="4" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="41" x="56" y="28" width="4" height="13" xoffset="3" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="42" x="106" y="124" width="8" height="5" xoffset="1" yoffset="5" xadvance="10" page="0" chnl="15" />
<char id="43" x="72" y="127" width="8" height="7" xoffset="1" yoffset="5" xadvance="10" page="0" chnl="15" />
<char id="44" x="38" y="135" width="5" height="3" xoffset="3" yoffset="11" xadvance="10" page="0" chnl="15" />
<char id="45" x="106" y="130" width="7" height="1" xoffset="2" yoffset="8" xadvance="10" page="0" chnl="15" />
<char id="46" x="49" y="135" width="3" height="2" xoffset="4" yoffset="11" xadvance="10" page="0" chnl="15" />
<char id="47" x="100" y="107" width="9" height="8" xoffset="1" yoffset="4" xadvance="10" page="0" chnl="15" />
<char id="48" x="52" y="97" width="7" height="10" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="49" x="58" y="108" width="6" height="10" xoffset="3" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="50" x="0" y="109" width="7" height="10" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="51" x="8" y="109" width="7" height="10" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="52" x="60" y="97" width="7" height="10" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="53" x="76" y="97" width="7" height="10" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="54" x="92" y="96" width="7" height="10" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="55" x="100" y="96" width="7" height="10" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="56" x="44" y="97" width="7" height="10" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="57" x="116" y="95" width="7" height="10" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="58" x="121" y="115" width="3" height="7" xoffset="4" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="59" x="7" y="120" width="5" height="8" xoffset="3" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="60" x="93" y="107" width="6" height="9" xoffset="2" yoffset="4" xadvance="10" page="0" chnl="15" />
<char id="61" x="30" y="136" width="7" height="3" xoffset="2" yoffset="7" xadvance="10" page="0" chnl="15" />
<char id="62" x="86" y="108" width="6" height="9" xoffset="2" yoffset="4" xadvance="10" page="0" chnl="15" />
<char id="63" x="84" y="97" width="7" height="10" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="64" x="90" y="28" width="9" height="11" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="65" x="11" y="53" width="10" height="10" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="66" x="27" y="75" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="67" x="36" y="75" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="68" x="45" y="75" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="69" x="54" y="75" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="70" x="63" y="75" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="71" x="0" y="65" width="9" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="72" x="0" y="54" width="10" height="10" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="73" x="51" y="108" width="6" height="10" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="74" x="20" y="64" width="9" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="75" x="30" y="64" width="9" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="76" x="72" y="75" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="77" x="107" y="40" width="10" height="10" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="78" x="19" y="42" width="10" height="10" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="79" x="81" y="75" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="80" x="40" y="64" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="81" x="81" y="28" width="8" height="12" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="82" x="53" y="53" width="9" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="83" x="90" y="74" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="84" x="41" y="42" width="10" height="10" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="85" x="22" y="53" width="10" height="10" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="86" x="63" y="42" width="10" height="10" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="87" x="74" y="41" width="10" height="10" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="88" x="85" y="41" width="10" height="10" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="89" x="96" y="40" width="10" height="10" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="90" x="99" y="74" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="91" x="51" y="28" width="4" height="13" xoffset="4" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="92" x="110" y="106" width="9" height="8" xoffset="1" yoffset="4" xadvance="10" page="0" chnl="15" />
<char id="93" x="123" y="14" width="4" height="13" xoffset="3" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="94" x="115" y="123" width="8" height="4" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="95" x="114" y="135" width="10" height="1" xoffset="0" yoffset="14" xadvance="10" page="0" chnl="15" />
<char id="96" x="53" y="135" width="3" height="2" xoffset="3" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="97" x="18" y="128" width="8" height="7" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="98" x="108" y="73" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="99" x="0" y="129" width="8" height="7" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="100" x="117" y="73" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="101" x="103" y="116" width="8" height="7" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="102" x="36" y="97" width="7" height="10" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="103" x="0" y="87" width="8" height="10" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="104" x="9" y="87" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="105" x="30" y="108" width="6" height="10" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="106" x="121" y="0" width="6" height="13" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="107" x="18" y="76" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="108" x="23" y="109" width="6" height="10" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="109" x="46" y="119" width="10" height="7" xoffset="0" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="110" x="76" y="118" width="8" height="7" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="111" x="63" y="127" width="8" height="7" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="112" x="18" y="87" width="8" height="10" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="113" x="27" y="86" width="8" height="10" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="114" x="57" y="119" width="9" height="7" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="115" x="9" y="129" width="8" height="7" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="116" x="68" y="108" width="8" height="9" xoffset="1" yoffset="4" xadvance="10" page="0" chnl="15" />
<char id="117" x="94" y="117" width="8" height="7" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="118" x="24" y="120" width="10" height="7" xoffset="0" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="119" x="35" y="119" width="10" height="7" xoffset="0" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="120" x="54" y="127" width="8" height="7" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="121" x="8" y="42" width="10" height="10" xoffset="0" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="122" x="27" y="128" width="8" height="7" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="123" x="9" y="28" width="6" height="13" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="124" x="66" y="28" width="2" height="13" xoffset="4" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="125" x="37" y="28" width="6" height="13" xoffset="3" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="126" x="21" y="136" width="8" height="3" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="127" x="123" y="51" width="4" height="10" xoffset="3" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="129" x="92" y="133" width="30" height="1" xoffset="-10" yoffset="15" xadvance="10" page="0" chnl="15" />
<char id="141" x="52" y="140" width="30" height="1" xoffset="-10" yoffset="15" xadvance="10" page="0" chnl="15" />
<char id="143" x="21" y="140" width="30" height="1" xoffset="-10" yoffset="15" xadvance="10" page="0" chnl="15" />
<char id="144" x="61" y="135" width="30" height="1" xoffset="-10" yoffset="15" xadvance="10" page="0" chnl="15" />
<char id="157" x="83" y="139" width="30" height="1" xoffset="-10" yoffset="15" xadvance="10" page="0" chnl="15" />
<char id="160" x="52" y="138" width="30" height="1" xoffset="-10" yoffset="15" xadvance="10" page="0" chnl="15" />
<char id="161" x="65" y="108" width="2" height="10" xoffset="4" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="162" x="0" y="42" width="7" height="11" xoffset="2" yoffset="4" xadvance="10" page="0" chnl="15" />
<char id="163" x="68" y="97" width="7" height="10" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="164" x="81" y="126" width="7" height="6" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="165" x="30" y="42" width="10" height="10" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="166" x="69" y="28" width="2" height="13" xoffset="4" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="167" x="110" y="28" width="8" height="11" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="168" x="100" y="135" width="5" height="1" xoffset="3" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="169" x="10" y="65" width="9" height="10" xoffset="1" yoffset="2" xadvance="10" page="0" chnl="15" />
<char id="170" x="120" y="106" width="7" height="8" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="171" x="67" y="119" width="8" height="7" xoffset="1" yoffset="5" xadvance="10" page="0" chnl="15" />
<char id="172" x="0" y="137" width="8" height="4" xoffset="1" yoffset="7" xadvance="10" page="0" chnl="15" />
<char id="173" x="92" y="135" width="7" height="1" xoffset="2" yoffset="8" xadvance="10" page="0" chnl="15" />
<char id="174" x="33" y="53" width="9" height="10" xoffset="1" yoffset="2" xadvance="10" page="0" chnl="15" />
<char id="175" x="81" y="133" width="10" height="1" xoffset="0" yoffset="1" xadvance="10" page="0" chnl="15" />
<char id="176" x="9" y="137" width="5" height="4" xoffset="3" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="177" x="77" y="108" width="8" height="9" xoffset="1" yoffset="4" xadvance="10" page="0" chnl="15" />
<char id="178" x="95" y="125" width="5" height="6" xoffset="3" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="179" x="89" y="126" width="5" height="6" xoffset="3" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="180" x="57" y="135" width="3" height="2" xoffset="4" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="181" x="100" y="28" width="9" height="11" xoffset="1" yoffset="5" xadvance="10" page="0" chnl="15" />
<char id="182" x="63" y="53" width="9" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="183" x="124" y="123" width="3" height="2" xoffset="4" yoffset="7" xadvance="10" page="0" chnl="15" />
<char id="184" x="44" y="135" width="4" height="3" xoffset="3" yoffset="13" xadvance="10" page="0" chnl="15" />
<char id="185" x="101" y="125" width="4" height="6" xoffset="3" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="186" x="0" y="120" width="6" height="8" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="187" x="85" y="118" width="8" height="7" xoffset="1" yoffset="5" xadvance="10" page="0" chnl="15" />
<char id="188" x="103" y="51" width="9" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="189" x="118" y="40" width="9" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="190" x="113" y="51" width="9" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="191" x="108" y="95" width="7" height="10" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="192" x="88" y="0" width="10" height="13" xoffset="0" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="193" x="11" y="0" width="10" height="13" xoffset="0" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="194" x="22" y="0" width="10" height="13" xoffset="0" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="195" x="22" y="14" width="10" height="13" xoffset="0" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="196" x="11" y="14" width="10" height="13" xoffset="0" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="197" x="0" y="14" width="10" height="13" xoffset="0" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="198" x="52" y="42" width="10" height="10" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="199" x="42" y="14" width="8" height="13" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="200" x="96" y="14" width="8" height="13" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="201" x="87" y="14" width="8" height="13" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="202" x="78" y="14" width="8" height="13" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="203" x="69" y="14" width="8" height="13" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="204" x="44" y="28" width="6" height="13" xoffset="2" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="205" x="23" y="28" width="6" height="13" xoffset="2" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="206" x="16" y="28" width="6" height="13" xoffset="2" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="207" x="30" y="28" width="6" height="13" xoffset="2" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="208" x="43" y="53" width="9" height="10" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="209" x="99" y="0" width="10" height="13" xoffset="0" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="210" x="60" y="14" width="8" height="13" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="211" x="51" y="14" width="8" height="13" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="212" x="0" y="28" width="8" height="13" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="213" x="114" y="14" width="8" height="13" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="214" x="105" y="14" width="8" height="13" xoffset="1" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="215" x="112" y="115" width="8" height="7" xoffset="1" yoffset="5" xadvance="10" page="0" chnl="15" />
<char id="216" x="45" y="86" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="217" x="110" y="0" width="10" height="13" xoffset="0" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="218" x="0" y="0" width="10" height="13" xoffset="0" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="219" x="44" y="0" width="10" height="13" xoffset="0" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="220" x="77" y="0" width="10" height="13" xoffset="0" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="221" x="55" y="0" width="10" height="13" xoffset="0" yoffset="0" xadvance="10" page="0" chnl="15" />
<char id="222" x="54" y="86" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="223" x="63" y="86" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="224" x="72" y="86" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="225" x="81" y="86" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="226" x="90" y="85" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="227" x="99" y="85" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="228" x="108" y="84" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="229" x="119" y="28" width="8" height="11" xoffset="1" yoffset="2" xadvance="10" page="0" chnl="15" />
<char id="230" x="13" y="120" width="10" height="7" xoffset="0" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="231" x="117" y="84" width="8" height="10" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="232" x="36" y="86" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="233" x="0" y="98" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="234" x="9" y="98" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="235" x="18" y="98" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="236" x="44" y="108" width="6" height="10" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="237" x="37" y="108" width="6" height="10" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="238" x="16" y="109" width="6" height="10" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="239" x="121" y="62" width="6" height="10" xoffset="2" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="240" x="27" y="97" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="241" x="49" y="64" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="242" x="58" y="64" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="243" x="67" y="64" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="244" x="76" y="64" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="245" x="85" y="63" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="246" x="94" y="63" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="247" x="36" y="127" width="8" height="7" xoffset="1" yoffset="5" xadvance="10" page="0" chnl="15" />
<char id="248" x="45" y="127" width="8" height="7" xoffset="1" yoffset="6" xadvance="10" page="0" chnl="15" />
<char id="249" x="103" y="62" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="250" x="112" y="62" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="251" x="0" y="76" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="252" x="9" y="76" width="8" height="10" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="253" x="66" y="0" width="10" height="13" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="254" x="33" y="14" width="8" height="13" xoffset="1" yoffset="3" xadvance="10" page="0" chnl="15" />
<char id="255" x="33" y="0" width="10" height="13" xoffset="0" yoffset="3" xadvance="10" page="0" chnl="15" />
</chars>
</font>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -0,0 +1,54 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BizHawk.Bizware.BizwareGL", "BizHawk.Bizware.BizwareGL\BizHawk.Bizware.BizwareGL.csproj", "{9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BizHawk.Bizware.Test", "BizHawk.Bizware.Test\BizHawk.Bizware.Test.csproj", "{B9925307-6A8F-4CD0-8EFB-0617FF0AE5AD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BizHawk.Bizware.BizwareGL.OpenTK", "BizHawk.Bizware.BizwareGL.OpenTK\BizHawk.Bizware.BizwareGL.OpenTK.csproj", "{5160CFB1-5389-47C1-B7F6-8A0DC97641EE}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|Mixed Platforms = Debug|Mixed Platforms
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|Mixed Platforms = Release|Mixed Platforms
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}.Debug|x86.ActiveCfg = Debug|Any CPU
{9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}.Release|Any CPU.Build.0 = Release|Any CPU
{9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}.Release|x86.ActiveCfg = Release|Any CPU
{B9925307-6A8F-4CD0-8EFB-0617FF0AE5AD}.Debug|Any CPU.ActiveCfg = Debug|x86
{B9925307-6A8F-4CD0-8EFB-0617FF0AE5AD}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
{B9925307-6A8F-4CD0-8EFB-0617FF0AE5AD}.Debug|Mixed Platforms.Build.0 = Debug|x86
{B9925307-6A8F-4CD0-8EFB-0617FF0AE5AD}.Debug|x86.ActiveCfg = Debug|x86
{B9925307-6A8F-4CD0-8EFB-0617FF0AE5AD}.Debug|x86.Build.0 = Debug|x86
{B9925307-6A8F-4CD0-8EFB-0617FF0AE5AD}.Release|Any CPU.ActiveCfg = Release|x86
{B9925307-6A8F-4CD0-8EFB-0617FF0AE5AD}.Release|Mixed Platforms.ActiveCfg = Release|x86
{B9925307-6A8F-4CD0-8EFB-0617FF0AE5AD}.Release|Mixed Platforms.Build.0 = Release|x86
{B9925307-6A8F-4CD0-8EFB-0617FF0AE5AD}.Release|x86.ActiveCfg = Release|x86
{B9925307-6A8F-4CD0-8EFB-0617FF0AE5AD}.Release|x86.Build.0 = Release|x86
{5160CFB1-5389-47C1-B7F6-8A0DC97641EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5160CFB1-5389-47C1-B7F6-8A0DC97641EE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5160CFB1-5389-47C1-B7F6-8A0DC97641EE}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{5160CFB1-5389-47C1-B7F6-8A0DC97641EE}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{5160CFB1-5389-47C1-B7F6-8A0DC97641EE}.Debug|x86.ActiveCfg = Debug|Any CPU
{5160CFB1-5389-47C1-B7F6-8A0DC97641EE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5160CFB1-5389-47C1-B7F6-8A0DC97641EE}.Release|Any CPU.Build.0 = Release|Any CPU
{5160CFB1-5389-47C1-B7F6-8A0DC97641EE}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{5160CFB1-5389-47C1-B7F6-8A0DC97641EE}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{5160CFB1-5389-47C1-B7F6-8A0DC97641EE}.Release|x86.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

Binary file not shown.

Binary file not shown.

BIN
References/OpenTK.dll Normal file

Binary file not shown.

View File

@ -0,0 +1,16 @@
<configuration>
<dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
<dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
<dllmap os="linux" dll="openal32.dll" target="libopenal.so.1"/>
<dllmap os="linux" dll="alut.dll" target="libalut.so.0"/>
<dllmap os="linux" dll="opencl.dll" target="libOpenCL.so"/>
<dllmap os="linux" dll="libX11" target="libX11.so.6"/>
<dllmap os="linux" dll="libXi" target="libXi.so.6"/>
<dllmap os="linux" dll="SDL2.dll" target="libSDL2-2.0.so.0"/>
<dllmap os="osx" dll="openal32.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
<dllmap os="osx" dll="alut.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
<dllmap os="osx" dll="libGLES.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
<dllmap os="osx" dll="libGLESv2.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
<dllmap os="osx" dll="opencl.dll" target="/System/Library/Frameworks/OpenCL.framework/OpenCL"/>
<dllmap os="osx" dll="SDL2.dll" target="libSDL2.dylib"/>
</configuration>