unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, ComCtrls;
type
{ TForm1 }
TForm1 = class(TForm)
StatusBar1: TStatusBar;
Timer1: TTimer;
procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
procedure FormPaint(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
private
procedure CreateShape;
public
end;
var
Form1: TForm1;
implementation
uses
BGRAScene3D, BGRABitmap, BGRABitmapTypes,
epiktimer, serialobject;
{$R *.lfm}
{ TForm1 }
var
scene: TBGRAScene3D;
obj3D: IBGRAObject3D;
bmp: TBGRABitmap;
base: array of IBGRAVertex3D;
topV: IBGRAVertex3D;
serial: TSerialObj;
eptimer: TEpikTimer;
procedure TForm1.FormPaint(Sender: TObject);
begin
CreateShape;
if not Assigned(serial) then
begin
serial := TSerialObj.Create;
if serial.OpenPort('/dev/ttyACM0', 115200) then
begin
Timer1.Enabled := true;
serial.FlushInput;
eptimer := TEpikTimer.Create(nil);
eptimer.Start;
end
else
begin
FreeAndNil(serial);
ShowMessage('Error opening serial port.');
end;
end;
end;
procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
Timer1.Enabled := false;
if Assigned(serial) then
FreeAndNil(serial);
if Assigned(scene) then
FreeAndNil(scene);
if Assigned(obj3D) then
FreeAndNil(obj3D);
if Assigned(bmp) then
FreeAndNil(bmp);
end;
var
x: integer = 0;
y: integer = 0;
z: Integer = 0;
procedure TForm1.Timer1Timer(Sender: TObject);
var
data: packed array[0..2] of int16;
databytes: packed array[0..5] of byte absolute data;
r: integer;
begin
Timer1.Enabled := false;
// Request new data
if Assigned(serial) then
begin
serial.FlushInput;
serial.Write(ord('.'));
end;
// Update display with previous values
StatusBar1.Panels[3].Text := IntToStr(x) + 'º';
StatusBar1.Panels[5].Text := IntToStr(y) + 'º';
StatusBar1.Panels[7].Text := IntToStr(z) + 'º';
eptimer.Clear;
eptimer.Start;
bmp.Canvas.Brush.Color := clBlack;
bmp.Canvas.FillRect(0, 0, ClientWidth, ClientHeight);
CreateShape;
obj3D.MainPart.RotateYDeg(y); // Rotate around vertical axis, + = clockwise as viewed from top
obj3D.MainPart.RotateXDeg(x); // vertical, - tilt top away from viewer
obj3D.MainPart.RotateZDeg(z); // vertical, - tilt top clockwise in front of viewer
scene.Render;
bmp.Draw(Canvas,0,0);
eptimer.Stop;
StatusBar1.Panels[1].Text := FloatToStrF(epTimer.Elapsed*1000, ffGeneral, 3, 2);
// Read new data
if Assigned(serial) then
begin
r := serial.ReadTimeout(databytes, 6, 50); // 3x 2 byte values
if r <> 6 then
ShowMessage('data error')
else
begin
y := data[0];
z := data[1];
x := -data[2];
end;
end;
Timer1.Enabled := true;
end;
procedure TForm1.CreateShape;
begin
if not Assigned(bmp) and not Assigned(scene) then
begin
bmp := TBGRABitmap.Create(ClientWidth,ClientHeight,BGRABlack);
scene := TBGRAScene3D.Create(bmp);
end
else
scene.Clear;
//create a pyramid
obj3D := scene.CreateObject(BGRA(255,240,128));
with obj3D do
begin
//create vertices
topV := MainPart.Add(0,-50,0);
//pyramid base is in a clockwise order if we look at the pyramid from below
base := MainPart.Add([-20,25,-20, 20,25,-20, 20,25,20, -20,25,20]);
AddFace(base, BGRA(127,127,127));
//add four faces, the three vertices are in a clockwise order
AddFace([base[0],topV,base[1]], BGRA(255, 0, 0));
AddFace([base[1],topV,base[2]], BGRA(0, 255, 0));
AddFace([base[2],topV,base[3]], BGRA(0, 0, 255));
AddFace([base[3],topV,base[0]]);
topV := nil;
base := nil;
end;
end;
end.