macintosh_cookbook/units/Graf3DScene/Graf3DScene.pas

311 lines
7.5 KiB
ObjectPascal
Raw Normal View History

2020-05-12 12:14:52 +00:00
unit Graf3DScene;
interface
uses
FixMath, Graf3D;
2020-05-15 02:35:20 +00:00
const
2020-05-16 12:08:19 +00:00
LIMIT_SHAPES = 30;
2020-05-15 02:35:20 +00:00
LIMIT_VERTICES = 32;
2020-05-15 03:09:12 +00:00
LIMIT_EDGES = 40;
2020-05-15 02:35:20 +00:00
LIMIT_FACES = 8;
2020-05-12 12:14:52 +00:00
type
Point3DPtr = ^Point3D;
2020-05-15 11:28:41 +00:00
Edge3D = record
2020-05-12 12:14:52 +00:00
a: Point3DPtr;
b: Point3DPtr;
end;
Face3D = record
a: Point3DPtr;
b: Point3DPtr;
c: Point3DPtr;
end;
Shape3D = record
origin: Point3D;
2020-05-16 01:27:37 +00:00
verticesLength: Integer;
edgesLength: Integer;
2020-05-15 11:28:41 +00:00
facesLength: Integer;
2020-05-15 02:35:20 +00:00
vertices: array[1..LIMIT_VERTICES] of Point3D;
2020-05-15 11:28:41 +00:00
edges: array[1..LIMIT_EDGES] of Edge3D;
2020-05-15 02:35:20 +00:00
faces: array[1..LIMIT_FACES] of Face3D;
2020-05-12 12:14:52 +00:00
end;
Shape3DPtr = ^Shape3D;
Scene3D = record
length: Integer;
2020-05-16 12:08:19 +00:00
shapes: array[1..LIMIT_SHAPES] of Shape3DPtr;
2020-05-12 12:14:52 +00:00
end;
Scene3DPtr = ^Scene3D;
2020-05-16 01:27:37 +00:00
Camera3D = record
pitch, yaw, roll: Longint;
end;
2020-05-12 12:14:52 +00:00
var
drawingRect: Rect; {A window Size}
viewWidth, viewHeight, padLeft, padTop: Integer;
myPort: GrafPort;
myPort3D: Port3D;
2020-05-16 01:27:37 +00:00
camera: Camera3D;
2020-05-12 12:14:52 +00:00
{cursor}
cursor, prev: Point;
isDown: Boolean;
scene: Scene3D;
procedure InitWindow;
procedure SetScene3D (var scene: Scene3D);
2020-05-16 12:08:19 +00:00
procedure AddShape3D (var scene: scene3D; shape: Shape3DPtr);
2020-05-16 01:42:48 +00:00
{scene}
procedure SetVertice3D (var vertice: Point3D; x, y, z: Longint);
2020-05-15 11:28:41 +00:00
procedure SetEdge3D (var edge: Edge3D; a, b: Point3DPtr);
procedure SetFace3D (var face: Face3D; a, b, c: Point3DPtr);
{ basics }
2020-05-16 01:42:48 +00:00
procedure AddVertice3D (var shape: Shape3D; x, y, z: LongInt);
2020-05-15 11:28:41 +00:00
procedure AddEdge3D (var shape: Shape3D; a, b: Integer);
procedure AddFace3D (var shape: Shape3D; a, b, c: Integer);
2020-05-12 12:14:52 +00:00
{ transforms }
2020-05-16 01:42:48 +00:00
procedure MoveShape3D (shape: Shape3DPtr; x, y, z: LongInt);
2020-05-12 12:14:52 +00:00
procedure ScaleShape3D (shape: Shape3DPtr; x, y, z: LongInt);
procedure TurnXShape3D (shape: Shape3DPtr);
procedure TurnYShape3D (shape: Shape3DPtr);
procedure TurnZShape3D (shape: Shape3DPtr);
{ draw }
2020-05-15 11:28:41 +00:00
procedure DrawEdge3D (edge: Edge3D);
2020-05-12 12:14:52 +00:00
procedure DrawShape3D (shape: Shape3DPtr);
procedure DrawScene3D (scene: Scene3D);
implementation
2020-05-15 02:35:20 +00:00
procedure SceneError (text: string);
begin
ShowText;
Writeln(text);
Halt;
end;
2020-05-16 01:42:48 +00:00
procedure SetVertice3D (var vertice: Point3D; x, y, z: Longint);
begin
SetPt3D(vertice, Long2Fix(x), Long2Fix(y), Long2Fix(z));
end;
procedure SetEdge3D (var edge: Edge3D; a, b: Point3DPtr);
begin
edge.a := a;
edge.b := b;
end;
procedure SetFace3D (var face: Face3D; a, b, c: Point3DPtr);
begin
face.a := a;
face.b := b;
face.c := c;
end;
procedure AddVertice3D (var shape: Shape3D; x, y, z: Fixed);
begin
if shape.verticesLength > LIMIT_VERTICES - 1 then
SceneError('Vertices limit reached');
shape.verticesLength := shape.verticesLength + 1;
SetPt3D(shape.vertices[shape.verticesLength], Long2Fix(x), Long2Fix(y), Long2Fix(z));
end;
procedure AddEdge3D (var shape: Shape3D; a, b: Integer);
begin
if shape.EdgesLength > LIMIT_EDGES - 1 then
SceneError('Edges limit reached');
shape.EdgesLength := shape.EdgesLength + 1;
SetEdge3D(shape.edges[shape.EdgesLength], @shape.vertices[a], @shape.vertices[b]);
end;
procedure AddFace3D (var shape: Shape3D; a, b, c: Integer);
begin
if shape.facesLength > LIMIT_FACES - 1 then
SceneError('Edges limit reached');
shape.facesLength := shape.facesLength + 1;
SetFace3D(shape.faces[shape.facesLength], @shape.vertices[a], @shape.vertices[b], @shape.vertices[c]);
end;
2020-05-12 12:14:52 +00:00
procedure AddShape3D (var scene: scene3D; shape: Shape3DPtr);
begin
2020-05-16 12:08:19 +00:00
if scene.length > LIMIT_SHAPES - 1 then
SceneError('Shapes limit reached');
2020-05-12 12:14:52 +00:00
scene.length := scene.length + 1;
scene.shapes[scene.length] := shape;
end;
procedure MoveShape3D (shape: Shape3DPtr; x, y, z: Fixed);
var
i: Integer;
begin
for i := 1 to shape^.verticesLength do
SetPt3D(shape^.vertices[i], shape^.vertices[i].x + Long2Fix(x), shape^.vertices[i].y + Long2Fix(y), shape^.vertices[i].z + Long2Fix(z));
end;
procedure ScaleShape3D (shape: Shape3DPtr; x, y, z: Fixed);
var
i: Integer;
begin
for i := 1 to shape^.verticesLength do
begin
SetPt3D(shape^.vertices[i], FixMul(shape^.vertices[i].x, Long2Fix(x)), FixMul(shape^.vertices[i].y, Long2Fix(y)), FixMul(shape^.vertices[i].z, Long2Fix(z)));
end;
end;
procedure TurnXShape3D (shape: Shape3DPtr);
var
i: Integer;
begin
SetPt3D(shape^.origin, shape^.origin.x, shape^.origin.z, shape^.origin.y);
for i := 1 to shape^.verticesLength do
2020-05-14 00:01:11 +00:00
SetPt3D(shape^.vertices[i], shape^.vertices[i].x, shape^.vertices[i].z - shape^.origin.y, shape^.vertices[i].y + shape^.origin.y);
2020-05-12 12:14:52 +00:00
end;
procedure TurnYShape3D (shape: Shape3DPtr);
var
i: Integer;
begin
for i := 1 to shape^.verticesLength do
2020-05-14 00:01:11 +00:00
SetPt3D(shape^.vertices[i], shape^.origin.z - shape^.vertices[i].z + shape^.origin.x, shape^.vertices[i].y, shape^.vertices[i].x - shape^.origin.x + shape^.origin.z);
2020-05-12 12:14:52 +00:00
end;
procedure TurnZShape3D (shape: Shape3DPtr);
var
i: Integer;
begin
SetPt3D(shape^.origin, shape^.origin.y, shape^.origin.x, shape^.origin.z);
for i := 1 to shape^.verticesLength do
SetPt3D(shape^.vertices[i], shape^.vertices[i].y, shape^.vertices[i].x, shape^.vertices[i].z);
end;
procedure SetScene3D (var scene: Scene3D);
begin
scene.length := 0;
end;
2020-05-15 11:28:41 +00:00
procedure DrawEdge3D (edge: Edge3D);
2020-05-12 12:14:52 +00:00
begin
2020-05-15 11:28:41 +00:00
MoveTo3D(edge.a^.x, edge.a^.y, edge.a^.z);
LineTo3D(edge.b^.x, edge.b^.y, edge.b^.z);
2020-05-12 12:14:52 +00:00
end;
procedure DrawFace3D (face: Face3D);
var
tempRgn: RgnHandle;
begin
tempRgn := NewRgn;
OpenRgn;
MoveTo3D(face.a^.X, face.a^.Y, face.a^.Z);
LineTo3D(face.b^.X, face.b^.Y, face.b^.Z);
LineTo3D(face.c^.X, face.c^.Y, face.c^.Z);
LineTo3D(face.a^.X, face.a^.Y, face.a^.Z);
CloseRgn(tempRgn);
2020-05-14 11:14:40 +00:00
FillRgn(tempRgn, white);
2020-05-12 12:14:52 +00:00
DisposeRgn(tempRgn);
end;
procedure DrawShape3D (shape: Shape3DPtr);
var
i: Integer;
begin
for i := 1 to shape^.facesLength do
DrawFace3D(shape^.faces[i]);
2020-05-15 10:18:33 +00:00
for i := 1 to shape^.EdgesLength do
2020-05-15 11:28:41 +00:00
DrawEdge3D(shape^.edges[i]);
2020-05-12 12:14:52 +00:00
end;
procedure DrawWidget (size: Integer);
begin
PenPat(black);
MoveTo3D(Long2Fix(size), 0, 0);
WriteDraw('x');
LineTo3D(0, 0, 0);
LineTo3D(0, Long2Fix(size), 0);
WriteDraw('y');
MoveTo3D(0, 0, 0);
LineTo3D(0, 0, Long2Fix(size));
WriteDraw('z');
end;
procedure DrawScene3D (scene: Scene3D);
var
i: Integer;
begin
2020-05-14 11:14:40 +00:00
{ DrawWidget(50); }
2020-05-12 12:14:52 +00:00
for i := 1 to scene.length do
DrawShape3D(scene.shapes[i]);
end;
procedure ClearScreen;
var
size: Rect;
begin
SetRect(size, 0, 0, viewWidth, viewWidth);
FillRect(size, white);
end;
procedure Redraw;
var
i: Integer;
begin
ClearScreen;
LookAt(Long2Fix(-viewWidth), Long2Fix(viewheight), Long2Fix(viewWidth), Long2Fix(-viewHeight));
ViewAngle(Long2Fix(50));
Identity;
2020-05-16 01:27:37 +00:00
Yaw(Long2Fix(camera.yaw));
Pitch(Long2Fix(camera.pitch));
2020-05-12 12:14:52 +00:00
DrawScene3D(scene);
end;
procedure WhenDownChanged;
begin
2020-05-16 01:27:37 +00:00
camera.yaw := camera.yaw + prev.h - cursor.h;
camera.pitch := camera.pitch + prev.v - cursor.v;
2020-05-12 12:14:52 +00:00
Redraw;
GetMouse(prev);
end;
procedure WhenDown;
begin
GetMouse(cursor);
if cursor.h <> prev.h then
if cursor.v <> prev.v then
WhenDownChanged;
end;
procedure MainLoop;
begin
repeat {Until we click outside screen}
while button do
begin
GetMouse(cursor);
GetMouse(prev);
repeat {Tight loop until button up}
WhenDown;
until not Button;
end;
until cursor.h < 0;
end;
procedure InitWindow;
begin
2020-05-16 04:07:00 +00:00
viewWidth := 640;
viewHeight := 405;
padLeft := 15;
2020-05-16 12:37:52 +00:00
padTop := 40;
2020-05-12 12:14:52 +00:00
SetRect(drawingRect, padLeft, padTop, padLeft + viewWidth, padTop + viewHeight);
SetDrawingRect(drawingRect);
ShowDrawing;
InitGrf3D(nil);
Open3DPort(@myPort3D);
ViewPort(thePort^.portRect);
Redraw;
MainLoop;
end;
end.