Graphic Delphi

Title: MNCadBuilder - RapidCAD with Delphi (OpenGL) (part III)
Question: Delphi and 3D CAD development - groups (displaying multiple entities)
Answer:
1. Please make sure you have read the articles "MNCadBuilder - RapidCAD with Delphi" and "MNCadBuilder - RapidCAD with Delphi (part II)" to avoid installation or configuration problems.
We take the basics from "MNCadBuilder - RapidCAD with Delphi (part II)" and extend the TMyShape.
TYPE
TMyShape = class (TMNEntity)
private
FLSize: double;
FSSize: double;
procedure SetLSize(const Value: double);
procedure SetSSize(const Value: double);
protected
procedure Draw; override;
public
// we define some properties to the MyShape
property LSize : double read FLSize write SetLSize;
property SSize : double read FSSize write SetSSize;
// and we overwrite the Initialize method (not the constructor,
// because we want our shape to be compatible with dotNET)
procedure Initialize; override;
end;
The Initialize method:
Initialize is called from the VCL constructor Create (aOwner) but also from the FCL constructor Create ().
// we overwrite the Initialize method (not the constructor,
// because we want our shape to be compatible with dotNET)
procedure TMyShape.Initialize;
begin
inherited;
LSize := 4;
SSize := 1.5;
end;
The SetLSize and SetSSize methods:
When you change properties of an entity, which influence the look of the shape (means that the Draw method should be called) you can use the property Changing:
* Changing := TRUE;
* ...
* Changing := FALSE;
procedure TMyShape.SetLSize(const Value: double);
begin
// Setting Changing to TRUE locks the entity from refreshing
Changing := TRUE;
FLSize := Value;
// Setting Changing to FALSE causes the entity to refresh
Changing := FALSE;
end;
Let's fill the Draw method with some instructions (and we use some additional features):
procedure TMyShape.Draw;
var
trans : TXYZ;
oldDrawBorder : Boolean;
oldPolygonMode : integer;
begin
// Draw a box of length=lsize at position Base
// we draw the box with a golden material
MNDevice.Material.Kind := maGold;
MNDevice.DrawBox(NewPt (lsize,lsize,lsize));
// now we draw some smaller boxes at each side of the box
// and we are going to play with some features of the MNCadBuilder
// - Materials ... how shapes appear
// - PolygonMode ... lined or filled style
// - DrawBorder ... filled and lined style
// we sitch the materials attributes to be bronze like
MNDevice.Material.Kind := MaPolishedBronze;
// push the current ModelMatrix
MNDevice.PushMatrix;
trans := NewPt(lsize/2-ssize/2,lsize/2-ssize/2,-ssize);
// modify the ModelMatrix by a translation
MNDevice.MultMatrix(TranslationToMatrix3D (trans));
// draw some primitive
MNDevice.DrawBox(NewPt (ssize,ssize,ssize));
// and pop the pushed Modelmatrix
MNDevice.PopMatrix;
MNDevice.PushMatrix;
trans := NewPt(-ssize,lsize/2-ssize/2,lsize/2-ssize/2);
MNDevice.MultMatrix(TranslationToMatrix3D (trans));
MNDevice.DrawBox(NewPt (ssize,ssize,ssize));
MNDevice.PopMatrix;
// we save the current PolygonMode
oldPolygonMode := MNDevice.PolygonMode;
// we draw this small box in line mode
MNDevice.PolygonMode := gl_line;
MNDevice.PushMatrix;
trans := NewPt(lsize/2-ssize/2,lsize/2-ssize/2,lsize);
MNDevice.MultMatrix(TranslationToMatrix3D (trans));
MNDevice.DrawBox(NewPt (ssize,ssize,ssize));
MNDevice.PopMatrix;
// we reset the saved PolygonMode
MNDevice.PolygonMode := oldPolygonMode;
// the rest of the small boxes again in fill mode ...
oldDrawBorder := MNDevice.DrawBorder;
// but we draw the lines additionally
MNDevice.DrawBorder := TRUE;
MNDevice.PushMatrix;
trans := NewPt(lsize,lsize/2-ssize/2,lsize/2-ssize/2);
MNDevice.MultMatrix(TranslationToMatrix3D (trans));
MNDevice.DrawBox(NewPt (ssize,ssize,ssize));
MNDevice.PopMatrix;
// after the box is drawn we reset the DrawBorder
MNDevice.DrawBorder := oldDrawBorder;
MNDevice.PushMatrix;
trans := NewPt(lsize/2-ssize/2,lsize,lsize/2-ssize/2);
MNDevice.MultMatrix(TranslationToMatrix3D (trans));
MNDevice.DrawBox(NewPt (ssize,ssize,ssize));
MNDevice.PopMatrix;
MNDevice.PushMatrix;
trans := NewPt(lsize/2-ssize/2,-ssize,lsize/2-ssize/2);
MNDevice.MultMatrix(TranslationToMatrix3D (trans));
MNDevice.DrawBox(NewPt (ssize,ssize,ssize));
MNDevice.PopMatrix;
end;
Now we want the possibility to create more than one of these shapes. So we embed the shapes in a group (of type TMNEntity, nothing special). We create the group in our FormShow method and set the _Entity property of the TMNOglCanvas to this group:
procedure TForm1.FormShow(Sender: TObject);
begin
// create the group ...
MyGroup := TMNEntity.Create (NIL);
// ... and tell the Device to draw the group
MNOglCanvas1._Entity := MyGroup;
end;
.. and we dispose the group in the Form's Close method:
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
// dispose the group
// please note that we do not have to destroy the shapes, because
// they will be destroyed by their MNParent
MyGroup.Free;
end;
Now the handling of the button to create the shapes:
//
// this will create a shape with the defined properties
//
// edO.Text ... Shape's Base.BaseO property - the origin of the shape
// edLSize.Text ... Shape's LSize property - the size of the large box
// edSSize.Text ... Shape's SSize property - the size of the small box
//
procedure TForm1.pbCreateClick(Sender: TObject);
var
B : TBase;
aShape : TMyShape;
begin
// create the shape
aShape := TMyShape.Create (NIL);
with aShape do begin
B := Base;
// we set the origin of the shape
B.BaseO := StrToXYZ (EdO.Text);
Base := B;
// we set the large size of the shape ...
LSize := StrToFloat (edLSize.Text);
// and set the small size of the shape
SSize := StrToFloat (edSSize.Text);
// finally we set the MNParent property of the shape to be the
// MyGroup entity - and because the MNOglCanvas._Entity is set to
// MyGroup, the shape will be drawn.
MNParent := MyGroup;
end;
end;
We can remove all shapes by simply call MyGroup.Clear.
procedure TForm1.pbClearClick(Sender: TObject);
begin
// Clear removes all children
MyGroup.Clear;
end;
These were the first steps of the MNCadBuilder's structural possibilities.
Here you will find the source.
Leopold Minikus
DeveloCAD.com