BizwareGL!
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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
|
|
@ -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>
|
After Width: | Height: | Size: 3.9 KiB |
|
@ -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;
|
||||
|
|
|
@ -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; } }
|
||||
|
|
32
BizHawk.sln
|
@ -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
|
||||
|
|
|
@ -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>
|
|
@ -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
|
||||
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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>();
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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>
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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/
|
|
@ -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,
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}";
|
||||
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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; }
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BizHawk.Bizware.BizwareGL
|
||||
{
|
||||
public interface IBlendState { }
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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>();
|
||||
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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; } }
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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; }
|
||||
}
|
||||
}
|
|
@ -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>
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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>
|
|
@ -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>
|
After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 9.6 KiB |
After Width: | Height: | Size: 6.9 KiB |
After Width: | Height: | Size: 7.4 KiB |
After Width: | Height: | Size: 7.6 KiB |
After Width: | Height: | Size: 2.1 KiB |
|
@ -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
|
|
@ -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>
|