110 lines
3.4 KiB
ObjectPascal
110 lines
3.4 KiB
ObjectPascal
unit ex1;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
{ This is a simple 3D objet, a pyramid with a hexagonal base. The object is designed in the constructor.
|
|
The CreateObject method returns an interface to an empty object. An interface is similar to a class
|
|
except you don't have to call Free.
|
|
|
|
A 3D object has a MainPart property, which contains the vertices describing the objet. It can contains subparts,
|
|
but here it is not the case. Parts can be rotated and scaled relative to their container. The MainPart is rotated
|
|
and scaled relative to the whole scene.
|
|
|
|
Faces are created using vertices, so that they will follow the movements of these vertices. Here the default color
|
|
SandColor is defined for the whole object.
|
|
|
|
In order to make it attractive, a lighting is defined. The simplest way is to use a directional light, so that
|
|
you don't have to bother with the coordinates of the light source.
|
|
|
|
The background is filled with a gradient. Note that it is a vertical gradient which is very fast to draw, because
|
|
each scanline is filled with one color. }
|
|
|
|
uses
|
|
Classes, SysUtils, BGRAScene3D, BGRABitmapTypes
|
|
{$IFNDEF NO_OPENGL_SURFACE}, BGRAOpenGL, BGRAOpenGL3D{$ENDIF};
|
|
|
|
type
|
|
|
|
{ TExample1 }
|
|
|
|
TExample1 = class({$IFNDEF NO_OPENGL_SURFACE}TBGLScene3D{$ELSE}TBGRAScene3D{$ENDIF})
|
|
SandColor: TBGRAPixel;
|
|
constructor Create;
|
|
procedure Render; override;
|
|
{$IFNDEF NO_OPENGL_SURFACE}
|
|
procedure RenderGL(ACanvas: TBGLCustomCanvas; AMaxZ: single=1000); override;
|
|
{$ENDIF}
|
|
end;
|
|
|
|
implementation
|
|
|
|
{ TExample1 }
|
|
|
|
constructor TExample1.Create;
|
|
var
|
|
base: array of IBGRAVertex3D;
|
|
top: IBGRAVertex3D;
|
|
begin
|
|
inherited Create;
|
|
|
|
SandColor := BGRA(255,240,128);
|
|
|
|
//create a pyramid
|
|
with CreateObject(SandColor) do
|
|
begin
|
|
top := MainPart.Add(0,-15,0);
|
|
//pyramid base is in a clockwise order if we look the pyramid from under
|
|
base := MainPart.Add([-20,15,-20, 0,15,-30, 20,15,-20, 20,15,20, 0,15,30, -20,15,20]);
|
|
AddFace(base);
|
|
//add four faces, the three vertices are in a clockwise order
|
|
AddFace([base[0],top,base[1]]);
|
|
AddFace([base[1],top,base[2]]);
|
|
AddFace([base[2],top,base[3]]);
|
|
AddFace([base[3],top,base[4]]);
|
|
AddFace([base[4],top,base[5]]);
|
|
AddFace([base[5],top,base[0]]);
|
|
|
|
MainPart.Scale(1.3);
|
|
MainPart.RotateYDeg(30);
|
|
MainPart.RotateXDeg(20);
|
|
MainPart.Translate(0,-5,0);
|
|
end;
|
|
|
|
//set ambiant lightness to dark (1 is normal lightness, 2 is complete whiteness)
|
|
AmbiantLightness := 0.5;
|
|
//add a directional light from top-left, maximum lightness will be 0.5 + 1 = 1.5
|
|
AddDirectionalLight(Point3D(1,1,1),0.5);
|
|
|
|
//we can have high quality antialiasing because it is a simple scene
|
|
RenderingOptions.PerspectiveMode := pmLinearMapping;
|
|
end;
|
|
|
|
procedure TExample1.Render;
|
|
begin
|
|
//fill background
|
|
Surface.GradientFill(0,0,Surface.Width,Surface.Height,
|
|
MergeBGRA(SandColor,1,BGRABlack,1),
|
|
MergeBGRA(SandColor,1,BGRABlack,2),
|
|
gtLinear,PointF(0,0),PointF(0,Surface.Height),dmSet);
|
|
|
|
inherited Render;
|
|
end;
|
|
|
|
{$IFNDEF NO_OPENGL_SURFACE}
|
|
procedure TExample1.RenderGL(ACanvas: TBGLCustomCanvas; AMaxZ: single);
|
|
begin
|
|
//fill background
|
|
ACanvas.FillRectLinearColor(0,0,BGLCanvas.Width,BGLCanvas.Height,
|
|
MergeBGRA(SandColor,1,BGRABlack,1),MergeBGRA(SandColor,1,BGRABlack,1),
|
|
MergeBGRA(SandColor,1,BGRABlack,2),MergeBGRA(SandColor,1,BGRABlack,2),
|
|
False);
|
|
|
|
inherited RenderGL(ACanvas, AMaxZ);
|
|
end;
|
|
{$ENDIF}
|
|
|
|
end.
|
|
|