mirror of
https://git.sr.ht/~rabbits/macintosh_cookbook
synced 2024-12-28 17:29:52 +00:00
248 lines
5.0 KiB
ObjectPascal
248 lines
5.0 KiB
ObjectPascal
program Boxes;
|
|
|
|
uses
|
|
FixMath, Graf3D;
|
|
|
|
type
|
|
Link3D = record
|
|
a: Integer;
|
|
b: Integer;
|
|
end;
|
|
|
|
var
|
|
w: WindowPtr; {A window to draw in}
|
|
r: Rect; {A window Size}
|
|
myPort: GrafPort;
|
|
myPort3D: Port3D;
|
|
pa, pb: Point3D;
|
|
hangle, vangle: Longint;
|
|
{cursor}
|
|
cursor, prev: Point;
|
|
isDown: Boolean;
|
|
{cube}
|
|
shape: array[1..9] of Point3D;
|
|
links: array[1..13] of Link3D;
|
|
|
|
{>>}
|
|
procedure SetLk3D (var lk3D: Link3D; a, b: Integer);
|
|
begin
|
|
lk3D.a := a;
|
|
lk3D.b := b;
|
|
end;
|
|
|
|
{>>}
|
|
procedure CreateCube;
|
|
begin
|
|
SetPt3D(shape[1], Long2Fix(20), Long2Fix(20), Long2Fix(20));
|
|
SetPt3D(shape[2], Long2Fix(20), Long2Fix(40), Long2Fix(-20));
|
|
SetPt3D(shape[3], Long2Fix(-20), Long2Fix(20), Long2Fix(-20));
|
|
SetPt3D(shape[4], Long2Fix(-20), Long2Fix(20), Long2Fix(20));
|
|
|
|
SetPt3D(shape[5], Long2Fix(20), Long2Fix(-20), Long2Fix(20));
|
|
SetPt3D(shape[6], Long2Fix(20), Long2Fix(-20), Long2Fix(-20));
|
|
SetPt3D(shape[7], Long2Fix(-20), Long2Fix(-20), Long2Fix(-20));
|
|
SetPt3D(shape[8], Long2Fix(-20), Long2Fix(-20), Long2Fix(20));
|
|
|
|
SetLk3D(links[1], 1, 2);
|
|
SetLk3D(links[2], 2, 3);
|
|
SetLk3D(links[3], 3, 4);
|
|
SetLk3D(links[4], 4, 1);
|
|
|
|
SetLk3D(links[5], 5, 6);
|
|
SetLk3D(links[6], 6, 7);
|
|
SetLk3D(links[7], 7, 8);
|
|
SetLk3D(links[8], 8, 5);
|
|
|
|
SetLk3D(links[9], 1, 5);
|
|
SetLk3D(links[10], 2, 6);
|
|
SetLk3D(links[11], 3, 7);
|
|
SetLk3D(links[12], 4, 8);
|
|
end;
|
|
|
|
{>>}
|
|
procedure PaintCube;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
|
|
for i := 1 to 12 do
|
|
begin
|
|
MoveTo3D(shape[links[i].a].x, shape[links[i].a].y, shape[links[i].a].z);
|
|
LineTo3D(shape[links[i].b].x, shape[links[i].b].y, shape[links[i].b].z);
|
|
end;
|
|
end;
|
|
|
|
{>>}
|
|
function Interpolate (a, b, t: Fixed): Fixed;
|
|
begin
|
|
Interpolate := a + FixMul(b - a, t);
|
|
end;
|
|
|
|
{>>}
|
|
function HasPixel3D (col, row: Integer): Boolean;
|
|
begin
|
|
HasPixel3D := ((col + (row mod 2 + 1)) mod 2 = 0)
|
|
end;
|
|
|
|
|
|
{>>}
|
|
procedure LerpPt (var dest, a, b: Point3D; t: Fixed);
|
|
begin
|
|
SetPt3D(dest, Interpolate(a.x, b.x, t), Interpolate(a.y, b.y, t), Interpolate(a.z, b.z, t))
|
|
end;
|
|
|
|
{>>}
|
|
procedure ToPlane (var dest, a, b, c, d: Point3D; col, row, limit: Integer);
|
|
var
|
|
top, bottom, left, right, result1, result2: Point3D;
|
|
begin
|
|
LerpPt(top, a, b, FixRatio(row, limit));
|
|
LerpPt(bottom, d, c, FixRatio(row, limit));
|
|
LerpPt(left, a, d, FixRatio(col, limit));
|
|
LerpPt(right, b, c, FixRatio(col, limit));
|
|
LerpPt(result1, top, bottom, FixRatio(col, limit));
|
|
LerpPt(result2, left, right, FixRatio(row, limit));
|
|
LerpPt(dest, result1, result2, FixRatio(col, 2));
|
|
end;
|
|
|
|
{>>}
|
|
procedure PaintFace (a, b, c, d: Point3D);
|
|
var
|
|
tempRgn: RgnHandle;
|
|
row, col: Integer;
|
|
hpt, vpt, minia, minib, minic, minid: Point3D;
|
|
x, y, z: Fixed;
|
|
limit: Integer;
|
|
begin
|
|
|
|
limit := 10;
|
|
|
|
tempRgn := NewRgn;
|
|
OpenRgn;
|
|
|
|
for col := 0 to limit - 1 do
|
|
begin
|
|
row := 0;
|
|
for row := 0 to limit - 1 do
|
|
begin
|
|
if HasPixel3D(col, row) then
|
|
begin
|
|
ToPlane(minia, a, b, c, d, row, col, limit);
|
|
ToPlane(minib, a, b, c, d, row + 1, col, limit);
|
|
ToPlane(minic, a, b, c, d, row, col + 1, limit);
|
|
ToPlane(minid, a, b, c, d, row + 1, col + 1, limit);
|
|
MoveTo3D(minia.x, minia.y, minia.z);
|
|
LineTo3D(minib.x, minib.y, minib.z);
|
|
LineTo3D(minid.x, minid.y, minid.z);
|
|
LineTo3D(minic.x, minic.y, minic.z);
|
|
LineTo3D(minia.x, minia.y, minia.z);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
CloseRgn(tempRgn);
|
|
PaintRgn(tempRgn);
|
|
DisposeRgn(tempRgn);
|
|
|
|
end;
|
|
|
|
{>>}
|
|
procedure PaintAxis (size: Integer);
|
|
begin
|
|
PenPat(black);
|
|
MoveTo3D(0, 0, 0);
|
|
LineTo3D(Long2Fix(size), 0, 0);
|
|
WriteDraw('x');
|
|
MoveTo3D(0, 0, 0);
|
|
LineTo3D(0, Long2Fix(size), 0);
|
|
WriteDraw('y');
|
|
MoveTo3D(0, 0, 0);
|
|
LineTo3D(0, 0, Long2Fix(size));
|
|
WriteDraw('z');
|
|
end;
|
|
|
|
{>>}
|
|
procedure WindowInit;
|
|
begin
|
|
SetRect(r, 100, 50, 300, 250);
|
|
w := NewWindow(nil, r, 'Mapping', true, zoomDocProc, WindowPtr(-1), false, 0);
|
|
SetPort(w);
|
|
end;
|
|
|
|
{>>}
|
|
procedure ClearScreen;
|
|
var
|
|
size: Rect;
|
|
begin
|
|
SetRect(size, 0, 0, 200, 200);
|
|
FillRect(size, white);
|
|
end;
|
|
|
|
{>>}
|
|
procedure Redraw;
|
|
begin
|
|
ClearScreen;
|
|
LookAt(Long2Fix(-50), Long2Fix(50), Long2Fix(50), Long2Fix(-50));
|
|
ViewAngle(Long2Fix(20));
|
|
Identity;
|
|
Roll(Long2Fix(hangle));
|
|
Pitch(Long2Fix(vangle)); { roll and pitch the plane }
|
|
|
|
PaintAxis(10);
|
|
PaintFace(shape[1], shape[2], shape[3], shape[4]);
|
|
PaintCube;
|
|
end;
|
|
|
|
{>>}
|
|
procedure WhenDownChanged;
|
|
var
|
|
hoff, voff: Integer;
|
|
begin
|
|
hoff := prev.h - cursor.h;
|
|
hangle := hangle + hoff;
|
|
voff := prev.v - cursor.v;
|
|
vangle := vangle + voff;
|
|
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;
|
|
|
|
begin
|
|
|
|
WindowInit;
|
|
InitGrf3D(nil);
|
|
Open3DPort(@myPort3D);
|
|
ViewPort(thePort^.portRect);
|
|
|
|
CreateCube;
|
|
|
|
hangle := 145;
|
|
vangle := 65;
|
|
|
|
Redraw;
|
|
MainLoop;
|
|
|
|
end. |