Sign in Join
Wiki copytemporary

BGRABitmap tutorial 15: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11This tutorial shows how to render 3D objects using the TBGRAScene3D object.
22
33## Scene object
44
55The scene object is in the BGRAScene3D unit. Here is a simple example:
66
77``` pascal
88uses BGRAScene3D, BGRABitmap, BGRABitmapTypes;
99
1010procedure TForm1.FormPaint(Sender: TObject);
1111var
1212 scene: TBGRAScene3D;
1313 bmp: TBGRABitmap;
1414 base: array of IBGRAVertex3D;
1515 topV: IBGRAVertex3D;
1616begin
1717 bmp := TBGRABitmap.Create(ClientWidth,ClientHeight,BGRABlack);
1818
1919 scene := TBGRAScene3D.Create(bmp);
2020 //create a pyramid
2121 with scene.CreateObject(BGRA(255,240,128)) do
2222 begin
2323 //create vertices
2424 topV := MainPart.Add(0,-15,0);
2525 //pyramid base is in a clockwise order if we look at the pyramid from below
2626 base := MainPart.Add([-20,15,-20, 20,15,-20, 20,15,20, -20,15,20]);
2727
2828 AddFace(base);
2929 //add four faces, the three vertices are in a clockwise order
3030 AddFace([base[0],topV,base[1]]);
3131 AddFace([base[1],topV,base[2]]);
3232 AddFace([base[2],topV,base[3]]);
3333 AddFace([base[3],topV,base[0]]);
3434 topV := nil;
3535 base := nil;
3636 end;
3737 scene.Render;
3838 scene.Free;
3939
4040 bmp.Draw(Canvas,0,0);
4141 bmp.Free;
4242end;
4343```
4444
4545The scene object draws itself on a TBGRABitmap object. You can either pass the bitmap as a parameter when creating the object, as done here, or assign the Surface property afterwards. The scene is automatically centered in the bitmap.
4646
4747The scene object provides the CreateObject function, which returns an interface to the created object. Objects inside a scene are freed automatically when you free the scene.
4848
4949An object has a MainPart property which allows you to create and access vertices. Coordinates can be given as three single values, TPoint3D records, or an array of single values which length must be a multiple of 3. When you create a vertex, you receive an IBGRAVertex3D interface which can be used to create faces. You can add sub parts inside MainPart by using the CreatePart method. There can be nested subparts, each being rotated with its own matrix relative to the main part.
5050
5151The X axis points to the right, the Y axis points to bottom, and the Z axis points forward (behind the screen). It means that XY works the same way as in a bitmap, and there is a depth value. The faces must be in clockwise order to be visible.
5252
5353Here the color is set for the whole object when creating it, but you can set it individually for each face, or for each vertex.
5454
55-<figure>
56-<img src="BGRATutorial15a.png" title="BGRATutorial15a.png" />
57-<figcaption>BGRATutorial15a.png</figcaption>
58-</figure>
55+![](/wiki-images/a/af/BGRATutorial15a.png)
5956
6057As you can see, the pyramid is viewed from one side, so we can only see one face. There is no lighting either.
6158
6259In the 'with' block, add the following lines:
6360
6461``` pascal
6562 MainPart.Scale(1.3);
6663 MainPart.RotateYDeg(30);
6764 MainPart.RotateXDeg(20);
6865 MainPart.Translate(0,-5,0);
6966```
7067
7168The first line makes the object a little bigger. Then two rotations are applied. The first is around the Y axis and the second around the X axis. To figure out the rotation sign, imagine you are looking in the direction of the axis. A positive value in degrees means a clockwise rotation, and a positive value in radians means an anti-clockwise rotation.
7269
7370Finally a vertical translation is applied to center the object.
7471
75-<figure>
76-<img src="BGRATutorial15b.png" title="BGRATutorial15b.png" />
77-<figcaption>BGRATutorial15b.png</figcaption>
78-</figure>
72+![](/wiki-images/2/29/BGRATutorial15b.png)
7973
8074Now let's add some lighting:
8175
8276``` pascal
8377 //set ambiant lightness to dark (1 is normal lightness, 2 is complete whiteness)
8478 scene.AmbiantLightness := 0.5;
8579 //add a directional light from top-left, maximum lightness will be 0.5 + 1 = 1.5
8680 scene.AddDirectionalLight(Point3D(1,1,1), 1);
8781```
8882
8983The example uses lightness values. 0 means black, 1 means unchanged color, and 2 means white. The directional takes a Point3D parameter to indicate the direction of the ray. It does not need to be normalized.
9084
91-<figure>
92-<img src="BGRATutorial15c.png" title="BGRATutorial15c.png" />
93-<figcaption>BGRATutorial15c.png</figcaption>
94-</figure>
85+![](/wiki-images/5/5d/BGRATutorial15c.png)
9586
9687## Deriving from TBGRAScene3D
9788
9889The scene code can be embedded in an object. Here is the previous example in a single unit:
9990
10091``` pascal
10192unit ex1;
10293
10394{$mode objfpc}{$H+}
10495
10596interface
10697
10798uses
10899 Classes, SysUtils, BGRAScene3D, BGRABitmapTypes;
109100
110101type
111102
112103 { TExample1 }
113104
114105 TExample1 = class(TBGRAScene3D)
115106 SandColor: TBGRAPixel;
116107 constructor Create;
117108 procedure Render; override;
118109 end;
119110
120111implementation
121112
122113{ TExample1 }
123114
124115constructor TExample1.Create;
125116var
126117 base: array of IBGRAVertex3D;
127118 top: IBGRAVertex3D;
128119begin
129120 inherited Create;
130121
131122 SandColor := BGRA(255,240,128);
132123
133124 //create a pyramid
134125 with CreateObject(SandColor) do
135126 begin
136127 top := MainPart.Add(0,-15,0);
137128 //pyramid base is in a clockwise order if we look at the pyramid from below
138129 base := MainPart.Add([-20,15,-20, 20,15,-20, 20,15,20, -20,15,20]);
139130 AddFace(base);
140131 //add four faces, the three vertices are in a clockwise order
141132 AddFace([base[0],top,base[1]]);
142133 AddFace([base[1],top,base[2]]);
143134 AddFace([base[2],top,base[3]]);
144135 AddFace([base[3],top,base[0]]);
145136
146137 MainPart.Scale(1.3);
147138 MainPart.RotateYDeg(30);
148139 MainPart.RotateXDeg(20);
149140 MainPart.Translate(0,-5,0);
150141 end;
151142
152143 //set ambiant lightness to dark (1 is normal lightness, 2 is complete whiteness)
153144 AmbiantLightness := 0.5;
154145 //add a directional light from top-left, maximum lightness will be 0.5 + 1 = 1.5
155146 AddDirectionalLight(Point3D(1,1,1),1);
156147
157148 //we can have antialiasing because it is a simple scene
158149 Antialiasing := True;
159150end;
160151
161152procedure TExample1.Render;
162153begin
163154 //fill background
164155 Surface.GradientFill(0,0,Surface.Width,Surface.Height,SandColor,MergeBGRA(SandColor,BGRABlack), gtRadial,PointF(0,0),PointF(Surface.Width,Surface.Height),dmSet);
165156
166157 inherited Render;
167158end;
168159
169160end.
170161```
171162
172163Now, to draw the scene, simply do:
173164
174165``` pascal
175166uses BGRABitmap, BGRABitmapTypes, BGRAScene3D, ex1;
176167
177168procedure TForm1.FormPaint(Sender: TObject);
178169var
179170 bmp: TBGRABitmap;
180171 scene: TBGRAScene3D;
181172begin
182173 bmp := TBGRABitmap.Create(ClientWidth,ClientHeight,BGRABlack);
183174
184175 scene := TExample1.Create;
185176 scene.Surface := bmp;
186177 scene.Render;
187178 scene.Free;
188179
189180 bmp.Draw(Canvas,0,0);
190181 bmp.Free;
191182end;
192183```
193184
194185By the way, antialiasing and a background have been added. Note that antialiasing works only for simple scenes. Complex scenes with texture and transparent colors may not render correctly.
195186
196-<figure>
197-<img src="BGRATutorial15d.png" title="BGRATutorial15d.png" />
198-<figcaption>BGRATutorial15d.png</figcaption>
199-</figure>
187+![](/wiki-images/9/95/BGRATutorial15d.png)
200188
201189[[BGRABitmap tutorial 14|Previous tutorial (canvas 2D)]] \| [[BGRABitmap tutorial 16|Next tutorial (textures with 3D objects)]]
202190
203191---
204192*From the Free Pascal wiki, page "BGRABitmap tutorial 15", as it stood on 2020-01-05 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
205193Category: BGRABitmap
206194Category: Graphics

Back to history