consolidate glfw examples
svn path=/trunk/tao/; revision=67650
This commit is contained in:
Родитель
1c24444d52
Коммит
3d2fd92d2b
|
@ -0,0 +1,670 @@
|
|||
#region License
|
||||
/*
|
||||
MIT License
|
||||
Copyright ©2003-2004 Randy Ridge
|
||||
http://www.taoframework.com
|
||||
All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#endregion License
|
||||
|
||||
#region Original Credits/License
|
||||
/*
|
||||
Copyright (c) 2002-2004 Marcus Geelnard
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would
|
||||
be appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not
|
||||
be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
|
||||
Marcus Geelnard
|
||||
marcus.geelnard at home.se
|
||||
*/
|
||||
|
||||
/*****************************************************************************
|
||||
* Title: GLBoing
|
||||
* Desc: Tribute to Amiga Boing.
|
||||
* Author: Jim Brooks <gfx@jimbrooks.org>
|
||||
* Original Amiga authors were R.J. Mical and Dale Luck.
|
||||
* GLFW conversion by Marcus Geelnard
|
||||
* Notes: - 360' = 2*PI [radian]
|
||||
*
|
||||
* - Distances between objects are created by doing a relative
|
||||
* Z translations.
|
||||
*
|
||||
* - Although OpenGL enticingly supports alpha-blending,
|
||||
* the shadow of the original Boing didn't affect the color
|
||||
* of the grid.
|
||||
*
|
||||
* - [Marcus] Changed timing scheme from interval driven to frame-
|
||||
* time based animation steps (which results in much smoother
|
||||
* movement)
|
||||
*
|
||||
* History of Amiga Boing:
|
||||
*
|
||||
* Boing was demonstrated on the prototype Amiga (codenamed "Lorraine") in
|
||||
* 1985. According to legend, it was written ad-hoc in one night by
|
||||
* R. J. Mical and Dale Luck. Because the bouncing ball animation was so fast
|
||||
* and smooth, attendees did not believe the Amiga prototype was really doing
|
||||
* the rendering. Suspecting a trick, they began looking around the booth for
|
||||
* a hidden computer or VCR.
|
||||
*****************************************************************************/
|
||||
#endregion Original Credits/License
|
||||
|
||||
using System;
|
||||
using Tao.Glfw;
|
||||
using Tao.OpenGl;
|
||||
|
||||
namespace GlfwExamples {
|
||||
#region Class Documentation
|
||||
/// <summary>
|
||||
/// This is a small test application for GLFW.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Tribute to Amiga's Boing.
|
||||
/// </remarks>
|
||||
#endregion Class Documentation
|
||||
public sealed class Boing {
|
||||
// --- Fields ---
|
||||
#region Private Constants
|
||||
private const float PI = 3.1415926535897932384626433832795f;
|
||||
private const int RAND_MAX = 4095;
|
||||
private const float RADIUS = 70;
|
||||
// 22.5 makes 8 bands like original Boing
|
||||
private const float STEP_LONGITUDE = 22.5f;
|
||||
private const float STEP_LATITUDE = 22.5f;
|
||||
private const float DISTANCE_BALL = RADIUS * 2 + RADIUS * 0.1f;
|
||||
// Distance from viewer to middle of buing area
|
||||
private const float VIEW_SCENE_DISTANCE = DISTANCE_BALL * 3 + 200;
|
||||
// Length (width) of grid
|
||||
private const float GRID_SIZE = (RADIUS * 4.5f);
|
||||
private const float BOUNCE_HEIGHT = (RADIUS * 2.1f);
|
||||
private const float BOUNCE_WIDTH = (RADIUS * 2.1f);
|
||||
// Maximum allowed delta time per physics iteration
|
||||
private const float MAX_DELTA_TIME = 0.02f;
|
||||
// Animation speed (50.0 mimics the original GLUT demo speed)
|
||||
private const float ANIMATION_SPEED = 50;
|
||||
private const float SHADOW_OFFSET_X = -20;
|
||||
private const float SHADOW_OFFSET_Y = 10;
|
||||
private const float SHADOW_OFFSET_Z = 0;
|
||||
private const float WALL_LEFT_OFFSET = 0;
|
||||
private const float WALL_RIGHT_OFFSET = 5f;
|
||||
#endregion Private Constants
|
||||
|
||||
#region Private Enums
|
||||
#region DrawType
|
||||
/// <summary>
|
||||
/// Draw type.
|
||||
/// </summary>
|
||||
private enum DrawType {
|
||||
/// <summary>
|
||||
/// Draw ball.
|
||||
/// </summary>
|
||||
DrawBall,
|
||||
/// <summary>
|
||||
/// Draw ball's shadow.
|
||||
/// </summary>
|
||||
DrawBallShadow
|
||||
}
|
||||
#endregion DrawType
|
||||
#endregion Private Enums
|
||||
|
||||
#region Private Structs
|
||||
#region Vertex
|
||||
/// <summary>
|
||||
/// Vertex structure.
|
||||
/// </summary>
|
||||
private struct Vertex {
|
||||
/// <summary>
|
||||
/// X coordinate.
|
||||
/// </summary>
|
||||
public float X;
|
||||
/// <summary>
|
||||
/// Y coordinate.
|
||||
/// </summary>
|
||||
public float Y;
|
||||
/// <summary>
|
||||
/// Z coordinate.
|
||||
/// </summary>
|
||||
public float Z;
|
||||
}
|
||||
#endregion Vertex
|
||||
#endregion Private Structs
|
||||
|
||||
#region Private Static Fields
|
||||
private static Random rand = new Random();
|
||||
private static double currentTime, oldTime, timeDifference;
|
||||
private static float yRotationDegree = 0;
|
||||
private static float yRotationDegreeIncrement = 2;
|
||||
private static float ballX = -RADIUS;
|
||||
private static float ballY = -RADIUS;
|
||||
private static float ballXIncrement = 1;
|
||||
private static float ballYIncrement = 2;
|
||||
private static DrawType drawType;
|
||||
private static bool isColor;
|
||||
#endregion Private Static Fields
|
||||
|
||||
// --- Application Entry Point ---
|
||||
#region Run()
|
||||
/// <summary>
|
||||
/// The main entry point for the application.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
public static void Run() {
|
||||
bool isRunning = true;
|
||||
|
||||
// Initialise GLFW
|
||||
Glfw.glfwInit();
|
||||
if(Glfw.glfwOpenWindow(400, 400, 0, 0, 0, 0, 16, 0, Glfw.GLFW_WINDOW) == Gl.GL_FALSE) {
|
||||
Glfw.glfwTerminate();
|
||||
return;
|
||||
}
|
||||
Glfw.glfwSetWindowTitle("Boing (classic Amiga demo)");
|
||||
Glfw.glfwSetWindowSizeCallback(new Glfw.GLFWwindowsizefun(Reshape));
|
||||
Glfw.glfwEnable(Glfw.GLFW_STICKY_KEYS);
|
||||
Glfw.glfwSwapInterval(1);
|
||||
// TODO: Glfw.glfwSetTime(0.0);
|
||||
|
||||
Init();
|
||||
|
||||
// Main loop
|
||||
while(isRunning) {
|
||||
// Timing
|
||||
currentTime = Glfw.glfwGetTime();
|
||||
timeDifference = currentTime - oldTime;
|
||||
oldTime = currentTime;
|
||||
|
||||
// Draw one frame
|
||||
Display();
|
||||
|
||||
// Swap buffers
|
||||
Glfw.glfwSwapBuffers();
|
||||
|
||||
// Check if we are still running
|
||||
isRunning = ((Glfw.glfwGetKey(Glfw.GLFW_KEY_ESC) == Glfw.GLFW_RELEASE) &&
|
||||
Glfw.glfwGetWindowParam(Glfw.GLFW_OPENED) == Gl.GL_TRUE);
|
||||
}
|
||||
|
||||
// Close OpenGL window and terminate GLFW
|
||||
Glfw.glfwTerminate();
|
||||
}
|
||||
#endregion Run()
|
||||
|
||||
// --- Private Static Methods ---
|
||||
#region BounceBall(double timeDifference)
|
||||
/// <summary>
|
||||
/// Bounces the ball.
|
||||
/// </summary>
|
||||
/// <param name="timeDifference">
|
||||
/// The time difference.
|
||||
/// </param>
|
||||
private static void BounceBall(double timeDifference) {
|
||||
float sign;
|
||||
float degree;
|
||||
|
||||
// Bounce on walls
|
||||
if(ballX > (BOUNCE_WIDTH / 2 + WALL_RIGHT_OFFSET)) {
|
||||
ballXIncrement = -0.5f - 0.75f * (float) rand.NextDouble() / (float) RAND_MAX;
|
||||
yRotationDegreeIncrement = -yRotationDegreeIncrement;
|
||||
}
|
||||
|
||||
if(ballX < -(BOUNCE_HEIGHT / 2 + WALL_LEFT_OFFSET)) {
|
||||
ballXIncrement = 0.5f + 0.75f * (float) rand.NextDouble() / (float) RAND_MAX;
|
||||
yRotationDegreeIncrement = -yRotationDegreeIncrement;
|
||||
}
|
||||
|
||||
// Bounce on floor / ceiling
|
||||
if(ballY > BOUNCE_HEIGHT / 2) {
|
||||
ballYIncrement = -0.75f - 1.0f * (float) rand.NextDouble() / (float) RAND_MAX;
|
||||
}
|
||||
|
||||
if(ballY < -BOUNCE_HEIGHT / 2 * 0.85f) {
|
||||
ballYIncrement = 0.75f + 1 * (float) rand.NextDouble() / (float) RAND_MAX;
|
||||
}
|
||||
|
||||
// Update ball position
|
||||
ballX += (float) (ballXIncrement * (timeDifference * ANIMATION_SPEED));
|
||||
ballY += (float) (ballYIncrement * (timeDifference * ANIMATION_SPEED));
|
||||
|
||||
// Simulate the effects of gravity on Y movement
|
||||
if(ballYIncrement < 0) {
|
||||
sign = -1;
|
||||
}
|
||||
else {
|
||||
sign = 1;
|
||||
}
|
||||
|
||||
degree = (ballY + BOUNCE_HEIGHT / 2) * 90 / BOUNCE_HEIGHT;
|
||||
|
||||
if(degree > 80) {
|
||||
degree = 80;
|
||||
}
|
||||
else if(degree < 10) {
|
||||
degree = 10;
|
||||
}
|
||||
|
||||
ballYIncrement = sign * 4 * (float) SinDegree(degree);
|
||||
}
|
||||
#endregion BounceBall(double timeDifference)
|
||||
|
||||
#region double CosDegree(double degree)
|
||||
/// <summary>
|
||||
/// 360' Cos().
|
||||
/// </summary>
|
||||
/// <param name="degree">
|
||||
/// The degree.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The Cos.
|
||||
/// </returns>
|
||||
private static double CosDegree(double degree) {
|
||||
return Math.Cos(DegreeToRadian(degree));
|
||||
}
|
||||
#endregion double CosDegree(double degree)
|
||||
|
||||
#region CrossProduct(Vertex a, Vertex b, Vertex c, out Vertex normal)
|
||||
/// <summary>
|
||||
/// Computes a cross product for a vector normal.
|
||||
/// </summary>
|
||||
/// <param name="a">
|
||||
/// First vector.
|
||||
/// </param>
|
||||
/// <param name="b">
|
||||
/// Second vector.
|
||||
/// </param>
|
||||
/// <param name="c">
|
||||
/// Third vector.
|
||||
/// </param>
|
||||
/// <param name="normal">
|
||||
/// The normalized vector.
|
||||
/// </param>
|
||||
private static void CrossProduct(Vertex a, Vertex b, Vertex c, out Vertex normal) {
|
||||
float u1, u2, u3;
|
||||
float v1, v2, v3;
|
||||
|
||||
u1 = b.X - a.X;
|
||||
u2 = b.Y - a.Y;
|
||||
u3 = b.Y - a.Z;
|
||||
|
||||
v1 = c.X - a.X;
|
||||
v2 = c.Y - a.Y;
|
||||
v3 = c.Z - a.Z;
|
||||
|
||||
normal.X = u2 * v3 - v2 * v3;
|
||||
normal.Y = u3 * v1 - v3 * u1;
|
||||
normal.Z = u1 * v2 - v1 * u2;
|
||||
}
|
||||
#endregion CrossProduct(Vertex a, Vertex b, Vertex c, out Vertex normal)
|
||||
|
||||
#region double DegreeToRadian(double degree)
|
||||
/// <summary>
|
||||
/// Converts a degree to a radian.
|
||||
/// </summary>
|
||||
/// <param name="degree">
|
||||
/// The degree.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The radian.
|
||||
/// </returns>
|
||||
private static double DegreeToRadian(double degree) {
|
||||
return degree / 360 * (2 * PI);
|
||||
}
|
||||
#endregion double DegreeToRadian(double degree)
|
||||
|
||||
#region Display()
|
||||
/// <summary>
|
||||
/// Draws a frame.
|
||||
/// </summary>
|
||||
private static void Display() {
|
||||
Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);
|
||||
Gl.glPushMatrix();
|
||||
drawType = DrawType.DrawBallShadow;
|
||||
DrawBoingBall();
|
||||
DrawGrid();
|
||||
drawType = DrawType.DrawBall;
|
||||
DrawBoingBall();
|
||||
Gl.glPopMatrix();
|
||||
Gl.glFlush();
|
||||
}
|
||||
#endregion Display()
|
||||
|
||||
#region DrawBoingBall()
|
||||
/// <summary>
|
||||
/// Draws the Boing ball.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The Boing ball is sphere in which each facet is a rectangle. Facet colors
|
||||
/// alternate between red and white. The ball is built by stacking latitudinal
|
||||
/// circles. Each circle is composed of a widely-separated set of points, so
|
||||
/// that each facet is noticably large.
|
||||
/// </remarks>
|
||||
private static void DrawBoingBall() {
|
||||
float degreeOfLongitude;
|
||||
double timeDifferenceTotal, timeDifferenceTemp;
|
||||
|
||||
Gl.glPushMatrix();
|
||||
Gl.glMatrixMode(Gl.GL_MODELVIEW);
|
||||
|
||||
// Another relative Z translation to separate objects
|
||||
Gl.glTranslatef(0, 0, (float) DISTANCE_BALL);
|
||||
|
||||
// Update ball position and rotation (iterate if necessary)
|
||||
timeDifferenceTotal = timeDifference;
|
||||
while(timeDifferenceTotal > 0.0) {
|
||||
timeDifferenceTemp = timeDifferenceTotal > MAX_DELTA_TIME ? MAX_DELTA_TIME :
|
||||
timeDifferenceTotal;
|
||||
timeDifferenceTotal -= timeDifferenceTemp;
|
||||
BounceBall(timeDifferenceTemp);
|
||||
yRotationDegree = TruncateDegree((float) (yRotationDegree + yRotationDegreeIncrement *
|
||||
(timeDifferenceTemp * ANIMATION_SPEED)));
|
||||
}
|
||||
|
||||
// Set ball position
|
||||
Gl.glTranslatef(ballX, ballY, 0);
|
||||
|
||||
// Offset the shadow
|
||||
if(drawType == DrawType.DrawBallShadow) {
|
||||
Gl.glTranslatef(SHADOW_OFFSET_X, SHADOW_OFFSET_Y, SHADOW_OFFSET_Z);
|
||||
}
|
||||
|
||||
// Tilt the ball
|
||||
Gl.glRotatef(-20, 0, 0, 1);
|
||||
|
||||
// Continually rotate ball around Y axis
|
||||
Gl.glRotatef(yRotationDegree, 0, 1, 0);
|
||||
|
||||
// Set OpenGL state for Boing ball
|
||||
Gl.glCullFace(Gl.GL_FRONT);
|
||||
Gl.glEnable(Gl.GL_CULL_FACE);
|
||||
Gl.glEnable(Gl.GL_NORMALIZE);
|
||||
|
||||
// Build a faceted latitude slice of the Boing ball, stepping same-sized vertical
|
||||
// bands of the sphere
|
||||
for(degreeOfLongitude = 0; degreeOfLongitude < 180;
|
||||
degreeOfLongitude += STEP_LONGITUDE) {
|
||||
// Draw a latitude circle at this longitude
|
||||
DrawBoingBallBand(degreeOfLongitude, degreeOfLongitude + STEP_LONGITUDE);
|
||||
}
|
||||
Gl.glPopMatrix();
|
||||
}
|
||||
#endregion DrawBoingBall()
|
||||
|
||||
#region DrawBoingBallBand(float low, float high)
|
||||
/// <summary>
|
||||
/// Drawa a faceted latitude band of the Boing ball.
|
||||
/// </summary>
|
||||
/// <param name="low">
|
||||
/// The low longitude of the slice.
|
||||
/// </param>
|
||||
/// <param name="high">
|
||||
/// The high longitude of the slice.
|
||||
/// </param>
|
||||
private static void DrawBoingBallBand(float low, float high) {
|
||||
// "ne" means north-east, so on
|
||||
Vertex neVertex;
|
||||
Vertex nwVertex;
|
||||
Vertex seVertex;
|
||||
Vertex swVertex;
|
||||
Vertex normalVertex;
|
||||
float degreeLatitude;
|
||||
|
||||
// Iterate thru the points of a latitude circle. A latitude circle is a 2D set of
|
||||
// X, Z points
|
||||
for(degreeLatitude = 0; degreeLatitude <= (360 - STEP_LATITUDE);
|
||||
degreeLatitude += STEP_LATITUDE) {
|
||||
// Color this polygon with red or white
|
||||
if(isColor) {
|
||||
Gl.glColor3f(0.8f, 0.1f, 0.1f);
|
||||
}
|
||||
else {
|
||||
Gl.glColor3f(0.95f, 0.95f, 0.95f);
|
||||
}
|
||||
|
||||
#if BOING_DEBUG
|
||||
if(degreeLatitude >= 180) {
|
||||
if(isColor) {
|
||||
Gl.glColor3f(0.1f, 0.8f, 0.1f);
|
||||
}
|
||||
else {
|
||||
Gl.glColor3f(0.5f, 0.5f, 0.95f);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
isColor = !isColor;
|
||||
|
||||
// Change color if drawing shadow
|
||||
if(drawType == DrawType.DrawBallShadow) {
|
||||
Gl.glColor3f(0.35f, 0.35f, 0.35f);
|
||||
}
|
||||
|
||||
// Assign each Y
|
||||
neVertex.Y = nwVertex.Y = (float) CosDegree(high) * RADIUS;
|
||||
swVertex.Y = seVertex.Y = (float) CosDegree(low) * RADIUS;
|
||||
|
||||
// Assign each X, Z with Sin, Cos values scaled by latitude radius indexed by
|
||||
// longitude. E.G. longitude = 0 and longitude = 180 are at the poles, so zero
|
||||
// scale is Sin(longitude), while longitude = 90 (Sin(90) = 1) is at equator
|
||||
neVertex.X = (float) CosDegree(degreeLatitude) * (float) (RADIUS * SinDegree(low + STEP_LONGITUDE));
|
||||
seVertex.X = (float) CosDegree(degreeLatitude) * (float) (RADIUS * SinDegree(low));
|
||||
nwVertex.X = (float) CosDegree(degreeLatitude + STEP_LATITUDE) * (float) (RADIUS * SinDegree(low + STEP_LONGITUDE));
|
||||
swVertex.X = (float) CosDegree(degreeLatitude + STEP_LATITUDE) * (float) (RADIUS * SinDegree(low));
|
||||
|
||||
neVertex.Z = (float) SinDegree(degreeLatitude) * (float) (RADIUS * SinDegree(low + STEP_LONGITUDE));
|
||||
seVertex.Z = (float) SinDegree(degreeLatitude) * (float) (RADIUS * SinDegree(low));
|
||||
nwVertex.Z = (float) SinDegree(degreeLatitude + STEP_LATITUDE) * (float) (RADIUS * SinDegree(low + STEP_LONGITUDE));
|
||||
swVertex.Z = (float) SinDegree(degreeLatitude + STEP_LATITUDE) * (float) (RADIUS * SinDegree(low));
|
||||
|
||||
// Draw the facet
|
||||
Gl.glBegin(Gl.GL_POLYGON);
|
||||
CrossProduct(neVertex, nwVertex, swVertex, out normalVertex);
|
||||
Gl.glNormal3f(normalVertex.X, normalVertex.Y, normalVertex.Z);
|
||||
Gl.glVertex3f(neVertex.X, neVertex.Y, neVertex.Z);
|
||||
Gl.glVertex3f(nwVertex.X, nwVertex.Y, nwVertex.Z);
|
||||
Gl.glVertex3f(swVertex.X, swVertex.Y, swVertex.Z);
|
||||
Gl.glVertex3f(seVertex.X, seVertex.Y, seVertex.Z);
|
||||
Gl.glEnd();
|
||||
|
||||
#if BOING_DEBUG
|
||||
Console.WriteLine("-----------------------------------------------------------");
|
||||
Console.WriteLine("lat = {0} low = {1} high = {2}", degreeLatitude, low, high);
|
||||
Console.WriteLine( "vert_ne x = %.8f y = %.8f z = %.8f \n", vert_ne.x, vert_ne.y, vert_ne.z );
|
||||
Console.WriteLine( "vert_nw x = %.8f y = %.8f z = %.8f \n", vert_nw.x, vert_nw.y, vert_nw.z );
|
||||
Console.WriteLine( "vert_se x = %.8f y = %.8f z = %.8f \n", vert_se.x, vert_se.y, vert_se.z );
|
||||
Console.WriteLine( "vert_sw x = %.8f y = %.8f z = %.8f \n", vert_sw.x, vert_sw.y, vert_sw.z );
|
||||
#endif
|
||||
}
|
||||
|
||||
// Toggle color so that next band will opposite red/white colors than this one
|
||||
isColor = !isColor;
|
||||
}
|
||||
#endregion DrawBoingBallBand(float low, float high)
|
||||
|
||||
#region DrawGrid()
|
||||
/// <summary>
|
||||
/// Draws the purple grid of lines behind the Boing ball.
|
||||
/// </summary>
|
||||
private static void DrawGrid() {
|
||||
int row, column;
|
||||
int rowTotal = 12; // must be divisible by 2
|
||||
int columnTotal = rowTotal; // must be same as rowTotal
|
||||
float widthLine = 2; // should be divisible by 2
|
||||
float sizeCell = (float) GRID_SIZE / rowTotal;
|
||||
float z_offset = -40;
|
||||
float xl, xr;
|
||||
float yt, yb;
|
||||
|
||||
Gl.glPushMatrix();
|
||||
Gl.glDisable(Gl.GL_CULL_FACE);
|
||||
|
||||
// Another relative Z translation to separate objects
|
||||
Gl.glTranslatef(0, 0, DISTANCE_BALL);
|
||||
|
||||
// Draw vertical lines (as skinny 3D rectangles)
|
||||
for(column = 0; column <= columnTotal; column++) {
|
||||
// Compute coordinatess of line
|
||||
xl = (float) -GRID_SIZE / 2 + column * sizeCell;
|
||||
xr = xl + widthLine;
|
||||
|
||||
yt = (float) GRID_SIZE / 2;
|
||||
yb = (float) -GRID_SIZE / 2 - widthLine;
|
||||
|
||||
Gl.glBegin(Gl.GL_POLYGON);
|
||||
Gl.glColor3f(0.6f, 0.1f, 0.6f); // purple
|
||||
Gl.glVertex3f(xr, yt, z_offset); // NE
|
||||
Gl.glVertex3f(xl, yt, z_offset); // NW
|
||||
Gl.glVertex3f(xl, yb, z_offset); // SW
|
||||
Gl.glVertex3f(xr, yb, z_offset); // SE
|
||||
Gl.glEnd();
|
||||
}
|
||||
|
||||
// Draw horizontal lines (as skinny 3D rectangles)
|
||||
for(row = 0; row <= rowTotal; row++) {
|
||||
// Compute coordinates of line
|
||||
yt = (float) GRID_SIZE / 2 - row * sizeCell;
|
||||
yb = yt - widthLine;
|
||||
|
||||
xl = (float) -GRID_SIZE / 2;
|
||||
xr = (float) GRID_SIZE / 2 + widthLine;
|
||||
|
||||
Gl.glBegin(Gl.GL_POLYGON);
|
||||
Gl.glColor3f(0.6f, 0.1f, 0.6f); // purple
|
||||
Gl.glVertex3f(xr, yt, z_offset); // NE
|
||||
Gl.glVertex3f(xl, yt, z_offset); // NW
|
||||
Gl.glVertex3f(xl, yb, z_offset); // SW
|
||||
Gl.glVertex3f(xr, yb, z_offset); // SE
|
||||
Gl.glEnd();
|
||||
}
|
||||
Gl.glPopMatrix();
|
||||
}
|
||||
#endregion DrawGrid()
|
||||
|
||||
#region Init()
|
||||
/// <summary>
|
||||
/// Initializes some GL settings.
|
||||
/// </summary>
|
||||
private static void Init() {
|
||||
// Clear background
|
||||
Gl.glClearColor(0.55f, 0.55f, 0.55f, 0.0f);
|
||||
// Flat shading
|
||||
Gl.glShadeModel(Gl.GL_FLAT);
|
||||
}
|
||||
#endregion Init()
|
||||
|
||||
#region double PerspectiveAngle(double size, double distance)
|
||||
/// <summary>
|
||||
/// Calculates the angle to be passed to <see cref="Glu.gluPerspective" /> so that
|
||||
/// a scene is visible.
|
||||
/// </summary>
|
||||
/// <param name="size">
|
||||
/// The size of the segment when the angle is intersected at
|
||||
/// <paramref name="distance" />.
|
||||
/// </param>
|
||||
/// <param name="distance">
|
||||
/// The distance from viewpoint to the scene.
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
private static double PerspectiveAngle(double size, double distance) {
|
||||
double radianTheta = 2 * Math.Atan2(size / 2, distance);
|
||||
return (double) (180 * radianTheta) / PI;
|
||||
}
|
||||
#endregion double PerspectiveAngle(double size, double distance)
|
||||
|
||||
#region double SinDegree(double degree)
|
||||
/// <summary>
|
||||
/// 360' Sin().
|
||||
/// </summary>
|
||||
/// <param name="degree">
|
||||
/// The degree.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The Sin.
|
||||
/// </returns>
|
||||
private static double SinDegree(double degree) {
|
||||
return Math.Sin(DegreeToRadian(degree));
|
||||
}
|
||||
#endregion double SinDegree(double degree)
|
||||
|
||||
#region float TruncateDegree(float degree)
|
||||
/// <summary>
|
||||
/// Truncates a degree.
|
||||
/// </summary>
|
||||
/// <param name="degree">
|
||||
/// The degree to truncate.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The truncated degree value.
|
||||
/// </returns>
|
||||
private static float TruncateDegree(float degree) {
|
||||
if(degree >= 360.0f) {
|
||||
return (degree - 360.0f);
|
||||
}
|
||||
else {
|
||||
return degree;
|
||||
}
|
||||
}
|
||||
#endregion float TruncateDegree(float degree)
|
||||
|
||||
// --- Private GLFW Callback Methods ---
|
||||
#region Reshape(int width, int height)
|
||||
/// <summary>
|
||||
/// Handles GLFW's window reshape callback.
|
||||
/// </summary>
|
||||
/// <param name="width">
|
||||
/// New window width.
|
||||
/// </param>
|
||||
/// <param name="height">
|
||||
/// New window height.
|
||||
/// </param>
|
||||
private static void Reshape(int width, int height) {
|
||||
Gl.glViewport(0, 0, width, height);
|
||||
|
||||
Gl.glMatrixMode(Gl.GL_PROJECTION);
|
||||
Gl.glLoadIdentity();
|
||||
|
||||
Glu.gluPerspective(PerspectiveAngle(RADIUS * 2, 200),
|
||||
(double) width / (double) height,
|
||||
1,
|
||||
VIEW_SCENE_DISTANCE);
|
||||
|
||||
Gl.glMatrixMode(Gl.GL_MODELVIEW);
|
||||
Gl.glLoadIdentity();
|
||||
|
||||
Glu.gluLookAt(0, 0, VIEW_SCENE_DISTANCE, // eye
|
||||
0, 0, 0, // center of vision
|
||||
0, -1, 0); // up vector
|
||||
}
|
||||
#endregion Reshape(int width, int height)
|
||||
}
|
||||
}
|
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
|
@ -0,0 +1,448 @@
|
|||
#region License
|
||||
/*
|
||||
MIT License
|
||||
Copyright ©2003-2004 Randy Ridge
|
||||
http://www.taoframework.com
|
||||
All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#endregion License
|
||||
|
||||
#region Original Credits/License
|
||||
/*
|
||||
Copyright (c) 2002-2004 Marcus Geelnard
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would
|
||||
be appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not
|
||||
be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
|
||||
Marcus Geelnard
|
||||
marcus.geelnard at home.se
|
||||
*/
|
||||
|
||||
/*
|
||||
* 3-D gear wheels. This program is in the public domain.
|
||||
*
|
||||
* Command line options:
|
||||
* -info print GL implementation information
|
||||
* -exit automatically exit after 30 seconds
|
||||
*
|
||||
*
|
||||
* Brian Paul
|
||||
*
|
||||
*
|
||||
* Marcus Geelnard:
|
||||
* - Conversion to GLFW
|
||||
* - Time based rendering (frame rate independent)
|
||||
* - Slightly modified camera that should work better for stereo viewing
|
||||
*/
|
||||
#endregion Original Credits/License
|
||||
|
||||
using System;
|
||||
using Tao.Glfw;
|
||||
using Tao.OpenGl;
|
||||
|
||||
namespace GlfwExamples {
|
||||
#region Class Documentation
|
||||
/// <summary>
|
||||
/// This is a small test application for GLFW.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Classic gears.
|
||||
/// </remarks>
|
||||
#endregion Class Documentation
|
||||
public sealed class Gears {
|
||||
// --- Fields ---
|
||||
#region Private Constants
|
||||
private const float PI = 3.141592654f;
|
||||
#endregion Private Constants
|
||||
|
||||
#region Private Static Fields
|
||||
private static bool isRunning = true;
|
||||
private static double currentTime = 0;
|
||||
private static double oldTime = 0;
|
||||
private static double timeDifference = 0;
|
||||
private static int frameCount;
|
||||
private static int autoExit = 0;
|
||||
private static float[] lightPosition = new float[] {5, 5, 10, 0};
|
||||
private static float[] redMaterial = new float[] {0.8f, 0.1f, 0, 1};
|
||||
private static float[] greenMaterial = new float[] {0, 0.8f, 0.2f, 1};
|
||||
private static float[] blueMaterial = new float[] {0.2f, 0.2f, 1, 1};
|
||||
private static float rotateX = 20, rotateY = 30, rotateZ = 0;
|
||||
private static int gear1, gear2, gear3;
|
||||
private static float angle = 0;
|
||||
#endregion Private Static Fields
|
||||
|
||||
// --- Application Entry Point ---
|
||||
#region Run()
|
||||
/// <summary>
|
||||
/// The main entry point for the application.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
public static void Run() {
|
||||
// Initialise GLFW and open window
|
||||
Glfw.glfwInit();
|
||||
if(Glfw.glfwOpenWindow(300, 300, 0, 0, 0, 0, 0, 0, Glfw.GLFW_WINDOW) == Gl.GL_FALSE) {
|
||||
Glfw.glfwTerminate();
|
||||
return;
|
||||
}
|
||||
Glfw.glfwSetWindowTitle("Gears");
|
||||
Glfw.glfwEnable(Glfw.GLFW_KEY_REPEAT);
|
||||
Glfw.glfwSwapInterval(0);
|
||||
|
||||
Init();
|
||||
|
||||
// Set callback functions
|
||||
Glfw.glfwSetWindowSizeCallback(new Glfw.GLFWwindowsizefun(Reshape));
|
||||
Glfw.glfwSetKeyCallback(new Glfw.GLFWkeyfun(Key));
|
||||
|
||||
// Main loop
|
||||
while(isRunning) {
|
||||
// Draw gears
|
||||
Draw();
|
||||
|
||||
// Update animation
|
||||
Animate();
|
||||
|
||||
// Swap Buffers
|
||||
Glfw.glfwSwapBuffers();
|
||||
|
||||
if(Glfw.glfwGetWindowParam(Glfw.GLFW_OPENED) == Gl.GL_FALSE) {
|
||||
isRunning = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Close OpenGL window and terminate GLFW
|
||||
Glfw.glfwTerminate();
|
||||
}
|
||||
#endregion Run()
|
||||
|
||||
// --- Private Static Methods ---
|
||||
#region Animate()
|
||||
/// <summary>
|
||||
/// Updates animation parameters.
|
||||
/// </summary>
|
||||
private static void Animate() {
|
||||
angle += 100 * (float) timeDifference;
|
||||
}
|
||||
#endregion Animate()
|
||||
|
||||
#region Draw()
|
||||
/// <summary>
|
||||
/// OpenGL draw function and timing.
|
||||
/// </summary>
|
||||
private static void Draw() {
|
||||
Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
Gl.glPushMatrix();
|
||||
Gl.glRotatef(rotateX, 1, 0, 0);
|
||||
Gl.glRotatef(rotateY, 0, 1, 0);
|
||||
Gl.glRotatef(rotateZ, 0, 0, 1);
|
||||
|
||||
Gl.glPushMatrix();
|
||||
Gl.glTranslatef(-3, -2, 0);
|
||||
Gl.glRotatef(angle, 0, 0, 1);
|
||||
Gl.glCallList(gear1);
|
||||
Gl.glPopMatrix();
|
||||
|
||||
Gl.glPushMatrix();
|
||||
Gl.glTranslatef(3.1f, -2, 0);
|
||||
Gl.glRotatef(-2 * angle - 9, 0, 0, 1);
|
||||
Gl.glCallList(gear2);
|
||||
Gl.glPopMatrix();
|
||||
|
||||
Gl.glPushMatrix();
|
||||
Gl.glTranslatef(-3.1f, 4.2f, 0);
|
||||
Gl.glRotatef(-2 * angle - 25, 0, 0, 1);
|
||||
Gl.glCallList(gear3);
|
||||
Gl.glPopMatrix();
|
||||
Gl.glPopMatrix();
|
||||
|
||||
frameCount++;
|
||||
|
||||
double newTime = Glfw.glfwGetTime();
|
||||
timeDifference = newTime - currentTime;
|
||||
currentTime = newTime;
|
||||
|
||||
if(currentTime - oldTime >= 5.0) {
|
||||
double seconds = currentTime - oldTime;
|
||||
double fps = frameCount / seconds;
|
||||
Console.WriteLine("{0} frames in {1} seconds = {2} FPS", frameCount, seconds, fps);
|
||||
oldTime = currentTime;
|
||||
frameCount = 0;
|
||||
if((currentTime >= 0.999 * autoExit) && (autoExit > 0)) {
|
||||
isRunning = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion Draw()
|
||||
|
||||
#region Gear(float innerRadius, float outerRadius, float width, float teeth, float toothDepth)
|
||||
private static void Gear(float innerRadius, float outerRadius, float width, float teeth, float toothDepth) {
|
||||
int i;
|
||||
float r0, r1, r2;
|
||||
float angle, da;
|
||||
float u, v, len;
|
||||
|
||||
r0 = innerRadius;
|
||||
r1 = outerRadius - toothDepth / 2;
|
||||
r2 = outerRadius + toothDepth / 2;
|
||||
|
||||
da = 2 * PI / teeth / 4;
|
||||
|
||||
Gl.glShadeModel(Gl.GL_FLAT);
|
||||
|
||||
Gl.glNormal3f(0, 0, 1);
|
||||
|
||||
// draw front face
|
||||
Gl.glBegin(Gl.GL_QUAD_STRIP);
|
||||
for(i = 0; i <= teeth; i++) {
|
||||
angle = i * 2 * PI / teeth;
|
||||
Gl.glVertex3f(r0 * (float) Math.Cos(angle), r0 * (float) Math.Sin(angle), width * 0.5f);
|
||||
Gl.glVertex3f(r1 * (float) Math.Cos(angle), r1 * (float) Math.Sin(angle), width * 0.5f);
|
||||
if(i < teeth) {
|
||||
Gl.glVertex3f(r0 * (float) Math.Cos(angle), r0 * (float) Math.Sin(angle), width * 0.5f);
|
||||
Gl.glVertex3f(r1 * (float) Math.Cos(angle + 3 * da), r1 * (float) Math.Sin(angle + 3 * da), width * 0.5f);
|
||||
}
|
||||
}
|
||||
Gl.glEnd();
|
||||
|
||||
// draw front sides of teeth
|
||||
Gl.glBegin(Gl.GL_QUADS);
|
||||
da = 2 * PI / teeth / 4;
|
||||
for(i = 0; i < teeth; i++) {
|
||||
angle = i * 2 * PI / teeth;
|
||||
Gl.glVertex3f(r1 * (float) Math.Cos(angle), r1 * (float) Math.Sin(angle), width * 0.5f);
|
||||
Gl.glVertex3f(r2 * (float) Math.Cos(angle + da), r2 * (float) Math.Sin(angle + da), width * 0.5f);
|
||||
Gl.glVertex3f(r2 * (float) Math.Cos(angle + 2 * da), r2 * (float) Math.Sin(angle + 2 * da), width * 0.5f);
|
||||
Gl.glVertex3f(r1 * (float) Math.Cos(angle + 3 * da), r1 * (float) Math.Sin(angle + 3 * da), width * 0.5f);
|
||||
}
|
||||
Gl.glEnd();
|
||||
|
||||
Gl.glNormal3f(0, 0, -1);
|
||||
|
||||
// draw back face
|
||||
Gl.glBegin(Gl.GL_QUAD_STRIP);
|
||||
for(i = 0; i <= teeth; i++) {
|
||||
angle = i * 2 * PI / teeth;
|
||||
Gl.glVertex3f(r1 * (float) Math.Cos(angle), r1 * (float) Math.Sin(angle), -width * 0.5f);
|
||||
Gl.glVertex3f(r0 * (float) Math.Cos(angle), r0 * (float) Math.Sin(angle), -width * 0.5f);
|
||||
if(i < teeth) {
|
||||
Gl.glVertex3f(r1 * (float) Math.Cos(angle + 3 * da), r1 * (float) Math.Sin(angle + 3 * da), -width * 0.5f);
|
||||
Gl.glVertex3f(r0 * (float) Math.Cos(angle), r0 * (float) Math.Sin(angle), -width * 0.5f);
|
||||
}
|
||||
}
|
||||
Gl.glEnd();
|
||||
|
||||
// draw back sides of teeth
|
||||
Gl.glBegin(Gl.GL_QUADS);
|
||||
da = 2 * PI / teeth / 4;
|
||||
for(i = 0; i < teeth; i++) {
|
||||
angle = i * 2 * PI / teeth;
|
||||
Gl.glVertex3f(r1 * (float) Math.Cos(angle + 3 * da), r1 * (float) Math.Sin(angle + 3 * da), -width * 0.5f);
|
||||
Gl.glVertex3f(r2 * (float) Math.Cos(angle + 2 * da), r2 * (float) Math.Sin(angle + 2 * da), -width * 0.5f);
|
||||
Gl.glVertex3f(r2 * (float) Math.Cos(angle + da), r2 * (float) Math.Sin(angle + da), -width * 0.5f);
|
||||
Gl.glVertex3f(r1 * (float) Math.Cos(angle), r1 * (float) Math.Sin(angle), -width * 0.5f);
|
||||
}
|
||||
Gl.glEnd();
|
||||
|
||||
// draw outward faces of teeth
|
||||
Gl.glBegin(Gl.GL_QUAD_STRIP);
|
||||
for(i = 0; i < teeth; i++) {
|
||||
angle = i * 2 * PI / teeth;
|
||||
Gl.glVertex3f(r1 * (float) Math.Cos(angle), r1 * (float) Math.Sin(angle), width * 0.5f);
|
||||
Gl.glVertex3f(r1 * (float) Math.Cos(angle), r1 * (float) Math.Sin(angle), -width * 0.5f);
|
||||
u = r2 * (float) Math.Cos(angle + da) - r1 * (float) Math.Cos(angle);
|
||||
v = r2 * (float) Math.Sin(angle + da) - r1 * (float) Math.Sin(angle);
|
||||
len = (float) Math.Sqrt(u * u + v * v);
|
||||
u /= len;
|
||||
v /= len;
|
||||
Gl.glNormal3f(v, -u, 0);
|
||||
Gl.glVertex3f(r2 * (float) Math.Cos(angle + da), r2 * (float) Math.Sin(angle + da), width * 0.5f);
|
||||
Gl.glVertex3f(r2 * (float) Math.Cos(angle + da), r2 * (float) Math.Sin(angle + da), -width * 0.5f);
|
||||
Gl.glNormal3f((float) Math.Cos(angle), (float) Math.Sin(angle), 0);
|
||||
Gl.glVertex3f(r2 * (float) Math.Cos(angle + 2 * da), r2 * (float) Math.Sin(angle + 2 * da), width * 0.5f);
|
||||
Gl.glVertex3f(r2 * (float) Math.Cos(angle + 2 * da), r2 * (float) Math.Sin(angle + 2 * da), -width * 0.5f);
|
||||
u = r1 * (float) Math.Cos(angle + 3 * da) - r2 * (float) Math.Cos(angle + 2 * da);
|
||||
v = r1 * (float) Math.Sin(angle + 3 * da) - r2 * (float) Math.Sin(angle + 2 * da);
|
||||
Gl.glNormal3f(v, -u, 0);
|
||||
Gl.glVertex3f(r1 * (float) Math.Cos(angle + 3 * da), r1 * (float) Math.Sin(angle + 3 * da), width * 0.5f);
|
||||
Gl.glVertex3f(r1 * (float) Math.Cos(angle + 3 * da), r1 * (float) Math.Sin(angle + 3 * da), -width * 0.5f);
|
||||
Gl.glNormal3f((float) Math.Cos(angle), (float) Math.Sin(angle), 0);
|
||||
}
|
||||
|
||||
Gl.glVertex3f(r1 * (float) Math.Cos(0), r1 * (float) Math.Sin(0), width * 0.5f);
|
||||
Gl.glVertex3f(r1 * (float) Math.Cos(0), r1 * (float) Math.Sin(0), -width * 0.5f);
|
||||
Gl.glEnd();
|
||||
|
||||
Gl.glShadeModel(Gl.GL_SMOOTH);
|
||||
|
||||
// draw inside radius cylinder
|
||||
Gl.glBegin(Gl.GL_QUAD_STRIP);
|
||||
for(i = 0; i <= teeth; i++) {
|
||||
angle = i * 2 * PI / teeth;
|
||||
Gl.glNormal3f((float) -Math.Cos(angle), (float) -Math.Sin(angle), 0);
|
||||
Gl.glVertex3f(r0 * (float) Math.Cos(angle), r0 * (float) Math.Sin(angle), -width * 0.5f);
|
||||
Gl.glVertex3f(r0 * (float) Math.Cos(angle), r0 * (float) Math.Sin(angle), width * 0.5f);
|
||||
}
|
||||
Gl.glEnd();
|
||||
}
|
||||
#endregion Gear(float innerRadius, float outerRadius, float width, float teeth, float toothDepth)
|
||||
|
||||
#region Init()
|
||||
/// <summary>
|
||||
/// Performs program and OpenGL initialization.
|
||||
/// </summary>
|
||||
/// <param name="arguments">
|
||||
/// The command line arguments.
|
||||
/// </param>
|
||||
private static void Init() {
|
||||
Gl.glLightfv(Gl.GL_LIGHT0, Gl.GL_POSITION, lightPosition);
|
||||
Gl.glEnable(Gl.GL_CULL_FACE);
|
||||
Gl.glEnable(Gl.GL_LIGHTING);
|
||||
Gl.glEnable(Gl.GL_LIGHT0);
|
||||
Gl.glEnable(Gl.GL_DEPTH_TEST);
|
||||
|
||||
// make the gears
|
||||
gear1 = Gl.glGenLists(1);
|
||||
Gl.glNewList(gear1, Gl.GL_COMPILE);
|
||||
Gl.glMaterialfv(Gl.GL_FRONT, Gl.GL_AMBIENT_AND_DIFFUSE, redMaterial);
|
||||
Gear(1, 4, 1, 20, 0.7f);
|
||||
Gl.glEndList();
|
||||
|
||||
gear2 = Gl.glGenLists(1);
|
||||
Gl.glNewList(gear2, Gl.GL_COMPILE);
|
||||
Gl.glMaterialfv(Gl.GL_FRONT, Gl.GL_AMBIENT_AND_DIFFUSE, greenMaterial);
|
||||
Gear(0.5f, 2, 2, 10, 0.7f);
|
||||
Gl.glEndList();
|
||||
|
||||
gear3 = Gl.glGenLists(1);
|
||||
Gl.glNewList(gear3, Gl.GL_COMPILE);
|
||||
Gl.glMaterialfv(Gl.GL_FRONT, Gl.GL_AMBIENT_AND_DIFFUSE, blueMaterial);
|
||||
Gear(1.3f, 2, 0.5f, 10, 0.7f);
|
||||
Gl.glEndList();
|
||||
|
||||
Gl.glEnable(Gl.GL_NORMALIZE);
|
||||
|
||||
//for(int i = 0; i < arguments.Length; i++) {
|
||||
// if(arguments[i] == "-info") {
|
||||
// Console.WriteLine("GL_RENDERER = {0}", Gl.glGetString(Gl.GL_RENDERER));
|
||||
// Console.WriteLine("GL_VERSION = {0}", Gl.glGetString(Gl.GL_VERSION));
|
||||
// Console.WriteLine("GL_VENDOR = {0}", Gl.glGetString(Gl.GL_VENDOR));
|
||||
// Console.WriteLine("GL_EXTENSIONS = {0}", Gl.glGetString(Gl.GL_EXTENSIONS));
|
||||
// }
|
||||
// else if(arguments[i] == "-exit") {
|
||||
// autoExit = 30;
|
||||
// Console.WriteLine("Auto Exit after {0} seconds.", autoExit);
|
||||
// }
|
||||
//}
|
||||
}
|
||||
#endregion Init()
|
||||
|
||||
// --- Private GLFW Callback Methods ---
|
||||
#region Key(int key, int action)
|
||||
/// <summary>
|
||||
/// Changes view angle, exits the app.
|
||||
/// </summary>
|
||||
/// <param name="key">
|
||||
/// The key.
|
||||
/// </param>
|
||||
/// <param name="action">
|
||||
/// The key action.
|
||||
/// </param>
|
||||
private static void Key(int key, int action) {
|
||||
if(action != Glfw.GLFW_PRESS) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch(key) {
|
||||
case (int) 'Z':
|
||||
if(Glfw.glfwGetKey(Glfw.GLFW_KEY_LSHIFT) == Gl.GL_TRUE) {
|
||||
rotateZ -= 5;
|
||||
}
|
||||
else {
|
||||
rotateZ += 5;
|
||||
}
|
||||
break;
|
||||
case Glfw.GLFW_KEY_ESC:
|
||||
isRunning = false;
|
||||
break;
|
||||
case Glfw.GLFW_KEY_UP:
|
||||
rotateX += 5;
|
||||
break;
|
||||
case Glfw.GLFW_KEY_DOWN:
|
||||
rotateX -= 5;
|
||||
break;
|
||||
case Glfw.GLFW_KEY_LEFT:
|
||||
rotateY += 5;
|
||||
break;
|
||||
case Glfw.GLFW_KEY_RIGHT:
|
||||
rotateY -= 5;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endregion Key(int key, int action)
|
||||
|
||||
#region Reshape(int width, int height)
|
||||
/// <summary>
|
||||
/// Reshape callback.
|
||||
/// </summary>
|
||||
/// <param name="width">
|
||||
/// The window width.
|
||||
/// </param>
|
||||
/// <param name="height">
|
||||
/// The window height.
|
||||
/// </param>
|
||||
private static void Reshape(int width, int height) {
|
||||
float h = (float) height / (float) width;
|
||||
float xMax, zNear, zFar;
|
||||
|
||||
zNear = 5;
|
||||
zFar = 30;
|
||||
xMax = zNear * 0.5f;
|
||||
|
||||
Gl.glViewport(0, 0, width, height);
|
||||
Gl.glMatrixMode(Gl.GL_PROJECTION);
|
||||
Gl.glLoadIdentity();
|
||||
Gl.glFrustum(-xMax, xMax, -xMax * h, xMax * h, zNear, zFar);
|
||||
Gl.glMatrixMode(Gl.GL_MODELVIEW);
|
||||
Gl.glLoadIdentity();
|
||||
Gl.glTranslatef(0, 0, -20);
|
||||
}
|
||||
#endregion Reshape(int width, int height)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
namespace GlfwExamples
|
||||
{
|
||||
partial class GlfwExamples
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.lstExamples = new System.Windows.Forms.ListBox();
|
||||
this.btnRun = new System.Windows.Forms.Button();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// lstExamples
|
||||
//
|
||||
this.lstExamples.FormattingEnabled = true;
|
||||
this.lstExamples.Location = new System.Drawing.Point(13, 13);
|
||||
this.lstExamples.Name = "lstExamples";
|
||||
this.lstExamples.Size = new System.Drawing.Size(258, 173);
|
||||
this.lstExamples.Sorted = true;
|
||||
this.lstExamples.TabIndex = 0;
|
||||
this.lstExamples.DoubleClick += new System.EventHandler(this.lstExamples_SelectedIndexChanged);
|
||||
//
|
||||
// btnRun
|
||||
//
|
||||
this.btnRun.Location = new System.Drawing.Point(94, 192);
|
||||
this.btnRun.Name = "btnRun";
|
||||
this.btnRun.Size = new System.Drawing.Size(95, 23);
|
||||
this.btnRun.TabIndex = 1;
|
||||
this.btnRun.Text = "Run";
|
||||
this.btnRun.UseVisualStyleBackColor = true;
|
||||
this.btnRun.Click += new System.EventHandler(this.btnRun_Click);
|
||||
//
|
||||
// GlfwExamples
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(283, 224);
|
||||
this.Controls.Add(this.btnRun);
|
||||
this.Controls.Add(this.lstExamples);
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
||||
this.MaximizeBox = false;
|
||||
this.Name = "GlfwExamples";
|
||||
this.Text = "GlfwExamples";
|
||||
this.Load += new System.EventHandler(this.frmExamples_Load);
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.ListBox lstExamples;
|
||||
private System.Windows.Forms.Button btnRun;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
MIT License
|
||||
Copyright ©2003-2004 Randy Ridge
|
||||
http://www.taoframework.com
|
||||
All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -0,0 +1,26 @@
|
|||
GlfwExamples
|
||||
http://www.taoframework.com
|
||||
Copyright ©2003-2004 Randy Ridge, All rights reserved.
|
||||
|
||||
These are C# ports of some OpenGL examples developed for GLFW, the originals
|
||||
are available from http://glfw.sourceforge.net.
|
||||
|
||||
These examples use Tao.OpenGl and Tao.Glfw. Make sure you have the
|
||||
appropriate native GLFW libraries for your system installed.
|
||||
|
||||
These examples are fairly well documented, however, do not take
|
||||
them to be 'best practices' for .NET OpenGL development. The
|
||||
intent of these ports is as an introduction or as a comparison
|
||||
against the original native versions.
|
||||
|
||||
If you'd like to contribute you can port the remaining examples as supplied
|
||||
with GLFW. I never got around to them, but they look pretty trivial.
|
||||
|
||||
Randy Ridge
|
||||
http://www.taoframework.com
|
||||
|
||||
|
||||
Change Log:
|
||||
|
||||
April 23, 2004:
|
||||
Initial release, version 1.0.0.0.
|
|
@ -0,0 +1,48 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using System.Reflection;
|
||||
|
||||
namespace GlfwExamples
|
||||
{
|
||||
public partial class GlfwExamples : Form
|
||||
{
|
||||
public GlfwExamples()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void frmExamples_Load(object sender, EventArgs e)
|
||||
{
|
||||
Type[] types = Assembly.GetExecutingAssembly().GetTypes();
|
||||
foreach (Type type in types)
|
||||
{
|
||||
MemberInfo[] runMethods = type.GetMember("Run");
|
||||
foreach (MemberInfo run in runMethods)
|
||||
{
|
||||
lstExamples.Items.Add(type.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void btnRun_Click(object sender, EventArgs e)
|
||||
{
|
||||
SelectExample();
|
||||
}
|
||||
|
||||
private void SelectExample()
|
||||
{
|
||||
Type example = Assembly.GetExecutingAssembly().GetType("GlfwExamples." + lstExamples.SelectedItem.ToString(), true, true);
|
||||
example.InvokeMember("Run", BindingFlags.InvokeMethod, null, null, null);
|
||||
}
|
||||
|
||||
private void lstExamples_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
SelectExample();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
|
@ -0,0 +1,324 @@
|
|||
#region License
|
||||
/*
|
||||
MIT License
|
||||
Copyright ©2003-2004 Randy Ridge
|
||||
http://www.taoframework.com
|
||||
All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#endregion License
|
||||
|
||||
#region Original Credits/License
|
||||
/*
|
||||
Copyright (c) 2002-2004 Marcus Geelnard
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would
|
||||
be appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not
|
||||
be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
|
||||
Marcus Geelnard
|
||||
marcus.geelnard at home.se
|
||||
*/
|
||||
#endregion Original Credits/License
|
||||
|
||||
using System;
|
||||
using Tao.Glfw;
|
||||
using Tao.OpenGl;
|
||||
|
||||
namespace GlfwExamples {
|
||||
#region Class Documentation
|
||||
/// <summary>
|
||||
/// This is a small test application for GLFW.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Keyboard input test.
|
||||
/// </remarks>
|
||||
#endregion Class Documentation
|
||||
public sealed class KeyTest {
|
||||
// --- Fields ---
|
||||
#region Private Static Fields
|
||||
private static bool isRunning = true;
|
||||
private static bool isKeyRepeat = false;
|
||||
private static bool isSystemKeys = true;
|
||||
#endregion Private Static Fields
|
||||
|
||||
// --- Application Entry Point ---
|
||||
#region Run()
|
||||
/// <summary>
|
||||
/// The main entry point for the application.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
public static void Run() {
|
||||
int windowWidth, windowHeight;
|
||||
double currentTime;
|
||||
|
||||
// Initialise GLFW
|
||||
Glfw.glfwInit();
|
||||
|
||||
// Open OpenGL window
|
||||
if(Glfw.glfwOpenWindow(250, 100, 0, 0, 0, 0, 0, 0, Glfw.GLFW_WINDOW) == Gl.GL_FALSE) {
|
||||
Glfw.glfwTerminate();
|
||||
return;
|
||||
}
|
||||
|
||||
// Set key callback function
|
||||
Glfw.glfwSetKeyCallback(new Glfw.GLFWkeyfun(Key));
|
||||
|
||||
// Set title
|
||||
Glfw.glfwSetWindowTitle("Press some keys!");
|
||||
|
||||
// Main loop
|
||||
while(isRunning) {
|
||||
// Get time
|
||||
currentTime = Glfw.glfwGetTime();
|
||||
|
||||
// Get window size (may be different than the requested size)
|
||||
Glfw.glfwGetWindowSize(out windowWidth, out windowHeight);
|
||||
windowHeight = windowHeight > 0 ? windowHeight : 1;
|
||||
|
||||
// Set viewport
|
||||
Gl.glViewport(0, 0, windowWidth, windowHeight);
|
||||
|
||||
// Clear color buffer
|
||||
Gl.glClearColor((float) (0.5f + 0.5f * (float) Math.Sin(3.0 * currentTime)),
|
||||
0, 0, 0);
|
||||
Gl.glClear(Gl.GL_COLOR_BUFFER_BIT);
|
||||
|
||||
// Swap buffers
|
||||
Glfw.glfwSwapBuffers();
|
||||
|
||||
// Check if the window was closed
|
||||
if(Glfw.glfwGetWindowParam(Glfw.GLFW_OPENED) == Gl.GL_FALSE) {
|
||||
isRunning = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Close OpenGL window and terminate GLFW
|
||||
Glfw.glfwTerminate();
|
||||
}
|
||||
#endregion Run()
|
||||
|
||||
// --- Private GLFW Callback Methods ---
|
||||
#region Key(int key, int action)
|
||||
/// <summary>
|
||||
/// Handles GLFW key callback.
|
||||
/// </summary>
|
||||
/// <param name="key">
|
||||
/// The key.
|
||||
/// </param>
|
||||
/// <param name="action">
|
||||
/// The key action.
|
||||
/// </param>
|
||||
private static void Key(int key, int action) {
|
||||
if(action != Glfw.GLFW_PRESS) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch(key) {
|
||||
case Glfw.GLFW_KEY_ESC:
|
||||
Console.WriteLine("ESC => quit program");
|
||||
isRunning = false;
|
||||
break;
|
||||
case Glfw.GLFW_KEY_F1:
|
||||
case Glfw.GLFW_KEY_F2:
|
||||
case Glfw.GLFW_KEY_F3:
|
||||
case Glfw.GLFW_KEY_F4:
|
||||
case Glfw.GLFW_KEY_F5:
|
||||
case Glfw.GLFW_KEY_F6:
|
||||
case Glfw.GLFW_KEY_F7:
|
||||
case Glfw.GLFW_KEY_F8:
|
||||
case Glfw.GLFW_KEY_F9:
|
||||
case Glfw.GLFW_KEY_F10:
|
||||
case Glfw.GLFW_KEY_F11:
|
||||
case Glfw.GLFW_KEY_F12:
|
||||
case Glfw.GLFW_KEY_F13:
|
||||
case Glfw.GLFW_KEY_F14:
|
||||
case Glfw.GLFW_KEY_F15:
|
||||
case Glfw.GLFW_KEY_F16:
|
||||
case Glfw.GLFW_KEY_F17:
|
||||
case Glfw.GLFW_KEY_F18:
|
||||
case Glfw.GLFW_KEY_F19:
|
||||
case Glfw.GLFW_KEY_F20:
|
||||
case Glfw.GLFW_KEY_F21:
|
||||
case Glfw.GLFW_KEY_F22:
|
||||
case Glfw.GLFW_KEY_F23:
|
||||
case Glfw.GLFW_KEY_F24:
|
||||
case Glfw.GLFW_KEY_F25:
|
||||
Console.WriteLine("F{0}", 1 + key - Glfw.GLFW_KEY_F1);
|
||||
break;
|
||||
case Glfw.GLFW_KEY_UP:
|
||||
Console.WriteLine("UP");
|
||||
break;
|
||||
case Glfw.GLFW_KEY_DOWN:
|
||||
Console.WriteLine("DOWN");
|
||||
break;
|
||||
case Glfw.GLFW_KEY_LEFT:
|
||||
Console.WriteLine("LEFT");
|
||||
break;
|
||||
case Glfw.GLFW_KEY_RIGHT:
|
||||
Console.WriteLine("RIGHT");
|
||||
break;
|
||||
case Glfw.GLFW_KEY_LSHIFT:
|
||||
Console.WriteLine("LSHIFT");
|
||||
break;
|
||||
case Glfw.GLFW_KEY_RSHIFT:
|
||||
Console.WriteLine("RSHIFT");
|
||||
break;
|
||||
case Glfw.GLFW_KEY_LCTRL:
|
||||
Console.WriteLine("LCTRL");
|
||||
break;
|
||||
case Glfw.GLFW_KEY_RCTRL:
|
||||
Console.WriteLine("RCTRL");
|
||||
break;
|
||||
case Glfw.GLFW_KEY_LALT:
|
||||
Console.WriteLine("LALT");
|
||||
break;
|
||||
case Glfw.GLFW_KEY_RALT:
|
||||
Console.WriteLine("RALT");
|
||||
break;
|
||||
case Glfw.GLFW_KEY_TAB:
|
||||
Console.WriteLine("TAB");
|
||||
break;
|
||||
case Glfw.GLFW_KEY_ENTER:
|
||||
Console.WriteLine("ENTER");
|
||||
break;
|
||||
case Glfw.GLFW_KEY_BACKSPACE:
|
||||
Console.WriteLine("BACKSPACE");
|
||||
break;
|
||||
case Glfw.GLFW_KEY_INSERT:
|
||||
Console.WriteLine("INSERT");
|
||||
break;
|
||||
case Glfw.GLFW_KEY_DEL:
|
||||
Console.WriteLine("DEL");
|
||||
break;
|
||||
case Glfw.GLFW_KEY_PAGEUP:
|
||||
Console.WriteLine("PAGEUP");
|
||||
break;
|
||||
case Glfw.GLFW_KEY_PAGEDOWN:
|
||||
Console.WriteLine("PAGEDOWN");
|
||||
break;
|
||||
case Glfw.GLFW_KEY_HOME:
|
||||
Console.WriteLine("HOME");
|
||||
break;
|
||||
case Glfw.GLFW_KEY_END:
|
||||
Console.WriteLine("END");
|
||||
break;
|
||||
case Glfw.GLFW_KEY_KP_0:
|
||||
Console.WriteLine("KEYPAD 0");
|
||||
break;
|
||||
case Glfw.GLFW_KEY_KP_1:
|
||||
Console.WriteLine("KEYPAD 1");
|
||||
break;
|
||||
case Glfw.GLFW_KEY_KP_2:
|
||||
Console.WriteLine("KEYPAD 2");
|
||||
break;
|
||||
case Glfw.GLFW_KEY_KP_3:
|
||||
Console.WriteLine("KEYPAD 3");
|
||||
break;
|
||||
case Glfw.GLFW_KEY_KP_4:
|
||||
Console.WriteLine("KEYPAD 4");
|
||||
break;
|
||||
case Glfw.GLFW_KEY_KP_5:
|
||||
Console.WriteLine("KEYPAD 5");
|
||||
break;
|
||||
case Glfw.GLFW_KEY_KP_6:
|
||||
Console.WriteLine("KEYPAD 6");
|
||||
break;
|
||||
case Glfw.GLFW_KEY_KP_7:
|
||||
Console.WriteLine("KEYPAD 7");
|
||||
break;
|
||||
case Glfw.GLFW_KEY_KP_8:
|
||||
Console.WriteLine("KEYPAD 8");
|
||||
break;
|
||||
case Glfw.GLFW_KEY_KP_9:
|
||||
Console.WriteLine("KEYPAD 9");
|
||||
break;
|
||||
case Glfw.GLFW_KEY_KP_DIVIDE:
|
||||
Console.WriteLine("KEYPAD DIVIDE");
|
||||
break;
|
||||
case Glfw.GLFW_KEY_KP_MULTIPLY:
|
||||
Console.WriteLine("KEYPAD MULTIPLY");
|
||||
break;
|
||||
case Glfw.GLFW_KEY_KP_SUBTRACT:
|
||||
Console.WriteLine("KEYPAD SUBTRACT");
|
||||
break;
|
||||
case Glfw.GLFW_KEY_KP_ADD:
|
||||
Console.WriteLine("KEYPAD ADD");
|
||||
break;
|
||||
case Glfw.GLFW_KEY_KP_DECIMAL:
|
||||
Console.WriteLine("KEYPAD DECIMAL");
|
||||
break;
|
||||
case Glfw.GLFW_KEY_KP_EQUAL:
|
||||
Console.WriteLine("KEYPAD =");
|
||||
break;
|
||||
case Glfw.GLFW_KEY_KP_ENTER:
|
||||
Console.WriteLine("KEYPAD ENTER");
|
||||
break;
|
||||
case Glfw.GLFW_KEY_SPACE:
|
||||
Console.WriteLine("SPACE");
|
||||
break;
|
||||
case (int) 'R':
|
||||
isKeyRepeat = !isKeyRepeat;
|
||||
if(isKeyRepeat) {
|
||||
Glfw.glfwEnable(Glfw.GLFW_KEY_REPEAT);
|
||||
}
|
||||
else {
|
||||
Glfw.glfwDisable(Glfw.GLFW_KEY_REPEAT);
|
||||
}
|
||||
Console.WriteLine("R => Key repeat: {0}", isKeyRepeat ? "ON" : "OFF");
|
||||
break;
|
||||
case (int) 'S':
|
||||
isSystemKeys = !isSystemKeys;
|
||||
if(isSystemKeys) {
|
||||
Glfw.glfwEnable(Glfw.GLFW_SYSTEM_KEYS);
|
||||
}
|
||||
else {
|
||||
Glfw.glfwDisable(Glfw.GLFW_SYSTEM_KEYS);
|
||||
}
|
||||
Console.WriteLine("S => System keys: {0}", isSystemKeys ? "ON" : "OFF");
|
||||
break;
|
||||
default:
|
||||
if(key > 0 && key < 256) {
|
||||
Console.WriteLine("{0}", (char) key);
|
||||
}
|
||||
else {
|
||||
Console.WriteLine("???");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endregion Key(int key, int action)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
#region License
|
||||
/*
|
||||
MIT License
|
||||
Copyright ©2003-2004 Randy Ridge
|
||||
http://www.taoframework.com
|
||||
All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#endregion License
|
||||
|
||||
#region Original Credits/License
|
||||
/*
|
||||
Copyright (c) 2002-2004 Marcus Geelnard
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would
|
||||
be appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not
|
||||
be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
|
||||
Marcus Geelnard
|
||||
marcus.geelnard at home.se
|
||||
*/
|
||||
#endregion Original Credits/License
|
||||
|
||||
using System;
|
||||
using Tao.Glfw;
|
||||
using Tao.OpenGl;
|
||||
|
||||
namespace GlfwExamples {
|
||||
#region Class Documentation
|
||||
/// <summary>
|
||||
/// This is a small test application for GLFW.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The program lists all available fullscreen video modes.
|
||||
/// </remarks>
|
||||
#endregion Class Documentation
|
||||
public sealed class ListModes {
|
||||
// --- Fields ---
|
||||
#region Private Constants
|
||||
// Maximum number of modes that we want to list
|
||||
private const int MAX_NUMBER_OF_MODES = 400;
|
||||
#endregion Private Constants
|
||||
|
||||
// --- Application Entry Point ---
|
||||
#region Run()
|
||||
/// <summary>
|
||||
/// The main entry point for the application.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
public static void Run() {
|
||||
Glfw.GLFWvidmode desktopMode;
|
||||
Glfw.GLFWvidmode[] availableModes = new Glfw.GLFWvidmode[MAX_NUMBER_OF_MODES];
|
||||
int modeCount;
|
||||
|
||||
// Initialize GLFW
|
||||
if(Glfw.glfwInit() == Gl.GL_FALSE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Show desktop video mode
|
||||
Glfw.glfwGetDesktopMode(out desktopMode);
|
||||
Console.WriteLine("Desktop mode: {0} x {1} x {2}", desktopMode.Width,
|
||||
desktopMode.Height, desktopMode.RedBits + desktopMode.GreenBits +
|
||||
desktopMode.BlueBits);
|
||||
|
||||
// List available video modes
|
||||
modeCount = Glfw.glfwGetVideoModes(availableModes, MAX_NUMBER_OF_MODES);
|
||||
Console.WriteLine("Available modes:");
|
||||
for(int i = 0; i < modeCount; i++) {
|
||||
Console.WriteLine("{0}: {1} x {2} x {3}", i, availableModes[i].Width,
|
||||
availableModes[i].Height, availableModes[i].RedBits +
|
||||
availableModes[i].GreenBits + availableModes[i].BlueBits);
|
||||
}
|
||||
|
||||
// Terminate GLFW
|
||||
Glfw.glfwTerminate();
|
||||
|
||||
Console.Write("\n\nPress Enter to exit...");
|
||||
Console.ReadLine();
|
||||
}
|
||||
#endregion Run()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,919 @@
|
|||
#region License
|
||||
/*
|
||||
MIT License
|
||||
Copyright ©2003-2006 The Tao Framework Team
|
||||
http://www.taoframework.com
|
||||
All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#endregion License
|
||||
|
||||
#region Tao Port Credits
|
||||
/* Original Tao port by Simon <the-real-sim@gmx.de> */
|
||||
#endregion Tao Port Credits
|
||||
|
||||
#region Original Credits/License
|
||||
/*
|
||||
Copyright (c) 2002-2004 Marcus Geelnard
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would
|
||||
be appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not
|
||||
be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
|
||||
Marcus Geelnard
|
||||
marcus.geelnard at home.se
|
||||
*/
|
||||
|
||||
//========================================================================
|
||||
// This is a small test application for GLFW.
|
||||
// This is an OpenGL port of the famous "PONG" game (the first computer
|
||||
// game ever?). It is very simple, and could be improved alot. It was
|
||||
// created in order to show off the gaming capabilities of GLFW.
|
||||
//========================================================================
|
||||
#endregion Original Credits/License
|
||||
|
||||
using System;
|
||||
using Tao.Glfw;
|
||||
using Tao.OpenGl;
|
||||
|
||||
namespace GlfwExamples {
|
||||
#region Class Documentation
|
||||
/// <summary>
|
||||
/// This is a small test application for GLFW
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is an OpenGL port of the famous "PONG" game (the first computer
|
||||
/// game ever?). It is very simple, and could be improved alot. It was
|
||||
/// created in order to show off the gaming capabilities of GLFW.
|
||||
/// </remarks>
|
||||
#endregion Class Documentation
|
||||
public sealed class Pong {
|
||||
|
||||
#region fields
|
||||
|
||||
/// <summary> Screen resolution: width </summary>
|
||||
public static int width = 640;
|
||||
|
||||
/// <summary> Screen resolution: height </summary>
|
||||
public static int height = 480;
|
||||
|
||||
/// <summary> Player size (units): X dimension </summary>
|
||||
public static float playerSizeX = 0.05f;
|
||||
|
||||
/// <summary> Player size (units): Y dimension </summary>
|
||||
public static float playerSizeY = 0.15f;
|
||||
|
||||
/// <summary> Ball size (units) </summary>
|
||||
public static float ballSize = 0.02f;
|
||||
|
||||
/// <summary> Maximum player movement speed (units / second) </summary>
|
||||
public static float maxSpeed = 1.5f;
|
||||
|
||||
/// <summary> Player movement acceleration (units / seconds^2) </summary>
|
||||
public static float acceleration = 4.0f;
|
||||
|
||||
/// <summary> Player movement deceleration (units / seconds^2) </summary>
|
||||
public static float deceleration = 2.0f;
|
||||
|
||||
/// <summary> Ball movement speed (units / second) </summary>
|
||||
public static float ballSpeed = 0.4f;
|
||||
|
||||
/// <summary>
|
||||
/// Menu options
|
||||
/// </summary>
|
||||
public enum MenuOption {
|
||||
None,Play,Quit
|
||||
}
|
||||
/// <summary>
|
||||
/// Game events
|
||||
/// </summary>
|
||||
public enum GameEvent {
|
||||
NobodyWins,
|
||||
Player1Wins,
|
||||
Player2Wins
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Game winners
|
||||
/// </summary>
|
||||
public enum Winner {
|
||||
Nobody,
|
||||
Player1,
|
||||
Player2
|
||||
}
|
||||
|
||||
/// <summary> The winning player </summary>
|
||||
public static int winningPlayer;
|
||||
|
||||
/// <summary>
|
||||
/// Camera positions
|
||||
/// </summary>
|
||||
public enum CameraPosition {
|
||||
Classic,
|
||||
Above,
|
||||
Spectator
|
||||
}
|
||||
|
||||
/// <summary> Default camera position </summary>
|
||||
public static CameraPosition cameraDefault = CameraPosition.Classic;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Textures
|
||||
/// </summary>
|
||||
public enum Textures {
|
||||
Title,
|
||||
Menu,
|
||||
Instr,
|
||||
Winner1,
|
||||
Winner2,
|
||||
Field,
|
||||
Num_textures
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Texture file names
|
||||
/// </summary>
|
||||
public static String[] TexName = {"Data/pong3d_title.tga",
|
||||
"Data/pong3d_menu.tga",
|
||||
"Data/pong3d_instr.tga",
|
||||
"Data/pong3d_winner1.tga",
|
||||
"Data/pong3d_winner2.tga",
|
||||
"Data/pong3d_field.tga"};
|
||||
|
||||
/// <summary> Frame information </summary>
|
||||
public static double thisTime, oldTime, dt, startTime;
|
||||
|
||||
/// <summary> Camera position information </summary>
|
||||
public static CameraPosition cameraPos;
|
||||
|
||||
/// <summary>
|
||||
/// Player information
|
||||
/// </summary>
|
||||
public struct Player {
|
||||
/// <summary> Player Id: Player 1 or Player 2 </summary>
|
||||
public int id;
|
||||
/// <summary> Y-position of player paddle: -1.0 to +1.0 </summary>
|
||||
public double posY;
|
||||
/// <summary> Maximum speed of player paddle: -MAX_SPEED to +MAX_SPEED </summary>
|
||||
public double speedY;
|
||||
}
|
||||
|
||||
/// <summary>Players</summary>
|
||||
public static Player Player1,Player2;
|
||||
|
||||
/// <summary> Ball information </summary>
|
||||
public struct Ball {
|
||||
public double posX, posY;
|
||||
public double speedX, speedY;
|
||||
}
|
||||
|
||||
/// <summary> The game ball </summary>
|
||||
public static Ball gameBall;
|
||||
|
||||
#region Lighting configuration
|
||||
public static float[] envAmbient;
|
||||
public static float[] light1Position;
|
||||
public static float[] light1Diffuse;
|
||||
public static float[] light1Ambient;
|
||||
#endregion Lighting configuration
|
||||
|
||||
#region Object material properties
|
||||
public static float[] Player1Diffuse;
|
||||
public static float[] Player1Ambient;
|
||||
public static float[] Player2Diffuse;
|
||||
public static float[] Player2Ambient;
|
||||
public static float[] ballDiffuse;
|
||||
public static float[] ballAmbient;
|
||||
public static float[] borderDiffuse;
|
||||
public static float[] borderAmbient;
|
||||
public static float[] floorDiffuse;
|
||||
public static float[] floorAmbient;
|
||||
#endregion Object material properties
|
||||
|
||||
/// <summary> OpenGL texture object IDs </summary>
|
||||
public static int[] TexId = new int[(int)Textures.Num_textures];
|
||||
|
||||
#endregion fields
|
||||
|
||||
/// <summary>
|
||||
/// LoadTextures
|
||||
///
|
||||
/// Load textures from disk and upload to OpenGL card
|
||||
/// </summary>
|
||||
public static void LoadTextures() {
|
||||
int i;
|
||||
|
||||
// Generate texture objects
|
||||
Gl.glGenTextures((int)Textures.Num_textures, TexId);
|
||||
|
||||
// Load textures
|
||||
for(i = 0; i < (int)Textures.Num_textures; i++) {
|
||||
|
||||
// Select texture object
|
||||
Gl.glBindTexture(Gl.GL_TEXTURE_2D, TexId[i]);
|
||||
|
||||
// Set texture parameters
|
||||
Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_WRAP_S, Gl.GL_REPEAT);
|
||||
Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_WRAP_T, Gl.GL_REPEAT);
|
||||
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);
|
||||
|
||||
// Upload texture from file to texture memory
|
||||
Glfw.glfwLoadTexture2D(TexName[i], 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DrawImage
|
||||
///
|
||||
/// Draw a 2d image as a texture
|
||||
/// </summary>
|
||||
/// <param name="texnum">An int</param>
|
||||
/// <param name="x1">A float</param>
|
||||
/// <param name="x2">A float</param>
|
||||
/// <param name="y1">A float</param>
|
||||
/// <param name="y2">A float</param>
|
||||
public static void DrawImage(int texnum, float x1, float x2, float y1, float y2) {
|
||||
Gl.glEnable(Gl.GL_TEXTURE_2D);
|
||||
Gl.glBindTexture(Gl.GL_TEXTURE_2D, TexId[texnum]);
|
||||
Gl.glBegin(Gl.GL_QUADS);
|
||||
Gl.glTexCoord2f(0.0f, 1.0f);
|
||||
Gl.glVertex2f(x1, y1);
|
||||
Gl.glTexCoord2f(1.0f, 1.0f);
|
||||
Gl.glVertex2f(x2, y1);
|
||||
Gl.glTexCoord2f(1.0f, 0.0f);
|
||||
Gl.glVertex2f(x2, y2);
|
||||
Gl.glTexCoord2f(0.0f, 0.0f);
|
||||
Gl.glVertex2f(x1, y2);
|
||||
Gl.glEnd();
|
||||
Gl.glDisable(Gl.GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// GameMenu
|
||||
///
|
||||
/// Returns menu option
|
||||
/// </summary>
|
||||
/// <returns>A MenuOption</returns>
|
||||
public static MenuOption GameMenu() {
|
||||
MenuOption option;
|
||||
|
||||
// Enable sticky keys
|
||||
Glfw.glfwEnable(Glfw.GLFW_STICKY_KEYS);
|
||||
|
||||
// Wait for a game menu key to be pressed
|
||||
do
|
||||
{
|
||||
// Get window size
|
||||
Glfw.glfwGetWindowSize(out width, out height);
|
||||
|
||||
// Set viewport
|
||||
Gl.glViewport(0, 0, width, height);
|
||||
|
||||
// Clear display
|
||||
Gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
Gl.glClear(Gl.GL_COLOR_BUFFER_BIT);
|
||||
|
||||
// Setup projection matrix
|
||||
Gl.glMatrixMode(Gl.GL_PROJECTION);
|
||||
Gl.glLoadIdentity();
|
||||
Gl.glOrtho(0.0f, 1.0f, 1.0f, 0.0f, -1.0f, 1.0f);
|
||||
|
||||
// Setup modelview matrix
|
||||
Gl.glMatrixMode(Gl.GL_MODELVIEW);
|
||||
Gl.glLoadIdentity();
|
||||
|
||||
// Display title
|
||||
Gl.glColor3f(1.0f, 1.0f, 1.0f);
|
||||
DrawImage((int)Textures.Title, 0.1f, 0.9f, 0.0f, 0.3f);
|
||||
|
||||
// Display menu
|
||||
Gl.glColor3f(1.0f, 1.0f, 0.0f);
|
||||
DrawImage((int)Textures.Menu, 0.38f, 0.62f, 0.35f, 0.5f);
|
||||
|
||||
// Display instructions
|
||||
Gl.glColor3f(0.0f, 1.0f, 1.0f);
|
||||
DrawImage((int)Textures.Instr, 0.32f, 0.68f, 0.65f, 0.85f);
|
||||
|
||||
// Swap buffers
|
||||
Glfw.glfwSwapBuffers();
|
||||
|
||||
// Check for keys
|
||||
if(Glfw.glfwGetKey('Q') == Gl.GL_TRUE || Glfw.glfwGetWindowParam(Glfw.GLFW_OPENED) == Gl.GL_FALSE) {
|
||||
option = MenuOption.Quit;
|
||||
}
|
||||
else if(Glfw.glfwGetKey(Glfw.GLFW_KEY_F1) == Gl.GL_TRUE) {
|
||||
option = MenuOption.Play;
|
||||
}
|
||||
else {
|
||||
option = MenuOption.None;
|
||||
}
|
||||
|
||||
// To avoid horrible busy waiting, sleep for at least 20 ms
|
||||
Glfw.glfwSleep(0.02);
|
||||
}
|
||||
while( option == MenuOption.None );
|
||||
|
||||
// Disable sticky keys
|
||||
Glfw.glfwDisable(Glfw.GLFW_STICKY_KEYS);
|
||||
|
||||
return option;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// NewGame
|
||||
///
|
||||
/// Initialize a new game
|
||||
/// </summary>
|
||||
public static void NewGame() {
|
||||
// Frame information
|
||||
startTime = thisTime = Glfw.glfwGetTime();
|
||||
|
||||
// Camera information
|
||||
cameraPos = cameraDefault;
|
||||
|
||||
// Player 1 information
|
||||
Player1.posY = 0.0;
|
||||
Player1.speedY = 0.0;
|
||||
|
||||
// Player 2 information
|
||||
Player2.posY = 0.0;
|
||||
Player2.speedY = 0.0;
|
||||
|
||||
// Ball information
|
||||
gameBall.posX = -1.0 + playerSizeX;
|
||||
gameBall.posY = Player1.posY;
|
||||
gameBall.speedX = 1.0;
|
||||
gameBall.speedY = 1.0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// PlayerControl
|
||||
/// </summary>
|
||||
public static void PlayerControl() {
|
||||
float[] joy1pos = new float[2];
|
||||
float[] joy2pos = new float[2];
|
||||
|
||||
// Get joystick X & Y axis positions
|
||||
Glfw.glfwGetJoystickPos(Glfw.GLFW_JOYSTICK_1, out joy1pos[0], 2);
|
||||
Glfw.glfwGetJoystickPos(Glfw.GLFW_JOYSTICK_2, out joy2pos[0], 2);
|
||||
|
||||
// Player 1 control
|
||||
if(Glfw.glfwGetKey('A') == Gl.GL_TRUE || joy1pos[1] > 0.2f) {
|
||||
Player1.speedY += dt * acceleration;
|
||||
if(Player1.speedY > maxSpeed) {
|
||||
Player1.speedY = maxSpeed;
|
||||
}
|
||||
}
|
||||
else if(Glfw.glfwGetKey('Z') == Gl.GL_TRUE || joy1pos[1] < -0.2f) {
|
||||
Player1.speedY -= dt * acceleration;
|
||||
if(Player1.speedY < -maxSpeed) {
|
||||
Player1.speedY = -maxSpeed;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Player1.speedY /= System.Math.Exp(deceleration * dt);
|
||||
}
|
||||
|
||||
// Player 2 control
|
||||
if(Glfw.glfwGetKey('K') == Gl.GL_TRUE || joy2pos[1] > 0.2f) {
|
||||
Player2.speedY += dt * acceleration;
|
||||
if(Player2.speedY > maxSpeed) {
|
||||
Player2.speedY = maxSpeed;
|
||||
}
|
||||
}
|
||||
else if(Glfw.glfwGetKey('M') == Gl.GL_TRUE || joy2pos[1] < -0.2f) {
|
||||
Player2.speedY -= dt * acceleration;
|
||||
if(Player2.speedY < -maxSpeed) {
|
||||
Player2.speedY = -maxSpeed;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Player2.speedY /= System.Math.Exp(deceleration * dt);
|
||||
}
|
||||
|
||||
// Update player 1 position
|
||||
Player1.posY += dt * Player1.speedY;
|
||||
if(Player1.posY > 1.0 - playerSizeY) {
|
||||
Player1.posY = 1.0 - playerSizeY;
|
||||
Player1.speedY = 0.0;
|
||||
}
|
||||
else if(Player1.posY < -1.0 + playerSizeY) {
|
||||
Player1.posY = -1.0 + playerSizeY;
|
||||
Player1.speedY = 0.0;
|
||||
}
|
||||
|
||||
// Update player 2 position
|
||||
Player2.posY += dt * Player2.speedY;
|
||||
if(Player2.posY > 1.0 - playerSizeY) {
|
||||
Player2.posY = 1.0 - playerSizeY;
|
||||
Player2.speedY = 0.0;
|
||||
}
|
||||
else if(Player2.posY < -1.0 + playerSizeY) {
|
||||
Player2.posY = -1.0 + playerSizeY;
|
||||
Player2.speedY = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// UpdateDisplay
|
||||
///
|
||||
/// Draw graphics (all game related OpenGL stuff goes here)
|
||||
/// </summary>
|
||||
public static void UpdateDisplay() {
|
||||
// Get window size
|
||||
Glfw.glfwGetWindowSize(out width, out height);
|
||||
|
||||
// Set viewport
|
||||
Gl.glViewport(0, 0, width, height);
|
||||
|
||||
// Clear display
|
||||
Gl.glClearColor(0.02f, 0.02f, 0.02f, 0.0f);
|
||||
Gl.glClearDepth(1.0f);
|
||||
Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// Setup projection matrix
|
||||
Gl.glMatrixMode(Gl.GL_PROJECTION);
|
||||
Gl.glLoadIdentity();
|
||||
Glu.gluPerspective(
|
||||
55.0f, // Angle of view
|
||||
(float)width / (float)height, // Aspect
|
||||
1.0f, // Near Z
|
||||
100.0f // Far Z
|
||||
);
|
||||
|
||||
// Setup modelview matrix
|
||||
Gl.glMatrixMode(Gl.GL_MODELVIEW);
|
||||
Gl.glLoadIdentity();
|
||||
|
||||
switch(cameraPos) {
|
||||
default:
|
||||
case CameraPosition.Classic:
|
||||
Glu.gluLookAt(
|
||||
0.0f, 0.0f, 2.5f,
|
||||
0.0f, 0.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f
|
||||
);
|
||||
break;
|
||||
|
||||
case CameraPosition.Above:
|
||||
Glu.gluLookAt(
|
||||
0.0f, 0.0f, 2.5f,
|
||||
(float)gameBall.posX, (float)gameBall.posY, 0.0f,
|
||||
0.0f, 1.0f, 0.0f
|
||||
);
|
||||
break;
|
||||
|
||||
case CameraPosition.Spectator:
|
||||
Glu.gluLookAt(
|
||||
0.0f, -2.0, 1.2f,
|
||||
(float)gameBall.posX, (float)gameBall.posY, 0.0f,
|
||||
0.0f, 0.0f, 1.0f
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
// Enable depth testing
|
||||
Gl.glEnable(Gl.GL_DEPTH_TEST);
|
||||
Gl.glDepthFunc(Gl.GL_LEQUAL);
|
||||
|
||||
// Enable lighting
|
||||
Gl.glEnable(Gl.GL_LIGHTING);
|
||||
Gl.glLightModelfv(Gl.GL_LIGHT_MODEL_AMBIENT, envAmbient);
|
||||
Gl.glLightModeli(Gl.GL_LIGHT_MODEL_LOCAL_VIEWER, Gl.GL_TRUE);
|
||||
Gl.glLightModeli(Gl.GL_LIGHT_MODEL_TWO_SIDE, Gl.GL_FALSE);
|
||||
Gl.glLightfv(Gl.GL_LIGHT1, Gl.GL_POSITION, light1Position);
|
||||
Gl.glLightfv(Gl.GL_LIGHT1, Gl.GL_DIFFUSE, light1Diffuse);
|
||||
Gl.glLightfv(Gl.GL_LIGHT1, Gl.GL_AMBIENT, light1Ambient);
|
||||
Gl.glEnable(Gl.GL_LIGHT1);
|
||||
|
||||
// Front face is counter-clock-wise
|
||||
Gl.glFrontFace(Gl.GL_CCW);
|
||||
|
||||
// Enable face culling (not necessary, but speeds up rendering)
|
||||
Gl.glCullFace(Gl.GL_BACK);
|
||||
Gl.glEnable(Gl.GL_CULL_FACE);
|
||||
|
||||
// Draw Player 1
|
||||
Gl.glMaterialfv(Gl.GL_FRONT, Gl.GL_DIFFUSE, Player1Diffuse);
|
||||
Gl.glMaterialfv(Gl.GL_FRONT, Gl.GL_AMBIENT, Player1Ambient);
|
||||
DrawBox(-1.0f, (float)Player1.posY - playerSizeY, 0.0f,
|
||||
-1.0f + playerSizeX, (float)Player1.posY + playerSizeY, 0.1f);
|
||||
|
||||
// Draw Player 2
|
||||
Gl.glMaterialfv(Gl.GL_FRONT, Gl.GL_DIFFUSE, Player2Diffuse);
|
||||
Gl.glMaterialfv(Gl.GL_FRONT, Gl.GL_AMBIENT, Player2Ambient);
|
||||
DrawBox(1.0f - playerSizeX, (float)Player2.posY - playerSizeY, 0.0f,
|
||||
1.0f, (float)Player2.posY + playerSizeY, 0.1f);
|
||||
|
||||
// Draw Ball
|
||||
Gl.glMaterialfv(Gl.GL_FRONT, Gl.GL_DIFFUSE, ballDiffuse);
|
||||
Gl.glMaterialfv(Gl.GL_FRONT, Gl.GL_AMBIENT, ballAmbient);
|
||||
DrawBox((float)gameBall.posX - ballSize, (float)gameBall.posY - ballSize, 0.0f,
|
||||
(float)gameBall.posX + ballSize, (float)gameBall.posY + ballSize, ballSize * 2);
|
||||
|
||||
// Top game field border
|
||||
Gl.glMaterialfv(Gl.GL_FRONT, Gl.GL_DIFFUSE, borderDiffuse);
|
||||
Gl.glMaterialfv(Gl.GL_FRONT, Gl.GL_AMBIENT, borderAmbient);
|
||||
DrawBox(-1.1f, 1.0f, 0.0f, 1.1f, 1.1f, 0.1f);
|
||||
// Bottom game field border
|
||||
Gl.glColor3f(0.0f, 0.0f, 0.7f);
|
||||
DrawBox(-1.1f, -1.1f, 0.0f, 1.1f, -1.0f, 0.1f);
|
||||
// Left game field border
|
||||
DrawBox(-1.1f, -1.0f, 0.0f, -1.0f, 1.0f, 0.1f);
|
||||
// Left game field border
|
||||
DrawBox(1.0f, -1.0f, 0.0f, 1.1f, 1.0f, 0.1f);
|
||||
|
||||
// Enable texturing
|
||||
Gl.glEnable(Gl.GL_TEXTURE_2D);
|
||||
Gl.glBindTexture(Gl.GL_TEXTURE_2D, TexId[(int)Textures.Field]);
|
||||
|
||||
// Game field floor
|
||||
Gl.glMaterialfv(Gl.GL_FRONT, Gl.GL_DIFFUSE, floorDiffuse);
|
||||
Gl.glMaterialfv(Gl.GL_FRONT, Gl.GL_AMBIENT, floorAmbient);
|
||||
DrawBox(-1.01f, -1.01f, -0.01f, 1.01f, 1.01f, 0.0f);
|
||||
|
||||
// Disable texturing
|
||||
Gl.glDisable(Gl.GL_TEXTURE_2D);
|
||||
|
||||
// Disable face culling
|
||||
Gl.glDisable(Gl.GL_CULL_FACE);
|
||||
|
||||
// Disable lighting
|
||||
Gl.glDisable(Gl.GL_LIGHTING);
|
||||
|
||||
// Disable depth testing
|
||||
Gl.glDisable(Gl.GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// GameOver
|
||||
/// </summary>
|
||||
public static void GameOver() {
|
||||
// Enable sticky keys
|
||||
Glfw.glfwEnable(Glfw.GLFW_STICKY_KEYS);
|
||||
|
||||
// Until the user presses ESC or SPACE
|
||||
while(Glfw.glfwGetKey(Glfw.GLFW_KEY_ESC) == Gl.GL_FALSE && Glfw.glfwGetKey(' ') == Gl.GL_FALSE &&
|
||||
Glfw.glfwGetWindowParam(Glfw.GLFW_OPENED) == Gl.GL_TRUE) {
|
||||
// Draw display
|
||||
UpdateDisplay();
|
||||
|
||||
// Setup projection matrix
|
||||
Gl.glMatrixMode(Gl.GL_PROJECTION);
|
||||
Gl.glLoadIdentity();
|
||||
Gl.glOrtho(0.0f, 1.0f, 1.0f, 0.0f, -1.0f, 1.0f);
|
||||
|
||||
// Setup modelview matrix
|
||||
Gl.glMatrixMode(Gl.GL_MODELVIEW);
|
||||
Gl.glLoadIdentity();
|
||||
|
||||
// Enable blending
|
||||
Gl.glEnable(Gl.GL_BLEND);
|
||||
|
||||
// Dim background
|
||||
Gl.glBlendFunc(Gl.GL_ONE_MINUS_SRC_ALPHA, Gl.GL_SRC_ALPHA);
|
||||
Gl.glColor4f(0.3f, 0.3f, 0.3f, 0.3f);
|
||||
Gl.glBegin(Gl.GL_QUADS);
|
||||
Gl.glVertex2f(0.0f, 0.0f);
|
||||
Gl.glVertex2f(1.0f, 0.0f);
|
||||
Gl.glVertex2f(1.0f, 1.0f);
|
||||
Gl.glVertex2f(0.0f, 1.0f);
|
||||
Gl.glEnd();
|
||||
|
||||
// Display winner text
|
||||
Gl.glBlendFunc(Gl.GL_ONE, Gl.GL_ONE_MINUS_SRC_COLOR);
|
||||
if(winningPlayer == (int)Winner.Player1) {
|
||||
Gl.glColor4f(1.0f, 0.5f, 0.5f, 1.0f);
|
||||
DrawImage((int)Textures.Winner1, 0.35f, 0.65f, 0.46f, 0.54f);
|
||||
}
|
||||
else if(winningPlayer == (int)Winner.Player2) {
|
||||
Gl.glColor4f(0.5f, 1.0f, 0.5f, 1.0f);
|
||||
DrawImage((int)Textures.Winner2, 0.35f, 0.65f, 0.46f, 0.54f);
|
||||
}
|
||||
|
||||
// Disable blending
|
||||
Gl.glDisable(Gl.GL_BLEND);
|
||||
|
||||
// Swap buffers
|
||||
Glfw.glfwSwapBuffers();
|
||||
}
|
||||
|
||||
// Disable sticky keys
|
||||
Glfw.glfwDisable(Glfw.GLFW_STICKY_KEYS);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DrawBox
|
||||
///
|
||||
/// Draw a 3D box
|
||||
/// </summary>
|
||||
/// <param name="x1">A float</param>
|
||||
/// <param name="y1">A float</param>
|
||||
/// <param name="z1">A float</param>
|
||||
/// <param name="x2">A float</param>
|
||||
/// <param name="y2">A float</param>
|
||||
/// <param name="z2">A float</param>
|
||||
public static void DrawBox(float x1, float y1, float z1, float x2, float y2, float z2) {
|
||||
float texScale = 4.0f;
|
||||
|
||||
// Draw six sides of a cube
|
||||
Gl.glBegin(Gl.GL_QUADS);
|
||||
// Side 1 (down)
|
||||
Gl.glNormal3f(0.0f, 0.0f, -1.0f);
|
||||
Gl.glTexCoord2f(0.0f, 0.0f);
|
||||
Gl.glVertex3f(x1, y2, z1);
|
||||
Gl.glTexCoord2f(texScale, 0.0f);
|
||||
Gl.glVertex3f(x2, y2, z1);
|
||||
Gl.glTexCoord2f(texScale, texScale);
|
||||
Gl.glVertex3f(x2, y1, z1);
|
||||
Gl.glTexCoord2f(0.0f, texScale);
|
||||
Gl.glVertex3f(x1, y1, z1);
|
||||
|
||||
// Side 2 (up)
|
||||
Gl.glNormal3f(0.0f, 0.0f, 1.0f);
|
||||
Gl.glTexCoord2f(0.0f, 0.0f);
|
||||
Gl.glVertex3f(x1, y1, z2);
|
||||
Gl.glTexCoord2f(texScale, 0.0f);
|
||||
Gl.glVertex3f(x2, y1, z2);
|
||||
Gl.glTexCoord2f(texScale, texScale);
|
||||
Gl.glVertex3f(x2, y2, z2);
|
||||
Gl.glTexCoord2f(0.0f, texScale);
|
||||
Gl.glVertex3f(x1, y2, z2);
|
||||
|
||||
// Side 3 (backward)
|
||||
Gl.glNormal3f(0.0f, -1.0f, 0.0f);
|
||||
Gl.glTexCoord2f(0.0f, 0.0f);
|
||||
Gl.glVertex3f(x1, y1, z1);
|
||||
Gl.glTexCoord2f(texScale, 0.0f);
|
||||
Gl.glVertex3f(x2, y1, z1);
|
||||
Gl.glTexCoord2f(texScale, texScale);
|
||||
Gl.glVertex3f(x2, y1, z2);
|
||||
Gl.glTexCoord2f(0.0f, texScale);
|
||||
Gl.glVertex3f(x1, y1, z2);
|
||||
|
||||
// Side 4 (forward)
|
||||
Gl.glNormal3f(0.0f, 1.0f, 0.0f);
|
||||
Gl.glTexCoord2f(0.0f, 0.0f);
|
||||
Gl.glVertex3f(x1, y2, z2);
|
||||
Gl.glTexCoord2f(texScale, 0.0f);
|
||||
Gl.glVertex3f(x2, y2, z2);
|
||||
Gl.glTexCoord2f(texScale, texScale);
|
||||
Gl.glVertex3f(x2, y2, z1);
|
||||
Gl.glTexCoord2f(0.0f, texScale);
|
||||
Gl.glVertex3f(x1, y2, z1);
|
||||
|
||||
// Side 5 (left)
|
||||
Gl.glNormal3f(-1.0f, 0.0f, 0.0f);
|
||||
Gl.glTexCoord2f(0.0f, 0.0f);
|
||||
Gl.glVertex3f(x1, y1, z2);
|
||||
Gl.glTexCoord2f(texScale, 0.0f);
|
||||
Gl.glVertex3f(x1, y2, z2);
|
||||
Gl.glTexCoord2f(texScale, texScale);
|
||||
Gl.glVertex3f(x1, y2, z1);
|
||||
Gl.glTexCoord2f(0.0f, texScale);
|
||||
Gl.glVertex3f(x1, y1, z1);
|
||||
|
||||
// Side 6 (right)
|
||||
Gl.glNormal3f(1.0f, 0.0f, 0.0f);
|
||||
Gl.glTexCoord2f(0.0f, 0.0f);
|
||||
Gl.glVertex3f(x2, y1, z1);
|
||||
Gl.glTexCoord2f(texScale, 0.0f);
|
||||
Gl.glVertex3f(x2, y2, z1);
|
||||
Gl.glTexCoord2f(texScale, texScale);
|
||||
Gl.glVertex3f(x2, y2, z2);
|
||||
Gl.glTexCoord2f(0.0f, texScale);
|
||||
Gl.glVertex3f(x2, y1, z2);
|
||||
Gl.glEnd();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// GameLoop
|
||||
/// </summary>
|
||||
static void GameLoop() {
|
||||
int playing;
|
||||
GameEvent gameEvent;
|
||||
|
||||
// Initialize a new game
|
||||
NewGame();
|
||||
|
||||
// Enable sticky keys
|
||||
Glfw.glfwEnable(Glfw.GLFW_STICKY_KEYS);
|
||||
|
||||
// Loop until the game ends
|
||||
playing = Gl.GL_TRUE;
|
||||
while(playing == Gl.GL_TRUE && Glfw.glfwGetWindowParam(Glfw.GLFW_OPENED) == Gl.GL_TRUE) {
|
||||
// Frame timer
|
||||
oldTime = thisTime;
|
||||
thisTime = Glfw.glfwGetTime();
|
||||
dt = thisTime - oldTime;
|
||||
|
||||
// Get user input and update player positions
|
||||
PlayerControl();
|
||||
|
||||
// Move the ball, and check if a player hits/misses the ball
|
||||
gameEvent = BallControl();
|
||||
|
||||
// Did we have a winner?
|
||||
switch(gameEvent) {
|
||||
case GameEvent.Player1Wins:
|
||||
winningPlayer = Player1.id;
|
||||
playing = Gl.GL_FALSE;
|
||||
break;
|
||||
|
||||
case GameEvent.Player2Wins:
|
||||
winningPlayer = Player2.id;
|
||||
playing = Gl.GL_FALSE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Did the user press ESC?
|
||||
if(Glfw.glfwGetKey(Glfw.GLFW_KEY_ESC) == Gl.GL_TRUE) {
|
||||
playing = Gl.GL_FALSE;
|
||||
}
|
||||
|
||||
// Did the user change camera view?
|
||||
if(Glfw.glfwGetKey('1') == Gl.GL_TRUE) {
|
||||
cameraPos = CameraPosition.Classic;
|
||||
}
|
||||
else if(Glfw.glfwGetKey('2') == Gl.GL_TRUE) {
|
||||
cameraPos = CameraPosition.Above;
|
||||
}
|
||||
else if(Glfw.glfwGetKey('3') == Gl.GL_TRUE) {
|
||||
cameraPos = CameraPosition.Spectator;
|
||||
}
|
||||
|
||||
// Draw display
|
||||
UpdateDisplay();
|
||||
|
||||
// Swap buffers
|
||||
Glfw.glfwSwapBuffers();
|
||||
}
|
||||
|
||||
// Disable sticky keys
|
||||
Glfw.glfwDisable(Glfw.GLFW_STICKY_KEYS);
|
||||
|
||||
// Show winner
|
||||
GameOver();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// BallControl
|
||||
/// </summary>
|
||||
/// <returns>A GameEvent</returns>
|
||||
public static GameEvent BallControl() {
|
||||
GameEvent gameEvent;
|
||||
double ballspeed;
|
||||
|
||||
// Calculate new ball speed
|
||||
ballspeed = ballSpeed * (1.0 + 0.02 * (thisTime - startTime));
|
||||
gameBall.speedX = gameBall.speedX > 0 ? ballspeed : -ballspeed;
|
||||
gameBall.speedY = gameBall.speedY > 0 ? ballspeed : -ballspeed;
|
||||
gameBall.speedY *= 0.74321;
|
||||
|
||||
// Update ball position
|
||||
gameBall.posX += dt * gameBall.speedX;
|
||||
gameBall.posY += dt * gameBall.speedY;
|
||||
|
||||
// Did the ball hit a top/bottom wall?
|
||||
if(gameBall.posY >= 1.0) {
|
||||
gameBall.posY = 2.0 - gameBall.posY;
|
||||
gameBall.speedY = -gameBall.speedY;
|
||||
}
|
||||
else if(gameBall.posY <= -1.0) {
|
||||
gameBall.posY = -2.0 - gameBall.posY;
|
||||
gameBall.speedY = -gameBall.speedY;
|
||||
}
|
||||
|
||||
// Did the ball hit/miss a player?
|
||||
gameEvent = GameEvent.NobodyWins;
|
||||
|
||||
// Is the ball entering the player 1 goal?
|
||||
if(gameBall.posX < -1.0 + playerSizeX) {
|
||||
// Did player 1 catch the ball?
|
||||
if(gameBall.posY > (Player1.posY - playerSizeY) &&
|
||||
gameBall.posY < (Player1.posY + playerSizeY)) {
|
||||
gameBall.posX = -2.0 + 2.0 * playerSizeX - gameBall.posX;
|
||||
gameBall.speedX = -gameBall.speedX;
|
||||
}
|
||||
else {
|
||||
gameEvent = GameEvent.Player2Wins;
|
||||
}
|
||||
}
|
||||
|
||||
// Is the ball entering the player 2 goal?
|
||||
if(gameBall.posX > 1.0 - playerSizeX) {
|
||||
// Did player 2 catch the ball?
|
||||
if(gameBall.posY > (Player2.posY - playerSizeY) &&
|
||||
gameBall.posY < (Player2.posY + playerSizeY)) {
|
||||
gameBall.posX = 2.0 - 2.0 * playerSizeX - gameBall.posX;
|
||||
gameBall.speedX = -gameBall.speedX;
|
||||
}
|
||||
else {
|
||||
gameEvent = GameEvent.Player1Wins;
|
||||
}
|
||||
}
|
||||
|
||||
return gameEvent;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Main
|
||||
///
|
||||
/// Program entry point
|
||||
/// </summary>
|
||||
public static void Run() {
|
||||
MenuOption menuoption;
|
||||
|
||||
envAmbient = new float[]{1.0f,1.0f,1.0f,1.0f};
|
||||
light1Position = new float[]{-3.0f,3.0f,2.0f,1.0f};
|
||||
light1Diffuse = new float[]{1.0f,1.0f,1.0f,0.0f};
|
||||
light1Ambient = new float[]{0.0f,0.0f,0.0f,0.0f};
|
||||
|
||||
Player1Diffuse = new float[]{1.0f,0.3f,0.3f,1.0f};
|
||||
Player1Ambient = new float[]{0.3f,0.1f,0.0f,1.0f};
|
||||
Player2Diffuse = new float[]{0.3f,1.0f,0.3f,1.0f};
|
||||
Player2Ambient = new float[]{0.1f,0.3f,0.1f,1.0f};
|
||||
ballDiffuse = new float[]{1.0f,1.0f,0.5f,1.0f};
|
||||
ballAmbient = new float[]{0.3f,0.3f,0.1f,1.0f};
|
||||
borderDiffuse = new float[]{0.3f,0.3f,1.0f,1.0f};
|
||||
borderAmbient = new float[]{0.1f,0.1f,0.3f,1.0f};
|
||||
floorDiffuse = new float[]{1.0f,1.0f,1.0f,1.0f};
|
||||
floorAmbient = new float[]{0.3f,0.3f,0.3f,1.0f};
|
||||
|
||||
Player1.id = 1;
|
||||
Player2.id = 2;
|
||||
|
||||
// Initialize GLFW
|
||||
if(Glfw.glfwInit() == Gl.GL_FALSE) {
|
||||
System.Environment.Exit(0);
|
||||
}
|
||||
|
||||
// Open OpenGL window
|
||||
if(Glfw.glfwOpenWindow(width, height, 0, 0, 0, 0, 16, 0, Glfw.GLFW_FULLSCREEN) == Gl.GL_FALSE) {
|
||||
Glfw.glfwTerminate();
|
||||
System.Environment.Exit(0);
|
||||
}
|
||||
|
||||
// Load all textures
|
||||
LoadTextures();
|
||||
|
||||
// Main loop
|
||||
do
|
||||
{
|
||||
// Get menu option
|
||||
menuoption = GameMenu();
|
||||
|
||||
// If the user wants to play, let him...
|
||||
if(menuoption == MenuOption.Play) {
|
||||
GameLoop();
|
||||
}
|
||||
}
|
||||
while( menuoption != MenuOption.Quit );
|
||||
|
||||
// Unload all textures
|
||||
if(Glfw.glfwGetWindowParam(Glfw.GLFW_OPENED) == Gl.GL_FALSE) {
|
||||
Gl.glDeleteTextures((int)Textures.Num_textures, TexId);
|
||||
}
|
||||
|
||||
// Terminate GLFW
|
||||
Glfw.glfwTerminate();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace GlfwExamples
|
||||
{
|
||||
static class Program
|
||||
{
|
||||
/// <summary>
|
||||
/// The main entry point for the application.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
static void Main()
|
||||
{
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
Application.Run(new GlfwExamples());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
#region License
|
||||
/*
|
||||
MIT License
|
||||
Copyright ©2003-2004 Randy Ridge
|
||||
http://www.taoframework.com
|
||||
All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#endregion License
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Security;
|
||||
using System.Security.Permissions;
|
||||
|
||||
[assembly: AllowPartiallyTrustedCallers]
|
||||
[assembly: AssemblyCompany("Randy Ridge http://www.taoframework.com")]
|
||||
#if DEBUG
|
||||
[assembly: AssemblyConfiguration("Debug")]
|
||||
#else
|
||||
[assembly: AssemblyConfiguration("Retail")]
|
||||
#endif
|
||||
[assembly: AssemblyCopyright("©2003-2004 Randy Ridge. All rights reserved.")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: AssemblyDefaultAlias("GlfwExamples.Triangle")]
|
||||
[assembly: AssemblyDelaySign(false)]
|
||||
[assembly: AssemblyDescription("GLFW Triangle example.")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
[assembly: AssemblyInformationalVersion("1.0.0.0")]
|
||||
[assembly: AssemblyKeyName("")]
|
||||
#if DEBUG
|
||||
[assembly: AssemblyProduct("GlfwExamples.Triangle.exe *** Debug Build ***")]
|
||||
#else
|
||||
[assembly: AssemblyProduct("GlfwExamples.Triangle.exe")]
|
||||
#endif
|
||||
[assembly: AssemblyTitle("GLFW Triangle Example")]
|
||||
[assembly: AssemblyTrademark("Randy Ridge")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: CLSCompliant(true)]
|
||||
[assembly: SecurityPermission(SecurityAction.RequestMinimum, Flags = SecurityPermissionFlag.Execution)]
|
||||
[assembly: SecurityPermission(SecurityAction.RequestMinimum, Flags = SecurityPermissionFlag.SkipVerification)]
|
||||
[assembly: SecurityPermission(SecurityAction.RequestMinimum, Flags = SecurityPermissionFlag.UnmanagedCode)]
|
|
@ -0,0 +1,169 @@
|
|||
#region License
|
||||
/*
|
||||
MIT License
|
||||
Copyright ©2003-2004 Randy Ridge
|
||||
http://www.taoframework.com
|
||||
All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#endregion License
|
||||
|
||||
#region Original Credits/License
|
||||
/*
|
||||
Copyright (c) 2002-2004 Marcus Geelnard
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would
|
||||
be appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not
|
||||
be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
|
||||
Marcus Geelnard
|
||||
marcus.geelnard at home.se
|
||||
*/
|
||||
#endregion Original Credits/License
|
||||
|
||||
using System;
|
||||
using Tao.Glfw;
|
||||
using Tao.OpenGl;
|
||||
|
||||
namespace GlfwExamples {
|
||||
#region Class Documentation
|
||||
/// <summary>
|
||||
/// This is a small test application for GLFW.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The program opens a window (640x480), and renders a spinning colored triangle (it
|
||||
/// is controlled with both the GLFW timer and the mouse). It also calculates the
|
||||
/// rendering speed (FPS), which is displayed in the window title bar.
|
||||
/// </remarks>
|
||||
#endregion Class Documentation
|
||||
public sealed class Triangle {
|
||||
// --- Application Entry Point ---
|
||||
#region Run()
|
||||
/// <summary>
|
||||
/// The main entry point for the application.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
public static void Run() {
|
||||
int windowWidth, windowHeight;
|
||||
int mouseX, mouseY;
|
||||
bool isRunning;
|
||||
double currentTime, startTime, frameRate;
|
||||
int frameCount;
|
||||
|
||||
// Initialise GLFW
|
||||
Glfw.glfwInit();
|
||||
|
||||
// Open OpenGL window
|
||||
if(Glfw.glfwOpenWindow(640, 480, 0, 0, 0, 0, 0, 0, Glfw.GLFW_WINDOW) == Gl.GL_FALSE) {
|
||||
Glfw.glfwTerminate();
|
||||
return;
|
||||
}
|
||||
|
||||
// Enable sticky keys
|
||||
Glfw.glfwEnable(Glfw.GLFW_STICKY_KEYS);
|
||||
|
||||
// Disable vertical sync (on cards that support it)
|
||||
Glfw.glfwSwapInterval(0);
|
||||
|
||||
// Main loop
|
||||
isRunning = true;
|
||||
frameCount = 0;
|
||||
startTime = Glfw.glfwGetTime();
|
||||
|
||||
while(isRunning) {
|
||||
// Get time and mouse position
|
||||
currentTime = Glfw.glfwGetTime();
|
||||
Glfw.glfwGetMousePos(out mouseX, out mouseY);
|
||||
|
||||
// Calculate and display FPS (frames per second)
|
||||
if((currentTime - startTime) > 1.0 || frameCount == 0) {
|
||||
frameRate = frameCount / (currentTime - startTime);
|
||||
Glfw.glfwSetWindowTitle(string.Format("Spinning Triangle ({0:0} FPS)",
|
||||
frameRate));
|
||||
startTime = currentTime;
|
||||
frameCount = 0;
|
||||
}
|
||||
|
||||
frameCount++;
|
||||
|
||||
// Get window size (may be different than the requested size)
|
||||
Glfw.glfwGetWindowSize(out windowWidth, out windowHeight);
|
||||
windowHeight = windowHeight > 0 ? windowHeight : 1;
|
||||
|
||||
// Set viewport
|
||||
Gl.glViewport(0, 0, windowWidth, windowHeight);
|
||||
|
||||
// Clear color buffer
|
||||
Gl.glClearColor(0, 0, 0, 0);
|
||||
Gl.glClear(Gl.GL_COLOR_BUFFER_BIT);
|
||||
|
||||
// Select and setup the projection matrix
|
||||
Gl.glMatrixMode(Gl.GL_PROJECTION);
|
||||
Gl.glLoadIdentity();
|
||||
Glu.gluPerspective(65, windowWidth / (double) windowHeight, 1, 100);
|
||||
|
||||
// Select and setup the modelview matrix
|
||||
Gl.glMatrixMode(Gl.GL_MODELVIEW);
|
||||
Gl.glLoadIdentity();
|
||||
Glu.gluLookAt(0, 1, 0, // Eye-position
|
||||
0, 20, 0, // View-point
|
||||
0, 0, 1); // Up-vector
|
||||
|
||||
// Draw a rotating colorful triangle
|
||||
Gl.glTranslatef(0, 14, 0);
|
||||
Gl.glRotatef(0.3f * (float) mouseX + (float) currentTime * 100, 0, 0, 1);
|
||||
Gl.glBegin(Gl.GL_TRIANGLES);
|
||||
Gl.glColor3f(1, 0, 0);
|
||||
Gl.glVertex3f(-5, 0, -4);
|
||||
Gl.glColor3f(0, 1, 0);
|
||||
Gl.glVertex3f(5, 0, -4);
|
||||
Gl.glColor3f(0, 0, 1);
|
||||
Gl.glVertex3f(0, 0, 6);
|
||||
Gl.glEnd();
|
||||
|
||||
// Swap buffers
|
||||
Glfw.glfwSwapBuffers();
|
||||
|
||||
// Check if the ESC key was pressed or the window was closed
|
||||
isRunning = ((Glfw.glfwGetKey(Glfw.GLFW_KEY_ESC) == Glfw.GLFW_RELEASE) &&
|
||||
Glfw.glfwGetWindowParam(Glfw.GLFW_OPENED) == Gl.GL_TRUE);
|
||||
}
|
||||
|
||||
// Close OpenGL window and terminate GLFW
|
||||
Glfw.glfwTerminate();
|
||||
}
|
||||
#endregion Run()
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче