📄 unit1.pas
字号:
//------------------------------------------------------------------------
//
// Author : Maarten Kronberger
// Email : Maartenk@tinderbox.co.za
// Website : http://www.sulaco.co.za
// http://www.tinderbox.co.za
// Date : 6 October 2002
// Version : 1.0
// Description : Bezier Curve Generator/Creator
//
// Special thanks to Digiben and the guys at www.gametutorials.com for the
// bezier curve source. :D
//------------------------------------------------------------------------
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, OpenGL,
ExtCtrls, StdCtrls, ComCtrls, Menus,Math;
type
TCoord = Record
X, Y, Z : glFLoat;
end;
TForm1 = class(TForm)
Panel1: TPanel;
Panel2: TPanel;
Button1: TButton;
GroupBox3: TGroupBox;
GroupBox4: TGroupBox;
GroupBox2: TGroupBox;
GroupBox1: TGroupBox;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
txtPoint1X: TEdit;
txtPoint1Y: TEdit;
txtPoint1Z: TEdit;
Label4: TLabel;
Label5: TLabel;
Label6: TLabel;
txtPoint2Z: TEdit;
txtPoint2Y: TEdit;
txtPoint2X: TEdit;
Label7: TLabel;
Label8: TLabel;
Label9: TLabel;
txtPoint3Z: TEdit;
txtPoint3Y: TEdit;
txtPoint3X: TEdit;
Label10: TLabel;
Label11: TLabel;
Label12: TLabel;
txtPoint4Z: TEdit;
txtPoint4Y: TEdit;
txtPoint4X: TEdit;
Button2: TButton;
UpDown1: TUpDown;
UpDown2: TUpDown;
UpDown3: TUpDown;
UpDown4: TUpDown;
UpDown5: TUpDown;
UpDown6: TUpDown;
UpDown7: TUpDown;
UpDown8: TUpDown;
UpDown9: TUpDown;
UpDown10: TUpDown;
UpDown11: TUpDown;
UpDown12: TUpDown;
Button3: TButton;
Button4: TButton;
chkAllBeziers: TCheckBox;
TTabControl1: TTabControl;
Button5: TButton;
Button6: TButton;
chkRotate: TCheckBox;
MainMenu1: TMainMenu;
File1: TMenuItem;
Save1: TMenuItem;
View1: TMenuItem;
ShowStart1: TMenuItem;
Rotate1: TMenuItem;
ShowAllCurves1: TMenuItem;
SaveControlPoints1: TMenuItem;
Timer1: TTimer;
Timer2: TTimer;
SaveDialog1: TSaveDialog;
OpenDialog1: TOpenDialog;
OpenControlPointFile1: TMenuItem;
New1: TMenuItem;
Help1: TMenuItem;
About1: TMenuItem;
procedure FormCreate(Sender: TObject);
procedure Panel1Resize(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormKeyPress(Sender: TObject; var Key: Char);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure UpDown1Click(Sender: TObject; Button: TUDBtnType);
procedure UpDown2Click(Sender: TObject; Button: TUDBtnType);
procedure UpDown3Click(Sender: TObject; Button: TUDBtnType);
procedure UpDown4Click(Sender: TObject; Button: TUDBtnType);
procedure UpDown5Click(Sender: TObject; Button: TUDBtnType);
procedure UpDown6Click(Sender: TObject; Button: TUDBtnType);
procedure UpDown7Click(Sender: TObject; Button: TUDBtnType);
procedure UpDown8Click(Sender: TObject; Button: TUDBtnType);
procedure UpDown9Click(Sender: TObject; Button: TUDBtnType);
procedure UpDown10Click(Sender: TObject; Button: TUDBtnType);
procedure UpDown11Click(Sender: TObject; Button: TUDBtnType);
procedure UpDown12Click(Sender: TObject; Button: TUDBtnType);
procedure Button3Click(Sender: TObject);
procedure GroupBox4Click(Sender: TObject);
procedure GroupBox3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure ShowStart1Click(Sender: TObject);
procedure Rotate1Click(Sender: TObject);
procedure ShowAllCurves1Click(Sender: TObject);
procedure Save1Click(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure Panel1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure Panel1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure Timer2Timer(Sender: TObject);
procedure Button5MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure Button6MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure Button6MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure Button5MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure SaveControlPoints1Click(Sender: TObject);
procedure OpenControlPointFile1Click(Sender: TObject);
procedure txtPoint1XEnter(Sender: TObject);
procedure txtPoint1XExit(Sender: TObject);
procedure txtPoint1YEnter(Sender: TObject);
procedure txtPoint1YExit(Sender: TObject);
procedure txtPoint1ZEnter(Sender: TObject);
procedure txtPoint1ZExit(Sender: TObject);
procedure txtPoint2XEnter(Sender: TObject);
procedure txtPoint2XExit(Sender: TObject);
procedure txtPoint2YEnter(Sender: TObject);
procedure txtPoint2YExit(Sender: TObject);
procedure txtPoint2ZEnter(Sender: TObject);
procedure txtPoint2ZExit(Sender: TObject);
procedure txtPoint3XEnter(Sender: TObject);
procedure txtPoint3XExit(Sender: TObject);
procedure txtPoint3YEnter(Sender: TObject);
procedure txtPoint3YExit(Sender: TObject);
procedure txtPoint3ZEnter(Sender: TObject);
procedure txtPoint3ZExit(Sender: TObject);
procedure txtPoint4XEnter(Sender: TObject);
procedure txtPoint4XExit(Sender: TObject);
procedure txtPoint4YEnter(Sender: TObject);
procedure txtPoint4YExit(Sender: TObject);
procedure txtPoint4ZEnter(Sender: TObject);
procedure txtPoint4ZExit(Sender: TObject);
procedure New1Click(Sender: TObject);
procedure About1Click(Sender: TObject);
private
{ Private declarations }
rc : HGLRC; // Rendering Context
dc : HDC; // Device Context
ElapsedTime, AppStart, LastTime : DWord; // Timing variables
g_CurrentTime : GLfloat; // This is the current position of the sphere along the curve (0 to 1)
procedure glDraw;
procedure Idle(Sender: TObject; var Done: Boolean);
procedure glInit;
procedure SetArrayLength;
procedure UpdateTextValues;
procedure SetTempValue(txtBox : TEdit);
procedure SetCoordValue(txtBox : TEdit);
procedure DoUpDown(txtBox : TEdit;Button: TUDBtnType);
procedure UpdatePointValues();
public
{ Public declarations }
end;
const
MAX_STEPS = 38.0;
BALL_SPEED = 0.02;
var
Form1: TForm1;
g_CurrentTime : GLfloat;
rotateY : GLfloat;
g_arrvStartPoint : array of TCoord; // Starting point of the curve
g_arrvControlPoint1 : array of TCoord; // First control point of the curve
g_arrvControlPoint2 : array of TCoord; // Second control point of the curve
g_arrvEndPoint : array of TCoord; // End point of the curve
g_arrIndex : integer;
zView : GLfloat;
g_ControlPoint1Color : glFloat;
g_ControlPoint2Color : glFloat;
zViewModifier : glFloat;
g_tempVar : glFloat;
implementation
{$R *.DFM}
Uses Unit2;
{------------------------------------------------------------------------}
{ This function renders a sphere to a given XYZ and with a given radius }
{------------------------------------------------------------------------}
procedure DrawSphere(x, y, z, radius : GLfloat);
var pSphere : GLUquadricObj;
begin
// To use Quadrics, we need to create a new one first. This is done below.
// The GLUquadricObj type is defined with the GLU32 library and associated header file.
pSphere := gluNewQuadric(); // Get a Quadric off the stack
// Let's put on a matrix so what ever we do it doesn't effect the rest of
// the objects we will display.
glPushMatrix(); // Push on a new matrix
glTranslatef(x, y, z); // Move the sphere to the desired (x, y, z)
// Draw the a sphere with a given radius and a width and height detail
// of 15 (15 by 15 is a good level of detail. The lower the detail the
// more jagged the sphere becomes, where the high the detail the more round it is.
gluSphere(pSphere, radius, 15, 15); // Draw the sphere with a radius of 0.2
glPopMatrix(); // Pop the current matrix
// Since we are done rendering the Quadric, we can free the object.
// gluDeleteQuadric() takes the object to be released. If you have a lot
// of Quadrics, you might not want to allocate and free them every frame.
gluDeleteQuadric(pSphere); // Free the quadric object
end;
{-----------------------------------------------------------------------------}
{ This function returns an XYZ point along the curve, depending on t (0 to 1) }
{-----------------------------------------------------------------------------}
function PointOnCurve(p1, p2, p3, p4: TCoord; t : GLfloat) : TCoord;
var var1, var2, var3 : glFloat;
vPoint : TCoord;
begin
vPoint.X := 0.0; vPoint.Y := 0.0; vPoint.Z := 0.0;
{-----------------------------------------------------------------------------}
{ Here is the juice of our tutorial. }
{ Below is the equation for a 4 control point bezier curve: }
{ B(t) = P1 * ( 1 - t )^3 }
{ + P2 * 3 * t * ( 1 - t )^2 }
{ + P3 * 3 * t^2 * ( 1 - t ) }
{ + P4 * t^3 }
{ Yes I agree, this isn't the most intuitive equation, }
{ but it is pretty straight forward. }
{ If you got up to Trig, you will notice that this is a polynomial. }
{ That is what a curve is. }
{ "t" is the time from 0 to 1. }
{ You could also think of it as the distance along the curve, }
{ because that is really what it is. }
{ P1 - P4 are the 4 control points. }
{ They each have an (x, y, z) associated with them. }
{ You notice that there is a lot of (1 - t) 's? }
{ Well, to clean up our code we will try to contain some of these }
{ repetitions into variables. }
{ This helps our repeated computations as well. }
{-----------------------------------------------------------------------------}
// Store the (1 - t) in a variable because it is used frequently
var1 := 1 - t;
// Store the (1 - t)^3 into a variable to cut down computation and create clean code
var2 := var1 * var1 * var1;
// Store the t^3 in a variable to cut down computation and create clean code
var3 := t * t * t;
{-----------------------------------------------------------------------------}
{ Now that we have some computation cut down, }
{ we just follow the equation above. }
{ If you multiply and simplify the equation, }
{ you come up with what we have below. }
{ If you don't see how we came to here from the equation, }
{ multiply the equation out and it will become more clear. }
{ I don't intend to go into any more detail on the math of a bezier curve, }
{ because there are far better places out there with graphical displays }
{ and tons of examples. }
{ Look in our * Quick Notes * for an EXCELLENT web site that does just this. }
{ It derives everything and has excellent visuals. }
{ It's the best I have seen so far. }
{-----------------------------------------------------------------------------}
vPoint.x := var2*p1.x + 3*t*var1*var1*p2.x + 3*t*t*var1*p3.x + var3*p4.x;
vPoint.y := var2*p1.y + 3*t*var1*var1*p2.y + 3*t*t*var1*p3.y + var3*p4.y;
vPoint.z := var2*p1.z + 3*t*var1*var1*p2.z + 3*t*t*var1*p3.z + var3*p4.z;
// Now we should have the point on the curve, so let's return it.
result := vPoint;
end;
{------------------------------------------------------------------}
{ Function to draw the actual scene }
{------------------------------------------------------------------}
procedure TForm1.glDraw();
var t : glFloat;
vPoint : TCoord;
I : integer;
begin
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
glLoadIdentity(); // Reset The matrix
{-----------------------------------------------------------------------------}
{ Below, we will draw a bezier curve with 4 control points }
{ (including the start/end point). We will use GL_LINES to draw the }
{ line segments of the curve. Then, using Quadrics, we will draw a sphere }
{ on the curve. You can use the LEFT and RIGHT arrow keys to move the }
{ sphere along the curve. If you are not familiar with quadrics, you can }
{ view our quadric tutorial at www.GameTutorials.com. I also include some }
{ comments from the tutorial in here in case you just want the basics. }
{ Quadrics are used to create cylinders and spheres quickly and easily. }
{-----------------------------------------------------------------------------}
// We set up our camera back a little bit to get the whole curve in view.
// Position View Up Vector
gluLookAt(0, 0.5, zView, 0, 0.5, 0, 0, 1, 0); // Set up our camera position and view
// Below we disable the lighting so you can clearly see the bezier curve.
glDisable(GL_LIGHTING); // Disable lighting for now
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -