home *** CD-ROM | disk | FTP | other *** search
- PROGRAM _3D;
- USES Intuition,Graphics;
-
- { geschrieben von: Michael Janich 1989 }
- { bearbeitet von: Jens "Himpelsoft" Gelhar }
- { ALL RIGHTS REVERSED. }
-
- { MaxonPascal3-Anpassung: Falk Zühlsdorff (PackMAN) 1994 }
-
- { Programm wird mit ESC beendet. }
- { Mit den Cursortasten kann man die Rotationsrichtung des }
- { Objekts ändern, mit einigen Tasten des Ziffernblocks }
- { den Standpunkt des Betrachters. }
- { In der vorliegenden Version gibt es noch Fehler, wenn }
- { Linien den Bildschirmrand überschreiten. }
-
- CONST width=640;
- height=256; { Screen }
-
- file_name = 'MPascal3:Demo/3D_coords/coords.haus';
- { Aus dieser Datei werden die Koordinaten gelesen }
-
- rot_angle=0.12; { rotation in one step }
-
- TYPE Point = REAL;
- Ptr2Point_3d = ^Point_3d;
- Point_3d = RECORD x, y, z: Point;
- END; { Rec Point_3d }
- Ptr2Point_2d = ^Point_2d;
- Point_2d = RECORD x, y: Point;
- END; { Rec Point_2d }
- Ptr2Coords = ^Coords;
- Coords = RECORD c: Point_3d;
- next: Ptr2Coords;
- END;
-
- VAR fin,helpscreen : BOOLEAN;
- FP : Point_3d;
- chain : Ptr2Coords;
- W1,W2 :^Window;
- Rast1 :^RastPort;
- MyScreen1 : ^Screen;
- Rast2 :^RastPort;
- Rast : ^RastPort;
- MyScreen2 : ^Screen;
- t1 : IntuiText;
- sin_rot_angle,
- cos_rot_angle : REAL;
- act_pos : STRING[99];
- Pointer : ^Byte; { Requiered for key-codes }
- LastKey : Byte;
- i : INTEGER;
- pro_Res,last : Point_2d; { Result of projetion-function }
- rot_res : Point_3d; { Result of rotation-func }
- rot,scr_no : INTEGER;
-
- (************************************************************************)
- (* Function: *)
- (* *)
- (* Open Screen *)
- (************************************************************************)
-
- PROCEDURE Init;
- VAR i: INTEGER;
-
- BEGIN { Init }
- fin := FALSE;
- Pointer := Ptr($bfec01);
- LastKey := 0;
- MyScreen1:=Open_Screen(0, 0, width, height, 1, 0, 1, HIRES or GENLOCK_VIDEO,'3d-Haus');
- MyScreen2:=Open_Screen(0, 0, width, height, 1, 0, 1, HIRES or GENLOCK_VIDEO,'3d-Haus');
- W1:=Open_Window(0,0,width,height,1,0,$0800,Nil,MyScreen1,width,height,width,height);
- W2:=Open_Window(0,0,width,height,1,0,$0800,Nil,MyScreen2,width,height,width,height);
- Rast1:=W1^.RPort;
- Rast2:=W2^.RPort;
- Rast := Rast1;
- SetRGB4(^MyScreen1^.ViewPort,0,1,1,1); { almost black }
- SetRGB4(^MyScreen2^.ViewPort,0,1,1,1);
- SetRGB4(^MyScreen1^.ViewPort,1,14,14,14); { almost withe }
- SetRGB4(^MyScreen2^.ViewPort,1,14,14,14);
- FP.x := -40; { Point of eye }
- FP.y := -40;
- FP.z := -40;
- sin_rot_angle := sin(rot_angle);
- cos_rot_angle := cos(rot_angle);
- last.x := width div 2; { else undefinded }
- last.y := height div 2;
- scr_no := 1; { screen_number toggles between 1 and 2 }
- rot := 2; { rotation axis 1,2,3 }
- END; { Proc Init }
-
- (************************************************************************)
- (* Input: *)
- (* *)
- (* 3d-Point; call by reference *)
- (************************************************************************)
- (* Output: *)
- (* *)
- (* 3d-Point *)
- (************************************************************************)
- (* Function: *)
- (* *)
- (* rotate point by the rot_angle *)
- (************************************************************************)
-
- PROCEDURE Rotate_alfa (VAR a: Point_3d); { We change the original point }
- BEGIN
- a.y := a.y * cos_rot_angle - a.z * sin_rot_angle;
- a.z := a.y * sin_rot_angle + a.z * cos_rot_angle;
- END; { Proc Rotate_alfa }
-
- PROCEDURE Rotate_beta (VAR a: Point_3d); { We change the original point }
- BEGIN
- a.x := a.x * cos_rot_angle + a.z * sin_rot_angle;
- a.z := a.z * cos_rot_angle - a.x * sin_rot_angle ;
- END; { Proc Rotate_beta }
-
- PROCEDURE Rotate_gamma (VAR a: Point_3d); { We change the original point }
- BEGIN
- a.x := a.x * cos_rot_angle - a.y * sin_rot_angle;
- a.y := a.x * sin_rot_angle + a.y * cos_rot_angle;
- END; { Proc Rotate_gamma }
-
- { please verify the +- in r_gamma }
-
- (************************************************************************)
- (* Input: *)
- (* *)
- (* 3d-Point *)
- (************************************************************************)
- (* Output: *)
- (* *)
- (* 2d-Point *)
- (************************************************************************)
- (* Function: *)
- (* *)
- (* Convert py central-perspectiv *)
- (************************************************************************)
-
- PROCEDURE Projection (a: Point_3d); { result in global Pro_res }
- VAR t: Point;
-
- BEGIN { Func Projection }
- {$if def debug}
- WriteLn("Projection: Eingabe: (",a.x,",",a.y,",",a.z,").");
- {$endif debug}
- IF abs(a.y - FP.y) <1e-3
- THEN t := 0
- ELSE t := a.y / (2*(a.y - FP.y));
- pro_res.x := 2*(a.x - t*(a.x - FP.x))+width/2;
- pro_res.y := (a.z - t*(a.z - FP.z))+height/2;
- {$if def debug}
- WriteLn("----------- Ausgabe: (",pro_res.x,",",pro_res.y,").");
- {$endif debug}
- END; { Func Projection }
-
- (************************************************************************)
- (* Input: *)
- (* *)
- (* 2d-Points *)
- (************************************************************************)
- (* Function: *)
- (* *)
- (* Check Point for screen-dimens. cut, if neccessary *)
- (************************************************************************)
-
- PROCEDURE Check (VAR a: Point_2d);
- VAR temp: Point_2d;
-
- BEGIN
- temp := a;
- IF a.x < 0 THEN { right of screen }
- IF (last.x-a.x)=0 THEN a.x := -1 ELSE BEGIN { check for division by 0 }
- a.y := last.y - (last.y-a.y)*last.x/(last.x-a.x); a.x := 0;
- END;
- IF a.y >= height THEN
- IF (last.y-a.y)=0 THEN a.x := -1 ELSE BEGIN
- a.x := a.x - (a.x-last.x)*(last.y-height)/(a.y-last.y); a.y := height-1;
- END;
- IF a.x >= width THEN BEGIN
- {$if def debug}
- WriteLn("a.x ist zu gross: ",a.x," >= ",width);
- {$endif}
- IF (a.x-last.x)=0 THEN a.x := -1 ELSE BEGIN
- a.y := last.y - (last.y-a.y)*(last.x-width)/(a.x-last.x); { an dieser Stelle gabs immer den /0-error }
- a.x := width-1;
- END;
- END;
- IF a.y < 0 THEN
- IF (last.y-a.y)=0 THEN a.x := -1 ELSE BEGIN
- a.x := a.x - (a.x-last.x)*last.y/(last.y-a.y); a.y := 0;
- END; { letztes ist noch zu überprüfen }
- {$if def debug}
- IF(a.x <> temp.x) OR (a.y <> temp.y) THEN
- WriteLn("Changes in Check-Procedure.");
- {$endif debug}
- last := temp;
-
- END; { Proc Check }
- (************************************************************************)
- (* Input: *)
- (* *)
- (* Two 2d-Points (from-Coord, to-Coord) *)
- (************************************************************************)
- (* Function: *)
- (* *)
- (* Draw Line on Screen *)
- (************************************************************************)
-
- PROCEDURE Draw_line(a: Point_2d);
- BEGIN
- Check (a);
- {$if def debug}
- WriteLn("Linie nach (",a.x,",",a.y,").");
- {$endif}
- IF a.x <> -1 THEN Draw (Rast, round(a.x), round(a.y));
- END; { Proc Draw }
-
- (************************************************************************)
- (* Input: *)
- (* *)
- (* 2d-Point (to-Coord) *)
- (************************************************************************)
- (* Function: *)
- (* *)
- (* Move Grafik-Cursor *)
- (************************************************************************)
-
- PROCEDURE Move_Line(a: Point_2d);
- BEGIN
- Check (a);
- {$if def debug}
- WriteLn("Bewegen nach (",a.x,",",a.y,").");
- {$endif}
- IF a.x <> -1 THEN Move(Rast, round(a.x), round(a.y));
- END; { Proc Move_line }
-
- (************************************************************************)
- (* Input: *)
- (* *)
- (* Keyboard *)
- (************************************************************************)
- (* Function: *)
- (* *)
- (* change point of eye *)
- (************************************************************************)
-
- PROCEDURE Read_Change;
- BEGIN
- LastKey := Pointer^;
- CASE LastKey OF
- 133: FP.x := FP.x + 1;
- 197: FP.x := FP.x - 1;
- 131: FP.y := FP.y + 1;
- 195: FP.y := FP.y - 1;
- 129: FP.z := FP.z + 1;
- 193: FP.z := FP.z - 1;
- 103: rot := 1;
- 101: rot := 1;
- 097: rot := 2;
- 099: rot := 2;
- 139: rot := 3;
- 201: rot := 3;
- 127, 117, 119: fin := TRUE;
- Otherwise
- END; { CASE }
-
- CASE scr_no OF
- 1: BEGIN Rast:=Rast2; ScreenToFront(MyScreen1) END;
- 2: BEGIN Rast:=Rast1; ScreenToFront(MyScreen2) END
- END;
-
- scr_no := 3-scr_no;
- SetAPen(Rast,0);
- RectFill(Rast,0,0,Width-1,Height-1);
- SetAPen(Rast,1);
- END; { Proc Read_Changes }
-
- (************************************************************************)
- (* Input: *)
- (* *)
- (* Chain of 3d-points *)
- (************************************************************************)
- (* Function: *)
- (* *)
- (* Calculate and Draw 3d-points *)
- (************************************************************************)
-
- PROCEDURE Calc_Draw (root: Ptr2Coords);
-
- BEGIN
- WHILE root <> NIL DO
- BEGIN
- IF root^.c.x = -1 THEN
- BEGIN
- root := root^.next;
- CASE rot OF
- 1: Rotate_alfa (root^.c);
- 2: Rotate_beta (root^.c);
- 3: Rotate_gamma(root^.c);
- ELSE; END; { case }
- Projection (root^.c);
- Move_Line(pro_res);
- END
- ELSE BEGIN
- CASE rot OF
- 1: Rotate_alfa (root^.c);
- 2: Rotate_beta (root^.c);
- 3: Rotate_gamma(root^.c);
- ELSE; END; { case }
- Projection(root^.c);
- Draw_Line(pro_res);
- END;
- root := root^.next;
- END; { WHILE }
- END; { Proc Calc_Draw }
-
- (************************************************************************)
- (* Input: *)
- (* *)
- (* File of coords of object *)
- (************************************************************************)
- (* Output: *)
- (* *)
- (* Root of chain *)
- (************************************************************************)
- (* Function: *)
- (* *)
- (* read file from extern device *)
- (************************************************************************)
-
- FUNCTION Read_Coords: Ptr2Coords;
- VAR f: FILE OF CHAR;
- old_coord, result, temp: Ptr2Coords;
-
- BEGIN
- New (result);
- WITH result^.c DO
- BEGIN
- x := -1;
- y := 0;
- z := 0;
- END; { WITH }
- old_coord := result;
- Reset (f, file_Name);
- IF EoF(f) THEN Error ("File not Found.");
- WHILE NOT EoF(f) DO
- BEGIN
- New (temp);
- WITH temp^.c DO
- BEGIN
- ReadLn (f, x, y, z);
- {$if def debug}
- WriteLn("Gelesene Coordinaten: (",x,",",y,",",z,").");
- {$endif}
- END; { WITH }
- old_coord^.next := temp;
- old_coord := temp;
- END; { WHILE }
- temp^.next := NIL; { End of chain }
- Read_Coords := result;
- END; { Func Read_Coords }
-
-
- (************************************************************************)
- (* Function: *)
- (* *)
- (* Close libraries and screen *)
- (************************************************************************)
-
-
- PROCEDURE Close_(list:Ptr2Coords);
- VAR temp: Ptr2Coords;
- BEGIN
- WHILE (list <> NIL) DO
- BEGIN
- temp := list^.next;
- dispose (list);
- list := temp;
- END; { WHILE }
- helpscreen:=CloseScreen(MyScreen1);
- helpscreen:=CloseScreen(MyScreen2);
- CloseLib(intuitionbase);
- CloseLib(GfxBase);
- END;
-
- BEGIN { Main }
- Init;
- chain := Read_Coords;
- REPEAT
- Calc_Draw (chain);
- Read_Change;
- act_pos := '('+RealStr(FP.x,0)+','+RealStr(FP.y,0)+','+RealStr(Fp.z,0)+')';
- t1:=IntuiText(1,0,1,0,0,Nil,act_pos,Nil);
- PrintIText (Rast1, ^t1, 10,190);
- PrintIText (Rast2, ^t1, 10,190);
- UNTIL fin;
- Close_(chain);
- END.
-
-