1 unit ex1;
2 
3 {$mode objfpc}{$H+}
4 
5 interface
6 
7 { This is a simple 3D objet, a pyramid with a hexagonal base. The object is designed in the constructor.
8   The CreateObject method returns an interface to an empty object. An interface is similar to a class
9   except you don't have to call Free.
10 
11   A 3D object has a MainPart property, which contains the vertices describing the objet. It can contains subparts,
12   but here it is not the case. Parts can be rotated and scaled relative to their container. The MainPart is rotated
13   and scaled relative to the whole scene.
14 
15   Faces are created using vertices, so that they will follow the movements of these vertices. Here the default color
16   SandColor is defined for the whole object.
17 
18   In order to make it attractive, a lighting is defined. The simplest way is to use a directional light, so that
19   you don't have to bother with the coordinates of the light source.
20 
21   The background is filled with a gradient. Note that it is a vertical gradient which is very fast to draw, because
22   each scanline is filled with one color. }
23 
24 uses
25   Classes, SysUtils, BGRAScene3D, BGRABitmapTypes
26   {$IFNDEF NO_OPENGL_SURFACE}, BGRAOpenGL, BGRAOpenGL3D{$ENDIF};
27 
28 type
29 
30   { TExample1 }
31 
32   TExample1 = class({$IFNDEF NO_OPENGL_SURFACE}TBGLScene3D{$ELSE}TBGRAScene3D{$ENDIF})
33     SandColor: TBGRAPixel;
34     constructor Create;
35     procedure Render; override;
36     {$IFNDEF NO_OPENGL_SURFACE}
37     procedure RenderGL(ACanvas: TBGLCustomCanvas; AMaxZ: single=1000); override;
38     {$ENDIF}
39   end;
40 
41 implementation
42 
43 { TExample1 }
44 
45 constructor TExample1.Create;
46 var
47   base: array of IBGRAVertex3D;
48   top: IBGRAVertex3D;
49 begin
50   inherited Create;
51 
52   SandColor := BGRA(255,240,128);
53 
54   //create a pyramid
55   with CreateObject(SandColor) do
56   begin
57     top := MainPart.Add(0,-15,0);
58     //pyramid base is in a clockwise order if we look the pyramid from under
59     base := MainPart.Add([-20,15,-20, 0,15,-30, 20,15,-20, 20,15,20, 0,15,30, -20,15,20]);
60     AddFace(base);
61     //add four faces, the three vertices are in a clockwise order
62     AddFace([base[0],top,base[1]]);
63     AddFace([base[1],top,base[2]]);
64     AddFace([base[2],top,base[3]]);
65     AddFace([base[3],top,base[4]]);
66     AddFace([base[4],top,base[5]]);
67     AddFace([base[5],top,base[0]]);
68 
69     MainPart.Scale(1.3);
70     MainPart.RotateYDeg(30);
71     MainPart.RotateXDeg(20);
72     MainPart.Translate(0,-5,0);
73   end;
74 
75   //set ambiant lightness to dark (1 is normal lightness, 2 is complete whiteness)
76   AmbiantLightness := 0.5;
77   //add a directional light from top-left, maximum lightness will be 0.5 + 1 = 1.5
78   AddDirectionalLight(Point3D(1,1,1),0.5);
79 
80   //we can have high quality antialiasing because it is a simple scene
81   RenderingOptions.PerspectiveMode := pmLinearMapping;
82 end;
83 
84 procedure TExample1.Render;
85 begin
86   //fill background
87   Surface.GradientFill(0,0,Surface.Width,Surface.Height,
88           MergeBGRA(SandColor,1,BGRABlack,1),
89           MergeBGRA(SandColor,1,BGRABlack,2),
90           gtLinear,PointF(0,0),PointF(0,Surface.Height),dmSet);
91 
92   inherited Render;
93 end;
94 
95 {$IFNDEF NO_OPENGL_SURFACE}
96 procedure TExample1.RenderGL(ACanvas: TBGLCustomCanvas; AMaxZ: single);
97 begin
98   //fill background
99   ACanvas.FillRectLinearColor(0,0,BGLCanvas.Width,BGLCanvas.Height,
100           MergeBGRA(SandColor,1,BGRABlack,1),MergeBGRA(SandColor,1,BGRABlack,1),
101           MergeBGRA(SandColor,1,BGRABlack,2),MergeBGRA(SandColor,1,BGRABlack,2),
102           False);
103 
104   inherited RenderGL(ACanvas, AMaxZ);
105 end;
106 {$ENDIF}
107 
108 end.
109 
110