First Commit of Joystick Tuning Code

pull/20/head
bm98 10 years ago
parent 29b5496afd
commit 3aadcbc8e4

@ -0,0 +1,275 @@
#region --- License ---
/* Licensed under the MIT/X11 license.
* Copyright (c) 2006-2008 the OpenTK Team.
* This notice may not be removed from any source distribution.
* See license.txt for licensing details.
*/
#endregion
using System;
using System.Drawing;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows.Forms;
using System.IO;
using System.Text;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using SCJMapper_V2.Shapes;
using SCJMapper_V2.TextureLoaders;
namespace SCJMapper_V2
{
[Example("DDS Cube Map", ExampleCategory.OpenGL, "2.x", Documentation = "DDSCubeMap")]
public class T13_GLSL_Earth: GameWindow
{
public T13_GLSL_Earth( )
: base( 800, 800 )
{
}
#region internal Fields
// Shader
int VertexShaderObject, FragmentShaderObject, ProgramObject;
const string VertexShaderFilename = "Data/Shaders/CubeMap_VS.glsl";
const string FragmentShaderFilename = "Data/Shaders/CubeMap_FS.glsl";
// Textures
const TextureUnit TMU0_Unit = TextureUnit.Texture0;
const int TMU0_UnitInteger = 0;
const string TMU0_Filename = "Data/Textures/earth-cubemap.dds";
uint TMU0_Handle;
TextureTarget TMU0_Target;
// DL
DrawableShape sphere;
// Camera
Vector3 EyePos = new Vector3( 0.0f, 0.0f, 6.0f );
Vector3 Trackball = Vector3.Zero;
#endregion internal Fields
/// <summary>Setup OpenGL and load resources here.</summary>
/// <param name="e">Not used.</param>
protected override void OnLoad(EventArgs e)
{
this.VSync = VSyncMode.Off;
// Check for necessary capabilities:
string extensions = GL.GetString(StringName.Extensions);
if (!GL.GetString(StringName.Extensions).Contains("GL_ARB_shading_language"))
{
throw new NotSupportedException(String.Format("This example requires OpenGL 2.0. Found {0}. Aborting.",
GL.GetString(StringName.Version).Substring(0, 3)));
}
if (!extensions.Contains("GL_ARB_texture_compression") ||
!extensions.Contains("GL_EXT_texture_compression_s3tc"))
{
throw new NotSupportedException("This example requires support for texture compression. Aborting.");
}
#region GL State
GL.ClearColor( 0f, 0f, 0f, 0f );
GL.Disable( EnableCap.Dither );
GL.Enable( EnableCap.CullFace );
GL.FrontFace( FrontFaceDirection.Ccw );
GL.PolygonMode( MaterialFace.Front, PolygonMode.Fill );
// GL.PolygonMode( MaterialFace.Back, PolygonMode.Line );
#endregion GL State
#region Shaders
string LogInfo;
// Load&Compile Vertex Shader
using ( StreamReader sr = new StreamReader( VertexShaderFilename ) )
{
VertexShaderObject = GL.CreateShader( ShaderType.VertexShader );
GL.ShaderSource( VertexShaderObject, sr.ReadToEnd( ) );
GL.CompileShader( VertexShaderObject );
}
GL.GetShaderInfoLog( VertexShaderObject, out LogInfo );
if ( LogInfo.Length > 0 && !LogInfo.Contains( "hardware" ) )
Trace.WriteLine( "Vertex Shader failed!\nLog:\n" + LogInfo );
else
Trace.WriteLine( "Vertex Shader compiled without complaint." );
// Load&Compile Fragment Shader
using ( StreamReader sr = new StreamReader( FragmentShaderFilename ) )
{
FragmentShaderObject = GL.CreateShader( ShaderType.FragmentShader );
GL.ShaderSource( FragmentShaderObject, sr.ReadToEnd( ) );
GL.CompileShader( FragmentShaderObject );
}
GL.GetShaderInfoLog( FragmentShaderObject, out LogInfo );
if ( LogInfo.Length > 0 && !LogInfo.Contains( "hardware" ) )
Trace.WriteLine( "Fragment Shader failed!\nLog:\n" + LogInfo );
else
Trace.WriteLine( "Fragment Shader compiled without complaint." );
// Link the Shaders to a usable Program
ProgramObject = GL.CreateProgram( );
GL.AttachShader( ProgramObject, VertexShaderObject );
GL.AttachShader( ProgramObject, FragmentShaderObject );
// link it all together
GL.LinkProgram( ProgramObject );
// flag ShaderObjects for delete when not used anymore
GL.DeleteShader( VertexShaderObject );
GL.DeleteShader( FragmentShaderObject );
int[] temp = new int[1];
GL.GetProgram( ProgramObject, ProgramParameter.LinkStatus, out temp[0] );
Trace.WriteLine( "Linking Program (" + ProgramObject + ") " + ( ( temp[0] == 1 ) ? "succeeded." : "FAILED!" ) );
if ( temp[0] != 1 )
{
GL.GetProgramInfoLog( ProgramObject, out LogInfo );
Trace.WriteLine( "Program Log:\n" + LogInfo );
}
GL.GetProgram( ProgramObject, ProgramParameter.ActiveAttributes, out temp[0] );
Trace.WriteLine( "Program registered " + temp[0] + " Attributes. (Should be 4: Pos, UV, Normal, Tangent)" );
Trace.WriteLine( "Tangent attribute bind location: " + GL.GetAttribLocation( ProgramObject, "AttributeTangent" ) );
Trace.WriteLine( "End of Shader build. GL Error: " + GL.GetError( ) );
#endregion Shaders
#region Textures
TextureLoaderParameters.FlipImages = false;
TextureLoaderParameters.MagnificationFilter = TextureMagFilter.Linear;
TextureLoaderParameters.MinificationFilter = TextureMinFilter.Linear;
TextureLoaderParameters.WrapModeS = TextureWrapMode.ClampToEdge;
TextureLoaderParameters.WrapModeT = TextureWrapMode.ClampToEdge;
TextureLoaderParameters.EnvMode = TextureEnvMode.Modulate;
ImageDDS.LoadFromDisk( TMU0_Filename, out TMU0_Handle, out TMU0_Target );
Trace.WriteLine( "Loaded " + TMU0_Filename + " with handle " + TMU0_Handle + " as " + TMU0_Target );
#endregion Textures
Trace.WriteLine( "End of Texture Loading. GL Error: " + GL.GetError( ) );
Trace.WriteLine( "");
sphere = new SlicedSphere(1.5f, Vector3d.Zero, SlicedSphere.eSubdivisions.Four, new SlicedSphere.eDir[] { SlicedSphere.eDir.All }, true);
}
protected override void OnUnload(EventArgs e)
{
sphere.Dispose();
GL.DeleteProgram( ProgramObject );
GL.DeleteTextures( 1, ref TMU0_Handle );
base.OnUnload( e );
}
/// <summary>Respond to resize events here.</summary>
/// <param name="e">Contains information on the new GameWindow size.</param>
/// <remarks>There is no need to call the base implementation.</remarks>
protected override void OnResize( EventArgs e )
{
GL.Viewport( 0, 0, Width, Height );
GL.MatrixMode( MatrixMode.Projection );
Matrix4 p = Matrix4.CreatePerspectiveFieldOfView(MathHelper.PiOver4, Width / (float)Height, 0.1f, 10.0f);
GL.LoadMatrix(ref p);
GL.MatrixMode( MatrixMode.Modelview );
GL.LoadIdentity( );
base.OnResize( e );
}
/// <summary>Add your game logic here.</summary>
/// <param name="e">Contains timing information.</param>
/// <remarks>There is no need to call the base implementation.</remarks>
protected override void OnUpdateFrame( FrameEventArgs e )
{
base.OnUpdateFrame( e );
if ( Keyboard[OpenTK.Input.Key.Escape] )
this.Exit( );
if ( Keyboard[OpenTK.Input.Key.Space] )
Trace.WriteLine( "GL: " + GL.GetError( ) );
Trackball.X = Mouse.X;
Trackball.Y = Mouse.Y;
Trackball.Z = Mouse.Wheel * 0.5f;
}
/// <summary>Add your game rendering code here.</summary>
/// <param name="e">Contains timing information.</param>
/// <remarks>There is no need to call the base implementation.</remarks>
protected override void OnRenderFrame(FrameEventArgs e)
{
this.Title = "FPS: " + (1 / e.Time).ToString("0.");
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.UseProgram(ProgramObject);
#region Textures
GL.ActiveTexture(TMU0_Unit);
GL.BindTexture(TMU0_Target, TMU0_Handle);
#endregion Textures
#region Uniforms
GL.Uniform1(GL.GetUniformLocation(ProgramObject, "Earth"), TMU0_UnitInteger);
#endregion Uniforms
GL.PushMatrix();
Matrix4 temp = Matrix4.LookAt(EyePos, Vector3.Zero, Vector3.UnitY);
GL.MultMatrix(ref temp);
GL.Rotate(Trackball.X, Vector3.UnitY);
GL.Rotate(Trackball.Y, Vector3.UnitX);
#region Draw
GL.Color3(1f, 1f, 1f);
sphere.Draw();
#endregion Draw
GL.PopMatrix();
this.SwapBuffers();
}
/// <summary>Entry point</summary>
[STAThread]
public static void Main( )
{
using ( T13_GLSL_Earth example = new T13_GLSL_Earth( ) )
{
Utilities.SetWindowTitle(example);
example.Run( 30.0, 0.0 );
}
}
}
}

85
Form1.Designer.cs generated

@ -16,6 +16,7 @@
timer1.Stop( );
// Unacquire all DirectInput objects.
foreach ( JoystickCls js in m_Joystick ) js.FinishDX( );
m_Joystick.Clear( );
if ( disposing && ( components != null ) ) {
components.Dispose( );
@ -34,7 +35,6 @@
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
this.btDumpList = new System.Windows.Forms.Button();
this.label3 = new System.Windows.Forms.Label();
this.rtb = new System.Windows.Forms.RichTextBox();
this.cmCopyPaste = new System.Windows.Forms.ContextMenuStrip(this.components);
this.tsiCopy = new System.Windows.Forms.ToolStripMenuItem();
@ -59,6 +59,7 @@
this.IL = new System.Windows.Forms.ImageList(this.components);
this.tc1 = new System.Windows.Forms.TabControl();
this.tabJS1 = new System.Windows.Forms.TabPage();
this.UC_JoyPanel = new SCJMapper_V2.UC_JoyPanel();
this.panel1 = new System.Windows.Forms.Panel();
this.txRebind = new System.Windows.Forms.TextBox();
this.linkLblReleases = new System.Windows.Forms.LinkLabel();
@ -72,6 +73,7 @@
this.tlpanel = new System.Windows.Forms.TableLayoutPanel();
this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel();
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
this.button1 = new System.Windows.Forms.Button();
this.cbxBlendUnmapped = new System.Windows.Forms.CheckBox();
this.txFilter = new System.Windows.Forms.TextBox();
this.btClearFilter = new System.Windows.Forms.Button();
@ -83,7 +85,6 @@
this.btLoadMyMapping = new System.Windows.Forms.Button();
this.txMappingName = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.statusStrip1 = new System.Windows.Forms.StatusStrip();
this.toolStripStatusLabel2 = new System.Windows.Forms.ToolStripStatusLabel();
this.tsDDbtProfiles = new System.Windows.Forms.ToolStripDropDownButton();
this.tsBtReset = new System.Windows.Forms.ToolStripDropDownButton();
@ -98,7 +99,7 @@
this.loadAndGrabToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.loadToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);
this.UC_JoyPanel = new SCJMapper_V2.UC_JoyPanel();
this.statusStrip1 = new System.Windows.Forms.StatusStrip();
this.cmCopyPaste.SuspendLayout();
this.panel2.SuspendLayout();
this.tc1.SuspendLayout();
@ -122,16 +123,6 @@
this.btDumpList.UseVisualStyleBackColor = true;
this.btDumpList.Click += new System.EventHandler(this.btDumpList_Click);
//
// label3
//
this.label3.Dock = System.Windows.Forms.DockStyle.Fill;
this.label3.Location = new System.Drawing.Point(606, 823);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(372, 36);
this.label3.TabIndex = 22;
this.label3.Text = "Right click above to open the context menu";
this.label3.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// rtb
//
this.rtb.AcceptsTab = true;
@ -373,6 +364,15 @@
this.tabJS1.TabIndex = 0;
this.tabJS1.Text = "Joystick 1";
//
// UC_JoyPanel
//
this.UC_JoyPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.UC_JoyPanel.JsAssignment = 0;
this.UC_JoyPanel.Location = new System.Drawing.Point(3, 3);
this.UC_JoyPanel.Name = "UC_JoyPanel";
this.UC_JoyPanel.Size = new System.Drawing.Size(275, 315);
this.UC_JoyPanel.TabIndex = 0;
//
// panel1
//
this.tlpanel.SetColumnSpan(this.panel1, 3);
@ -470,7 +470,6 @@
this.tlpanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tlpanel.Controls.Add(this.rtb, 2, 1);
this.tlpanel.Controls.Add(this.panel1, 0, 0);
this.tlpanel.Controls.Add(this.label3, 2, 4);
this.tlpanel.Controls.Add(this.treeView1, 0, 1);
this.tlpanel.Controls.Add(this.flowLayoutPanel1, 1, 1);
this.tlpanel.Controls.Add(this.tableLayoutPanel1, 1, 2);
@ -509,6 +508,7 @@
this.tableLayoutPanel1.Controls.Add(this.btDump, 0, 0);
this.tableLayoutPanel1.Controls.Add(this.btGrab, 1, 0);
this.tableLayoutPanel1.Controls.Add(this.btDumpList, 0, 1);
this.tableLayoutPanel1.Controls.Add(this.button1, 1, 4);
this.tableLayoutPanel1.Controls.Add(this.cbxBlendUnmapped, 0, 4);
this.tableLayoutPanel1.Controls.Add(this.txFilter, 0, 2);
this.tableLayoutPanel1.Controls.Add(this.btClearFilter, 0, 3);
@ -525,6 +525,16 @@
this.tableLayoutPanel1.Size = new System.Drawing.Size(294, 153);
this.tableLayoutPanel1.TabIndex = 23;
//
// button1
//
this.button1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.button1.Location = new System.Drawing.Point(171, 123);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(120, 24);
this.button1.TabIndex = 17;
this.button1.Text = "Joystick Tuning";
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// cbxBlendUnmapped
//
this.cbxBlendUnmapped.AutoSize = true;
@ -657,24 +667,6 @@
this.label1.TabIndex = 16;
this.label1.Text = "Mapping name:";
//
// statusStrip1
//
this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.toolStripStatusLabel2,
this.tsDDbtProfiles,
this.tsBtReset,
this.toolStripStatusLabel3,
this.toolStripStatusLabel1,
this.tsDDbtMappings,
this.tsBtLoad});
this.statusStrip1.Location = new System.Drawing.Point(0, 832);
this.statusStrip1.Name = "statusStrip1";
this.statusStrip1.RenderMode = System.Windows.Forms.ToolStripRenderMode.Professional;
this.statusStrip1.ShowItemToolTips = true;
this.statusStrip1.Size = new System.Drawing.Size(984, 30);
this.statusStrip1.TabIndex = 26;
this.statusStrip1.Text = "statusStrip1";
//
// toolStripStatusLabel2
//
this.toolStripStatusLabel2.BackColor = System.Drawing.Color.DarkKhaki;
@ -802,14 +794,23 @@
this.loadToolStripMenuItem.Text = "Load !";
this.loadToolStripMenuItem.Click += new System.EventHandler(this.loadToolStripMenuItem_Click);
//
// UC_JoyPanel
// statusStrip1
//
this.UC_JoyPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.UC_JoyPanel.JsAssignment = 0;
this.UC_JoyPanel.Location = new System.Drawing.Point(3, 3);
this.UC_JoyPanel.Name = "UC_JoyPanel";
this.UC_JoyPanel.Size = new System.Drawing.Size(275, 315);
this.UC_JoyPanel.TabIndex = 0;
this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.toolStripStatusLabel2,
this.tsDDbtProfiles,
this.tsBtReset,
this.toolStripStatusLabel3,
this.toolStripStatusLabel1,
this.tsDDbtMappings,
this.tsBtLoad});
this.statusStrip1.Location = new System.Drawing.Point(0, 832);
this.statusStrip1.Name = "statusStrip1";
this.statusStrip1.RenderMode = System.Windows.Forms.ToolStripRenderMode.Professional;
this.statusStrip1.ShowItemToolTips = true;
this.statusStrip1.Size = new System.Drawing.Size(984, 30);
this.statusStrip1.TabIndex = 26;
this.statusStrip1.Text = "statusStrip1";
//
// MainForm
//
@ -823,6 +824,8 @@
this.MinimumSize = new System.Drawing.Size(1000, 900);
this.Name = "MainForm";
this.Text = "SC Joystick Mapper";
this.Activated += new System.EventHandler(this.MainForm_Activated);
this.Deactivate += new System.EventHandler(this.MainForm_Deactivate);
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing);
this.Load += new System.EventHandler(this.MainForm_Load);
this.cmCopyPaste.ResumeLayout(false);
@ -849,7 +852,6 @@
#endregion
private System.Windows.Forms.Button btDumpList;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.RichTextBox rtb;
private System.Windows.Forms.Button btGrab;
private System.Windows.Forms.Button btDump;
@ -886,7 +888,6 @@
private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2;
private System.Windows.Forms.StatusStrip statusStrip1;
private System.Windows.Forms.ToolStripDropDownButton tsDDbtProfiles;
private System.Windows.Forms.ToolStripDropDownButton tsDDbtMappings;
private System.Windows.Forms.ToolStripDropDownButton tsBtReset;
@ -914,6 +915,8 @@
private System.Windows.Forms.Button btSettings;
private System.Windows.Forms.CheckBox cbxBlendUnmapped;
private System.Windows.Forms.Button btJsReassign;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.StatusStrip statusStrip1;
}
}

@ -31,6 +31,8 @@ namespace SCJMapper_V2
///</remarks>
private ActionTree m_AT = null;
private FormJSCalCurve JSCAL = null;
#region Main Form Handling
@ -239,7 +241,7 @@ namespace SCJMapper_V2
log.Debug( "InitActionTree - Entry" );
// build TreeView and the ActionMaps
m_AT = new ActionTree( cbxBlendUnmapped.Checked );
m_AT = new ActionTree( cbxBlendUnmapped.Checked, m_Joystick );
m_AT.Ctrl = treeView1; // the ActionTree owns the TreeView control
m_AT.IgnoreMaps = m_AppSettings.IgnoreActionmaps;
m_AT.LoadTree( m_AppSettings.DefProfileName, addDefaultBinding ); // Init with default profile filepath
@ -798,6 +800,82 @@ namespace SCJMapper_V2
#endregion
private void button1_Click( object sender, EventArgs e )
{
timer1.Enabled = false; // must be off while a modal window is shown, else DX gets crazy
JSCAL = new FormJSCalCurve( );
// get current mapping from ActionMaps
String cmd = "";
// attach Yaw command
cmd = m_AT.FindCommand( "v_yaw - js" );
if ( cmd.ToLowerInvariant( ).EndsWith( "x" ) ) {
m_AT.ActionMaps.TuningX.Command = cmd;
JSCAL.YawTuning = m_AT.ActionMaps.TuningX;
}
else if ( cmd.ToLowerInvariant( ).EndsWith( "y" ) ) {
m_AT.ActionMaps.TuningY.Command = cmd;
JSCAL.YawTuning = m_AT.ActionMaps.TuningY;
}
else if ( cmd.ToLowerInvariant( ).EndsWith( "z" ) ) {
m_AT.ActionMaps.TuningZ.Command = cmd;
JSCAL.YawTuning = m_AT.ActionMaps.TuningZ;
}
// attach Pitch command
cmd = m_AT.FindCommand( "v_pitch - js" );
if ( cmd.ToLowerInvariant( ).EndsWith( "x" ) ) {
m_AT.ActionMaps.TuningX.Command = cmd;
JSCAL.PitchTuning = m_AT.ActionMaps.TuningX;
}
else if ( cmd.ToLowerInvariant( ).EndsWith( "y" ) ) {
m_AT.ActionMaps.TuningY.Command = cmd;
JSCAL.PitchTuning = m_AT.ActionMaps.TuningY;
}
else if ( cmd.ToLowerInvariant( ).EndsWith( "z" ) ) {
m_AT.ActionMaps.TuningZ.Command = cmd;
JSCAL.PitchTuning = m_AT.ActionMaps.TuningZ;
}
// attach Roll command
cmd = m_AT.FindCommand( "v_roll - js" );
if ( cmd.ToLowerInvariant( ).EndsWith( "x" ) ) {
m_AT.ActionMaps.TuningX.Command = cmd;
JSCAL.RollTuning = m_AT.ActionMaps.TuningX;
}
else if ( cmd.ToLowerInvariant( ).EndsWith( "y" ) ) {
m_AT.ActionMaps.TuningY.Command = cmd;
JSCAL.RollTuning = m_AT.ActionMaps.TuningY;
}
else if ( cmd.ToLowerInvariant( ).EndsWith( "z" ) ) {
m_AT.ActionMaps.TuningZ.Command = cmd;
JSCAL.RollTuning = m_AT.ActionMaps.TuningZ;
}
// run
JSCAL.ShowDialog( );
m_AT.Dirty = true;
// get from dialog
JSCAL = null; // get rid and create a new one next time..
if ( m_AT.Dirty ) btDump.BackColor = MyColors.DirtyColor;
timer1.Enabled = true;
}
private void MainForm_Deactivate( object sender, EventArgs e )
{
timer1.Enabled = false;
m_Joystick.Deactivate( );
}
private void MainForm_Activated( object sender, EventArgs e )
{
timer1.Enabled =true;
m_Joystick.Activate( );
}

@ -392,7 +392,7 @@
AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w
LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAAQ
DgAAAk1TRnQBSQFMAgEBBwEAAdABCQHQAQkBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo
DgAAAk1TRnQBSQFMAgEBBwEAARgBCgEYAQoBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo
AwABQAMAASADAAEBAQABCAYAAQgYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA
AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5
AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA
@ -536,9 +536,6 @@
<metadata name="SFD.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>421, 17</value>
</metadata>
<metadata name="statusStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<data name="tsDDbtProfiles.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
@ -644,6 +641,9 @@
<metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>555, 17</value>
</metadata>
<metadata name="statusStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAABAAEAQEAAAAEAIAAoQgAAFgAAACgAAABAAAAAgAAAAAEAIAAAAAAAAD4AAAAAAAAAAAAAAAAAAAAA

@ -38,9 +38,10 @@ namespace SCJMapper_V2
private String version { get; set; }
private String ignoreversion { get; set; }
private UICustHeader uiCustHeader = new UICustHeader( );
private Deviceoptions deviceOptions = new Deviceoptions( );
private Options options = new Options( );
private JoystickList m_joystickList = null;
private UICustHeader m_uiCustHeader = null;
private Options m_options = null;
private Deviceoptions m_deviceOptions = null;
// own additions for JS mapping - should not harm..
@ -64,12 +65,38 @@ namespace SCJMapper_V2
}
// provide access to Tuning items of the Options obj to the owner
/// <summary>
/// Returns the X-Tuning item
/// </summary>
public JoystickTuningParameter TuningX
{
get { return m_options.TuneX; }
}
/// <summary>
/// Returns the Y-Tuning item
/// </summary>
public JoystickTuningParameter TuningY
{
get { return m_options.TuneY; }
}
/// <summary>
/// Returns the Z-Tuning item
/// </summary>
public JoystickTuningParameter TuningZ
{
get { return m_options.TuneZ; }
}
/// <summary>
/// ctor
/// </summary>
public ActionMapsCls( )
public ActionMapsCls( JoystickList jsList )
{
version = "0";
m_joystickList = jsList; // have to save this for Reassign
// create the Joystick assignments
Array.Resize( ref m_js, JoystickCls.JSnum_MAX + 1 );
@ -78,6 +105,11 @@ namespace SCJMapper_V2
m_js[i] = ""; m_GUIDs[i] = "";
}
// create options objs
m_uiCustHeader = new UICustHeader( );
m_options = new Options( m_joystickList );
m_deviceOptions = new Deviceoptions( m_options );
LoadActionMaps( ); // get them from config
}
@ -89,12 +121,12 @@ namespace SCJMapper_V2
/// <returns>The ActionMaps copy with reassigned input</returns>
public ActionMapsCls ReassignJsN( Dictionary<int, int> newJsList )
{
ActionMapsCls newMaps = new ActionMapsCls( );
ActionMapsCls newMaps = new ActionMapsCls( m_joystickList );
// full copy from 'this'
newMaps.uiCustHeader = this.uiCustHeader;
newMaps.deviceOptions = this.deviceOptions;
newMaps.options = this.options;
newMaps.m_uiCustHeader = this.m_uiCustHeader;
newMaps.m_deviceOptions = this.m_deviceOptions;
newMaps.m_options = this.m_options;
for ( int i=0; i < JoystickCls.JSnum_MAX; i++ ) {
newMaps.jsN[i] = this.jsN[i]; newMaps.jsNGUID[i] = this.jsNGUID[i];
@ -104,6 +136,8 @@ namespace SCJMapper_V2
newMaps.Add( am.ReassignJsN( newJsList ) );
}
m_options.ReassignJsN( newJsList );
return newMaps;
}
@ -165,11 +199,12 @@ namespace SCJMapper_V2
// close the tag
r += String.Format( ">\n" );
// and dump the contents
if ( uiCustHeader.Count > 0 ) r += uiCustHeader.toXML( ) + String.Format( "\n" );
if ( deviceOptions.Count > 0 ) r += deviceOptions.toXML( ) + String.Format( "\n" );
if ( options.Count > 0 ) r += options.toXML( ) + String.Format( "\n" );
// and dump the option contents
if ( m_uiCustHeader.Count > 0 ) r += m_uiCustHeader.toXML( ) + String.Format( "\n" );
if ( m_options.Count > 0 ) r += m_options.toXML( ) + String.Format( "\n" );
if ( m_deviceOptions.Count > 0 ) r += m_deviceOptions.toXML( ) + String.Format( "\n" );
// finally the action maps
foreach ( ActionMapCls amc in this ) {
r += String.Format( "{0}\n", amc.toXML( ) );
}
@ -178,7 +213,6 @@ namespace SCJMapper_V2
}
/// <summary>
/// Read an ActionMaps from XML - do some sanity check
/// </summary>
@ -189,10 +223,11 @@ namespace SCJMapper_V2
log.Debug( "fromXML - Entry" );
// Reset those options...
uiCustHeader = new UICustHeader( );
deviceOptions = new Deviceoptions( );
options = new Options( );
m_uiCustHeader = new UICustHeader( );
m_options = new Options( m_joystickList );
m_deviceOptions = new Deviceoptions( m_options );
XmlReaderSettings settings = new XmlReaderSettings( );
settings.ConformanceLevel = ConformanceLevel.Fragment;
settings.IgnoreWhitespace = true;
@ -233,19 +268,20 @@ namespace SCJMapper_V2
}
else if ( reader.Name == "CustomisationUIHeader" ) {
String x = reader.ReadOuterXml( );
uiCustHeader.fromXML( x );
m_uiCustHeader.fromXML( x );
}
else if ( reader.Name == "deviceoptions" ) {
String x = reader.ReadOuterXml( );
deviceOptions.fromXML( x );
m_deviceOptions.fromXML( x );
}
else if ( reader.Name == "options" ) {
String x = reader.ReadOuterXml( );
options.fromXML( x );
m_options.fromXML( x );
}
else {
reader.Read( );
}
}
return true;
}

@ -48,14 +48,16 @@ namespace SCJMapper_V2
public String IgnoreMaps { get; set; }
private String m_Filter = ""; // the tree content filter
private JoystickList m_jsList = null;
/// <summary>
/// ctor
/// </summary>
public ActionTree( Boolean blendUnmapped )
public ActionTree( Boolean blendUnmapped, JoystickList jsList )
{
BlendUnmapped = blendUnmapped;
m_jsList = jsList;
IgnoreMaps = ""; // nothing to ignore
}
@ -67,7 +69,7 @@ namespace SCJMapper_V2
/// <returns>The ActionTree Copy with reassigned input</returns>
public ActionTree ReassignJsN( Dictionary<int, int> newJsList )
{
ActionTree nTree = new ActionTree( BlendUnmapped );
ActionTree nTree = new ActionTree( BlendUnmapped, m_jsList );
// full copy from 'this'
nTree.m_MasterTree = this.m_MasterTree;
nTree.m_ctrl = this.m_ctrl;
@ -184,7 +186,7 @@ namespace SCJMapper_V2
ActionCls ac = null;
ActionMapCls acm = null;
ActionMaps = new ActionMapsCls( );
ActionMaps = new ActionMapsCls( m_jsList );
m_MasterTree.Nodes.Clear( );
@ -416,6 +418,27 @@ namespace SCJMapper_V2
}
/// <summary>
/// Find a control that contains the string and mark it
/// this method is applied to the GUI TreeView only
/// </summary>
/// <param name="m_MasterTree">The string to find</param>
public String FindCommand( String ctrl )
{
log.Debug( "FindCtrl - Entry" );
foreach ( TreeNode tn in Ctrl.Nodes ) {
// have to search nodes of nodes
foreach ( TreeNode stn in tn.Nodes ) {
if ( stn.Text.Contains( ctrl ) ) {
return stn.Text;
}
}
}
return "";
}
/// <summary>
/// Reports a summary list of the mapped items
/// </summary>

@ -22,8 +22,31 @@ namespace SCJMapper_V2
/// Saitek X52 Pro Flight Controller
///
/// </summary>
class Deviceoptions : List<String>
public class Deviceoptions
{
private static readonly log4net.ILog log = log4net.LogManager.GetLogger( System.Reflection.MethodBase.GetCurrentMethod( ).DeclaringType );
List<String> m_stringOptions = new List<String>( );
Options m_options = null;
JoystickTuningParameter m_tuningX = null;
JoystickTuningParameter m_tuningY = null;
JoystickTuningParameter m_tuningZ = null;
// ctor
public Deviceoptions( Options options )
{
m_options = options;
m_tuningX = m_options.TuneX;
m_tuningY = m_options.TuneY;
m_tuningZ = m_options.TuneZ;
}
public int Count
{
get { return ( m_stringOptions.Count + ( ( m_tuningX != null ) ? 1 : 0 ) + ( ( m_tuningY != null ) ? 1 : 0 ) + ( ( m_tuningZ != null ) ? 1 : 0 ) ); }
}
private String[] FormatXml( string xml )
{
@ -37,15 +60,15 @@ namespace SCJMapper_V2
}
/// <summary>
/// Dump the CustomisationUIHeader as partial XML nicely formatted
/// Dump the Deviceoptions as partial XML nicely formatted
/// </summary>
/// <returns>the action as XML fragment</returns>
public String toXML( )
{
String r = "";
// and dump the contents
foreach ( String x in this ) {
// and dump the contents of plain string options
foreach ( String x in m_stringOptions ) {
if ( !String.IsNullOrWhiteSpace( x ) ) {
foreach ( String line in FormatXml( x ) ) {
@ -55,19 +78,96 @@ namespace SCJMapper_V2
r += String.Format( "\n" );
}
// dump Tuning
r += m_tuningX.Deviceoptions_toXML( );
r += m_tuningY.Deviceoptions_toXML( );
r += m_tuningZ.Deviceoptions_toXML( );
return r;
}
/// <summary>
/// Read an CustomisationUIHeader from XML - do some sanity check
/// Read an Deviceoptions from XML - do some sanity check
/// </summary>
/// <param name="xml">the XML action fragment</param>
/// <returns>True if an action was decoded</returns>
public Boolean fromXML( String xml )
{
if ( !this.Contains( xml ) ) this.Add( xml );
/*
* This can be a lot of the following options
* try to do our best....
*
* <deviceoptions name="Joystick - HOTAS Warthog">
<!-- Reduce the deadzone -->
<option input="x" deadzone="0.015" />
<option input="y" deadzone="0.015" />
</deviceoptions>
*
*/
XmlReaderSettings settings = new XmlReaderSettings( );
settings.ConformanceLevel = ConformanceLevel.Fragment;
settings.IgnoreWhitespace = true;
settings.IgnoreComments = true;
XmlReader reader = XmlReader.Create( new StringReader( xml ), settings );
reader.Read( );
String name = "";
if ( reader.HasAttributes ) {
name = reader["name"];
reader.Read( );
// try to disassemble the items
while ( !reader.EOF ) {
if ( reader.Name == "option" ) {
if ( reader.HasAttributes ) {
String input = reader["input"];
String deadzone = reader["deadzone"];
if ( ! (String.IsNullOrWhiteSpace( input ) || String.IsNullOrWhiteSpace( deadzone )) ) {
if ( input.ToLowerInvariant( ).EndsWith("x") ) {
if ( String.IsNullOrWhiteSpace( m_tuningX.CommandCtrl ) ) m_tuningX.CommandCtrl = input; // if no options have been given...
if ( string.IsNullOrWhiteSpace( m_tuningX.DeviceName ) ) m_tuningX.DeviceName = name; // if no devicename has been given...
m_tuningX.DeadzoneUsed = true; m_tuningX.Deadzone = deadzone;
}
else if ( input.ToLowerInvariant( ).EndsWith("y") ) {
if ( String.IsNullOrWhiteSpace( m_tuningY.CommandCtrl ) ) m_tuningY.CommandCtrl = input; // if no options have been given...
if ( string.IsNullOrWhiteSpace( m_tuningY.DeviceName ) ) m_tuningY.DeviceName = name; // if no devicename has been given...
m_tuningY.DeadzoneUsed = true; m_tuningY.Deadzone = deadzone;
}
else if ( input.ToLowerInvariant( ).EndsWith( "z" ) ) {
if ( String.IsNullOrWhiteSpace( m_tuningZ.CommandCtrl )) m_tuningZ.CommandCtrl=input; // if no options have been given...
if ( string.IsNullOrWhiteSpace( m_tuningZ.DeviceName ) ) m_tuningZ.DeviceName = name; // if no devicename has been given...
m_tuningZ.DeadzoneUsed = true; m_tuningZ.Deadzone = deadzone;
}
else {
//?? option node refers to unknown axis (not x,y,rotz)
log.ErrorFormat( "Deviceoptions.fromXML: option node refers to unknown axis {0}", input );
}
}
else {
//? option node has not the needed attributes
log.ErrorFormat( "Deviceoptions.fromXML: option node has not the needed attributes" );
}
}
else {
//?? option node has NO attributes
log.ErrorFormat( "Deviceoptions.fromXML: option node has NO attributes" );
}
}
reader.Read( );
}//while
}
else {
//??
if ( !m_stringOptions.Contains( xml ) ) m_stringOptions.Add( xml );
}
return true;
}

@ -15,7 +15,7 @@ namespace SCJMapper_V2
/// In addition provide some static tools to handle JS props here in one place
/// Also owns the GUI i.e. the user control that shows all values
/// </summary>
class JoystickCls
public class JoystickCls
{
private static readonly log4net.ILog log = log4net.LogManager.GetLogger( System.Reflection.MethodBase.GetCurrentMethod( ).DeclaringType );
private static readonly AppSettings appSettings = new AppSettings( );
@ -178,6 +178,7 @@ namespace SCJMapper_V2
private int m_senseLimit = 150; // axis jitter avoidance...
private int m_joystickNumber = 0; // seq number of the enumerated joystick
private bool[] m_ignoreButtons;
private bool m_activated = false;
private UC_JoyPanel m_jPanel = null; // the GUI panel
private TabPage m_jTab = null;
@ -224,6 +225,14 @@ namespace SCJMapper_V2
public int ButtonCount { get { return m_device.Capabilities.ButtonCount; } }
public int POVCount { get { return m_device.Capabilities.PovCount; } }
public Boolean Activated
{
get { return m_activated;}
set { m_activated = value;
if ( m_activated == false ) m_device.Unacquire( ); // explicitely if not longer active
}
}
/// <summary>
/// ctor and init
@ -240,6 +249,7 @@ namespace SCJMapper_V2
m_joystickNumber = joystickNum;
m_jPanel = panel;
m_jTab = tab;
Activated = false;
m_senseLimit = AppConfiguration.AppConfig.jsSenseLimit; // can be changed in the app.config file if it is still too little
@ -260,7 +270,7 @@ namespace SCJMapper_V2
// Set the data format to the c_dfDIJoystick pre-defined format.
//m_device.SetDataFormat( DeviceDataFormat.Joystick );
// Set the cooperative level for the device.
m_device.SetCooperativeLevel( m_hwnd, CooperativeLevel.Exclusive | CooperativeLevel.Foreground );
m_device.SetCooperativeLevel( m_hwnd, CooperativeLevel.NonExclusive | CooperativeLevel.Background );
// Enumerate all the objects on the device.
foreach ( DeviceObjectInstance d in m_device.GetObjects( ) ) {
// For axes that are returned, set the DIPROP_RANGE property for the
@ -278,6 +288,7 @@ namespace SCJMapper_V2
}
ApplySettings( ); // get whatever is needed here from Settings
Activated = true;
}
@ -536,8 +547,10 @@ namespace SCJMapper_V2
/// <summary>
/// Collect the current data from the device
/// </summary>
public void GetData( )
public void GetAxisData( out int x, out int y, out int rz )
{
x = 0; y = 0; rz = 0;
// Make sure there is a valid device.
if ( null == m_device )
return;
@ -566,6 +579,121 @@ namespace SCJMapper_V2
}
// Get the state of the device - retaining the previous state to find the lates change
m_prevState = m_state;
try { m_state = m_device.GetCurrentState( ); }
// Catch any exceptions. None will be handled here,
// any device re-aquisition will be handled above.
catch ( SharpDXException ) {
return;
}
x = m_state.X; y = m_state.Y; rz = m_state.RotationZ;
}
/// <summary>
/// Collect the current data from the device
/// </summary>
public void GetCmdData( String cmd, out int data )
{
// TODO: Expand this out into a joystick class (see commit for details)
Dictionary<string, string> axies = new Dictionary<string, string>( )
{
{"x","X"},
{"y","Y"},
{"z","Z"},
{"rotx","RotationX"},
{"roty","RotationY"},
{"rotz","RotationZ"}
};
data = 0;
// Make sure there is a valid device.
if ( null == m_device )
return;
// Poll the device for info.
try {
m_device.Poll( );
}
catch ( SharpDXException e ) {
if ( ( e.ResultCode == ResultCode.NotAcquired ) || ( e.ResultCode == ResultCode.InputLost ) ) {
// Check to see if either the app needs to acquire the device, or
// if the app lost the device to another process.
try {
// Acquire the device.
m_device.Acquire( );
}
catch ( SharpDXException ) {
// Failed to acquire the device. This could be because the app doesn't have focus.
return; // EXIT unaquired
}
}
else {
log.Error( "Unexpected Poll Exception", e );
return; // EXIT see ex code
}
}
// Get the state of the device - retaining the previous state to find the lates change
m_prevState = m_state;
try { m_state = m_device.GetCurrentState( ); }
// Catch any exceptions. None will be handled here,
// any device re-aquisition will be handled above.
catch ( SharpDXException ) {
return;
}
try {
PropertyInfo axisProperty = typeof( JoystickState ).GetProperty( axies[cmd] );
data = ( int )axisProperty.GetValue( this.m_state, null );
}
catch {
data = 0;
}
}
/// <summary>
/// Collect the current data from the device
/// </summary>
public void GetData( )
{
// Make sure there is a valid device.
if ( null == m_device )
return;
// Poll the device for info.
try {
m_device.Poll( );
}
catch ( SharpDXException e ) {
if ( ( e.ResultCode == ResultCode.NotAcquired ) || ( e.ResultCode == ResultCode.InputLost ) ) {
// Check to see if either the app needs to acquire the device, or
// if the app lost the device to another process.
try {
// Acquire the device - if the (main)window is active
if ( Activated ) m_device.Acquire( );
}
catch ( SharpDXException ) {
// Failed to acquire the device. This could be because the app doesn't have focus.
return; // EXIT unaquired
}
}
else {
log.Error( "Unexpected Poll Exception", e );
return; // EXIT see ex code
}
}
// Get the state of the device - retaining the previous state to find the lates change
m_prevState = m_state;
try { m_state = m_device.GetCurrentState( ); }

@ -6,13 +6,23 @@ using System.Windows.Forms;
namespace SCJMapper_V2
{
class JoystickList : List<JoystickCls>
public class JoystickList : List<JoystickCls>
{
private FormReassign FR = null;
public Dictionary<int, int> JsReassingList { get; set; } // oldJs, newJs
public List<int> NewJsList { get; set; } // index is this[idx]
public void Deactivate( )
{
foreach ( JoystickCls j in this ) j.Activated = false;
}
public void Activate( )
{
foreach ( JoystickCls j in this ) j.Activated =true;
}
/// <summary>
/// Show the jsN Reassign Dialog
/// </summary>

@ -0,0 +1,318 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
namespace SCJMapper_V2
{
/// <summary>
/// set of parameters to tune the Joystick
/// </summary>
public class JoystickTuningParameter
{
private static readonly log4net.ILog log = log4net.LogManager.GetLogger( System.Reflection.MethodBase.GetCurrentMethod( ).DeclaringType );
private String m_command = ""; // v_pitch - js1_x ..
private String m_cmdCtrl = ""; // x, y, rotz ...
private int m_jsN = 0; // jsN
String m_option = ""; // the option name (level where it applies)
private String m_deviceName = "";
private bool m_deadzoneEnabled = false; // default
private String m_deadzone = "0.000";
private bool m_senseEnabled = false; // default
private String m_sense = "1.00";
private bool m_invertEnabled = false; // default
private bool m_expEnabled = false; // default
private String m_exponent = "1.000";
private bool m_ptsEnabled = false; // default
private List<String> m_PtsIn = new List<String>( );
private List<String> m_PtsOut = new List<String>( );
private JoystickList m_joystickList = null;
private JoystickCls m_js = null;
public JoystickTuningParameter( JoystickList jsList )
{
m_joystickList = jsList;
}
#region Properties
public JoystickCls JsDevice
{
get { return m_js; }
}
public int JsN
{
get { return m_jsN; }
set
{
m_jsN = value;
m_js = m_joystickList.Find_jsN( m_jsN );
m_deviceName = m_js.DevName;
}
}
public String DeviceName
{
get { return m_deviceName; }
set { m_deviceName = value; }
}
public String Command
{
get { return m_command; }
set { m_command = value; DecomposeCommand( ); }
}
public String CommandCtrl
{
get { return m_cmdCtrl; }
set { m_cmdCtrl = value; }
}
public bool DeadzoneUsed
{
get { return m_deadzoneEnabled; }
set { m_deadzoneEnabled = value; }
}
public String Deadzone
{
get { return m_deadzone; }
set { m_deadzone = value; }
}
public bool SensitivityUsed
{
get { return m_senseEnabled; }
set { m_senseEnabled = value; }
}
public String Sensitivity
{
get { return m_sense; }
set { m_sense = value; }
}
public bool InvertUsed
{
get { return m_invertEnabled; }
set { m_invertEnabled = value; }
}
public bool ExponentUsed
{
get { return m_expEnabled; }
set { m_expEnabled = value; }
}
public String Exponent
{
get { return m_exponent; }
set { m_exponent = value; }
}
public bool NonLinCurveUsed
{
get { return m_ptsEnabled; }
set { m_ptsEnabled = value; }
}
public List<String> NonLinCurvePtsIn
{
get { return m_PtsIn; }
set { m_PtsIn = value; }
}
public List<String> NonLinCurvePtsOut
{
get { return m_PtsOut; }
set { m_PtsOut = value; }
}
#endregion
/// <summary>
/// Derive values from a command (e.g. v_pitch - js1_x)
/// </summary>
private void DecomposeCommand( )
{
// pobulate from input
String[] e = Command.Split( new Char[] { '-' } ); // v_pitch - js1_x
m_cmdCtrl = ""; m_jsN = 0;
if ( e.Length > 1 ) {
// get parts
m_cmdCtrl = e[1].Trim( ).Split( new Char[] { '_' } )[1]; //js1_x -> x
m_jsN = JoystickCls.JSNum( e[1].Trim( ) ); // get the right Joystick from jsN
m_js = m_joystickList.Find_jsN( m_jsN );
m_deviceName = m_js.DevName;
m_option = String.Format( "pilot_move_{0}", m_cmdCtrl ); // update from Command
}
}
/// <summary>
/// Format an XML -deviceoptions- node from the tuning contents
/// </summary>
/// <returns>The XML string or an empty string</returns>
public String Deviceoptions_toXML( )
{
/*
<deviceoptions name="Joystick - HOTAS Warthog">
<!-- Reduce the deadzone -->
<option input="x" deadzone="0.015" />
<option input="y" deadzone="0.015" />
</deviceoptions>
*/
String tmp = "";
if ( m_deadzoneEnabled ) {
tmp += String.Format( "\t<deviceoptions name=\"{0}\">\n", m_deviceName );
tmp += String.Format( "\t\t<option input=\"{0}\" deadzone=\"{1}\" />\n", m_cmdCtrl, m_deadzone );
tmp += String.Format( "\t</deviceoptions>\n \n" );
}
return tmp;
}
/// <summary>
/// Format an XML -options- node from the tuning contents
/// </summary>
/// <returns>The XML string or an empty string</returns>
public String Options_toXML( )
{
if ( ( m_senseEnabled || m_expEnabled || m_invertEnabled || m_ptsEnabled ) == false ) return ""; // not used
String tmp = "";
tmp += String.Format( "\t<options type=\"joystick\" instance=\"{0}\">\n", m_jsN.ToString( ) );
tmp += String.Format( "\t\t<{0} ", m_option );
if ( InvertUsed ) {
tmp += String.Format( "invert=\"1\" " );
}
if ( SensitivityUsed ) {
tmp += String.Format( "sensitivity=\"{0}\" ", m_sense );
}
if ( NonLinCurveUsed ) {
// add exp to avoid merge of things...
tmp += String.Format( "exponent=\"1.00\" > \n" ); // CIG get to default expo 2.something if not set to 1 here
tmp += String.Format( "\t\t\t<nonlinearity_curve>\n" );
tmp += String.Format( "\t\t\t\t<point in=\"{0}\" out=\"{1}\"/>\n", m_PtsIn[0], m_PtsOut[0] );
tmp += String.Format( "\t\t\t\t<point in=\"{0}\" out=\"{1}\"/>\n", m_PtsIn[1], m_PtsOut[1] );
tmp += String.Format( "\t\t\t\t<point in=\"{0}\" out=\"{1}\"/>\n", m_PtsIn[2], m_PtsOut[2] );
tmp += String.Format( "\t\t\t</nonlinearity_curve>\n" );
tmp += String.Format( "\t\t</{0}> \n", m_option );
}
else if ( ExponentUsed ) {
// only exp used
tmp += String.Format( "exponent=\"{0}\" /> \n", m_exponent );
}
else {
// neither exp or curve
tmp += String.Format( "exponent=\"1.00\" /> \n" );// CIG get to default expo 2.something if not set to 1 here
}
tmp += String.Format( "\t</options>\n \n" );
return tmp;
}
/// <summary>
/// Read the options from the XML
/// can get only the 3 ones for Move X,Y,RotZ right now
/// </summary>
/// <param name="reader">A prepared XML reader</param>
/// <param name="instance">the Josyticj instance number</param>
/// <returns></returns>
public Boolean Options_fromXML( XmlReader reader, int instance )
{
String invert = "";
String sensitivity = "";
String exponent = "";
String instance_inv = "";
m_option = reader.Name;
JsN = instance;
// derive from pilot_move_x || pilot_move_rotx (nothing bad should arrive here)
String[] e = m_option.ToLowerInvariant( ).Split( new char[] { '_' } );
if ( e.Length >= 2 ) m_cmdCtrl = e[2];
if ( reader.HasAttributes ) {
invert = reader["invert"];
if ( !String.IsNullOrWhiteSpace( invert ) ) {
m_invertEnabled = false;
if ( invert == "1" ) m_invertEnabled = true;
}
instance_inv = reader["instance"]; // CIG wrong attr name ?!
if ( !String.IsNullOrWhiteSpace( instance_inv ) ) {
m_invertEnabled = false;
if ( instance_inv == "1" ) m_invertEnabled = true;
}
sensitivity = reader["sensitivity"];
if ( !String.IsNullOrWhiteSpace( sensitivity ) ) {
m_sense = sensitivity;
m_senseEnabled = true;
}
exponent = reader["exponent"];
if ( !String.IsNullOrWhiteSpace( exponent ) ) {
m_exponent = exponent;
m_expEnabled = true;
}
}
// we may have a nonlin curve...
reader.Read( );
if ( !reader.EOF ) {
if ( reader.Name.ToLowerInvariant( ) == "nonlinearity_curve" ) {
m_PtsIn.Clear( ); m_PtsOut.Clear( ); // reset pts
reader.Read( );
while ( !reader.EOF ) {
String ptIn = "";
String ptOut = "";
if ( reader.Name.ToLowerInvariant( ) == "point" ) {
if ( reader.HasAttributes ) {
ptIn = reader["in"];
ptOut = reader["out"];
m_PtsIn.Add( ptIn ); m_PtsOut.Add( ptOut ); m_ptsEnabled = true;
}
}
reader.Read( );
}//while
// sanity check - we've have to have 3 pts here - else we subst
// add 2nd
if ( m_PtsIn.Count < 2 ) {
m_PtsIn.Add( "0.5" ); m_PtsOut.Add( "0.5" );
log.Info( "Options_fromXML: got only one nonlin point, added (0.5|0.5)" );
}
// add 3rd
if ( m_PtsIn.Count < 3 ) {
m_PtsIn.Add( "0.75" ); m_PtsOut.Add( "0.75" );
log.Info( "Options_fromXML: got only two nonlin points, added (0.75|0.75)" );
}
}
}
return true;
}
}
}

@ -23,8 +23,67 @@ namespace SCJMapper_V2
/// [value] : for invert use 0/1; for others use 0.0 to 2.0
///
/// </summary>
class Options : List<String>
public class Options
{
private static readonly log4net.ILog log = log4net.LogManager.GetLogger( System.Reflection.MethodBase.GetCurrentMethod( ).DeclaringType );
List<String> m_stringOptions = new List<String>( );
JoystickTuningParameter m_tuningX = null;
JoystickTuningParameter m_tuningY = null;
JoystickTuningParameter m_tuningZ = null;
// ctor
public Options( JoystickList jsList )
{
m_tuningX = new JoystickTuningParameter( jsList ); // can be x or rotx
m_tuningY = new JoystickTuningParameter( jsList ); // can be y or roty
m_tuningZ = new JoystickTuningParameter( jsList ); // can be z or rotz
}
public int Count
{
get { return ( m_stringOptions.Count + ( ( m_tuningX != null ) ? 1 : 0 ) + ( ( m_tuningY != null ) ? 1 : 0 ) + ( ( m_tuningZ != null ) ? 1 : 0 ) ); }
}
// provide access to Tuning items
/// <summary>
/// Returns the X-Tuning item
/// </summary>
public JoystickTuningParameter TuneX
{
get { return m_tuningX; }
}
/// <summary>
/// Returns the Y-Tuning item
/// </summary>
public JoystickTuningParameter TuneY
{
get { return m_tuningY; }
}
/// <summary>
/// Returns the Z-Tuning item
/// </summary>
public JoystickTuningParameter TuneZ
{
get { return m_tuningZ; }
}
/// <summary>
/// reassign the JsN Tag
/// </summary>
/// <param name="newJsList">The JsN reassign list (old,new)</param>
public void ReassignJsN( Dictionary<int, int> newJsList )
{
foreach ( KeyValuePair<int,int> kv in newJsList ) {
if ( m_tuningX.JsN == kv.Key ) m_tuningX.JsN = kv.Value;
if ( m_tuningY.JsN == kv.Key ) m_tuningY.JsN = kv.Value;
if ( m_tuningZ.JsN == kv.Key ) m_tuningZ.JsN = kv.Value;
}
}
private String[] FormatXml( string xml )
{
@ -38,15 +97,15 @@ namespace SCJMapper_V2
}
/// <summary>
/// Dump the CustomisationUIHeader as partial XML nicely formatted
/// Dump the Options as partial XML nicely formatted
/// </summary>
/// <returns>the action as XML fragment</returns>
public String toXML( )
{
String r = "";
// and dump the contents
foreach ( String x in this ) {
// and dump the contents of plain string options
foreach ( String x in m_stringOptions ) {
if ( !String.IsNullOrWhiteSpace( x ) ) {
foreach ( String line in FormatXml( x ) ) {
@ -56,19 +115,142 @@ namespace SCJMapper_V2
r += String.Format( "\n" );
}
// dump Tuning
r += m_tuningX.Options_toXML( );
r += m_tuningY.Options_toXML( );
r += m_tuningZ.Options_toXML( );
return r;
}
/// <summary>
/// Read an CustomisationUIHeader from XML - do some sanity check
/// Read an Options from XML - do some sanity check
/// </summary>
/// <param name="xml">the XML action fragment</param>
/// <returns>True if an action was decoded</returns>
public Boolean fromXML( String xml )
{
if ( !this.Contains( xml ) ) this.Add( xml );
/*
* This can be a lot of the following options
* try to do our best....
*
* <options type="joystick" instance="1">
<pilot_rot_moveyaw instance="1" sensitivity="0.8" exponent="1.2" />
</options>
* <options type="joystick" instance="1">
<!-- Make all main stick piloting input linear -->
<pilot_move_main exponent="1" />
</options>
*
<options type="joystick" instance="1">
<pilot>
<nonlinearity_curve>
<point in="0.1" out="0.001"/>
<point in="0.25" out="0.02"/>
<point in="0.5" out="0.1"/>
<point in="0.75" out="0.125"/>
<point in="0.85" out="0.15"/>
<point in="0.90" out="0.175"/>
<point in="0.925" out="0.25"/>
<point in="0.94" out="0.45"/>
<point in="0.95" out="0.75"/>
</nonlinearity_curve>
</pilot>
</options>
*/
XmlReaderSettings settings = new XmlReaderSettings( );
settings.ConformanceLevel = ConformanceLevel.Fragment;
settings.IgnoreWhitespace = true;
settings.IgnoreComments = true;
XmlReader reader = XmlReader.Create( new StringReader( xml ), settings );
reader.Read( );
String type = "";
String instance = "";
if ( reader.HasAttributes ) {
type = reader["type"];
if ( type.ToLowerInvariant( ) != "joystick" ) {
// save as plain text
if ( !m_stringOptions.Contains( xml ) ) m_stringOptions.Add( xml );
return true;
}
// further on..
instance = reader["instance"];
reader.Read( );
// try to disassemble the items
/*
* <pilot> instance="0/1" sensitivity="n.nn" exponent="n.nn" (instance should be invert)
* <pilot_move>
* <pilot_move_main>
* <pilot_move_x>
* <pilot_move_y>
* <pilot_move_z>
* <pilot_move_rot>
* <pilot_move_rotx>
* <pilot_move_roty>
* <pilot_move_rotz>
* <pilot_move_sliders>
* <pilot_move_slider1>
* <pilot_move_slider2>
* <pilot_throttle> invert="0/1"
* <pilot_aim>
* <pilot_aim_main>
* <pilot_aim_x>
* <pilot_aim_y>
* <pilot_aim_rot>
* <pilot_aim_rotz>
* <pilot_view>
* <pilot_view_main>
* <pilot_view_x>
* <pilot_view_y>
* <pilot_view_rot>
* <pilot_view_rotz>
*
*
<nonlinearity_curve>
<point in="0.1" out="0.001"/>
* ..
</nonlinearity_curve>
*
*
*
*/
while ( !reader.EOF ) {
if ( reader.Name == "pilot_move_x" || reader.Name == "pilot_move_rotx" ) {
m_tuningX.Options_fromXML( reader, int.Parse( instance ) );
}
else if ( reader.Name == "pilot_move_y" || reader.Name == "pilot_move_roty" ) {
m_tuningY.Options_fromXML( reader, int.Parse( instance ) );
}
else if ( reader.Name == "pilot_move_z" || reader.Name == "pilot_move_rotz" ) {
m_tuningZ.Options_fromXML( reader, int.Parse( instance ) );
}
else if ( reader.Name == "pilot_throttle" ) {
// supports invert
//jtp.Options_fromXML( reader, int.Parse( instance ) );
log.InfoFormat( "Options.fromXML: pilot_throttle node not yet supported" );
}
else {
//??
log.InfoFormat( "Options.fromXML: unknown node - {0} - stored as is", reader.Name );
if ( !m_stringOptions.Contains( xml ) ) m_stringOptions.Add( xml );
}
reader.Read( );
}
}
return true;
}

@ -0,0 +1,169 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OpenTK;
namespace SCJMapper_V2
{
/// <summary>
/// contains the x(in) and y(out) points of the nonlin curve for joysticks (MAX 3 interpolation pts)
/// automatically adds zero/endpoints and goes symmetric around below 0
/// </summary>
public class xyPoints
{
private int m_maxpts = 10;
private Vector2[] m_points = null;
private double[] m_outCurve = null;
private int m_Npoints = 0;
private CalcCurve m_curve;
public xyPoints( int maxPoints )
{
m_maxpts = maxPoints;
m_outCurve = new double[m_maxpts];
}
private void Setup( int dimension )
{
if ( ( dimension < 1 ) || ( dimension > 3 ) ) return; // just ignore...
m_Npoints = dimension + 2; // 3,4,5
Array.Resize( ref m_points, m_Npoints ); // add endPts and zero
Array.Resize( ref m_points, m_Npoints ); // add endPts and zero
// not math just static assignment...
int i=0;
switch ( dimension ) {
case 1: {
m_points[i++] = new Vector2( 0f, 0f );
m_points[i++] = new Vector2( 0.5f, 0.5f );
m_points[i++] = new Vector2( 1.0f, 1.0f );
break;
}
case 2: {
m_points[i++] = new Vector2( 0f, 0f );
m_points[i++] = new Vector2( 0.333333f, 0.333333f );
m_points[i++] = new Vector2( 0.666667f, 0.666667f );
m_points[i++] = new Vector2( 1.0f, 1.0f );
break;
}
case 3: {
m_points[i++] = new Vector2( 0f, 0f );
m_points[i++] = new Vector2( 0.25f, 0.25f );
m_points[i++] = new Vector2( 0.5f, 0.5f );
m_points[i++] = new Vector2( 0.75f, 0.75f );
m_points[i++] = new Vector2( 1.0f, 1.0f );
break;
}
default: {
// does not get here
break;
}
}
}
private void GetOutput( float[] input )
{
// assuming it is continous...
m_outCurve[0] = 0.0; // force Zero...
int idx = 0;
for ( int i = 1; i < m_maxpts; i++ ) {
double sense = i / ( double )m_maxpts;
while ( ( input[idx] < sense ) && ( idx < ( ( m_maxpts - 1 ) * 2 ) ) ) idx += 2;
m_outCurve[i] = input[idx + 1];
idx = ( idx < ( m_maxpts * 2 ) ) ? idx : ( m_maxpts - 1 ) * 2; // we shall not overrun...
}
m_outCurve[m_maxpts - 1] = 1.0; // force MAX
}
public void Curve( )
{
Setup( 1 );
float[] cout = new float[m_maxpts * 2];
int resolution = m_maxpts; // The number of points in the bezier curve
m_curve = new BezierInterpolation( m_points, resolution );
Vector2 pos = Vector2.One;
for ( int p = 0; p <= resolution; p++ ) {
pos = m_curve.CalculatePoint( ( float )p / ( float )resolution );
cout[p * 2] = pos.X; cout[p * 2 + 1] = pos.Y;
}
GetOutput( cout );
}
public void Curve( float x1, float y1 )
{
Setup( 1 );
// zero
int i = 1;
m_points[i++] = new Vector2(x1, y1);
float[] cout = new float[m_maxpts * 2];
int resolution = m_maxpts; // The number of points in the bezier curve
m_curve = new BezierInterpolation( m_points, resolution );
Vector2 pos = Vector2.One;
for ( int p = 0; p <= resolution; p++ ) {
pos = m_curve.CalculatePoint( ( float )p / ( float )resolution );
cout[p * 2] = pos.X; cout[p * 2 + 1] = pos.Y;
}
GetOutput( cout );
}
public void Curve( float x1, float y1, float x2, float y2 )
{
Setup( 2 );
// zero
int i = 1;
m_points[i++] = new Vector2( x1, y1 );
m_points[i++] = new Vector2( x2, y2 );
float[] cout = new float[m_maxpts * 2];
int resolution = m_maxpts; // The number of points in the bezier curve
m_curve = new BezierInterpolation( m_points, resolution );
Vector2 pos = Vector2.One;
for ( int p = 0; p <= resolution; p++ ) {
pos = m_curve.CalculatePoint( ( float )p / ( float )resolution );
cout[p * 2] = pos.X; cout[p * 2 + 1] = pos.Y;
}
GetOutput( cout );
}
public void Curve( float x1, float y1, float x2, float y2, float x3, float y3 )
{
Setup( 3 );
// zero
int i = 1;
m_points[i++] = new Vector2( x1, y1 );
m_points[i++] = new Vector2( x2, y2 );
m_points[i++] = new Vector2( x3, y3 );
float[] cout = new float[m_maxpts * 2];
int resolution = m_maxpts-1; // The number of points in the bezier curve
m_curve = new BezierInterpolation( m_points, resolution );
Vector2 pos = Vector2.One;
for ( int p = 0; p <= resolution; p++ ) {
pos = m_curve.CalculatePoint( ( float )p / ( float )resolution );
cout[p * 2] = pos.X; cout[p * 2 + 1] = pos.Y;
}
GetOutput( cout );
}
public double EvalX( int atX )
{
int sng = Math.Sign( atX );
int x = Math.Abs( atX );
if ( x < m_maxpts ) return m_outCurve[x] * sng;
// if out of rng return MAX
return m_outCurve[m_maxpts-1] * sng;
}
}
}

@ -0,0 +1,124 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms.DataVisualization.Charting;
using System.Windows.Forms;
using OpenTK;
namespace SCJMapper_V2
{
public class BezierPointCollection : List<DataPoint>
{
}
/// <span class="code-SummaryComment"><summary>
/// You can use this Series like any other series in the MS web charting control
/// http://www.codeproject.com/Articles/169962/Bezier-curve-for-the-Microsoft-Web-Chart-control
/// <span class="code-SummaryComment"></summary>
public class BezierSeries : Series
{
#region fields
private int _pointsOnCurve = 50;
private BezierPointCollection _bezierPoints = new BezierPointCollection();
#endregion
#region properties
/// <span class="code-SummaryComment"><summary>
/// Defines how many points the resulting curve will have;
/// min = 2, must be an even number
/// <span class="code-SummaryComment"></summary>
public int PointsOnCurve
{
get { return _pointsOnCurve; }
set
{
//min value is 2
if ( value < 2 ) {
value = 2;
}
//it must be an even number
if ( value % 2 == 1 ) {
value++;
}
_pointsOnCurve = value;
}
}
/// <span class="code-SummaryComment"><summary>
/// Points that should be used to calculate the bezier graph
/// <span class="code-SummaryComment"></summary>
public BezierPointCollection BezierPoints
{
get
{
return _bezierPoints;
}
set
{
this.Points.Clear( );
if ( value != null ) {
_bezierPoints = value;
float[] cout = new float[PointsOnCurve*2];
CalcCurve( cout );
//bezier curve points
this.ChartType = SeriesChartType.Line;
for ( int i = 0; i < cout.Length; i = i + 2 ) {
this.Points.AddXY( cout[i], cout[i + 1] );
}
}
}
}
public void Invalidate( Control owner)
{
this.Points.Clear( );
float[] cout = new float[PointsOnCurve*2];
CalcCurve( cout );
//bezier curve points
this.ChartType = SeriesChartType.Line;
for ( int i = 0; i < cout.Length; i = i + 2 ) {
this.Points.AddXY( cout[i], cout[i + 1] );
}
owner.Invalidate( );
}
private void CalcCurve( float[] cout )
{
Vector2[] ptList = new Vector2[_bezierPoints.Count];
//convert bezier points to flat list
int pIdx = 0;
foreach ( DataPoint point in _bezierPoints ) {
ptList[pIdx++] = new Vector2( ( float )point.XValue, ( float )point.YValues[0] );
}
//bezier curve calculation
int resolution = PointsOnCurve - 1;
CalcCurve bc = new BezierInterpolation( ptList, PointsOnCurve );
pIdx = 0;
Vector2 pos = Vector2.One;
for ( int p = 0; p <= resolution; p++ ) {
pos = bc.CalculatePoint( ( float )p / ( float )resolution );
cout[p * 2] = pos.X; cout[p * 2 + 1] = pos.Y;
}
}
#endregion
}
}

@ -0,0 +1,209 @@
using System;
using OpenTK;
using System.Collections.Generic;
namespace SCJMapper_V2
{
public abstract class CalcCurve
{
protected List<Vector2> m_points;
protected int m_resolution;
/// <summary>
/// Constructs a new OpenTK.BezierCurve.
/// </summary>
/// <param name="points">The points.</param>
protected CalcCurve( IEnumerable<Vector2> points, int resolution )
{
if ( points == null )
throw new ArgumentNullException( "points", "Must point to a valid list of Vector2 structures." );
this.m_points = new List<Vector2>( points );
this.m_resolution = resolution;
}
/// <summary>
/// Gets the points of this curve.
/// </summary>
public IList<Vector2> Points
{
get { return m_points; }
}
/// <summary>
/// Calculates the point with the specified t.
/// </summary>
/// <param name="t">The t value, between 0.0f and 1.0f.</param>
/// <returns>Resulting point.</returns>
abstract public Vector2 CalculatePoint( float t );
}
/// <summary>
/// BezierCurve from OpenTK (Wrapper)
///
/// </summary>
public class Bezier : CalcCurve
{
private BezierCurve m_curve;
/// <summary>
/// Constructs a new OpenTK.BezierCurve.
/// </summary>
/// <param name="points">The points.</param>
public Bezier( IEnumerable<Vector2> points, int resolution )
: base( points, resolution )
{
m_curve = new BezierCurve( m_points );
// resolution is not used here
}
/// <summary>
/// Calculates the point with the specified t.
/// </summary>
/// <param name="t">The t value, between 0.0f and 1.0f.</param>
/// <returns>Resulting point.</returns>
override public Vector2 CalculatePoint( float t )
{
return m_curve.CalculatePoint( t );
}
}
/// <summary>
/// Interpolating cubic B-spline
///
/// See http://www.ibiblio.org/e-notes/Splines/b-int.html
/// code http://www.ibiblio.org/e-notes/Splines/b-interpolate.js
/// </summary>
public class BezierInterpolation : CalcCurve
{
private int nPts = 2;
private int n1Pts = 3;
private int segments = 0;
private int segPts = 26;
private double[] B0;
private double[] B1;
private double[] B2;
private double[] B3;
private Vector2[] d; // tangents
private Vector2[] cout; // out array
/// <summary>
/// Constructs a new OpenTK.BezierCurve.
/// </summary>
/// <param name="points">The points.</param>
public BezierInterpolation( IEnumerable<Vector2> points, int resolution )
: base( points, resolution )
{
// tangets via user points
nPts = m_points.Count - 2;
// tangents not by user
nPts = m_points.Count;
n1Pts = nPts + 1;
segments = nPts - 1; // number of curve segments
segPts = (int)Math.Ceiling( ( double )resolution / ( double )segments ); // pts per curve segment @ resolution
d = new Vector2[m_points.Count];
cout = new Vector2[segments * segPts];
// init table 0.0 .. 1.0 with 0.04 inc
B0 = new double[segPts];
B1 = new double[segPts];
B2 = new double[segPts];
B3 = new double[segPts];
double t = 0; double increment = 1.0 / ( segPts - 1 );
for ( int i= 0; i < segPts; i++ ) {
double t1 = 1.0 - t;
double t12 = t1 * t1;
double t2 = t * t;
B0[i] = t1 * t12; B1[i] = 3.0 * t * t12; B2[i] = 3.0 * t2 * t1; B3[i] = t * t2;
t += increment;
}
findCPoints( );
CalcCurve( );
}
private void findCPoints( )
{
/*
// tangets via user points
d[0].X = m_points[nPts].X - m_points[0].X;
d[0].Y = m_points[nPts].Y - m_points[0].Y;
d[nPts - 1].X = -( m_points[n1Pts].X - m_points[nPts - 1].X );
d[nPts - 1].Y = -( m_points[n1Pts].Y - m_points[nPts - 1].Y );
*/
// tangents not by user
d[0].X = ( m_points[1].X - m_points[0].X ) / 3f;
d[0].Y = ( m_points[1].Y - m_points[0].Y ) / 3f;
d[nPts - 1].X = ( m_points[nPts - 1].X - m_points[nPts - 2].X ) / 3f;
d[nPts - 1].Y = ( m_points[nPts - 1].Y - m_points[nPts - 2].Y ) / 3f;
Vector2[] A = new Vector2[m_points.Count];
float[] Bi = new float[m_points.Count];
Bi[1] = -0.25f;
A[1].X = ( m_points[2].X - m_points[0].X - d[0].X ) / 4f;
A[1].Y = ( m_points[2].Y - m_points[0].Y - d[0].Y ) / 4f;
for ( int i = 2; i < nPts - 1; i++ ) {
Bi[i] = -1.0f / ( 4.0f + Bi[i - 1] );
A[i].X = -( m_points[i + 1].X - m_points[i - 1].X - A[i - 1].X ) * Bi[i];
A[i].Y = -( m_points[i + 1].Y - m_points[i - 1].Y - A[i - 1].Y ) * Bi[i];
}
for ( var i = nPts - 2; i > 0; i-- ) {
d[i].X = A[i].X + d[i + 1].X * Bi[i];
d[i].Y = A[i].Y + d[i + 1].Y * Bi[i];
}
}
private void CalcCurve( )
{
// curve segments
int segIdx = 0;
for ( int i = 0; i < segments; i++ ) {
// resolution per segment
for ( int k = 0; k < segPts; k++ ) {
cout[segIdx].X = ( float )( m_points[i].X * B0[k] + ( m_points[i].X + d[i].X ) * B1[k] + ( m_points[i + 1].X - d[i + 1].X ) * B2[k] + m_points[i + 1].X * B3[k] );
cout[segIdx].Y = ( float )( m_points[i].Y * B0[k] + ( m_points[i].Y + d[i].Y ) * B1[k] + ( m_points[i + 1].Y - d[i + 1].Y ) * B2[k] + m_points[i + 1].Y * B3[k] );
segIdx++;
}
}
}
/// <summary>
/// Calculates the point with the specified t.
/// </summary>
/// <param name="t">The t value, between 0.0f and 1.0f.</param>
/// <returns>Resulting point.</returns>
override public Vector2 CalculatePoint( float t )
{
int pt = ( int )(t * m_resolution); // get an index within resolution of the out array
// sanity checks
pt = ( pt < 0 ) ? 0 : pt;
pt = ( pt >= m_resolution ) ? m_resolution - 1 : pt;
return cout[pt];
}
}
}

@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace SCJMapper_V2.Shapes
{
public class Chunk
{
public VertexT2dN3dV3d[] Vertices;
public uint[] Indices;
public uint VertexCount
{
get
{
return (uint)Vertices.Length;
}
}
public uint IndexCount
{
get
{
return (uint)Indices.Length;
}
}
public Chunk( uint vertexcount, uint indexcount )
{
Vertices = new VertexT2dN3dV3d[vertexcount];
Indices = new uint[indexcount];
}
public Chunk( ref VertexT2dN3dV3d[] vbo, ref uint[] ibo )
{
Vertices = new VertexT2dN3dV3d[vbo.Length];
for ( int i = 0; i < Vertices.Length; i++ )
{
Vertices[i] = vbo[i];
}
Indices = new uint[ibo.Length];
for ( int i = 0; i < Indices.Length; i++ )
{
Indices[i] = ibo[i];
}
}
public static void GetArray( ref List<Chunk> c, out VertexT2dN3dV3d[] vbo, out uint[] ibo )
{
uint VertexCounter = 0;
uint IndexCounter = 0;
foreach ( Chunk ch in c )
{
VertexCounter += ch.VertexCount;
IndexCounter += ch.IndexCount;
}
vbo = new VertexT2dN3dV3d[VertexCounter];
ibo = new uint[IndexCounter];
VertexCounter = 0;
IndexCounter = 0;
foreach ( Chunk ch in c )
{
for ( int i = 0; i < ch.Vertices.Length; i++ )
{
vbo[VertexCounter + i] = ch.Vertices[i];
}
for ( int i = 0; i < ch.Indices.Length; i++ )
{
ibo[IndexCounter + i] = ch.Indices[i] + VertexCounter;
}
VertexCounter += (uint)ch.VertexCount;
IndexCounter += (uint)ch.IndexCount;
}
}
}
}

@ -0,0 +1,416 @@
//
// Author: Ryan Seghers
//
// Copyright (C) 2013-2014 Ryan Seghers
//
// 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 irrevocable, perpetual, worldwide, and royalty-free
// rights to use, copy, modify, merge, publish, distribute, sublicense,
// display, perform, create derivative works from and/or sell copies of
// the Software, both in source and object code form, 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 OpenTK;
namespace SCJMapper_V2
{
/// <summary>
/// Cubic spline interpolation.
/// Call Fit (or use the corrector constructor) to compute spline coefficients, then Eval to evaluate the spline at other X coordinates.
/// </summary>
/// <remarks>
/// <para>
/// This is implemented based on the wikipedia article:
/// http://en.wikipedia.org/wiki/Spline_interpolation
/// I'm not sure I have the right to include a copy of the article so the equation numbers referenced in
/// comments will end up being wrong at some point.
/// </para>
/// <para>
/// This is not optimized, and is not MT safe.
/// This can extrapolate off the ends of the splines.
/// You must provide points in X sort order.
/// </para>
/// </remarks>
public class CubicSpline
{
#region Fields
// N-1 spline coefficients for N points
private float[] a;
private float[] b;
// Save the original x and y for Eval
private float[] xOrig;
private float[] yOrig;
#endregion
#region Ctor
/// <summary>
/// Default ctor.
/// </summary>
public CubicSpline()
{
}
/// <summary>
/// Construct and call Fit.
/// </summary>
/// <param name="x">Input. X coordinates to fit.</param>
/// <param name="y">Input. Y coordinates to fit.</param>
/// <param name="startSlope">Optional slope constraint for the first point. Single.NaN means no constraint.</param>
/// <param name="endSlope">Optional slope constraint for the final point. Single.NaN means no constraint.</param>
public CubicSpline(float[] x, float[] y, float startSlope = float.NaN, float endSlope = float.NaN, bool debug = false)
{
Fit(x, y, startSlope, endSlope );
}
/// <summary>
/// Construct and call Fit.
/// </summary>
/// <param name="xyPts">Input. XY coordinates to fit</param>
/// <param name="startSlope">Optional slope constraint for the first point. Single.NaN means no constraint.</param>
/// <param name="endSlope">Optional slope constraint for the final point. Single.NaN means no constraint.</param>
public CubicSpline( Vector2[] xyPts, float startSlope = float.NaN, float endSlope = float.NaN, bool debug = false )
{
float[] x = new float[xyPts.Length];
float[] y = new float[xyPts.Length];
for ( int i = 0; i < xyPts.Length; i++ ) {
x[i] = xyPts[i].X; y[i] = xyPts[i].Y;
}
Fit( x, y, startSlope, endSlope );
}
#endregion
#region Private Methods
/// <summary>
/// Throws if Fit has not been called.
/// </summary>
private void CheckAlreadyFitted( )
{
if (a == null) throw new Exception("Fit must be called before you can evaluate.");
}
private int _lastIndex = 0;
/// <summary>
/// Find where in xOrig the specified x falls, by simultaneous traverse.
/// This allows xs to be less than x[0] and/or greater than x[n-1]. So allows extrapolation.
/// This keeps state, so requires that x be sorted and xs called in ascending order, and is not multi-thread safe.
/// </summary>
private int GetNextXIndex(float x)
{
if (x < xOrig[_lastIndex])
{
throw new ArgumentException("The X values to evaluate must be sorted.");
}
while ((_lastIndex < xOrig.Length - 2) && (x > xOrig[_lastIndex + 1]))
{
_lastIndex++;
}
return _lastIndex;
}
/// <summary>
/// Evaluate the specified x value using the specified spline.
/// </summary>
/// <param name="x">The x value.</param>
/// <param name="j">Which spline to use.</param>
/// <param name="debug">Turn on console output. Default is false.</param>
/// <returns>The y value.</returns>
private float EvalSpline(float x, int j)
{
float dx = xOrig[j + 1] - xOrig[j];
float t = (x - xOrig[j]) / dx;
float y = (1 - t) * yOrig[j] + t * yOrig[j + 1] + t * (1 - t) * (a[j] * (1 - t) + b[j] * t); // equation 9
return y;
}
#endregion
#region Fit*
/// <summary>
/// Fit x,y and then eval at points xs and return the corresponding y's.
/// This does the "natural spline" style for ends.
/// This can extrapolate off the ends of the splines.
/// You must provide points in X sort order.
/// </summary>
/// <param name="x">Input. X coordinates to fit.</param>
/// <param name="y">Input. Y coordinates to fit.</param>
/// <param name="xs">Input. X coordinates to evaluate the fitted curve at.</param>
/// <param name="startSlope">Optional slope constraint for the first point. Single.NaN means no constraint.</param>
/// <param name="endSlope">Optional slope constraint for the final point. Single.NaN means no constraint.</param>
/// <param name="debug">Turn on console output. Default is false.</param>
/// <returns>The computed y values for each xs.</returns>
public float[] FitAndEval(float[] x, float[] y, float[] xs, float startSlope = float.NaN, float endSlope = float.NaN)
{
Fit(x, y, startSlope, endSlope);
return Eval(xs);
}
/// <summary>
/// Compute spline coefficients for the specified x,y points.
/// This does the "natural spline" style for ends.
/// This can extrapolate off the ends of the splines.
/// You must provide points in X sort order.
/// </summary>
/// <param name="x">Input. X coordinates to fit.</param>
/// <param name="y">Input. Y coordinates to fit.</param>
/// <param name="startSlope">Optional slope constraint for the first point. Single.NaN means no constraint.</param>
/// <param name="endSlope">Optional slope constraint for the final point. Single.NaN means no constraint.</param>
/// <param name="debug">Turn on console output. Default is false.</param>
public void Fit(float[] x, float[] y, float startSlope = float.NaN, float endSlope = float.NaN)
{
if (Single.IsInfinity(startSlope) || Single.IsInfinity(endSlope))
{
throw new Exception("startSlope and endSlope cannot be infinity.");
}
// Save x and y for eval
this.xOrig = x;
this.yOrig = y;
int n = x.Length;
float[] r = new float[n]; // the right hand side numbers: wikipedia page overloads b
TriDiagonalMatrixF m = new TriDiagonalMatrixF(n);
float dx1, dx2, dy1, dy2;
// First row is different (equation 16 from the article)
if (float.IsNaN(startSlope))
{
dx1 = x[1] - x[0];
m.C[0] = 1.0f / dx1;
m.B[0] = 2.0f * m.C[0];
r[0] = 3 * (y[1] - y[0]) / (dx1 * dx1);
}
else
{
m.B[0] = 1;
r[0] = startSlope;
}
// Body rows (equation 15 from the article)
for (int i = 1; i < n - 1; i++)
{
dx1 = x[i] - x[i - 1];
dx2 = x[i + 1] - x[i];
m.A[i] = 1.0f / dx1;
m.C[i] = 1.0f / dx2;
m.B[i] = 2.0f * (m.A[i] + m.C[i]);
dy1 = y[i] - y[i - 1];
dy2 = y[i + 1] - y[i];
r[i] = 3 * (dy1 / (dx1 * dx1) + dy2 / (dx2 * dx2));
}
// Last row also different (equation 17 from the article)
if (float.IsNaN(endSlope))
{
dx1 = x[n - 1] - x[n - 2];
dy1 = y[n - 1] - y[n - 2];
m.A[n - 1] = 1.0f / dx1;
m.B[n - 1] = 2.0f * m.A[n - 1];
r[n - 1] = 3 * (dy1 / (dx1 * dx1));
}
else
{
m.B[n - 1] = 1;
r[n - 1] = endSlope;
}
// k is the solution to the matrix
float[] k = m.Solve(r);
// a and b are each spline's coefficients
this.a = new float[n - 1];
this.b = new float[n - 1];
for (int i = 1; i < n; i++)
{
dx1 = x[i] - x[i - 1];
dy1 = y[i] - y[i - 1];
a[i - 1] = k[i - 1] * dx1 - dy1; // equation 10 from the article
b[i - 1] = -k[i] * dx1 + dy1; // equation 11 from the article
}
}
#endregion
#region Eval*
/// <summary>
/// Evaluate the spline at the specified x coordinate.
/// This can extrapolate off the ends of the splines.
/// The spline must already be computed before calling this, meaning you must have already called Fit() or FitAndEval().
/// </summary>
/// <param name="x">Input. X coordinate to evaluate the fitted curve at.</param>
/// <returns>The computed y values for x.</returns>
public float Eval( float x )
{
CheckAlreadyFitted( );
float y;
_lastIndex = 0; // Reset simultaneous traversal in case there are multiple calls
int j = GetNextXIndex( x );
// Evaluate using j'th spline
y = EvalSpline( x, j );
return y;
}
/// <summary>
/// Evaluate the spline at the specified x coordinates.
/// This can extrapolate off the ends of the splines.
/// You must provide X's in ascending order.
/// The spline must already be computed before calling this, meaning you must have already called Fit() or FitAndEval().
/// </summary>
/// <param name="x">Input. X coordinates to evaluate the fitted curve at.</param>
/// <returns>The computed y values for each x.</returns>
public float[] Eval( float[] x )
{
CheckAlreadyFitted( );
int n = x.Length;
float[] y = new float[n];
_lastIndex = 0; // Reset simultaneous traversal in case there are multiple calls
for ( int i = 0; i < n; i++ ) {
// Find which spline can be used to compute this x (by simultaneous traverse)
int j = GetNextXIndex( x[i] );
// Evaluate using j'th spline
y[i] = EvalSpline( x[i], j );
}
return y;
}
/// <summary>
/// Evaluate (compute) the slope of the spline at the specified x coordinates.
/// This can extrapolate off the ends of the splines.
/// You must provide X's in ascending order.
/// The spline must already be computed before calling this, meaning you must have already called Fit() or FitAndEval().
/// </summary>
/// <param name="x">Input. X coordinates to evaluate the fitted curve at.</param>
/// <returns>The computed y values for each x.</returns>
public float[] EvalSlope(float[] x )
{
CheckAlreadyFitted();
int n = x.Length;
float[] qPrime = new float[n];
_lastIndex = 0; // Reset simultaneous traversal in case there are multiple calls
for (int i = 0; i < n; i++)
{
// Find which spline can be used to compute this x (by simultaneous traverse)
int j = GetNextXIndex(x[i]);
// Evaluate using j'th spline
float dx = xOrig[j + 1] - xOrig[j];
float dy = yOrig[j + 1] - yOrig[j];
float t = (x[i] - xOrig[j]) / dx;
// From equation 5 we could also compute q' (qp) which is the slope at this x
qPrime[i] = dy / dx
+ (1 - 2 * t) * (a[j] * (1 - t) + b[j] * t) / dx
+ t * (1 - t) * (b[j] - a[j]) / dx;
}
return qPrime;
}
#endregion
#region Static Methods
/// <summary>
/// Static all-in-one method to fit the splines and evaluate at X coordinates.
/// </summary>
/// <param name="x">Input. X coordinates to fit.</param>
/// <param name="y">Input. Y coordinates to fit.</param>
/// <param name="xs">Input. X coordinates to evaluate the fitted curve at.</param>
/// <param name="startSlope">Optional slope constraint for the first point. Single.NaN means no constraint.</param>
/// <param name="endSlope">Optional slope constraint for the final point. Single.NaN means no constraint.</param>
/// <returns>The computed y values for each xs.</returns>
public static float[] Compute(float[] x, float[] y, float[] xs, float startSlope = float.NaN, float endSlope = float.NaN )
{
CubicSpline spline = new CubicSpline();
return spline.FitAndEval(x, y, xs, startSlope, endSlope );
}
/// <summary>
/// Fit the input x,y points using a 'geometric' strategy so that y does not have to be a single-valued
/// function of x.
/// </summary>
/// <param name="x">Input x coordinates.</param>
/// <param name="y">Input y coordinates, do not need to be a single-valued function of x.</param>
/// <param name="nOutputPoints">How many output points to create.</param>
/// <param name="xs">Output (interpolated) x values.</param>
/// <param name="ys">Output (interpolated) y values.</param>
public static void FitGeometric(float[] x, float[] y, int nOutputPoints, out float[] xs, out float[] ys)
{
// Compute distances
int n = x.Length;
float[] dists = new float[n]; // cumulative distance
dists[0] = 0;
float totalDist = 0;
for (int i = 1; i < n; i++)
{
float dx = x[i] - x[i - 1];
float dy = y[i] - y[i - 1];
float dist = (float)Math.Sqrt(dx * dx + dy * dy);
totalDist += dist;
dists[i] = totalDist;
}
// Create 'times' to interpolate to
float dt = totalDist / (nOutputPoints - 1);
float[] times = new float[nOutputPoints];
times[0] = 0;
for (int i = 1; i < nOutputPoints; i++)
{
times[i] = times[i - 1] + dt;
}
// Spline fit both x and y to times
CubicSpline xSpline = new CubicSpline();
xs = xSpline.FitAndEval(dists, x, times);
CubicSpline ySpline = new CubicSpline();
ys = ySpline.FitAndEval(dists, y, times);
}
#endregion
}
}

@ -0,0 +1,181 @@
#region --- License ---
/* Copyright (c) 2006, 2007 Stefanos Apostolopoulos
* See license.txt for license info
*/
#endregion
using System;
using OpenTK;
using OpenTK.Graphics.OpenGL;
namespace SCJMapper_V2.Shapes
{
// Abstract base class for procedurally generated geometry
//
// All classes derived from it must produce Counter-Clockwise (CCW) primitives.
// Derived classes must create a single VBO and IBO, without primitive restarts for strips.
// Uses an double-precision all-possible-attributes VertexT2dN3dV3d Array internally.
// Cannot directly use VBO, but has Get-methods to retrieve VBO-friendly data.
// Can use a Display List to prevent repeated immediate mode draws.
//
public abstract class DrawableShape: IDisposable
{
protected PrimitiveType PrimitiveMode;
protected VertexT2dN3dV3d[] VertexArray;
protected uint[] IndexArray;
public int GetTriangleCount
{
get
{
switch ( PrimitiveMode )
{
case PrimitiveType.Triangles:
if ( IndexArray != null )
{
return IndexArray.Length / 3;
} else
{
return VertexArray.Length / 3;
}
// break;
default: throw new NotImplementedException("Unknown primitive type.");
}
}
}
#region Display List
private bool UseDisplayList;
private int DisplayListHandle = 0;
#endregion Display List
public DrawableShape( bool useDisplayList )
{
UseDisplayList = useDisplayList;
PrimitiveMode = PrimitiveType.Triangles;
VertexArray = null;
IndexArray = null;
}
#region Convert to VBO
public void GetArraysforVBO( out PrimitiveType primitives, out VertexT2dN3dV3d[] vertices, out uint[] indices )
{
primitives = PrimitiveMode;
vertices = new VertexT2dN3dV3d[VertexArray.Length];
for (uint i = 0; i < VertexArray.Length; i++)
{
vertices[i].TexCoord = VertexArray[i].TexCoord;
vertices[i].Normal = VertexArray[i].Normal;
vertices[i].Position = VertexArray[i].Position;
}
indices = IndexArray;
}
public void GetArraysforVBO( out PrimitiveType primitives, out VertexT2fN3fV3f[] vertices, out uint[] indices )
{
primitives = PrimitiveMode;
vertices = new VertexT2fN3fV3f[VertexArray.Length];
for (uint i = 0; i < VertexArray.Length; i++)
{
vertices[i].TexCoord = (Vector2)VertexArray[i].TexCoord;
vertices[i].Normal = (Vector3)VertexArray[i].Normal;
vertices[i].Position = (Vector3)VertexArray[i].Position;
}
indices = IndexArray;
}
public void GetArraysforVBO( out PrimitiveType primitives, out VertexT2hN3hV3h[] vertices, out uint[] indices )
{
primitives = PrimitiveMode;
vertices = new VertexT2hN3hV3h[VertexArray.Length];
for (uint i = 0; i < VertexArray.Length; i++)
{
vertices[i].TexCoord = (Vector2h)VertexArray[i].TexCoord;
vertices[i].Normal = (Vector3h)VertexArray[i].Normal;
vertices[i].Position = (Vector3h)VertexArray[i].Position;
}
indices = IndexArray;
}
#endregion Convert to VBO
private void DrawImmediateMode()
{
GL.Begin( PrimitiveMode );
{
if ( IndexArray == null )
foreach ( VertexT2dN3dV3d v in VertexArray )
{
GL.TexCoord2( v.TexCoord.X, v.TexCoord.Y );
GL.Normal3( v.Normal.X, v.Normal.Y, v.Normal.Z );
GL.Vertex3( v.Position.X, v.Position.Y, v.Position.Z );
} else
{
for ( uint i = 0; i < IndexArray.Length; i++ )
{
uint index = IndexArray[i];
GL.TexCoord2( VertexArray[index].TexCoord.X, VertexArray[index].TexCoord.Y );
GL.Normal3( VertexArray[index].Normal.X, VertexArray[index].Normal.Y, VertexArray[index].Normal.Z );
GL.Vertex3( VertexArray[index].Position.X, VertexArray[index].Position.Y, VertexArray[index].Position.Z );
}
}
}
GL.End();
}
/// <summary>
/// Does not touch any state/matrices. Does call Begin/End and Vertex&Co.
/// Creates and compiles a display list if not present yet. Requires an OpenGL context.
/// </summary>
public void Draw()
{
if ( !UseDisplayList )
DrawImmediateMode();
else
if ( DisplayListHandle == 0 )
{
if ( VertexArray == null )
throw new Exception("Cannot draw null Vertex Array.");
DisplayListHandle = GL.GenLists( 1 );
GL.NewList( DisplayListHandle, ListMode.CompileAndExecute );
DrawImmediateMode();
GL.EndList();
} else
GL.CallList( DisplayListHandle );
}
#region IDisposable Members
/// <summary>
/// Removes reference to VertexArray and IndexArray.
/// Deletes the Display List, so it requires an OpenGL context.
/// The instance is effectively destroyed.
/// </summary>
public void Dispose()
{
if ( VertexArray != null )
VertexArray = null;
if ( IndexArray != null )
IndexArray = null;
if ( DisplayListHandle != 0 )
{
GL.DeleteLists( DisplayListHandle, 1 );
DisplayListHandle = 0;
}
}
#endregion
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,408 @@
<?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>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAABAAEAQEAAAAEAIAAoQgAAFgAAACgAAABAAAAAgAAAAAEAIAAAAAAAAD4AAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANvc
3yTb2+Ak29viJNvb4iTb2+Mk29rlJNvb5iTb3OYk29zmJNvd5yTb3uck293nJNvd5yTb3egk29vgJNvb
3STb2+Ak29vhJNvb4STb2+Ak29vhJNvb4CTb298k29vgJNvb3yTb294k29vfJNvb3STb290k29veJNvb
3STb298k29vhJNvb5CTb2+Yk29vmJNvb5CTb2+Ik29viJNvb4STb294k29vbJNvb2yTb29sk29vbJNvb
2yTb29sk29vbJNvb3STb294k29vcJNvb3iTb294k29vfJNvb3yTb298k29vfJNvb3STb29sk29vbJNvb
2yTb29sk29vbJNvb3CQHCDn6BQU/+gUFRvoFBE36BQlW+gUTYfoFHGj6BR1q+gUjbvoFKnX6BSp0+gUp
cvoFKXP6BSh0+gUWVPoFBDD6BQU7+gUFQfoFBUn6BQVE+gUFR/oFBUP6BQU7+gUFP/oFBTz6BQU4+gUF
NvoFBS36BQUv+gUFM/oFBTb6BQVB+gUFUvoFBWL6BQdx+gUGcfoFBVv6BQVO+gUFTPoFBUb6BQU1+gUF
KPoFBRr6BQUQ+gUFDvoFBQj6BQUG+gUFDfoFBSH6BQUw+gUFK/oFBTP6BQU4+gUFOfoFBT36BQU++gUF
NvoFBSX6BQUR+gUFCPoFBQX6BQUF+gUFBfoFBQb6AABE/wAASv8AAFH/AApZ/wAWZv8AI2//ACh2/wAn
dv8AL33/ADWD/wA1gv8AMX7/ADN//wAwfP8AKHT/AANI/wAAP/8AAEf/AABR/wAATf8AAEr/AABM/wAA
T/8AAE3/AABD/wAAQf8AAD7/AAA9/wAAOv8AADz/AABC/wAAUP8AAGX/AAB2/wAOhP8ACYD/AABj/wAA
Vv8AAFH/AABM/wAAQv8AADP/AAAg/wAAD/8AAAb/AAAH/wAADP8AABP/AAAj/wAALP8AADH/AAA4/wAA
P/8AAEL/AABE/wAAP/8AAB//AAAF/wAABP8AAAD/AAAA/wAAAP8AAAD/AAAA/wIDU/8AA1b/ABRh/wAk
bv8AMHj/ADR9/wA1gf8ANYH/ADiF/wA/if8AQor/AD2G/wA+h/8AOoT/ADaA/wAcZv8AAEz/AABU/wAA
Vv8AAFP/AABS/wAAVP8AAF3/AABZ/wAAT/8AAEr/AABK/wAAUP8AAEz/AABL/wAAVP8AAGX/AAB0/wAO
g/8AIJL/ABiL/wADcf8AAF7/AABV/wAATv8AAEj/AAA5/wAAI/8AABH/AAAH/wAADP8AABX/AAAk/wAA
Lv8AADb/AAA4/wAAOf8AADf/AAA5/wAAN/8AAC3/AAAM/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
Af8CC13/AA5f/wAhbP8ALXn/ADWA/wA5hP8AOob/AD6K/wBCjP8ASI//AEqS/wBFjf8AQIn/ADqD/wA3
gP8AMXv/AAZX/wAAVv8AAFP/AABS/wAAVP8AAFf/AABc/wAAW/8AAFj/AABX/wAAW/8AAGL/AABd/wAA
X/8AAmn/AAZ5/wAMgv8AHI7/AC2e/wAnl/8ACnv/AABl/wAAW/8AAFH/AABK/wAAPf8AACn/AAAd/wAA
Ev8AABH/AAAY/wAAKv8AADf/AAA8/wAAOP8AAC7/AAAe/wAAFv8AABD/AAAI/wAAAv8AAAD/AAAA/wAA
AP8AAAD/AAAA/wAAAP8AAAH/Ahln/wAYaP8AHmz/AC55/wA2gv8AOIX/ADqG/wBBi/8AR5D/AEuS/wBM
lP8ASpP/AEKL/wA6hP8AN4L/ADeB/wAaY/8AAEz/AABW/wAAUf8AAFT/AABa/wAAXf8AAFz/AABe/wAG
bf8ABG7/AAZv/wAGbv8AB3P/ABaB/wAaiv8AH5L/AC2e/wBArf8AOan/AByM/wAHc/8AAWr/AABg/wAA
Wf8AAFb/AABG/wAAL/8AACP/AAAn/wAAM/8AADX/AAA5/wAAOP8AADr/AAA2/wAAH/8AAA//AAAC/wAA
AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAB/wIYZ/8AFmn/ABlo/wAjb/8AMHv/ADSB/wA8
hv8ARI3/AEqT/wBNlf8ATZb/AEyT/wBEi/8APYb/ADuE/wA+hv8AM33/AAJJ/wAATv8AAFP/AABU/wAA
XP8AAF3/AABj/wAAZ/8ADHX/AA95/wATfP8AGIH/ABuE/wAmlP8ALJz/ADGi/wBArv8AVL3/AFC5/wAy
n/8AHIb/ABV//wAQev8AA2//AABn/wAAXv8AAEv/AABE/wAARf8AAEj/AAA//wAAPf8AADz/AABD/wAA
Pv8AACf/AAAW/wAACv8AAAf/AAAQ/wAADP8AAAP/AAAA/wAAAP8AAAD/AAAA/wAAAf8CHGv/AB1r/wAh
bf8AJ3D/ADF4/wAzfP8AOYD/AEKJ/wBJkv8AS5P/AE2U/wBNk/8ASY//AESM/wBGjP8ASI7/AESM/wAT
W/8AAEj/AABS/wAAXf8AAGH/AABn/wAAb/8AAnL/AAt8/wAQfv8AIYn/ACyV/wA1m/8AO6T/AESt/wBM
tf8AWL//AG3K/wBuyP8AULT/ADyd/wA3lv8ALpP/AByH/wAPe/8ACnX/AAlt/wAIZ/8ABGH/AAJb/wAB
WP8AAFb/AABQ/wAARf8AADb/AAAn/wAAH/8AABf/AAAV/wAAG/8AAAv/AAAB/wAAAP8AAAD/AAAA/wAA
AP8AAAH/Ai13/wAod/8AKXf/AC54/wA1fP8AO4H/ADuC/wBFif8AUJX/AFWX/wBZmf8AXJr/AFyY/wBZ
mP8AV5j/AFWY/wBRlv8AMHz/AABS/wAAXv8AAGf/AABt/wAAc/8ABXj/AA5+/wAUhf8AGoj/AC2V/wA7
of8ARKj/AFK0/wBjwf8Ab8v/AHnT/wCR3P8Ak9z/AHrN/wBmuv8AWrH/AE2p/wBAov8AO5v/ADiX/wA1
k/8ALYr/ACSA/wAVeP8ABnD/AAFi/wAAU/8AAEX/AAAw/wAAKv8AACf/AAAi/wAAGv8AABX/AAAE/wAA
AP8AAAD/AAAA/wAAAP8AAAD/AAAB/wITQf8AEUD/ABRH/wAUTv8AGlX/ACJh/wAnav8AOHj/AFCK/wVj
mf8QcKL/EnWn/wxzpv8Gbab/AGSi/wBhoP8AXqD/AFWZ/wARc/8ACXT/ABF7/wATgP8AFYH/AB2K/wAg
jv8AI5H/ACeU/wA2nv8AQqb/AFWw/wBuxv8AUrv/ADKs/wBDs/8AcM//BJLb/wCD0/8AaMH/AHXF/wBw
wf8Abb3/AGu7/wBkuP8AWbD/AEql/wA2lf8AIYH/AA1z/wABZf8AAFL/AABE/wAAM/8AACz/AAAm/wAA
Jf8AACf/AAAv/wAAHf8AAAj/AAAA/wAAAP8AAAD/AAAA/wAAAf8BABP/AAAP/wAAF/8AACL/AAAt/wAA
PP8ADE//AClm/wBEfP8BWIz/BGOW/wRlmv8CWpf/AU2R/wBHk/8APY//AEaV/wBUnf8AUJz/AFWh/wBi
q/8AZq//AF6s/wBarP8AWK3/AFCq/wBQq/8AUq//AF60/wBww/8AQ63/ABaM/wEnmf8AP6r/Ale8/xOG
0v8KbsH/B2q1/wKZ0/8AoNr/AJrY/wCO0/8AgMr/AGq//wBSrv8APZz/ACqK/wAXeP8ABWf/AABZ/wAA
Tf8AAD7/AAA1/wAALf8AACn/AAAf/wAAG/8AABD/AAAE/wAAAP8AAAD/AAAA/wAAAP8AAAH/AQIH/wAA
B/8AAAz/AAAT/wAAHv8AATf/ABJR/wAmYf8AN3L/ADt4/wA1d/8AMHf/ADF6/wAtef8AMoD/ADaG/wBB
k/8ATJv/AF6n/wBys/8CicP/CpfO/w2Z0P8Jlc7/BZHN/wKNzf8Aicv/AIvM/wCOz/8AUKf/ADWS/wBi
tP8Hh87/AIjU/zW75/+Q7vv/auH3/1bZ9f9Kz/D/Ncft/xm36P8Fotz/AIrR/wB1xf8AXrb/AEyn/wA7
mf8AJ4j/ABZ3/wADa/8AAF3/AABQ/wAAQP8AAC//AAAj/wAAFP8AAA7/AAAF/wAADP8AABj/AAAK/wAA
AP8AAAD/AAAB/wICHP8AABz/AAAp/wABM/8ACj7/ABhS/wAgWv8AJGH/ACZn/wAhZP8AIWP/ACtt/wA7
ff8AQ4X/AFCP/wBbmv8AWZz/AFuf/wBco/8AVKL/AGWu/wN5u/8Ih8T/CpTL/w+e0/8Podb/CaDW/w+l
2/8Bcrv/AFWh/wBwt/8Ag8j/AJrZ/wKx5/9S2fT/5v7//8D1/v+g7Pv/geT5/2DX8/87xez/GLLj/wKg
2v8AjdL/AHzE/wBsuf8AW67/AEqf/wA5kv8AJYP/ABZz/wASbv8AClz/AAVG/wACOf8AASX/AAAQ/wAA
F/8AACT/AAAe/wAABf8AAAD/AAAA/wAAAf8BAiP/AAAo/wAAOv8AC0n/ABxZ/wAqZP8ALmf/ACNj/wAd
Yf8AJmX/ADFt/wA/ev8ATIj/AE2O/wBRkv8AYJ7/AnGr/wd7s/8MgLn/D4O9/wyFv/8Dg7//BonD/xmZ
zv8jpNb/KKnZ/yWs2/8Fi8v/BHm6/wuUy/8Qo9f/Hq3e/xm45/820/T/w/T8///////p/v7/sO/8/37g
9v9X0PD/Nb/o/xuv4f8En9j/AI/O/wB7wv8Aa7j/AF+w/wBVpv8ASZv/ADuR/wAxiP8AJnz/ABtx/wAQ
Zf8AB1f/AARN/wAAP/8AAkn/AAFC/wAALP8AABP/AAAC/wAAAf8AAAP/AQIZ/wAAKv8ABEL/ABtX/wAo
Y/8ALmf/AChh/wAeWv8AE1P/ABFV/wATWv8AFWH/ABpn/wAca/8AIXH/ADCA/wBNl/8BaKr/Bn65/xaR
xf8hmsz/HJvO/xyczv81rNj/R7je/1fB4/8tr9v/IaLQ/0G43f9BwOX/YdHu/4zo+f9x5fj/uvX9////
////////9v///7vy/P+C4Pb/Vc3u/zK85f8Tqdz/BZTS/wGGxv8AdL7/AGW0/wBdrv8ATqL/AESY/wA+
j/8ANoj/AC5+/wAldP8AGmn/AAxd/wAEVP8AAVL/AABM/wAAQP8AADP/AAAi/wAADP8AAAb/AgIM/wEB
Cv8AAB3/AAQ9/wAMS/8AFlL/ABlT/wASTP8ADkb/AA9J/wAOTf8ABkf/AAA7/wAARP8ABlj/ABhs/wAp
e/8APov/AFCb/wBfp/8AcbL/BoO9/xaSx/8uodD/SrHa/2PA4v9Etd7/PK/X/1m93/9vyuf/Ycjo/4XZ
8f9g1PH/feD2//b9/////////////+7+///B9P3/kOX5/2nW8v9Ox+v/Lrbk/xOm3P8Jntb/AI3N/wB6
v/8AbLX/AFWk/wBHmP8AOo7/ACyC/wAgdf8AFmr/AA5g/wAJVv8AA0j/AANK/wABRP8AADn/AAAx/wAA
K/8AACP/AAAZ/wICGf8BAB//AAA1/wAUU/8AHlv/AB9c/wAYVv8ABUX/AAE+/wABPv8AADb/AAAo/wAD
MP8ABUv/AApf/wAOZv8AEGj/ABxz/wAuhP8AQpL/AFSd/wBqq/8Lgrn/NJvJ/0+s1f8+p9P/QqfQ/3TC
4P+Ayub/gc7p/3/M5/990u3/XMrr/7zs+P/9////+v////T////Y+f7/sO/8/4ji9/9m1PL/SMXr/yay
4v8IoNf/ApXS/wCIy/8AfML/AG+5/wBeqP8AVJ7/AEuW/wBAif8ANHz/ACZv/wAbZf8AFlr/AAtH/wAH
O/8AAy//AAEn/wAAHv8AACD/AAAp/wAAMP8CAzX/Aixn/wAybP8AQHf/AEl//wBIgf8AN3P/ACFe/wAb
WP8AE1X/AAxP/wANUf8AEFz/AA5g/wAKX/8AC2H/ABxw/wAyhf8APo//AEqW/wBgov8OerL/LJDA/zCT
xv8pksP/UabP/3/B3/+Ozef/gszn/3TF4/+Z1uz/e87r/5TZ8P/p/P7/8v///+/////c+v7/wvP9/6Ho
+P932fP/Scbr/y+45f8Uq93/AJrU/wCJyv8AecD/AGu0/wBZpv8ATJj/AEWQ/wBAjP8AOIP/ADF5/wAs
cP8AKG3/ACRn/wAaYP8ADU//AAM//wABOP8AAjP/AAU7/wAIPf8AAi7/AQMe/wJYkP8AX5T/AGaX/wBr
nf8Ab6H/AGue/wBjlv8DZ5f/C2uc/wFPjP8ANnn/ACZv/wAfa/8AIW//ACNw/wAsdP8AO4D/AEaJ/wBa
mP8Jcaj/JYW3/zeWxP85k8L/Z6/P/4DB3/9qutz/OaHO/yyZyf+Ax+L/i9Tr/1jA5P9JvOT/WsHn/6fh
8v+m4PT/xvP8/7rw/f+T4fX/Zs3u/ze35P8TpNn/AJXQ/wCMzP8Ahcb/AH3B/wBos/8AVaL/AEaT/wA3
hP8ALnn/ACVv/wAgZv8AHGD/ACNm/wAhZv8AF1z/AApJ/wAEPv8AAz3/AANC/wACQ/8AA0D/AAI+/wIE
Nv8CVov/AFuP/wBhlv8AYZj/AGGY/wBil/8FaJr/HHqp/xlonP8CSon/AEqI/wBSj/8AWJP/AFuV/wBa
k/8AVo7/AFqR/wBHgf8AMGv/AlOI/x56qf9Mm8L/dLPT/4TC3f9Op87/EHiy/wBZnv8AXaD/F4i//xuM
xf8QgsL/AHG7/wBgt/8Aa7z/AG/B/ziZ0v+b3PL/jN/2/1HB5/8jqtz/CprS/wCBxP8Ab7n/AGaw/wBm
r/8AXav/AFWi/wBKl/8AOIX/ACly/wAeZv8AFFv/AA1S/wAPU/8ADVL/AAVH/wACQP8AATz/AAI6/wAC
Of8AADT/AAAw/wAAMv8CAzP/AluP/wBjkv8AbJr/AGyd/wBnmv8BYJT/GmmW/y5/p/8ocpr/JWiS/x5g
jv8XXYv/EF2L/wdcjP8GXoz/CGqV/wBEcv8ADDf/AClc/xpsmP9DkLb/cK/O/3O31P8/nMf/BVub/wAv
eP8AR4z/Bmqp/wBNmf8ARJP/ADuR/wAtif8AN5b/AE+o/wBetP8AW7L/E2qz/1as1f9Vv+T/KKjY/wiT
zf8Aer7/AFyp/wBHlf8AQI7/ADyM/wA+i/8APIf/ADV//wArdP8AHmb/ABFY/wAITP8ABkf/AApK/wAL
Sv8ACEX/AAI//wABNv8AAC7/AAAr/wAAKf8AACv/AgMu/wJck/8AZ5j/AHGd/wByn/8Abp//AGea/w5h
lf8cZpX/JWqS/zZ6mv9Ii6P/V5mp/2Kjr/9hoq3/hbK3/2+arf8AABD/ABRA/wFBb/8wf6H/Wp29/1yl
xv8lgrL/AEOC/wAVXP8AIGb/AC52/wpgov8BLn7/ABZp/wAIYf8AGnb/ADGF/wBYp/8AZrL/AGCy/wBF
mf8AQ5D/Qp/L/ziw2v8OlMv/AHy7/wBhp/8ASpP/ADOA/wAjcv8AGmb/ABpj/wAeZv8AHmP/ABpc/wAT
Vv8AC07/AAhL/wALTv8ACEj/AAlF/wAGQ/8ABD3/AAAw/wAAKP8AACL/AAAi/wIDKf8CWJL/AGeb/wBv
nv8AdKP/AXGi/w5qnP8acKD/G26f/xZfkv8PToP/DEp+/wxNf/8XXoj/PICa/4a1v/87U2P/AAAJ/wAZ
Rf8HUHj/MXqf/y2Bp/8HWo3/ACNh/wABPP8AAz3/ABVW/wAsdv8AE1D/AAlB/wAAN/8AAEb/AAZg/wAa
cP8APY//Alun/wFVpv8AMYX/BDB6/0ijy/83rNj/Do7G/wB1tP8AZKf/AFGZ/wA9if8AJHP/ABJe/wAG
Uf8AAkX/AAZH/wALSf8ACkf/AAtL/wAPVf8AD1X/AAVJ/wAGR/8AB0X/AAI9/wAANv8AACv/AAAg/wAA
HP8CAx//AVeQ/whpm/8ui7T/M4+4/yB9qv8aapz/GWeY/xhqmf8XZpX/FVuN/xZakf8SVI3/CU2G/wpU
iv8LVIf/AAQN/wAAB/8AHEX/DFt//xRpkP8BQXX/ABFE/wAAGf8AABv/AAAO/wAJL/8ACUD/AAAV/wAA
Cv8AABb/AAAo/wAAPP8ABFH/ABJt/wAjfv8ANoz/AAth/wIITf9JnMP/RbLd/yKbzf8LicL/A3u4/wBt
r/8AX6j/AEiW/wA9if8AI3D/ABJY/wAJTP8AB0f/AAZH/wAFR/8ACk//AApS/wAFTf8ABEn/AAJE/wAC
Q/8AADz/AAAu/wAAIv8AABv/AgMd/wVTj/8cbJz/VqLG/ziNuP8ieKP/FWWU/xNhk/8VY5L/FF6M/xBQ
gP8QS37/E1OJ/xRTiP8QVIb/BEZ+/wAACf8AAA//AB9L/wFNd/8BSHX/ABxR/wABKf8AAAH/AAAA/wAA
AP8AAAr/AAAC/wAAAP8AAAD/AAAF/wAGMv8AATf/AABF/wABV/8AEmv/ABZw/wAAQv8ZMGX/UbLa/0Kt
2P8wptP/HpzP/wuQyP8AgcD/AG6v/wBgp/8AWqH/AFOb/wBGjf8AMnz/ACl2/wATXP8ACVH/AAtT/wAQ
Wf8AGmD/ABhf/wARWP8ADFH/AABA/wAAOP8AADX/AAAv/wICL/8HUIr/FGCU/zqNtv8ziLb/Kn2m/xxy
nf8TYZD/FV6I/xVhjP8VXYz/EUx//w9Fef8IPnD/AjZg/wAWKv8AAAb/AAEa/wATQf8AGkn/ABM//wAm
U/8AF0f/AAAD/wAAAP8AAAP/AAAC/wAAAP8AAAD/AAAA/wAAB/8AAxb/AAEX/wAALf8AAED/AAJX/wAA
VP8IFFj/O5C8/z6o0/8zo8//HpbI/w2Oxf8Ci8T/AIC+/wBxr/8AaKr/AGut/wBprP8AYKf/AGCm/wBW
nv8AKnX/ABVe/wAUYP8AGWL/ACRp/wAqcv8AHGT/AAtQ/wAGS/8ADlP/AAxQ/wAITf8CC0//AkV+/whG
eP8aaZX/KoCs/yp8pP8oeqD/F2WO/xFSef8SVnz/F2CH/xdii/8OWYX/AS9R/wAFDf8AAAD/AAAA/wAA
Bv8AAA7/Aw8v/wI5Yv8AKVr/AAQr/wAAA/8AAAL/AAEG/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
AP8AAAX/AAgz/wMGVv8UMHj/KYKz/x+Nuv8Nfa//BXet/wBzq/8AdK3/AH64/wB0rf8AZKL/AGCi/wBu
rv8AcK//AGus/wBmp/8AX6D/AFab/wBIjv8ARY3/AC12/wAtcv8AIGb/ABJX/wAKSf8ABUP/AAxM/wAJ
S/8ACU3/AhNV/wJKif8AOW3/BUpz/xppk/8gc53/InKZ/xttkv8UWYD/EUx0/xFTd/8LV3v/Ai5F/wAB
A/8AAAD/AAAA/wAAAP8AAAD/BRIg/yttkf8CKVv/AAAg/wAACP8AAAD/AAcO/wAECv8AAAD/AAAA/wAA
AP8AAAD/AAAA/wAAAP8AAAD/AAAK/wADMv8GM3X/LpfC/y2YxP8Sfq7/AHGk/wBsov8AbqX/AG6m/wBp
pP8AZZ//AGGf/wBamv8AVZP/AFSO/wBSjv8AU5T/AE6P/wBMjf8AV5j/AEiJ/wA5ff8AMnP/ACNk/wAY
WP8ADEn/AAQ7/wACNv8ABDL/AAQp/wIFJv8CWJn/ADp2/wA6af8QU3z/F2CL/xVdh/8WYIT/F2SI/xFa
g/8DOVn/AA0X/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAUJ/x5kff9HncD/GkRz/wAAAP8AAAD/AAAA/wIS
IP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAf8AAAD/AAAC/wAPNf8AIF//KoO0/zqjz/8njLz/DXir/wBr
nv8AZpv/AGmh/wBrpf8AaaP/AGOc/wBdmf8AW5X/AFeQ/wBVjv8AVo//AFiW/wBbm/8AW5r/AFWW/wBQ
jv8AR4L/ADV3/wAlaf8AFlb/AAtA/wAGMP8ABDD/AAIv/wAAKv8CAi3/Aj96/wAuZf8AJ1f/BDhi/w9M
df8RT3j/Dkty/w9UeP8ENU7/AAQI/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAB/wcNEf8OLDr/L3mZ/zuI
ov8eUG3/Bhov/wIJEP8CERv/AAML/wAAAP8AAAD/AAAA/wAAAP8AAAX/AQkP/wIcNf8VSHj/NI27/z2g
zP8okcL/FICx/wRuov8AZpn/AGSY/wBnnf8AaqP/AGym/wBnn/8AZJv/AGOa/wBimP8BXpb/AVyW/wBa
lv8AV5P/AFKM/wBOh/8ATIb/AEiD/wA/ff8ANHT/ACtn/wAhXP8AGFj/AAxS/wACSv8AADz/AgMx/wIi
WP8AHE//AB9O/wAmVv8BOmT/Bj1o/wQsV/8AFCX/AAAA/wAAAP8AAAD/AAMJ/wABCP8GAgH/BgoL/wAD
CP8KJS3/ByU3/xYzSf8waoH/LnOW/0aMrv9Nian/OWuI/yJPbv8TLUL/Chgm/wkZIv8hQVb/O3CO/0aL
r/8+irH/P5O9/zWTvv8ki7v/GYK2/whwo/8AXpL/AFWK/wBPhv8AU4r/AFiR/wFYk/8AUo7/AE6I/wBN
h/8ATYn/AE+M/wBUjf8AVpL/AFaS/wBWjP8AVov/AFeM/wBTif8ASIH/ADt0/wApZf8AGFX/AA1E/wAE
NP8AACf/AAAa/wEBEv8CHlX/ABpR/wAeU/8AH1L/AB9I/wAaPv8ABhT/AAAA/wAAAP8DCxP/ABkv/wBE
b/8AQHL/Ay5X/wMLGP8AAAD/AAAA/wALFf8TRWP/JWqM/y54mf82fJ3/OH2c/z2Bof8+g6b/PYWp/zuB
p/87g6f/RpC1/0GMs/8ygqn/J3un/xpyo/8QbaP/CW2k/wVnoP8BU4z/AER7/wBCd/8AQXn/AEaB/wBR
iv8AWI7/AFiP/wBVjf8AU4v/AFOL/wBOiP8ASoX/AEmG/wBCgP8AN3P/AC9q/wAmX/8AHlX/ABNH/wAK
Pv8ABC//AAEY/wAABP8AAAD/AAAA/wAAAP8AAAD/AhlY/wAVT/8AEUL/AAg2/wACFv8AAAP/AAAA/wAA
AP8AAQH/CDha/wA8cf8APWT/ADJN/wAXIf8AAAD/AAMJ/wAZLv8ANlr/Bkxv/wtFaf8HPmb/BkJp/wNB
Z/8ERmz/B091/wxagf8WZYr/G2qP/xhskf8WbJX/D2qW/wdpl/8DZZn/AGGW/wBgmf8AWpf/AEeB/wA5
b/8ANGr/AC9o/wAuav8AL27/ACxq/wAmZP8AIF3/ABlW/wATUP8ADUX/AAhE/wAFRf8AA0X/AAA7/wAA
Mv8AACX/AAAd/wAAGf8AABv/AAAR/wAAAf8AAAD/AAAA/wAAAP8AAAD/AAAB/wIZYf8ACEf/AAEx/wAB
Nv8AACb/AAAM/wAAAP8ACSj/AAs6/wAIGf8AECn/AAYJ/wAAAP8AAAL/AA4k/wAiRP8ALlP/AC1R/wAr
Tf8AHz//ACBA/wAjRf8AJkf/ACtK/wAvUv8BNFn/AjRb/wIxXP8BL1//ASxg/wAqY/8AJWL/AB5b/wAY
W/8AFmX/ABFk/wAHRf8AAi//AAEn/wAALP8AAC//AAAz/wAANP8AADH/AAAu/wAAJ/8AACP/AAAe/wAA
Hv8AACD/AAAe/wAAGP8AABb/AAAU/wAADP8AAAb/AAAC/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
Af8CJ3X/AA5c/wAGTP8ADlb/AApS/wAAHv8AAAD/AAYQ/wAJJf8AAAD/AAAA/wAABf8ACSb/ABVD/wAe
SP8AIUb/ACNK/wAkTP8AHT//AAAG/wAAAv8AAAL/AAAC/wAAAf8AAAT/AAAK/wAADv8AABP/AAAb/wAA
If8AACf/AAAl/wAAJ/8AADH/AABG/wAASP8AACv/AAAX/wAAFv8AABz/AAAh/wAAJv8AACj/AAAl/wAA
If8AAB3/AAAa/wAAGv8AABr/AAAX/wAAD/8AAAf/AAAB/wAABP8AAAL/AAAA/wAAAP8AAAD/AAAA/wAA
AP8AAAD/AAAA/wAAAP8AAAH/AiJy/wAZa/8AF2f/ABdo/wAGOP8AAAD/AAED/wADGP8AAAD/AAAH/wAI
Kv8AE0n/ABxT/wAeUP8AHk//ACBN/wAiTf8AI1H/ABYz/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
AP8AAAD/AAAA/wAAAv8AAAn/AAAN/wAADP8AABH/AAAf/wAANv8AADn/AAAg/wAAE/8AABf/AAAc/wAA
HP8AAB7/AAAf/wAAHv8AABz/AAAa/wAAHf8AAB7/AAAf/wAAIv8AAB7/AAAV/wAAC/8AAAb/AAAB/wAA
Af8AAAX/AAAC/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAB/wIcbv8AFmn/ABFf/wATYv8DD0n/ChIe/wAB
AP8AEEH/AAtD/wAVUf8AGlz/ABpX/wAcUv8AH1T/AB9W/wAiV/8AI1X/ACFV/wALIP8AAAD/AAAA/wAA
AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAC/wAAEf8AACn/AAAu/wAA
Gf8AAA//AAAW/wAAIP8AAB//AAAa/wAAGv8AAB3/AAAb/wAAHf8AACr/AAAs/wAALP8AAC//AAAk/wAA
Hv8AABj/AAAN/wAAB/8AAAT/AAAE/wAAAv8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAf8CEWf/AAlf/wAI
WP8AC1j/AxVc/wgZXP8AACL/AAYl/wAVXv8AG13/ABdY/wAVVP8AF1H/ABtT/wAdVP8AHlT/ABxQ/wAX
Sf8AAgv/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
AP8AAAv/AAAf/wAAI/8AAA//AAAG/wAAD/8AABn/AAAh/wAAGf8AABH/AAAQ/wAAEf8AAB7/AAAt/wAA
Lv8AADH/AAAn/wAAG/8AABT/AAAQ/wAAC/8AAAz/AAAJ/wAAB/8AAAH/AAAA/wAAAP8AAAD/AAAA/wAA
AP8AAAH/AgRc/wAAU/8AAFD/AABN/wACTf8AAEX/AABC/wADQv8ADlL/ABFS/wAPUP8ADlD/ABFM/wAW
Tv8AF0z/ABZK/wAVSf8ACzH/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
AP8AAAD/AAAA/wAAAP8AAAD/AAAF/wAAGP8AABn/AAAD/wAAAP8AAAX/AAAN/wAAGP8AAA3/AAAD/wAA
AP8AAAr/AAAb/wAAFP8AABf/AAAk/wAAGP8AAAz/AAAJ/wAAB/8AAAb/AAAL/wAACP8AAAb/AAAD/wAA
Af8AAAD/AAAA/wAAAP8AAAD/AAAB/wAAQ/8AADv/AAAy/wAALv8AACr/AAAl/wAAKv8AADj/AABA/wAA
QP8AAEH/AABA/wAEQP8ABD//AAM7/wACOv8AAjX/AAAM/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAb/AAAG/wAAAP8AAAD/AAAA/wAA
AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAv8AAAD/AAAA/wAACf8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
Af8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8fIUnlHR9D5R0fPOUdHznlHR855R0f
PuUdH0blHR9M5R0fVOUdH1XlHR9S5R0fUuUeIVXlHiJU5R4gTuUeH0zlHR495RoaHOUaGhvlGhob5Roa
G+UaGhvlGhob5RoaG+UaGhvlGhob5RoaG+UaGhvlGhsc5RobHOUaGxzlGhsc5RobHOUaGxzlGhse5Rob
IeUaGxzlGhsb5RobHOUaGxvlGhsb5RobG+UaGxzlGhsc5RobG+UaGxvlGhob5R0hJuUbHB7lGhsb5Rob
HOUaGxzlGhsc5RobHOUaGx3lGhsc5RobHeUaGxzlGhsc5RobHOUaGxzlGhob5RoaG+UaGhvl9fb3DPX2
9wz19vcM9fb3DPX29wz19vgM9fb4DPX2+Az19vgM9fb4DPX2+Az19vgM9fb4DPX2+Az19vcM9fb3DPX1
9Qzz8/MM8/PzDPPz8wzz8/MM8/P0DPPz9Azz8/QM8/P0DPPz9Azz8/QM8/P0DPPz9Azz8/QM8/P0DPPz
9Azz8/QM8/P0DPP09Azz9PQM8/P0DPPz9Azz8/QM8/P0DPPz9Azz8/QM8/P0DPPz9Azz8/QM8/T0DPPz
9Az19/gM8/T1DPPz9Azz8/QM8/P0DPPz9Azz9PQM8/T0DPPz9Azz8/QM8/P0DPPz9Azz8/QM8/P0DPPz
9Azz8/QM8/PzDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAA////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAP//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////8=
</value>
</data>
</root>

@ -0,0 +1,711 @@
#region --- License ---
/* Licensed under the MIT/X11 license.
* Copyright (c) 2006-2008 the OpenTK Team.
* This notice may not be removed from any source distribution.
* See license.txt for licensing details.
*/
#endregion
// #define READALL
// uncomment so ALL fields read from file are interpreted and filled. Necessary to implement uncompressed DDS
// TODO: Find app that can build compressed dds cubemaps and verify that the import code works.
using System;
using System.IO;
using System.Diagnostics;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
namespace SCJMapper_V2.TextureLoaders
{
/// <summary>
/// Expects the presence of a valid OpenGL Context and Texture Compression Extensions (GL 1.5) and Cube Maps (GL 1.3).
/// You will get what you give. No automatic Mipmap generation or automatic compression is done. (both bad quality)
/// Textures are never rescaled or checked if Power of 2, but you should make the Width and Height a multiple of 4 because DXTn uses 4x4 blocks.
/// (Image displays correctly but runs extremely slow with non-power-of-two Textures on FX5600, Cache misses?)
/// CubeMap support is experimental and the file must specify all 6 faces to work at all.
/// </summary>
static class ImageDDS
{
#region Constants
private const byte HeaderSizeInBytes = 128; // all non-image data together is 128 Bytes
private const uint BitMask = 0x00000007; // bits = 00 00 01 11
private static NotImplementedException Unfinished = new NotImplementedException( "ERROR: Only 2 Dimensional DXT1/3/5 compressed images for now. 1D/3D Textures may not be compressed according to spec." );
#endregion Constants
#region Simplified In-Memory representation of the Image
private static bool _IsCompressed;
private static int _Width, _Height, _Depth, _MipMapCount;
private static int _BytesForMainSurface; // must be handled with care when implementing uncompressed formats!
private static byte _BytesPerBlock;
private static PixelInternalFormat _PixelInternalFormat;
#endregion Simplified In-Memory representation of the Image
#region Flag Enums
[Flags] // Surface Description
private enum eDDSD: uint
{
CAPS = 0x00000001, // is always present
HEIGHT = 0x00000002, // is always present
WIDTH = 0x00000004, // is always present
PITCH = 0x00000008, // is set if the image is uncompressed
PIXELFORMAT = 0x00001000, // is always present
MIPMAPCOUNT = 0x00020000, // is set if the image contains MipMaps
LINEARSIZE = 0x00080000, // is set if the image is compressed
DEPTH = 0x00800000 // is set for 3D Volume Textures
}
[Flags] // Pixelformat
private enum eDDPF: uint
{
NONE = 0x00000000, // not part of DX, added for convenience
ALPHAPIXELS = 0x00000001,
FOURCC = 0x00000004,
RGB = 0x00000040,
RGBA = 0x00000041
}
/// <summary>This list was derived from nVidia OpenGL SDK</summary>
[Flags] // Texture types
private enum eFOURCC: uint
{
UNKNOWN = 0,
#if READALL
R8G8B8 = 20,
A8R8G8B8 = 21,
X8R8G8B8 = 22,
R5G6B5 = 23,
X1R5G5B5 = 24,
A1R5G5B5 = 25,
A4R4G4B4 = 26,
R3G3B2 = 27,
A8 = 28,
A8R3G3B2 = 29,
X4R4G4B4 = 30,
A2B10G10R10 = 31,
A8B8G8R8 = 32,
X8B8G8R8 = 33,
G16R16 = 34,
A2R10G10B10 = 35,
A16B16G16R16 = 36,
L8 = 50,
A8L8 = 51,
A4L4 = 52,
D16_LOCKABLE = 70,
D32 = 71,
D24X8 = 77,
D16 = 80,
D32F_LOCKABLE = 82,
L16 = 81,
// s10e5 formats (16-bits per channel)
R16F = 111,
G16R16F = 112,
A16B16G16R16F = 113,
// IEEE s23e8 formats (32-bits per channel)
R32F = 114,
G32R32F = 115,
A32B32G32R32F = 116
#endif
DXT1 = 0x31545844,
DXT2 = 0x32545844,
DXT3 = 0x33545844,
DXT4 = 0x34545844,
DXT5 = 0x35545844,
}
[Flags] // dwCaps1
private enum eDDSCAPS: uint
{
NONE = 0x00000000, // not part of DX, added for convenience
COMPLEX = 0x00000008, // should be set for any DDS file with more than one main surface
TEXTURE = 0x00001000, // should always be set
MIPMAP = 0x00400000 // only for files with MipMaps
}
[Flags] // dwCaps2
private enum eDDSCAPS2: uint
{
NONE = 0x00000000, // not part of DX, added for convenience
CUBEMAP = 0x00000200,
CUBEMAP_POSITIVEX = 0x00000400,
CUBEMAP_NEGATIVEX = 0x00000800,
CUBEMAP_POSITIVEY = 0x00001000,
CUBEMAP_NEGATIVEY = 0x00002000,
CUBEMAP_POSITIVEZ = 0x00004000,
CUBEMAP_NEGATIVEZ = 0x00008000,
CUBEMAP_ALL_FACES = 0x0000FC00,
VOLUME = 0x00200000 // for 3D Textures
}
#endregion Flag Enums
#region Private Members
private static string idString; // 4 bytes, must be "DDS "
private static UInt32 dwSize; // Size of structure is 124 bytes, 128 including all sub-structs and the header
private static UInt32 dwFlags; // Flags to indicate valid fields.
private static UInt32 dwHeight; // Height of the main image in pixels
private static UInt32 dwWidth; // Width of the main image in pixels
private static UInt32 dwPitchOrLinearSize; // For compressed formats, this is the total number of bytes for the main image.
private static UInt32 dwDepth; // For volume textures, this is the depth of the volume.
private static UInt32 dwMipMapCount; // total number of levels in the mipmap chain of the main image.
#if READALL
private static UInt32[] dwReserved1; // 11 UInt32s
#endif
// Pixelformat sub-struct, 32 bytes
private static UInt32 pfSize; // Size of Pixelformat structure. This member must be set to 32.
private static UInt32 pfFlags; // Flags to indicate valid fields.
private static UInt32 pfFourCC; // This is the four-character code for compressed formats.
#if READALL
private static UInt32 pfRGBBitCount; // For RGB formats, this is the total number of bits in the format. dwFlags should include DDpf_RGB in this case. This value is usually 16, 24, or 32. For A8R8G8B8, this value would be 32.
private static UInt32 pfRBitMask; // For RGB formats, these three fields contain the masks for the red, green, and blue channels. For A8R8G8B8, these values would be 0x00ff0000, 0x0000ff00, and 0x000000ff respectively.
private static UInt32 pfGBitMask; // ..
private static UInt32 pfBBitMask; // ..
private static UInt32 pfABitMask; // For RGB formats, this contains the mask for the alpha channel, if any. dwFlags should include DDpf_ALPHAPIXELS in this case. For A8R8G8B8, this value would be 0xff000000.
#endif
// Capabilities sub-struct, 16 bytes
private static UInt32 dwCaps1; // always includes DDSCAPS_TEXTURE. with more than one main surface DDSCAPS_COMPLEX should also be set.
private static UInt32 dwCaps2; // For cubic environment maps, DDSCAPS2_CUBEMAP should be included as well as one or more faces of the map (DDSCAPS2_CUBEMAP_POSITIVEX, DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY, DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ). For volume textures, DDSCAPS2_VOLUME should be included.
#if READALL
private static UInt32[] dwReserved2; // 3 = 2 + 1 UInt32
#endif
#endregion Private Members
/// <summary>
/// This function will generate, bind and fill a Texture Object with a DXT1/3/5 compressed Texture in .dds Format.
/// MipMaps below 4x4 Pixel Size are discarded, because DXTn's smallest unit is a 4x4 block of Pixel data.
/// It will set correct MipMap parameters, Filtering, Wrapping and EnvMode for the Texture.
/// The only call inside this function affecting OpenGL State is GL.BindTexture();
/// </summary>
/// <param name="filename">The name of the file you wish to load, including path and file extension.</param>
/// <param name="texturehandle">0 if invalid, otherwise a Texture Object usable with GL.BindTexture().</param>
/// <param name="dimension">0 if invalid, will output what was loaded (typically Texture1D/2D/3D or Cubemap)</param>
public static void LoadFromDisk( string filename, out uint texturehandle, out TextureTarget dimension )
{
#region Prep data
// invalidate whatever it was before
dimension = (TextureTarget) 0;
texturehandle = TextureLoaderParameters.OpenGLDefaultTexture;
ErrorCode GLError = ErrorCode.NoError;
_IsCompressed = false;
_Width = 0;
_Height = 0;
_Depth = 0;
_MipMapCount = 0;
_BytesForMainSurface = 0;
_BytesPerBlock = 0;
_PixelInternalFormat = PixelInternalFormat.Rgba8;
byte[] _RawDataFromFile;
#endregion
#region Try
try // Exceptions will be thrown if any Problem occurs while working on the file.
{
_RawDataFromFile = File.ReadAllBytes( @filename );
#region Translate Header to less cryptic representation
ConvertDX9Header( ref _RawDataFromFile ); // The first 128 Bytes of the file is non-image data
// start by checking if all forced flags are present. Flags indicate valid fields, but aren't written by every tool .....
if ( idString != "DDS " || // magic key
dwSize != 124 || // constant size of struct, never reused
pfSize != 32 || // constant size of struct, never reused
!CheckFlag( dwFlags, (uint) eDDSD.CAPS ) || // must know it's caps
!CheckFlag( dwFlags, (uint) eDDSD.PIXELFORMAT ) || // must know it's format
!CheckFlag( dwCaps1, (uint) eDDSCAPS.TEXTURE ) // must be a Texture
)
throw new ArgumentException( "ERROR: File has invalid signature or missing Flags." );
#region Examine Flags
if ( CheckFlag( dwFlags, (uint) eDDSD.WIDTH ) )
_Width = (int) dwWidth;
else
throw new ArgumentException( "ERROR: Flag for Width not set." );
if ( CheckFlag( dwFlags, (uint) eDDSD.HEIGHT ) )
_Height = (int) dwHeight;
else
throw new ArgumentException( "ERROR: Flag for Height not set." );
if ( CheckFlag( dwFlags, (uint) eDDSD.DEPTH ) && CheckFlag( dwCaps2, (uint) eDDSCAPS2.VOLUME ) )
{
dimension = TextureTarget.Texture3D; // image is 3D Volume
_Depth = (int) dwDepth;
throw Unfinished;
} else
{// image is 2D or Cube
if ( CheckFlag( dwCaps2, (uint) eDDSCAPS2.CUBEMAP ) )
{
dimension = TextureTarget.TextureCubeMap;
_Depth = 6;
} else
{
dimension = TextureTarget.Texture2D;
_Depth = 1;
}
}
// these flags must be set for mipmaps to be included
if ( CheckFlag( dwCaps1, (uint) eDDSCAPS.MIPMAP ) && CheckFlag( dwFlags, (uint) eDDSD.MIPMAPCOUNT ) )
_MipMapCount = (int) dwMipMapCount; // image contains MipMaps
else
_MipMapCount = 1; // only 1 main image
// Should never happen
if ( CheckFlag( dwFlags, (uint) eDDSD.PITCH ) && CheckFlag( dwFlags, (uint) eDDSD.LINEARSIZE ) )
throw new ArgumentException( "INVALID: Pitch AND Linear Flags both set. Image cannot be uncompressed and DTXn compressed at the same time." );
// This flag is set if format is uncompressed RGB RGBA etc.
if ( CheckFlag( dwFlags, (uint) eDDSD.PITCH ) )
{
// _BytesForMainSurface = (int) dwPitchOrLinearSize; // holds bytes-per-scanline for uncompressed
_IsCompressed = false;
throw Unfinished;
}
// This flag is set if format is compressed DXTn.
if ( CheckFlag( dwFlags, (uint) eDDSD.LINEARSIZE ) )
{
_BytesForMainSurface = (int) dwPitchOrLinearSize;
_IsCompressed = true;
}
#endregion Examine Flags
#region Examine Pixel Format, anything but DXTn will fail atm.
if ( CheckFlag( pfFlags, (uint) eDDPF.FOURCC ) )
switch ( (eFOURCC) pfFourCC )
{
case eFOURCC.DXT1:
_PixelInternalFormat = (PixelInternalFormat) ExtTextureCompressionS3tc.CompressedRgbS3tcDxt1Ext;
_BytesPerBlock = 8;
_IsCompressed = true;
break;
//case eFOURCC.DXT2:
case eFOURCC.DXT3:
_PixelInternalFormat = (PixelInternalFormat) ExtTextureCompressionS3tc.CompressedRgbaS3tcDxt3Ext;
_BytesPerBlock = 16;
_IsCompressed = true;
break;
//case eFOURCC.DXT4:
case eFOURCC.DXT5:
_PixelInternalFormat = (PixelInternalFormat) ExtTextureCompressionS3tc.CompressedRgbaS3tcDxt5Ext;
_BytesPerBlock = 16;
_IsCompressed = true;
break;
default:
throw Unfinished; // handle uncompressed formats
} else
throw Unfinished;
// pf*Bitmasks should be examined here
#endregion
// Works, but commented out because some texture authoring tools don't set this flag.
/* Safety Check, if file is only 1x 2D surface without mipmaps, eDDSCAPS.COMPLEX should not be set
if ( CheckFlag( dwCaps1, (uint) eDDSCAPS.COMPLEX ) )
{
if ( result == eTextureDimension.Texture2D && _MipMapCount == 1 ) // catch potential problem
Trace.WriteLine( "Warning: Image is declared complex, but contains only 1 surface." );
}*/
if ( TextureLoaderParameters.Verbose )
Trace.WriteLine( "\n" + GetDescriptionFromMemory( filename, dimension ) );
#endregion Translate Header to less cryptic representation
#region send the Texture to GL
#region Generate and Bind Handle
GL.GenTextures( 1, out texturehandle );
GL.BindTexture( dimension, texturehandle );
#endregion Generate and Bind Handle
int Cursor = HeaderSizeInBytes;
// foreach face in the cubemap, get all it's mipmaps levels. Only one iteration for Texture2D
for ( int Slices = 0 ; Slices < _Depth ; Slices++ )
{
int trueMipMapCount = _MipMapCount - 1; // TODO: triplecheck correctness
int Width = _Width;
int Height = _Height;
for ( int Level = 0 ; Level < _MipMapCount ; Level++ ) // start at base image
{
#region determine Dimensions
int BlocksPerRow = ( Width + 3 ) >> 2;
int BlocksPerColumn = ( Height + 3 ) >> 2;
int SurfaceBlockCount = BlocksPerRow * BlocksPerColumn; // // DXTn stores Texels in 4x4 blocks, a Color block is 8 Bytes, an Alpha block is 8 Bytes for DXT3/5
int SurfaceSizeInBytes = SurfaceBlockCount * _BytesPerBlock;
// this check must evaluate to false for 2D and Cube maps, or it's impossible to determine MipMap sizes.
if ( TextureLoaderParameters.Verbose && Level == 0 && _IsCompressed && _BytesForMainSurface != SurfaceSizeInBytes )
Trace.WriteLine( "Warning: Calculated byte-count of main image differs from what was read from file." );
#endregion determine Dimensions
// skip mipmaps smaller than a 4x4 Pixels block, which is the smallest DXTn unit.
if ( Width > 2 && Height > 2 )
{ // Note: there could be a potential problem with non-power-of-two cube maps
#region Prepare Array for TexImage
byte[] RawDataOfSurface = new byte[SurfaceSizeInBytes];
if ( !TextureLoaderParameters.FlipImages )
{ // no changes to the image, copy as is
Array.Copy( _RawDataFromFile, Cursor, RawDataOfSurface, 0, SurfaceSizeInBytes );
} else
{ // Turn the blocks upside down and the rows aswell, done in a single pass through all blocks
for ( int sourceColumn = 0 ; sourceColumn < BlocksPerColumn ; sourceColumn++ )
{
int targetColumn = BlocksPerColumn - sourceColumn - 1;
for ( int row = 0 ; row < BlocksPerRow ; row++ )
{
int target = ( targetColumn * BlocksPerRow + row ) * _BytesPerBlock;
int source = ( sourceColumn * BlocksPerRow + row ) * _BytesPerBlock + Cursor;
#region Swap Bytes
switch ( _PixelInternalFormat )
{
case (PixelInternalFormat) ExtTextureCompressionS3tc.CompressedRgbS3tcDxt1Ext:
// Color only
RawDataOfSurface[target + 0] = _RawDataFromFile[source + 0];
RawDataOfSurface[target + 1] = _RawDataFromFile[source + 1];
RawDataOfSurface[target + 2] = _RawDataFromFile[source + 2];
RawDataOfSurface[target + 3] = _RawDataFromFile[source + 3];
RawDataOfSurface[target + 4] = _RawDataFromFile[source + 7];
RawDataOfSurface[target + 5] = _RawDataFromFile[source + 6];
RawDataOfSurface[target + 6] = _RawDataFromFile[source + 5];
RawDataOfSurface[target + 7] = _RawDataFromFile[source + 4];
break;
case (PixelInternalFormat) ExtTextureCompressionS3tc.CompressedRgbaS3tcDxt3Ext:
// Alpha
RawDataOfSurface[target + 0] = _RawDataFromFile[source + 6];
RawDataOfSurface[target + 1] = _RawDataFromFile[source + 7];
RawDataOfSurface[target + 2] = _RawDataFromFile[source + 4];
RawDataOfSurface[target + 3] = _RawDataFromFile[source + 5];
RawDataOfSurface[target + 4] = _RawDataFromFile[source + 2];
RawDataOfSurface[target + 5] = _RawDataFromFile[source + 3];
RawDataOfSurface[target + 6] = _RawDataFromFile[source + 0];
RawDataOfSurface[target + 7] = _RawDataFromFile[source + 1];
// Color
RawDataOfSurface[target + 8] = _RawDataFromFile[source + 8];
RawDataOfSurface[target + 9] = _RawDataFromFile[source + 9];
RawDataOfSurface[target + 10] = _RawDataFromFile[source + 10];
RawDataOfSurface[target + 11] = _RawDataFromFile[source + 11];
RawDataOfSurface[target + 12] = _RawDataFromFile[source + 15];
RawDataOfSurface[target + 13] = _RawDataFromFile[source + 14];
RawDataOfSurface[target + 14] = _RawDataFromFile[source + 13];
RawDataOfSurface[target + 15] = _RawDataFromFile[source + 12];
break;
case (PixelInternalFormat) ExtTextureCompressionS3tc.CompressedRgbaS3tcDxt5Ext:
// Alpha, the first 2 bytes remain
RawDataOfSurface[target + 0] = _RawDataFromFile[source + 0];
RawDataOfSurface[target + 1] = _RawDataFromFile[source + 1];
// extract 3 bits each and flip them
GetBytesFromUInt24( ref RawDataOfSurface, (uint) target + 5, FlipUInt24( GetUInt24( ref _RawDataFromFile, (uint) source + 2 ) ) );
GetBytesFromUInt24( ref RawDataOfSurface, (uint) target + 2, FlipUInt24( GetUInt24( ref _RawDataFromFile, (uint) source + 5 ) ) );
// Color
RawDataOfSurface[target + 8] = _RawDataFromFile[source + 8];
RawDataOfSurface[target + 9] = _RawDataFromFile[source + 9];
RawDataOfSurface[target + 10] = _RawDataFromFile[source + 10];
RawDataOfSurface[target + 11] = _RawDataFromFile[source + 11];
RawDataOfSurface[target + 12] = _RawDataFromFile[source + 15];
RawDataOfSurface[target + 13] = _RawDataFromFile[source + 14];
RawDataOfSurface[target + 14] = _RawDataFromFile[source + 13];
RawDataOfSurface[target + 15] = _RawDataFromFile[source + 12];
break;
default:
throw new ArgumentException( "ERROR: Should have never arrived here! Bad _PixelInternalFormat! Should have been dealt with much earlier." );
}
#endregion Swap Bytes
}
}
}
#endregion Prepare Array for TexImage
#region Create TexImage
switch ( dimension )
{
case TextureTarget.Texture2D:
GL.CompressedTexImage2D( TextureTarget.Texture2D,
Level,
_PixelInternalFormat,
Width,
Height,
TextureLoaderParameters.Border,
SurfaceSizeInBytes,
RawDataOfSurface );
break;
case TextureTarget.TextureCubeMap:
GL.CompressedTexImage2D( TextureTarget.TextureCubeMapPositiveX + Slices,
Level,
_PixelInternalFormat,
Width,
Height,
TextureLoaderParameters.Border,
SurfaceSizeInBytes,
RawDataOfSurface );
break;
case TextureTarget.Texture1D: // Untested
case TextureTarget.Texture3D: // Untested
default:
throw new ArgumentException( "ERROR: Use DXT for 2D Images only. Cannot evaluate " + dimension );
}
GL.Finish( );
#endregion Create TexImage
#region Query Success
int width, height, internalformat, compressed;
switch ( dimension )
{
case TextureTarget.Texture1D:
case TextureTarget.Texture2D:
case TextureTarget.Texture3D:
GL.GetTexLevelParameter( dimension, Level, GetTextureParameter.TextureWidth, out width );
GL.GetTexLevelParameter( dimension, Level, GetTextureParameter.TextureHeight, out height );
GL.GetTexLevelParameter( dimension, Level, GetTextureParameter.TextureInternalFormat, out internalformat );
GL.GetTexLevelParameter( dimension, Level, GetTextureParameter.TextureCompressed, out compressed );
break;
case TextureTarget.TextureCubeMap:
GL.GetTexLevelParameter( TextureTarget.TextureCubeMapPositiveX + Slices, Level, GetTextureParameter.TextureWidth, out width );
GL.GetTexLevelParameter( TextureTarget.TextureCubeMapPositiveX + Slices, Level, GetTextureParameter.TextureHeight, out height );
GL.GetTexLevelParameter( TextureTarget.TextureCubeMapPositiveX + Slices, Level, GetTextureParameter.TextureInternalFormat, out internalformat );
GL.GetTexLevelParameter( TextureTarget.TextureCubeMapPositiveX + Slices, Level, GetTextureParameter.TextureCompressed, out compressed );
break;
default:
throw Unfinished;
}
GLError = GL.GetError( );
if ( TextureLoaderParameters.Verbose )
Trace.WriteLine( "GL: " + GLError.ToString( ) + " Level: " + Level + " DXTn: " + ( ( compressed == 1 ) ? "Yes" : "No" ) + " Frmt:" + (ExtTextureCompressionS3tc) internalformat + " " + width + "*" + height );
if ( GLError != ErrorCode.NoError || compressed == 0 || width == 0 || height == 0 || internalformat == 0 )
{
GL.DeleteTextures( 1, ref texturehandle );
throw new ArgumentException( "ERROR: Something went wrong after GL.CompressedTexImage(); Last GL Error: " + GLError.ToString( ) );
}
#endregion Query Success
} else
{
if ( trueMipMapCount > Level )
trueMipMapCount = Level - 1; // The current Level is invalid
}
#region Prepare the next MipMap level
Width /= 2;
if ( Width < 1 )
Width = 1;
Height /= 2;
if ( Height < 1 )
Height = 1;
Cursor += SurfaceSizeInBytes;
#endregion Prepare the next MipMap level
}
#region Set States properly
GL.TexParameter( dimension, (TextureParameterName) All.TextureBaseLevel, 0 );
GL.TexParameter( dimension, (TextureParameterName) All.TextureMaxLevel, trueMipMapCount );
int TexMaxLevel;
GL.GetTexParameter( dimension, GetTextureParameter.TextureMaxLevel, out TexMaxLevel );
if ( TextureLoaderParameters.Verbose )
Trace.WriteLine( "Verification: GL: " + GL.GetError( ).ToString( ) + " TextureMaxLevel: " + TexMaxLevel + ( ( TexMaxLevel == trueMipMapCount ) ? " (Correct.)" : " (Wrong!)" ) );
#endregion Set States properly
}
#region Set Texture Parameters
GL.TexParameter( dimension, TextureParameterName.TextureMinFilter, (int) TextureLoaderParameters.MinificationFilter );
GL.TexParameter( dimension, TextureParameterName.TextureMagFilter, (int) TextureLoaderParameters.MagnificationFilter );
GL.TexParameter( dimension, TextureParameterName.TextureWrapS, (int) TextureLoaderParameters.WrapModeS );
GL.TexParameter( dimension, TextureParameterName.TextureWrapT, (int) TextureLoaderParameters.WrapModeT );
GL.TexEnv( TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (int) TextureLoaderParameters.EnvMode );
GLError = GL.GetError( );
if ( GLError != ErrorCode.NoError )
{
throw new ArgumentException( "Error setting Texture Parameters. GL Error: " + GLError );
}
#endregion Set Texture Parameters
// If it made it here without throwing any Exception the result is a valid Texture.
return; // success
#endregion send the Texture to GL
} catch ( Exception e )
{
dimension = (TextureTarget) 0;
texturehandle = TextureLoaderParameters.OpenGLDefaultTexture;
throw new ArgumentException( "ERROR: Exception caught when attempting to load file " + filename + ".\n" + e + "\n" + GetDescriptionFromFile( filename ) );
// return; // failure
} finally
{
_RawDataFromFile = null; // clarity, not really needed
}
#endregion Try
}
#region Helpers
private static void ConvertDX9Header( ref byte[] input )
{
UInt32 offset = 0;
idString = GetString( ref input, offset );
offset += 4;
dwSize = GetUInt32( ref input, offset );
offset += 4;
dwFlags = GetUInt32( ref input, offset );
offset += 4;
dwHeight = GetUInt32( ref input, offset );
offset += 4;
dwWidth = GetUInt32( ref input, offset );
offset += 4;
dwPitchOrLinearSize = GetUInt32( ref input, offset );
offset += 4;
dwDepth = GetUInt32( ref input, offset );
offset += 4;
dwMipMapCount = GetUInt32( ref input, offset );
offset += 4;
#if READALL
dwReserved1 = new UInt32[11]; // reserved
#endif
offset += 4 * 11;
pfSize = GetUInt32( ref input, offset );
offset += 4;
pfFlags = GetUInt32( ref input, offset );
offset += 4;
pfFourCC = GetUInt32( ref input, offset );
offset += 4;
#if READALL
pfRGBBitCount = GetUInt32( ref input, offset );
offset += 4;
pfRBitMask = GetUInt32( ref input, offset );
offset += 4;
pfGBitMask = GetUInt32( ref input, offset );
offset += 4;
pfBBitMask = GetUInt32( ref input, offset );
offset += 4;
pfABitMask = GetUInt32( ref input, offset );
offset += 4;
#else
offset += 20;
#endif
dwCaps1 = GetUInt32( ref input, offset );
offset += 4;
dwCaps2 = GetUInt32( ref input, offset );
offset += 4;
#if READALL
dwReserved2 = new UInt32[3]; // offset is 4+112 here, + 12 = 4+124
#endif
offset += 4 * 3;
}
/// <summary> Returns true if the flag is set, false otherwise</summary>
private static bool CheckFlag( uint variable, uint flag )
{
return ( variable & flag ) > 0 ? true : false;
}
private static string GetString( ref byte[] input, uint offset )
{
return "" + (char) input[offset + 0] + (char) input[offset + 1] + (char) input[offset + 2] + (char) input[offset + 3];
}
private static uint GetUInt32( ref byte[] input, uint offset )
{
return (uint) ( ( ( input[offset + 3] * 256 + input[offset + 2] ) * 256 + input[offset + 1] ) * 256 + input[offset + 0] );
}
private static uint GetUInt24( ref byte[] input, uint offset )
{
return (uint) ( ( input[offset + 2] * 256 + input[offset + 1] ) * 256 + input[offset + 0] );
}
private static void GetBytesFromUInt24( ref byte[] input, uint offset, uint splitme )
{
input[offset + 0] = (byte) ( splitme & 0x000000ff );
input[offset + 1] = (byte) ( ( splitme & 0x0000ff00 ) >> 8 );
input[offset + 2] = (byte) ( ( splitme & 0x00ff0000 ) >> 16 );
return;
}
/// <summary>DXT5 Alpha block flipping, inspired by code from Evan Hart (nVidia SDK)</summary>
private static uint FlipUInt24( uint inputUInt24 )
{
byte[][] ThreeBits = new byte[2][];
for ( int i = 0 ; i < 2 ; i++ )
ThreeBits[i] = new byte[4];
// extract 3 bits each into the array
ThreeBits[0][0] = (byte) ( inputUInt24 & BitMask );
inputUInt24 >>= 3;
ThreeBits[0][1] = (byte) ( inputUInt24 & BitMask );
inputUInt24 >>= 3;
ThreeBits[0][2] = (byte) ( inputUInt24 & BitMask );
inputUInt24 >>= 3;
ThreeBits[0][3] = (byte) ( inputUInt24 & BitMask );
inputUInt24 >>= 3;
ThreeBits[1][0] = (byte) ( inputUInt24 & BitMask );
inputUInt24 >>= 3;
ThreeBits[1][1] = (byte) ( inputUInt24 & BitMask );
inputUInt24 >>= 3;
ThreeBits[1][2] = (byte) ( inputUInt24 & BitMask );
inputUInt24 >>= 3;
ThreeBits[1][3] = (byte) ( inputUInt24 & BitMask );
// stuff 8x 3bits into 3 bytes
uint Result = 0;
Result = Result | (uint) ( ThreeBits[1][0] << 0 );
Result = Result | (uint) ( ThreeBits[1][1] << 3 );
Result = Result | (uint) ( ThreeBits[1][2] << 6 );
Result = Result | (uint) ( ThreeBits[1][3] << 9 );
Result = Result | (uint) ( ThreeBits[0][0] << 12 );
Result = Result | (uint) ( ThreeBits[0][1] << 15 );
Result = Result | (uint) ( ThreeBits[0][2] << 18 );
Result = Result | (uint) ( ThreeBits[0][3] << 21 );
return Result;
}
#endregion Helpers
#region String Representations
private static string GetDescriptionFromFile( string filename )
{
return "\n--> Header of " + filename +
"\nID: " + idString +
"\nSize: " + dwSize +
"\nFlags: " + dwFlags + " (" + (eDDSD) dwFlags + ")" +
"\nHeight: " + dwHeight +
"\nWidth: " + dwWidth +
"\nPitch: " + dwPitchOrLinearSize +
"\nDepth: " + dwDepth +
"\nMipMaps: " + dwMipMapCount +
"\n\n---PixelFormat---" + filename +
"\nSize: " + pfSize +
"\nFlags: " + pfFlags + " (" + (eDDPF) pfFlags + ")" +
"\nFourCC: " + pfFourCC + " (" + (eFOURCC) pfFourCC + ")" +
#if READALL
"\nBitcount: " + pfRGBBitCount +
"\nBitMask Red: " + pfRBitMask +
"\nBitMask Green: " + pfGBitMask +
"\nBitMask Blue: " + pfBBitMask +
"\nBitMask Alpha: " + pfABitMask +
#endif
"\n\n---Capabilities---" + filename +
"\nCaps1: " + dwCaps1 + " (" + (eDDSCAPS) dwCaps1 + ")" +
"\nCaps2: " + dwCaps2 + " (" + (eDDSCAPS2) dwCaps2 + ")";
}
private static string GetDescriptionFromMemory( string filename, TextureTarget Dimension )
{
return "\nFile: " + filename +
"\nDimension: " + Dimension +
"\nSize: " + _Width + " * " + _Height + " * " + _Depth +
"\nCompressed: " + _IsCompressed +
"\nBytes for Main Image: " + _BytesForMainSurface +
"\nMipMaps: " + _MipMapCount;
}
#endregion String Representations
}
}

@ -0,0 +1,50 @@
#region --- License ---
/* Licensed under the MIT/X11 license.
* Copyright (c) 2006-2008 the OpenTK Team.
* This notice may not be removed from any source distribution.
* See license.txt for licensing details.
*/
#endregion
using System;
using OpenTK.Graphics.OpenGL;
namespace SCJMapper_V2.TextureLoaders
{
/// <summary>The parameters in this class have only effect on the following Texture loads.</summary>
public static class TextureLoaderParameters
{
/// <summary>(Debug Aid, should be set to false) If set to false only Errors will be printed. If set to true, debug information (Warnings and Queries) will be printed in addition to Errors.</summary>
public static bool Verbose = false;
/// <summary>Always-valid fallback parameter for GL.BindTexture (Default: 0). This number will be returned if loading the Texture failed. You can set this to a checkerboard texture or similar, which you have already loaded.</summary>
public static uint OpenGLDefaultTexture = 0;
/// <summary>Compressed formats must have a border of 0, so this is constant.</summary>
public const int Border = 0;
/// <summary>false==DirectX TexCoords, true==OpenGL TexCoords (Default: true)</summary>
public static bool FlipImages = true;
/// <summary>When enabled, will use Glu to create MipMaps for images loaded with GDI+ (Default: false)</summary>
public static bool BuildMipmapsForUncompressed = false;
/// <summary>Selects the Magnification filter for following Textures to be loaded. (Default: Nearest)</summary>
public static TextureMagFilter MagnificationFilter = TextureMagFilter.Nearest;
/// <summary>Selects the Minification filter for following Textures to be loaded. (Default: Nearest)</summary>
public static TextureMinFilter MinificationFilter = TextureMinFilter.Nearest;
/// <summary>Selects the S Wrapping for following Textures to be loaded. (Default: Repeat)</summary>
public static TextureWrapMode WrapModeS = TextureWrapMode.Repeat;
/// <summary>Selects the T Wrapping for following Textures to be loaded. (Default: Repeat)</summary>
public static TextureWrapMode WrapModeT = TextureWrapMode.Repeat;
/// <summary>Selects the Texture Environment Mode for the following Textures to be loaded. Default: Modulate)</summary>
public static TextureEnvMode EnvMode = TextureEnvMode.Modulate;
}
}

@ -0,0 +1,89 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OpenTK;
namespace SCJMapper_V2
{
/// <summary>
/// 4th order Runge-Kutta integrator
/// </summary>
public class RK4Integrator
{
private StateModel m_currState;
private const double _6th = 1.0/6.0;
public struct StateModel
{
public Vector3d a; // position
public Vector3d v; // velocity
};
private struct Derivative
{
public Vector3d da; // derivative of position: velocity
public Vector3d dv; // derivative of velocity: acceleration
};
// ctor
public RK4Integrator( )
{
m_currState.a = Vector3d.Zero;
m_currState.v = Vector3d.Zero;
}
public StateModel State
{
get { return m_currState; }
set { m_currState = value; }
}
public Vector3d Position
{
get { return m_currState.a; }
set { m_currState.a = value; }
}
public Vector3d Velocity
{
get { return m_currState.v; }
set { m_currState.v = value; }
}
private Vector3d Acceleration( StateModel state, double dampK, double dampB )
{
return (-dampK * state.a) - (dampB * state.v);
}
private Derivative Evaluate( StateModel initial, double dt, Derivative d, double dampK, double dampB )
{
StateModel state;
state.a = initial.a + (d.da * dt);
state.v = initial.v + (d.dv * dt);
Derivative output = new Derivative( );
output.da = state.v;
output.dv = Acceleration( state, dampK, dampB );
return output;
}
public Vector3d Integrate( double dt, double dampK, double dampB )
{
Derivative a = Evaluate( m_currState, 0.0, new Derivative( ), dampK, dampB );
Derivative b = Evaluate( m_currState, dt * 0.5, a, dampK, dampB );
Derivative c = Evaluate( m_currState, dt * 0.5, b, dampK, dampB );
Derivative d = Evaluate( m_currState, dt, c, dampK, dampB );
Vector3d dadt = _6th * ( a.da + (2.0 * ( b.da + c.da )) + d.da );
Vector3d dvdt = _6th * ( a.dv + (2.0 * ( b.dv + c.dv )) + d.dv );
m_currState.a += (dadt * dt);
m_currState.v += (dvdt * dt);
return ( dvdt * dt );
}
}
}

@ -0,0 +1,196 @@
using System;
using System.Collections.Generic;
using System.Text;
using OpenTK;
namespace SCJMapper_V2.Shapes
{
public sealed class SlicedSphere: DrawableShape
{
public enum eSubdivisions
{
Zero = 0,
One = 1,
Two = 2,
Three = 3,
Four = 4,
Five=5,
Six=6,
Seven=7,
Eight=8,
}
public enum eDir
{
All,
FrontTopRight,
FrontBottomRight,
FrontBottomLeft,
FrontTopLeft,
BackTopRight,
BackBottomRight,
BackBottomLeft,
BackTopLeft,
}
public SlicedSphere( double radius, Vector3d offset, eSubdivisions subdivs, eDir[] sides, bool useDL )
: base( useDL )
{
double Diameter = radius;
PrimitiveMode = OpenTK.Graphics.OpenGL.PrimitiveType.Triangles;
if ( sides[0] == eDir.All )
{
sides = new eDir[] { eDir.FrontTopRight,
eDir.FrontBottomRight,
eDir.FrontBottomLeft,
eDir.FrontTopLeft,
eDir.BackTopRight,
eDir.BackBottomRight,
eDir.BackBottomLeft,
eDir.BackTopLeft,};
}
VertexArray = new VertexT2dN3dV3d[sides.Length * 3];
IndexArray = new uint[sides.Length * 3];
uint counter = 0;
foreach ( eDir s in sides )
{
GetDefaultVertices( s, Diameter, out VertexArray[counter + 0], out VertexArray[counter + 1], out VertexArray[counter + 2] );
IndexArray[counter + 0] = counter + 0;
IndexArray[counter + 1] = counter + 1;
IndexArray[counter + 2] = counter + 2;
counter += 3;
}
if ( subdivs != eSubdivisions.Zero )
{
for ( int s = 0; s < (int)subdivs; s++ )
{
#region Assemble Chunks and convert to Arrays
List<Chunk> AllChunks = new List<Chunk>();
for ( uint i = 0; i < IndexArray.Length; i += 3 )
{
Chunk chu;
Subdivide( Diameter,
ref VertexArray[IndexArray[i + 0]],
ref VertexArray[IndexArray[i + 1]],
ref VertexArray[IndexArray[i + 2]],
out chu );
AllChunks.Add( chu );
}
Chunk.GetArray( ref AllChunks, out VertexArray, out IndexArray );
AllChunks.Clear();
#endregion Assemble Chunks and convert to Arrays
}
}
for (int i=0; i<VertexArray.Length;i++)
{
Vector3d.Add(ref VertexArray[i].Position, ref offset, out VertexArray[i].Position);
}
}
private void GetDefaultVertices( eDir s, double scale, out VertexT2dN3dV3d first, out VertexT2dN3dV3d second, out VertexT2dN3dV3d third )
{
VertexT2dN3dV3d t1 = new VertexT2dN3dV3d(),
t2 = new VertexT2dN3dV3d(),
t3 = new VertexT2dN3dV3d();
switch ( s )
{
case eDir.FrontTopRight:
t1 = new VertexT2dN3dV3d( new Vector2d( 0.5, 1.0 ), Vector3d.UnitY, Vector3d.UnitY * scale );
t2 = new VertexT2dN3dV3d( new Vector2d( 0.0, 0.0 ), Vector3d.UnitZ, Vector3d.UnitZ * scale );
t3 = new VertexT2dN3dV3d( new Vector2d( 0.5, 0.0 ), Vector3d.UnitX, Vector3d.UnitX * scale );
break;
case eDir.FrontBottomRight:
t1 = new VertexT2dN3dV3d( new Vector2d( 0.5, 0.0 ), Vector3d.UnitX, Vector3d.UnitX * scale );
t2 = new VertexT2dN3dV3d( new Vector2d( 0.0, 0.0 ), Vector3d.UnitZ, Vector3d.UnitZ * scale );
t3 = new VertexT2dN3dV3d( new Vector2d( 0.5, 1.0 ), -Vector3d.UnitY, -Vector3d.UnitY * scale );
break;
case eDir.FrontBottomLeft:
t1 = new VertexT2dN3dV3d( new Vector2d( 0.5, 0.0 ), Vector3d.UnitX, Vector3d.UnitX * scale );
t2 = new VertexT2dN3dV3d( new Vector2d( 0.5, 1.0 ), -Vector3d.UnitY, -Vector3d.UnitY * scale );
t3 = new VertexT2dN3dV3d( new Vector2d( 1.0, 0.0 ), -Vector3d.UnitZ, -Vector3d.UnitZ * scale );
break;
case eDir.FrontTopLeft:
t1 = new VertexT2dN3dV3d( new Vector2d( 1.0, 0.0 ), -Vector3d.UnitZ, -Vector3d.UnitZ * scale );
t2 = new VertexT2dN3dV3d( new Vector2d( 0.5, 1.0 ), Vector3d.UnitY, Vector3d.UnitY * scale );
t3 = new VertexT2dN3dV3d( new Vector2d( 0.5, 0.0 ), Vector3d.UnitX, Vector3d.UnitX * scale );
break;
case eDir.BackTopRight:
t1 = new VertexT2dN3dV3d( new Vector2d( 0.5, 1.0 ), Vector3d.UnitY, Vector3d.UnitY * scale );
t2 = new VertexT2dN3dV3d( new Vector2d( 0.0, 1.0 ), -Vector3d.UnitX, -Vector3d.UnitX * scale );
t3 = new VertexT2dN3dV3d( new Vector2d( 0.0, 0.0 ), Vector3d.UnitZ, Vector3d.UnitZ * scale );
break;
case eDir.BackBottomRight:
t1 = new VertexT2dN3dV3d( new Vector2d( 0.5, 1.0 ), -Vector3d.UnitY, -Vector3d.UnitY * scale );
t2 = new VertexT2dN3dV3d( new Vector2d( 0.0, 0.0 ), Vector3d.UnitZ, Vector3d.UnitZ * scale );
t3 = new VertexT2dN3dV3d( new Vector2d( 0.0, 1.0 ), -Vector3d.UnitX, -Vector3d.UnitX * scale );
break;
case eDir.BackBottomLeft:
t1 = new VertexT2dN3dV3d( new Vector2d( 0.5, 1.0 ), -Vector3d.UnitY, -Vector3d.UnitY * scale );
t2 = new VertexT2dN3dV3d( new Vector2d( 1.0, 1.0 ), -Vector3d.UnitX, -Vector3d.UnitX * scale );
t3 = new VertexT2dN3dV3d( new Vector2d( 1.0, 0.0 ), -Vector3d.UnitZ, -Vector3d.UnitZ * scale );
break;
case eDir.BackTopLeft:
t1 = new VertexT2dN3dV3d( new Vector2d( 0.5, 1.0 ), Vector3d.UnitY, Vector3d.UnitY * scale );
t2 = new VertexT2dN3dV3d( new Vector2d( 1.0, 0.0 ), -Vector3d.UnitZ, -Vector3d.UnitZ * scale );
t3 = new VertexT2dN3dV3d( new Vector2d( 1.0, 1.0 ), -Vector3d.UnitX, -Vector3d.UnitX * scale );
break;
}
first = t1;
second = t2;
third = t3;
}
private void Subdivide( double Scale, ref VertexT2dN3dV3d first, ref VertexT2dN3dV3d second, ref VertexT2dN3dV3d third, out Chunk c )
{
c = new Chunk(6, 12);
c.Vertices[0] = first;
Vector3d.Lerp(ref first.Position, ref second.Position, 0.5,out c.Vertices[1].Normal );
c.Vertices[1].Normal.Normalize();
c.Vertices[1].Position = c.Vertices[1].Normal * Scale;
Vector2d.Lerp( ref first.TexCoord, ref second.TexCoord, 0.5, out c.Vertices[1].TexCoord );
Vector3d.Lerp( ref third.Position, ref first.Position, 0.5, out c.Vertices[2].Normal );
c.Vertices[2].Normal.Normalize();
c.Vertices[2].Position = c.Vertices[2].Normal * Scale;
Vector2d.Lerp( ref third.TexCoord, ref first.TexCoord, 0.5, out c.Vertices[2].TexCoord );
c.Vertices[3] = second;
Vector3d.Lerp( ref second.Position, ref third.Position, 0.5, out c.Vertices[4].Normal );
c.Vertices[4].Normal.Normalize();
c.Vertices[4].Position = c.Vertices[4].Normal * Scale;
Vector2d.Lerp( ref second.TexCoord, ref third.TexCoord, 0.5, out c.Vertices[4].TexCoord );
c.Vertices[5] = third;
#region Indices
c.Indices[0]=0;
c.Indices[1]=1;
c.Indices[2]=2;
c.Indices[3]=2;
c.Indices[4]=1;
c.Indices[5]=4;
c.Indices[6]=1;
c.Indices[7]=3;
c.Indices[8]=4;
c.Indices[9]=2;
c.Indices[10]=4;
c.Indices[11]=5;
#endregion Indices
}
}
}

@ -0,0 +1,214 @@
//
// Author: Ryan Seghers
//
// Copyright (C) 2013-2014 Ryan Seghers
//
// 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 irrevocable, perpetual, worldwide, and royalty-free
// rights to use, copy, modify, merge, publish, distribute, sublicense,
// display, perform, create derivative works from and/or sell copies of
// the Software, both in source and object code form, 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.Diagnostics;
using System.Text;
namespace SCJMapper_V2
{
/// <summary>
/// A tri-diagonal matrix has non-zero entries only on the main diagonal, the diagonal above the main (super), and the
/// diagonal below the main (sub).
/// </summary>
/// <remarks>
/// <para>
/// This is based on the wikipedia article: http://en.wikipedia.org/wiki/Tridiagonal_matrix_algorithm
/// </para>
/// <para>
/// The entries in the matrix on a particular row are A[i], B[i], and C[i] where i is the row index.
/// B is the main diagonal, and so for an NxN matrix B is length N and all elements are used.
/// So for row 0, the first two values are B[0] and C[0].
/// And for row N-1, the last two values are A[N-1] and B[N-1].
/// That means that A[0] is not actually on the matrix and is therefore never used, and same with C[N-1].
/// </para>
/// </remarks>
public class TriDiagonalMatrixF
{
/// <summary>
/// The values for the sub-diagonal. A[0] is never used.
/// </summary>
public float[] A;
/// <summary>
/// The values for the main diagonal.
/// </summary>
public float[] B;
/// <summary>
/// The values for the super-diagonal. C[C.Length-1] is never used.
/// </summary>
public float[] C;
/// <summary>
/// The width and height of this matrix.
/// </summary>
public int N
{
get { return (A != null ? A.Length : 0); }
}
/// <summary>
/// Indexer. Setter throws an exception if you try to set any not on the super, main, or sub diagonals.
/// </summary>
public float this[int row, int col]
{
get
{
int di = row - col;
if (di == 0)
{
return B[row];
}
else if (di == -1)
{
Debug.Assert(row < N - 1);
return C[row];
}
else if (di == 1)
{
Debug.Assert(row > 0);
return A[row];
}
else return 0;
}
set
{
int di = row - col;
if (di == 0)
{
B[row] = value;
}
else if (di == -1)
{
Debug.Assert(row < N - 1);
C[row] = value;
}
else if (di == 1)
{
Debug.Assert(row > 0);
A[row] = value;
}
else
{
throw new ArgumentException("Only the main, super, and sub diagonals can be set.");
}
}
}
/// <summary>
/// Construct an NxN matrix.
/// </summary>
public TriDiagonalMatrixF(int n)
{
this.A = new float[n];
this.B = new float[n];
this.C = new float[n];
}
/// <summary>
/// Produce a string representation of the contents of this matrix.
/// </summary>
/// <param name="fmt">Optional. For String.Format. Must include the colon. Examples are ':0.000' and ',5:0.00' </param>
/// <param name="prefix">Optional. Per-line indentation prefix.</param>
public string ToDisplayString(string fmt = "", string prefix = "")
{
if (this.N > 0)
{
var s = new StringBuilder();
string formatString = "{0" + fmt + "}";
for (int r = 0; r < N; r++)
{
s.Append(prefix);
for (int c = 0; c < N; c++)
{
s.AppendFormat(formatString, this[r, c]);
if (c < N - 1) s.Append(", ");
}
s.AppendLine();
}
return s.ToString();
}
else
{
return prefix + "0x0 Matrix";
}
}
/// <summary>
/// Solve the system of equations this*x=d given the specified d.
/// </summary>
/// <remarks>
/// Uses the Thomas algorithm described in the wikipedia article: http://en.wikipedia.org/wiki/Tridiagonal_matrix_algorithm
/// Not optimized. Not destructive.
/// </remarks>
/// <param name="d">Right side of the equation.</param>
public float[] Solve(float[] d)
{
int n = this.N;
if (d.Length != n)
{
throw new ArgumentException("The input d is not the same size as this matrix.");
}
// cPrime
float[] cPrime = new float[n];
cPrime[0] = C[0] / B[0];
for (int i = 1; i < n; i++)
{
cPrime[i] = C[i] / (B[i] - cPrime[i-1] * A[i]);
}
// dPrime
float[] dPrime = new float[n];
dPrime[0] = d[0] / B[0];
for (int i = 1; i < n; i++)
{
dPrime[i] = (d[i] - dPrime[i-1]*A[i]) / (B[i] - cPrime[i - 1] * A[i]);
}
// Back substitution
float[] x = new float[n];
x[n - 1] = dPrime[n - 1];
for (int i = n-2; i >= 0; i--)
{
x[i] = dPrime[i] - cPrime[i] * x[i + 1];
}
return x;
}
}
}

@ -0,0 +1,36 @@
using System;
using OpenTK;
namespace SCJMapper_V2.Shapes
{
public struct VertexT2dN3dV3d
{
public Vector2d TexCoord;
public Vector3d Normal;
public Vector3d Position;
public VertexT2dN3dV3d( Vector2d texcoord, Vector3d normal, Vector3d position )
{
TexCoord = texcoord;
Normal = normal;
Position = position;
}
}
public struct VertexT2fN3fV3f
{
public Vector2 TexCoord;
public Vector3 Normal;
public Vector3 Position;
}
public struct VertexT2hN3hV3h
{
public Vector2h TexCoord;
public Vector3h Normal;
public Vector3h Position;
}
}

@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion( "2.6.0.26" )]
[assembly: AssemblyFileVersion( "2.6.0.26" )]
[assembly: AssemblyVersion( "2.7.0.32" )]
[assembly: AssemblyFileVersion( "2.7.0.32" )]

@ -60,6 +60,26 @@ namespace SCJMapper_V2.Properties {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap _300i1 {
get {
object obj = ResourceManager.GetObject("300i1", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap aurora {
get {
object obj = ResourceManager.GetObject("aurora", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
@ -83,15 +103,35 @@ namespace SCJMapper_V2.Properties {
/// &lt;action name=&quot;v_attack1_group2&quot; /&gt;
/// &lt;action name=&quot;v_attack1_group3&quot; /&gt;
/// &lt;/actiongroup&gt;
///
/// &lt;actionmap name=&quot;debug&quot; version=&quot;22&quot;&gt;
/// &lt;!-- debug keys - move to debug when we can switch devmode--&gt;
/// &lt;action name=&quot;flymode&quot; onPres [rest of string was truncated]&quot;;.
///
/// &lt;CustomisationUIHeader&gt;
/// &lt;keyboard label=&quot;Default&quot; description=&quot;@ui_KeyboardDefaultDesc&quot; image=&quot;KeyboardDefault&quot; /&gt;
/// &lt;xboxpad labe [rest of string was truncated]&quot;;.
/// </summary>
internal static string defaultProfile {
get {
return ResourceManager.GetString("defaultProfile", resourceCulture);
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap hornet {
get {
object obj = ResourceManager.GetObject("hornet", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap YPR {
get {
object obj = ResourceManager.GetObject("YPR", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
}
}

@ -118,10 +118,22 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="Cassini_Logo2_s" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\graphics\Cassini_Logo2_s.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
<data name="hornet" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\graphics\hornet.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="defaultProfile" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\defaultprofile.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
</data>
<data name="300i1" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\graphics\300i.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Cassini_Logo2_s" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\graphics\Cassini_Logo2_s.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="YPR" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\graphics\YPR.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="aurora" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\graphics\aurora.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

@ -26,8 +26,8 @@
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>26</ApplicationRevision>
<ApplicationVersion>2.6.0.%2a</ApplicationVersion>
<ApplicationRevision>32</ApplicationRevision>
<ApplicationVersion>2.7.0.%2a</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
@ -84,6 +84,12 @@
<Reference Include="log4net">
<HintPath>packages\log4net.2.0.3\lib\net40-full\log4net.dll</HintPath>
</Reference>
<Reference Include="OpenTK">
<HintPath>packages\OpenTK.1.1.1589.5942\lib\NET40\OpenTK.dll</HintPath>
</Reference>
<Reference Include="OpenTK.GLControl">
<HintPath>packages\OpenTK.GLControl.1.1.1589.5942\lib\NET40\OpenTK.GLControl.dll</HintPath>
</Reference>
<Reference Include="SharpDX">
<HintPath>$(SharpDXPackageBinDir)\SharpDX.dll</HintPath>
</Reference>
@ -93,6 +99,7 @@
<Reference Include="System" />
<Reference Include="System.configuration" />
<Reference Include="System.Core" />
<Reference Include="System.Windows.Forms.DataVisualization" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
@ -105,6 +112,17 @@
<ItemGroup>
<Compile Include="appConfiguration.cs" />
<Compile Include="AppSettings.cs" />
<Compile Include="OGL\BezierSeries.cs" />
<Compile Include="OGL\CalcBezierCurve.cs" />
<Compile Include="Joystick\JoystickTuningParameter.cs" />
<Compile Include="OGL\CubicSpline.cs" />
<Compile Include="OGL\LoaderStatics.cs" />
<Compile Include="OGL\FormJSCalCurve.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="OGL\FormJSCalCurve.Designer.cs">
<DependentUpon>FormJSCalCurve.cs</DependentUpon>
</Compile>
<Compile Include="Joystick\Deviceoptions.cs" />
<Compile Include="Form1.cs">
<SubType>Form</SubType>
@ -139,15 +157,23 @@
<DependentUpon>UC_JoyPanel.cs</DependentUpon>
</Compile>
<Compile Include="Joystick\Options.cs" />
<Compile Include="OGL\LoaderDDS.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="OGL\RK4Integrator.cs" />
<Compile Include="SC\SCDefaultProfile.cs" />
<Compile Include="SC\SCMappings.cs" />
<Compile Include="SC\SCPath.cs" />
<Compile Include="TheUser.cs" />
<Compile Include="Joystick\UICustHeader.cs" />
<Compile Include="OGL\TriDiagonalMatrix.cs" />
<Compile Include="Joystick\xyPoints.cs" />
<EmbeddedResource Include="Form1.resx">
<DependentUpon>Form1.cs</DependentUpon>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="OGL\FormJSCalCurve.resx">
<DependentUpon>FormJSCalCurve.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Joystick\FormReassign.resx">
<DependentUpon>FormReassign.cs</DependentUpon>
@ -169,6 +195,24 @@
<DesignTime>True</DesignTime>
</Compile>
<None Include="app.config" />
<None Include="graphics\SB_BigSight.dds">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="graphics\SB_Canyon.dds">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="graphics\SB_Highway.dds">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="graphics\SB_OutThere1.dds">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="graphics\SB_Shiodome.dds">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="graphics\Skybox.dds">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="log4net.config">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
@ -186,13 +230,20 @@
<ItemGroup>
<Content Include="Cassini_Logo_Icon.ico" />
<Content Include="defaultProfile.xml" />
<None Include="graphics\YPR.png" />
<None Include="graphics\300i.jpg" />
<None Include="graphics\aurora.jpg" />
<Content Include="graphics\Cassini_Logo2_s.jpg" />
<Content Include="graphics\Cassini_Logo_Icon.ico" />
<None Include="graphics\hornet.jpg" />
<Content Include="graphics\invalid.png" />
<Content Include="graphics\Joystick.ico" />
<Content Include="graphics\keyboard_key.ico" />
<Content Include="graphics\map.png" />
<Content Include="graphics\PS3.ico" />
<Content Include="graphics\Readme.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="graphics\selected.png" />
<Content Include="graphics\XBOX.ico" />
</ItemGroup>

@ -14,7 +14,7 @@
<!-- This is the minimal change that detects a movement of an axis
default is 150 - you may change it to get the detection less sensitive -->
<AppConfiguration jsSenseLimit="150"
scAcionmaps="multiplayer,
scActionmaps="multiplayer,
singleplayer,
player,
flycam,

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

@ -0,0 +1,3 @@
http://www.hdrlabs.com/sibl/archive.html
sIBL Archive - Free HDRI sets for smart Image-Based Lighting

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

@ -2,6 +2,8 @@
<packages>
<package id="DotNetZip.Reduced" version="1.9.1.8" targetFramework="net40" />
<package id="log4net" version="2.0.3" targetFramework="net40" />
<package id="OpenTK" version="1.1.1589.5942" targetFramework="net40" />
<package id="OpenTK.GLControl" version="1.1.1589.5942" targetFramework="net40" />
<package id="SharpDX" version="2.6.2" targetFramework="net20" />
<package id="SharpDX.DirectInput" version="2.6.2" targetFramework="net40" />
</packages>

@ -0,0 +1,25 @@
<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="opengl32.dll" target="/System/Library/Frameworks/OpenGL.framework/OpenGL"/>
<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="libGLESv1_CM.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"/>
<!-- XQuartz compatibility (X11 on Mac) -->
<dllmap os="osx" dll="libGL.so.1" target="/usr/X11/lib/libGL.dylib"/>
<dllmap os="osx" dll="libX11" target="/usr/X11/lib/libX11.dylib"/>
<dllmap os="osx" dll="libXcursor.so.1" target="/usr/X11/lib/libXcursor.dylib"/>
<dllmap os="osx" dll="libXi" target="/usr/X11/lib/libXi.dylib"/>
<dllmap os="osx" dll="libXinerama" target="/usr/X11/lib/libXinerama.dylib"/>
<dllmap os="osx" dll="libXrandr.so.2" target="/usr/X11/lib/libXrandr.dylib"/>
</configuration>

File diff suppressed because it is too large Load Diff

@ -0,0 +1,191 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>OpenTK.GLControl</name>
</assembly>
<members>
<member name="T:OpenTK.GLControl">
<summary>
OpenGL-aware WinForms control.
The WinForms designer will always call the default constructor.
Inherit from this class and call one of its specialized constructors
to enable antialiasing or custom <see cref="P:OpenTK.GLControl.GraphicsMode"/>s.
</summary>
</member>
<member name="F:OpenTK.GLControl.components">
<summary>
Required designer variable.
</summary>
</member>
<member name="M:OpenTK.GLControl.Dispose(System.Boolean)">
<summary>
Clean up any resources being used.
</summary>
<param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
</member>
<member name="M:OpenTK.GLControl.InitializeComponent">
<summary>
Required method for Designer support - do not modify
the contents of this method with the code editor.
</summary>
</member>
<member name="M:OpenTK.GLControl.#ctor">
<summary>
Constructs a new instance.
</summary>
</member>
<member name="M:OpenTK.GLControl.#ctor(OpenTK.Graphics.GraphicsMode)">
<summary>
Constructs a new instance with the specified GraphicsMode.
</summary>
<param name="mode">The OpenTK.Graphics.GraphicsMode of the control.</param>
</member>
<member name="M:OpenTK.GLControl.#ctor(OpenTK.Graphics.GraphicsMode,System.Int32,System.Int32,OpenTK.Graphics.GraphicsContextFlags)">
<summary>
Constructs a new instance with the specified GraphicsMode.
</summary>
<param name="mode">The OpenTK.Graphics.GraphicsMode of the control.</param>
<param name="major">The major version for the OpenGL GraphicsContext.</param>
<param name="minor">The minor version for the OpenGL GraphicsContext.</param>
<param name="flags">The GraphicsContextFlags for the OpenGL GraphicsContext.</param>
</member>
<member name="M:OpenTK.GLControl.OnHandleCreated(System.EventArgs)">
<summary>Raises the HandleCreated event.</summary>
<param name="e">Not used.</param>
</member>
<member name="M:OpenTK.GLControl.OnHandleDestroyed(System.EventArgs)">
<summary>Raises the HandleDestroyed event.</summary>
<param name="e">Not used.</param>
</member>
<member name="M:OpenTK.GLControl.OnPaint(System.Windows.Forms.PaintEventArgs)">
<summary>
Raises the System.Windows.Forms.Control.Paint event.
</summary>
<param name="e">A System.Windows.Forms.PaintEventArgs that contains the event data.</param>
</member>
<member name="M:OpenTK.GLControl.OnResize(System.EventArgs)">
<summary>
Raises the Resize event.
Note: this method may be called before the OpenGL context is ready.
Check that IsHandleCreated is true before using any OpenGL methods.
</summary>
<param name="e">A System.EventArgs that contains the event data.</param>
</member>
<member name="M:OpenTK.GLControl.PerformContextUpdate">
<summary>
Execute the delayed context update
</summary>
</member>
<member name="M:OpenTK.GLControl.OnParentChanged(System.EventArgs)">
<summary>
Raises the ParentChanged event.
</summary>
<param name="e">A System.EventArgs that contains the event data.</param>
</member>
<member name="M:OpenTK.GLControl.SwapBuffers">
<summary>
Swaps the front and back buffers, presenting the rendered scene to the screen.
This method will have no effect on a single-buffered <c>GraphicsMode</c>.
</summary>
</member>
<member name="M:OpenTK.GLControl.MakeCurrent">
<summary>
<para>
Makes <see cref="P:OpenTK.GLControl.Context"/> current in the calling thread.
All OpenGL commands issued are hereafter interpreted by this context.
</para>
<para>
When using multiple <c>GLControl</c>s, calling <c>MakeCurrent</c> on
one control will make all other controls non-current in the calling thread.
</para>
<seealso cref="P:OpenTK.GLControl.Context"/>
<para>
A <c>GLControl</c> can only be current in one thread at a time.
To make a control non-current, call <c>GLControl.Context.MakeCurrent(null)</c>.
</para>
</summary>
</member>
<member name="M:OpenTK.GLControl.GrabScreenshot">
<summary>
Grabs a screenshot of the frontbuffer contents.
When using multiple <c>GLControl</c>s, ensure that <see cref="P:OpenTK.GLControl.Context"/>
is current before accessing this property.
<seealso cref="P:OpenTK.GLControl.Context"/>
<seealso cref="M:OpenTK.GLControl.MakeCurrent"/>
</summary>
<returns>A System.Drawing.Bitmap, containing the contents of the frontbuffer.</returns>
<exception cref="T:OpenTK.Graphics.GraphicsContextException">
Occurs when no OpenTK.Graphics.GraphicsContext is current in the calling thread.
</exception>
</member>
<member name="P:OpenTK.GLControl.CreateParams">
<summary>
Gets the <c>CreateParams</c> instance for this <c>GLControl</c>
</summary>
</member>
<member name="P:OpenTK.GLControl.IsIdle">
<summary>
Gets a value indicating whether the current thread contains pending system messages.
</summary>
</member>
<member name="P:OpenTK.GLControl.Context">
<summary>
Gets the <c>IGraphicsContext</c> instance that is associated with the <c>GLControl</c>.
The associated <c>IGraphicsContext</c> is updated whenever the <c>GLControl</c>
handle is created or recreated.
When using multiple <c>GLControl</c>s, ensure that <c>Context</c>
is current before performing any OpenGL operations.
<seealso cref="M:OpenTK.GLControl.MakeCurrent"/>
</summary>
</member>
<member name="P:OpenTK.GLControl.AspectRatio">
<summary>
Gets the aspect ratio of this GLControl.
</summary>
</member>
<member name="P:OpenTK.GLControl.VSync">
<summary>
Gets or sets a value indicating whether vsync is active for this <c>GLControl</c>.
When using multiple <c>GLControl</c>s, ensure that <see cref="P:OpenTK.GLControl.Context"/>
is current before accessing this property.
<seealso cref="P:OpenTK.GLControl.Context"/>
<seealso cref="M:OpenTK.GLControl.MakeCurrent"/>
</summary>
</member>
<member name="P:OpenTK.GLControl.GraphicsMode">
<summary>
Gets the <c>GraphicsMode</c> of the <c>IGraphicsContext</c> associated with
this <c>GLControl</c>. If you wish to change <c>GraphicsMode</c>, you must
destroy and recreate the <c>GLControl</c>.
</summary>
</member>
<member name="P:OpenTK.GLControl.WindowInfo">
<summary>
Gets the <see cref="T:OpenTK.Platform.IWindowInfo"/> for this instance.
</summary>
</member>
<member name="T:OpenTK.GLControl.DelayUpdate">
<summary>
Needed to delay the invoke on OS X. Also needed because OpenTK is .NET 2, otherwise I'd use an inline Action.
</summary>
</member>
<member name="M:OpenTK.Platform.MacOS.Agl.aglChoosePixelFormat(System.IntPtr,System.Int32,System.Int32[])">
<summary>
Use this overload only with IntPtr.Zero for the first argument.
</summary>
<param name="gdevs">
</param>
<param name="ndev">
</param>
<param name="attribs">
</param>
<returns>
</returns>
</member>
<member name="T:OpenTK.Platform.MacOS.AglContext">
<summary>
AGL context implementation for WinForms compatibility.
</summary>
</member>
</members>
</doc>
Loading…
Cancel
Save