using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Tao.OpenGl;
using Tao.Platform.Windows;
namespace Core {
#region Class Documentation
///
/// Lesson 15: Adding Textures To Outline Fonts.
///
///
///
/// Original Author: Jeff Molofee (NeHe)
/// http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=15
///
///
/// C# Implementation: Randy Ridge
/// http://www.taoframework.com
///
///
#endregion Class Documentation
public sealed class SuperShape : Form {
static float m=1,n1=1,n2=1,n3=1;
// --- Fields ---
#region Private Static Fields
private static IntPtr hDC; // Private GDI Device Context
private static IntPtr hRC; // Permanent Rendering Context
private static Form form; // Our Current Windows Form
private static bool[] keys = new bool[256]; // Array Used For The Keyboard Routine
private static bool active = true; // Window Active Flag, Set To True By Default
private static bool fullscreen = true; // Fullscreen Flag, Set To Fullscreen Mode By Default
private static bool done = false; // Bool Variable To Exit Main Loop
private static int[] texture = new int[1]; // One Texture Map
private static int fontbase; // Base Display List For The Font Set
private static float rot=0,rotspeed=0; // Used To Rotate The Text
#endregion Private Static Fields
// --- Constructors & Destructors ---
#region SuperShape
///
/// Creates a new instance.
///
public SuperShape() {
this.CreateParams.ClassStyle = this.CreateParams.ClassStyle | // Redraw On Size, And Own DC For Window.
User.CS_HREDRAW | User.CS_VREDRAW | User.CS_OWNDC;
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); // No Need To Erase Form Background
this.SetStyle(ControlStyles.DoubleBuffer, true); // Buffer Control
this.SetStyle(ControlStyles.Opaque, true); // No Need To Draw Form Background
this.SetStyle(ControlStyles.ResizeRedraw, true); // Redraw On Resize
this.SetStyle(ControlStyles.UserPaint, true); // We'll Handle Painting Ourselves
this.Activated += new EventHandler(this.Form_Activated); // On Activate Event Call Form_Activated
this.Closing += new CancelEventHandler(this.Form_Closing); // On Closing Event Call Form_Closing
this.Deactivate += new EventHandler(this.Form_Deactivate); // On Deactivate Event Call Form_Deactivate
this.KeyDown += new KeyEventHandler(this.Form_KeyDown); // On KeyDown Event Call Form_KeyDown
this.KeyUp += new KeyEventHandler(this.Form_KeyUp); // On KeyUp Event Call Form_KeyUp
this.Resize += new EventHandler(this.Form_Resize); // On Resize Event Call Form_Resize
}
#endregion SuperShape
// --- Entry Point ---
#region Main(string[] commandLineArguments)
///
/// The application's entry point.
///
///
/// Any supplied command line arguments.
///
[STAThread]
public static void Main(string[] commandLineArguments) {
// Ask The User Which Screen Mode They Prefer
if(MessageBox.Show("Would You Like To Run In Fullscreen Mode?", "Start FullScreen?",
MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No) {
fullscreen = false; // Windowed Mode
}
// Create Our OpenGL Window
if(!CreateGLWindow("Paul Burkes super surfaces by Irrational Exuberance", 640, 480, 16, fullscreen)) {
return; // Quit If Window Was Not Created
}
while(!done) { // Loop That Runs While done = false
Application.DoEvents(); // Process Events
// Draw The Scene. Watch For ESC Key And Quit Messages From DrawGLScene()
if((active && (form != null) && !DrawGLScene()) || keys[(int) Keys.Escape]) { // Active? Was There A Quit Received?
done = true; // ESC Or DrawGLScene Signalled A Quit
}
else { // Not Time To Quit, Update Screen
Gdi.SwapBuffers(hDC); // Swap Buffers (float Buffering)
}
if(keys[(int) Keys.F1]) { // Is F1 Being Pressed?
keys[(int) Keys.F1] = false; // If So Make Key false
KillGLWindow(); // Kill Our Current Window
fullscreen = !fullscreen; // Toggle Fullscreen / Windowed Mode
// Recreate Our OpenGL Window
if(!CreateGLWindow("NeHe's Texturemapped Outline Font Tutorial", 640, 480, 16, fullscreen)) {
return; // Quit If Window Was Not Created
}
done = false; // We're Not Done Yet
}
const float fraction = 0.05f;
if (keys[(int)Keys.P]) m+=fraction;
if (keys[(int)Keys.M]) m-=fraction;
if (keys[(int)Keys.O]) n1+=fraction;
if (keys[(int)Keys.L]) n1-=fraction;
if (keys[(int)Keys.I]) n2+=fraction;
if (keys[(int)Keys.K]) n2-=fraction;
if (keys[(int)Keys.U]) n3+=fraction;
if (keys[(int)Keys.J]) n3-=fraction;
// keys[(int)Keys.J]=keys[(int)Keys.U]=
// keys[(int)Keys.K]=keys[(int)Keys.I]=
// keys[(int)Keys.L]=keys[(int)Keys.O]=
// keys[(int)Keys.M]=keys[(int)Keys.P]=false;
float rotadd=0.01f;
if(keys[(int) Keys.PageUp]) rotspeed+=rotadd;
if(keys[(int) Keys.PageDown]) rotspeed-=rotadd;
if(keys[(int) Keys.Home]) rotspeed=0f;
if(keys[(int) Keys.End]) m=n1=n2=n3=1.0f;
}
// Shutdown
KillGLWindow(); // Kill The Window
return; // Exit The Program
}
#endregion Main(string[] commandLineArguments)
// --- Private Static Methods ---
#region BuildFont()
///
/// Builds our bitmap font.
///
private static void BuildFont() {
Gdi.GLYPHMETRICSFLOAT[] gmf = new Gdi.GLYPHMETRICSFLOAT[256]; // Address Buffer For Font Storage
IntPtr font; // Windows Font ID
fontbase = Gl.glGenLists(256); // Storage For 256 Characters
font = Gdi.CreateFont( // Create The Font
-12, // Height Of Font
0, // Width Of Font
0, // Angle Of Escapement
0, // Orientation Angle
Gdi.FW_BOLD, // Font Weight
false, // Italic
false, // Underline
false, // Strikeout
Gdi.SYMBOL_CHARSET, // Character Set Identifier
Gdi.OUT_TT_PRECIS, // Output Precision
Gdi.CLIP_DEFAULT_PRECIS, // Clipping Precision
Gdi.ANTIALIASED_QUALITY, // Output Quality
Gdi.FF_DONTCARE | Gdi.DEFAULT_PITCH, // Family And Pitch
"Wingdings"); // Font Name
Gdi.SelectObject(hDC, font); // Selects The Font We Created
Wgl.wglUseFontOutlines(
hDC, // Select The Current DC
0, // Starting Character
255, // Number Of Display Lists To Build
fontbase, // Starting Display Lists
0.1f, // Deviation From The True Outlines
0.2f, // Font Thickness In The Z Direction
Wgl.WGL_FONT_POLYGONS, // Use Polygons, Not Lines
gmf); // Address Of Buffer To Recieve Data
}
#endregion BuildFont()
#region bool CreateGLWindow(string title, int width, int height, int bits, bool fullscreenflag)
///
/// Creates our OpenGL Window.
///
///
/// The title to appear at the top of the window.
///
///
/// The width of the GL window or fullscreen mode.
///
///
/// The height of the GL window or fullscreen mode.
///
///
/// The number of bits to use for color (8/16/24/32).
///
///
/// Use fullscreen mode (true) or windowed mode (false).
///
///
/// true on successful window creation, otherwise false.
///
private static bool CreateGLWindow(string title, int width, int height, int bits, bool fullscreenflag) {
int pixelFormat; // Holds The Results After Searching For A Match
fullscreen = fullscreenflag; // Set The Global Fullscreen Flag
form = null; // Null The Form
GC.Collect(); // Request A Collection
// This Forces A Swap
Kernel.SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle, -1, -1);
if(fullscreen) { // Attempt Fullscreen Mode?
Gdi.DEVMODE dmScreenSettings = new Gdi.DEVMODE(); // Device Mode
// Size Of The Devmode Structure
dmScreenSettings.dmSize = (short) Marshal.SizeOf(dmScreenSettings);
dmScreenSettings.dmPelsWidth = width; // Selected Screen Width
dmScreenSettings.dmPelsHeight = height; // Selected Screen Height
dmScreenSettings.dmBitsPerPel = bits; // Selected Bits Per Pixel
dmScreenSettings.dmFields = Gdi.DM_BITSPERPEL | Gdi.DM_PELSWIDTH | Gdi.DM_PELSHEIGHT;
// Try To Set Selected Mode And Get Results. NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar.
if(User.ChangeDisplaySettings(ref dmScreenSettings, User.CDS_FULLSCREEN) != User.DISP_CHANGE_SUCCESSFUL) {
// If The Mode Fails, Offer Two Options. Quit Or Use Windowed Mode.
if(MessageBox.Show("The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?", "NeHe GL",
MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.Yes) {
fullscreen = false; // Windowed Mode Selected. Fullscreen = false
}
else {
// Pop up A Message Box Lessing User Know The Program Is Closing.
MessageBox.Show("Program Will Now Close.", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Stop);
return false; // Return false
}
}
}
form = new SuperShape(); // Create The Window
if(fullscreen) { // Are We Still In Fullscreen Mode?
form.FormBorderStyle = FormBorderStyle.None; // No Border
Cursor.Hide(); // Hide Mouse Pointer
}
else { // If Windowed
form.FormBorderStyle = FormBorderStyle.Sizable; // Sizable
Cursor.Show(); // Show Mouse Pointer
}
form.Width = width; // Set Window Width
form.Height = height; // Set Window Height
form.Text = title; // Set Window Title
Gdi.PIXELFORMATDESCRIPTOR pfd = new Gdi.PIXELFORMATDESCRIPTOR(); // pfd Tells Windows How We Want Things To Be
pfd.nSize = (short) Marshal.SizeOf(pfd); // Size Of This Pixel Format Descriptor
pfd.nVersion = 1; // Version Number
pfd.dwFlags = Gdi.PFD_DRAW_TO_WINDOW | // Format Must Support Window
Gdi.PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
Gdi.PFD_DOUBLEBUFFER; // Format Must Support float Buffering
pfd.iPixelType = (byte) Gdi.PFD_TYPE_RGBA; // Request An RGBA Format
pfd.cColorBits = (byte) bits; // Select Our Color Depth
pfd.cRedBits = 0; // Color Bits Ignored
pfd.cRedShift = 0;
pfd.cGreenBits = 0;
pfd.cGreenShift = 0;
pfd.cBlueBits = 0;
pfd.cBlueShift = 0;
pfd.cAlphaBits = 0; // No Alpha Buffer
pfd.cAlphaShift = 0; // Shift Bit Ignored
pfd.cAccumBits = 0; // No Accumulation Buffer
pfd.cAccumRedBits = 0; // Accumulation Bits Ignored
pfd.cAccumGreenBits = 0;
pfd.cAccumBlueBits = 0;
pfd.cAccumAlphaBits = 0;
pfd.cDepthBits = 16; // 16Bit Z-Buffer (Depth Buffer)
pfd.cStencilBits = 0; // No Stencil Buffer
pfd.cAuxBuffers = 0; // No Auxiliary Buffer
pfd.iLayerType = (byte) Gdi.PFD_MAIN_PLANE; // Main Drawing Layer
pfd.bReserved = 0; // Reserved
pfd.dwLayerMask = 0; // Layer Masks Ignored
pfd.dwVisibleMask = 0;
pfd.dwDamageMask = 0;
hDC = User.GetDC(form.Handle); // Attempt To Get A Device Context
if(hDC == IntPtr.Zero) { // Did We Get A Device Context?
KillGLWindow(); // Reset The Display
MessageBox.Show("Can't Create A GL Device Context.", "ERROR",
MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
pixelFormat = Gdi.ChoosePixelFormat(hDC, ref pfd); // Attempt To Find An Appropriate Pixel Format
if(pixelFormat == 0) { // Did Windows Find A Matching Pixel Format?
KillGLWindow(); // Reset The Display
MessageBox.Show("Can't Find A Suitable PixelFormat.", "ERROR",
MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
if(!Gdi.SetPixelFormat(hDC, pixelFormat, ref pfd)) { // Are We Able To Set The Pixel Format?
KillGLWindow(); // Reset The Display
MessageBox.Show("Can't Set The PixelFormat.", "ERROR",
MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
hRC = Wgl.wglCreateContext(hDC); // Attempt To Get The Rendering Context
if(hRC == IntPtr.Zero) { // Are We Able To Get A Rendering Context?
KillGLWindow(); // Reset The Display
MessageBox.Show("Can't Create A GL Rendering Context.", "ERROR",
MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
if(!Wgl.wglMakeCurrent(hDC, hRC)) { // Try To Activate The Rendering Context
KillGLWindow(); // Reset The Display
MessageBox.Show("Can't Activate The GL Rendering Context.", "ERROR",
MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
form.Show(); // Show The Window
form.TopMost = true; // Topmost Window
form.Focus(); // Focus The Window
if(fullscreen) { // This Shouldn't Be Necessary, But Is
Cursor.Hide();
}
ReSizeGLScene(width, height); // Set Up Our Perspective GL Screen
if(!InitGL()) { // Initialize Our Newly Created GL Window
KillGLWindow(); // Reset The Display
MessageBox.Show("Initialization Failed.", "ERROR",
MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
return true; // Success
}
#endregion bool CreateGLWindow(string title, int width, int height, int bits, bool fullscreenflag)
#region bool DrawGLScene()
///
/// Here's where we do all the drawing.
///
///
/// true on successful drawing, otherwise false.
///
private static bool DrawGLScene() {
Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT); // Clear the Screen and the Depth Buffer
Gl.glMatrixMode(Gl.GL_MODELVIEW); // Modelview Matrix
Gl.glLoadIdentity(); // reset the current modelview matrix
AddLight();
Gl.glTranslatef(-1.5f,0.0f,-6.0f); // move 1.5 Units left and 6 Units into the screen
Gl.glRotatef(rot,1,1,1);
if (keys[(int)Keys.W])
Gl.glBegin(Gl.GL_LINES);
else
Gl.glBegin(Gl.GL_QUADS);
DoCalc(40,40,m,n1,n2,n3);
// DoQuad();
Gl.glEnd();
rot += rotspeed; // Increase The Rotation Variable
return true;
}
#endregion bool DrawGLScene()
static void DoQuad() {
Gl.glColor3f(1.0f,0.5f,0.0f); // orange
Gl.glVertex3f(1.0f,-1.0f,1.0f); // top right (bottom)
Gl.glVertex3f(-1.0f,-1.0f,1.0f); // top left (bottom)
Gl.glVertex3f(-1.0f,-1.0f,-1.0f); // bottom left (bottom)
Gl.glVertex3f(1.0f,-1.0f,-1.0f); // bottom right (bottom)
}
//2D supershape Paul Burke
static void Eval2D(float m,float n1,float n2,float n3,float phi,ref float x,ref float y){
double r;
double t1,t2;
double a=1,b=1;
t1 = Math.Cos(m * phi / 4) / a;
t1 = Math.Abs(t1);
t1 = Math.Pow(t1,n2);
t2 = Math.Sin(m * phi / 4) / b;
t2 = Math.Abs(t2);
t2 = Math.Pow(t2,n3);
r = Math.Pow(t1+t2,1/n1);
if (Math.Abs(r) == 0) {
x = 0;
y = 0;
} else {
r = 1 / r;
x = (float)(r * Math.Cos(phi));
y = (float)(r * Math.Sin(phi));
}
}
//3D supershape Paul Burke
static void Eval3D(float m,float n1,float n2,float n3,float phi,float theta,ref float x,ref float y,ref float z){
double r;
double t1,t2;
double a=1,b=1;
Eval2D(m,n1,n2,n3,phi,ref x,ref y);
t1 = Math.Cos(m * theta / 4) / a;
t1 = Math.Abs(t1);
t1 = Math.Pow(t1,n2);
t2 = Math.Sin(m * theta / 4) / b;
t2 = Math.Abs(t2);
t2 = Math.Pow(t2,n3);
r = Math.Pow(t1+t2,1/n1);
if (Math.Abs(r) == 0) {
x = 0;
y = 0;
z = 0;
} else {
r = 1 / r;
x *= (float)(r * Math.Cos(theta));
y *= (float)(r * Math.Cos(theta));
z = (float) (r * Math.Sin(theta));
}
}
static void AddLight()
{
float[] LightAmbient= { 0.5f, 0.5f, 0.5f, 1.0f }; // Ambient Light Values ( NEW )
float[] LightDiffuse= { 1.0f, 1.0f, 1.0f, 1.0f }; // Diffuse Light Values ( NEW )
float[] LightPosition= { 0.0f, 0.0f, -6.0f, 1.0f }; // Light Position ( NEW )
Gl.glLightfv(Gl.GL_LIGHT1, Gl.GL_AMBIENT, LightAmbient); // Setup The Ambient Light
Gl.glLightfv(Gl.GL_LIGHT1, Gl.GL_DIFFUSE, LightDiffuse); // Setup The Diffuse Light
Gl.glLightfv(Gl.GL_LIGHT1, Gl.GL_POSITION,LightPosition); // Position The Light
Gl.glEnable(Gl.GL_LIGHT1); // Enable Light One
}
static void DoCalc(float stepsx,float stepsy,float m,float n1,float n2,float n3) {
float phi = -(float)Math.PI;
float addPhi = (float)Math.PI*2 / stepsx;
float theta;
float addTheta = (float)Math.PI/stepsy;
float x1=0,y1=0,z1=0;
float x2=0,y2=0,z2=0;
float x3=0,y3=0,z3=0;
float x4=0,y4=0,z4=0;
float scale=1;
for (int i=0;i<=stepsx;i++) {
theta = -(float)Math.PI/2;
for (int j=0;j
// create vectors
float v1x=x1-x2; float v2x=x2-x3;
float v1y=y1-y2; float v2y=y2-y3;
float v1z=z1-z2; float v2z=z2-z3;
// Get cross product of vectors
float nx = (v1y * v2z) - (v1z * v2y);
float ny = (v1z * v2x) - (v1x * v2z);
float nz = (v1x * v2y) - (v1y * v2x);
// Normalise final vector
float vLen = (float)Math.Sqrt( (nx * nx) + (ny * ny) + (nz * nz) );
Gl.glNormal3f(nx/vLen, ny/vLen, nz/vLen);
Gl.glVertex3f(x1*scale, y1*scale, z1*scale);
Gl.glVertex3f(x2*scale, y2*scale, z2*scale);
Gl.glVertex3f(x3*scale, y3*scale, z3*scale);
Gl.glVertex3f(x4*scale, y4*scale, z4*scale);
theta+=addTheta;
}
phi+=addPhi;
}
}
#region glPrint(string text)
///
/// Custom GL "print" routine.
///
///
/// The text to print.
///
private static void glPrint(string text) {
if(text == null || text.Length == 0) { // If There's No Text
return; // Do Nothing
}
Gl.glPushAttrib(Gl.GL_LIST_BIT); // Pushes The Display List Bits
Gl.glListBase(fontbase); // Sets The Base Character to 0
// .NET: We can't draw text directly, it's a string!
byte [] textbytes = new byte [text.Length];
for (int i = 0; i < text.Length; i++) textbytes[i] = (byte) text[i];
Gl.glCallLists(text.Length, Gl.GL_UNSIGNED_BYTE, textbytes); // Draws The Display List Text
Gl.glPopAttrib(); // Pops The Display List Bits
}
#endregion glPrint(string text)
#region bool InitGL()
///
/// All setup for OpenGL goes here.
///
///
/// true on successful initialization, otherwise false.
///
private static bool InitGL() {
/* if(!LoadGLTextures()) { // Jump To Texture Loading Routine
return false; // If Texture Didn't Load Return False
}
*/ BuildFont(); // Build The Font
Gl.glShadeModel(Gl.GL_SMOOTH); // Enable Smooth Shading
Gl.glClearColor(0, 0, 0.5f, 0.5f); // Black Background
Gl.glClearDepth(1); // Depth Buffer Setup
Gl.glEnable(Gl.GL_DEPTH_TEST); // Enables Depth Testing
Gl.glDepthFunc(Gl.GL_LEQUAL); // The Type Of Depth Testing To Do
Gl.glEnable(Gl.GL_LIGHT0); // Quick And Dirty Lighting (Assumes Light0 Is Set Up)
Gl.glEnable(Gl.GL_LIGHTING); // Enable Lighting
Gl.glHint(Gl.GL_PERSPECTIVE_CORRECTION_HINT, Gl.GL_NICEST); // Really Nice Perspective Calculations
// Gl.glEnable(Gl.GL_TEXTURE_2D); // Enable Texture Mapping
// Gl.glBindTexture(Gl.GL_TEXTURE_2D, texture[0]); // Select The Texture
return true;
}
#endregion bool InitGL()
#region KillFont()
///
/// Delete the font list.
///
private static void KillFont() {
Gl.glDeleteLists(fontbase, 256); // Delete All 256 Characters
}
#endregion KillFont()
#region KillGLWindow()
///
/// Properly kill the window.
///
private static void KillGLWindow() {
if(fullscreen) { // Are We In Fullscreen Mode?
User.ChangeDisplaySettings(IntPtr.Zero, 0); // If So, Switch Back To The Desktop
Cursor.Show(); // Show Mouse Pointer
}
if(hRC != IntPtr.Zero) { // Do We Have A Rendering Context?
if(!Wgl.wglMakeCurrent(IntPtr.Zero, IntPtr.Zero)) { // Are We Able To Release The DC and RC Contexts?
MessageBox.Show("Release Of DC And RC Failed.", "SHUTDOWN ERROR",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
if(!Wgl.wglDeleteContext(hRC)) { // Are We Able To Delete The RC?
MessageBox.Show("Release Rendering Context Failed.", "SHUTDOWN ERROR",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
hRC = IntPtr.Zero; // Set RC To Null
}
if(hDC != IntPtr.Zero) { // Do We Have A Device Context?
if(form != null && !form.IsDisposed) { // Do We Have A Window?
if(form.Handle != IntPtr.Zero) { // Do We Have A Window Handle?
if(!User.ReleaseDC(form.Handle, hDC)) { // Are We Able To Release The DC?
MessageBox.Show("Release Device Context Failed.", "SHUTDOWN ERROR",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
hDC = IntPtr.Zero; // Set DC To Null
}
if(form != null) { // Do We Have A Windows Form?
form.Hide(); // Hide The Window
form.Close(); // Close The Form
form = null; // Set form To Null
}
KillFont();
}
#endregion KillGLWindow()
#region Bitmap LoadBMP(string fileName)
///
/// Loads a bitmap image.
///
///
/// The filename to load.
///
///
/// The bitmap if it exists, otherwise null.
///
private static Bitmap LoadBMP(string fileName) {
if(fileName == null || fileName == string.Empty) { // Make Sure A Filename Was Given
return null; // If Not Return Null
}
string fileName1 = string.Format("Data{0}{1}", // Look For Data\Filename
Path.DirectorySeparatorChar, fileName);
string fileName2 = string.Format("{0}{1}{0}{1}Data{1}{2}", // Look For ..\..\Data\Filename
"..", Path.DirectorySeparatorChar, fileName);
// Make Sure The File Exists In One Of The Usual Directories
if(!File.Exists(fileName) && !File.Exists(fileName1) && !File.Exists(fileName2)) {
return null; // If Not Return Null
}
if(File.Exists(fileName)) { // Does The File Exist Here?
return new Bitmap(fileName); // Load The Bitmap
}
else if(File.Exists(fileName1)) { // Does The File Exist Here?
return new Bitmap(fileName1); // Load The Bitmap
}
else if(File.Exists(fileName2)) { // Does The File Exist Here?
return new Bitmap(fileName2); // Load The Bitmap
}
return null; // If Load Failed Return Null
}
#endregion Bitmap LoadBMP(string fileName)
#region bool LoadGLTextures()
///
/// Load bitmaps and convert to textures.
///
///
/// true on success, otherwise false.
///
private static bool LoadGLTextures() {
bool status = false; // Status Indicator
Bitmap[] textureImage = new Bitmap[1]; // Create Storage Space For The Texture
textureImage[0] = LoadBMP(@"c:\tmp\x\Lights.bmp"); // Load The Bitmap
// Check For Errors, If Bitmap's Not Found, Quit
if(textureImage[0] != null) {
status = true; // Set The Status To True
Gl.glGenTextures(1, out texture[0]); // Create The Texture
textureImage[0].RotateFlip(RotateFlipType.RotateNoneFlipY); // Flip The Bitmap Along The Y-Axis
// Rectangle For Locking The Bitmap In Memory
Rectangle rectangle = new Rectangle(0, 0, textureImage[0].Width, textureImage[0].Height);
// Get The Bitmap's Pixel Data From The Locked Bitmap
BitmapData bitmapData = textureImage[0].LockBits(rectangle, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
// Typical Texture Generation Using Data From The Bitmap
Gl.glBindTexture(Gl.GL_TEXTURE_2D, texture[0]);
Glu.gluBuild2DMipmaps(Gl.GL_TEXTURE_2D, Gl.GL_RGB8, textureImage[0].Width, textureImage[0].Height, Gl.GL_RGB, Gl.GL_UNSIGNED_BYTE, bitmapData.Scan0);
Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MAG_FILTER, Gl.GL_LINEAR);
Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MIN_FILTER, Gl.GL_LINEAR_MIPMAP_NEAREST);
Gl.glTexGeni(Gl.GL_S, Gl.GL_TEXTURE_GEN_MODE, Gl.GL_OBJECT_LINEAR);
Gl.glTexGeni(Gl.GL_T, Gl.GL_TEXTURE_GEN_MODE, Gl.GL_OBJECT_LINEAR);
Gl.glEnable(Gl.GL_TEXTURE_GEN_S);
Gl.glEnable(Gl.GL_TEXTURE_GEN_T);
if(textureImage[0] != null) { // If Texture Exists
textureImage[0].UnlockBits(bitmapData); // Unlock The Pixel Data From Memory
textureImage[0].Dispose(); // Dispose The Bitmap
}
}
return status; // Return The Status
}
#endregion bool LoadGLTextures()
#region ReSizeGLScene(int width, int height)
///
/// Resizes and initializes the GL window.
///
///
/// The new window width.
///
///
/// The new window height.
///
private static void ReSizeGLScene(int width, int height) {
if(height == 0) { // Prevent A Divide By Zero...
height = 1; // By Making Height Equal To One
}
Gl.glViewport(0, 0, width, height); // Reset The Current Viewport
Gl.glMatrixMode(Gl.GL_PROJECTION); // Select The Projection Matrix
Gl.glLoadIdentity(); // Reset The Projection Matrix
Glu.gluPerspective(45, width / (float) height, 0.1, 100); // Calculate The Aspect Ratio Of The Window
Gl.glMatrixMode(Gl.GL_MODELVIEW); // Select The Modelview Matrix
Gl.glLoadIdentity(); // Reset The Modelview Matrix
}
#endregion ReSizeGLScene(int width, int height)
// --- Private Instance Event Handlers ---
#region Form_Activated
///
/// Handles the form's activated event.
///
///
/// The event sender.
///
///
/// The event arguments.
///
private void Form_Activated(object sender, EventArgs e) {
active = true; // Program Is Active
}
#endregion Form_Activated
#region Form_Closing(object sender, CancelEventArgs e)
///
/// Handles the form's closing event.
///
///
/// The event sender.
///
///
/// The event arguments.
///
private void Form_Closing(object sender, CancelEventArgs e) {
done = true; // Send A Quit Message
}
#endregion Form_Closing(object sender, CancelEventArgs e)
#region Form_Deactivate(object sender, EventArgs e)
///
/// Handles the form's deactivate event.
///
///
/// The event sender.
///
///
/// The event arguments.
///
private void Form_Deactivate(object sender, EventArgs e) {
active = false; // Program Is No Longer Active
}
#endregion Form_Deactivate(object sender, EventArgs e)
#region Form_KeyDown(object sender, KeyEventArgs e)
///
/// Handles the form's key down event.
///
///
/// The event sender.
///
///
/// The event arguments.
///
private void Form_KeyDown(object sender, KeyEventArgs e) {
keys[e.KeyValue] = true; // Key Has Been Pressed, Mark It As true
}
#endregion Form_KeyDown(object sender, KeyEventArgs e)
#region Form_KeyUp(object sender, KeyEventArgs e)
///
/// Handles the form's key down event.
///
///
/// The event sender.
///
///
/// The event arguments.
///
private void Form_KeyUp(object sender, KeyEventArgs e) {
keys[e.KeyValue] = false; // Key Has Been Pressed, Mark It As true
}
#endregion Form_KeyUp(object sender, KeyEventArgs e)
#region Form_Resize(object sender, EventArgs e)
///
/// Handles the form's resize event.
///
///
/// The event sender.
///
///
/// The event arguments.
///
private void Form_Resize(object sender, EventArgs e) {
ReSizeGLScene(form.Width, form.Height); // Resize The OpenGL Window
}
#endregion Form_Resize(object sender, EventArgs e)
}
}