home *** CD-ROM | disk | FTP | other *** search
- (* ------------------------------------------------------ *)
- (* WUERFEL.PAS *)
- (* (c) 1898 Martin Müller & TOOLBOX *)
- (* ------------------------------------------------------ *)
- PROGRAM Vier_Dimensionen;
-
- USES Graph3, Crt;
-
- CONST xpix = 320; (* Hälfte der Bildschirmgröße *)
- ypix = 100; (* Pixelzahl in Punkten *)
- lx = 1.5; (* Hälfte der Projektionsschirmgröße *)
- ly = 1.0;
-
- TYPE vektor = RECORD (* vierdimensionaler Vektor *)
- x, y, z, q : REAL;
- END;
-
- VAR ecken : ARRAY [1..16] OF vektor;
- (* Ecken des Würfels *)
- o : vektor; (* Ursprung P(0/0/0/0) *)
- position4, position3,
- e4x, e4y, e4z, e4q,
- e3x, e3y, e3z, v : vektor;
-
- (* Positionen der Beobachter im 3d- und 4d-Raum und *)
- (* Einheitsvektoren der gedrehten Koordinatensysteme *)
-
- schirmentf4,
- schirmentf3,schrittw : REAL;
- taste, ebene, dim : CHAR; (* dient zum Umschalten *)
- bewegen : BOOLEAN;
-
- FUNCTION skprod(v1, v2 : vektor) : REAL;
- (* ergibt das innere Produkt *)
- BEGIN (* der Vektoren v1 und v2 *)
- skprod := v1.x*v2.x + v1.y*v2.y + v1.z*v2.z + v1.q*v2.q;
- END;
-
- FUNCTION L(v : vektor) : REAL;
- BEGIN (* ergibt den Betrag (Länge) des Vektors *)
- L := Sqrt(Sqr(v.x) + Sqr(v.y) + Sqr(v.z) + Sqr(v.q));
- END;
-
- PROCEDURE plus(v1, v2 : vektor; VAR v : vektor);
- BEGIN (* Addiert zwei Vektoren *)
- v.x := v2.x + v1.x;
- v.y := v2.y + v1.y;
- v.z := v2.z + v1.z;
- v.q := v2.q + v1.q;
- END;
-
- PROCEDURE mal(k : REAL; v : vektor; VAR e : vektor);
- BEGIN (* multipliziert einen *)
- e.x := k*v.x; (* Vektor mit einer Zahl *)
- e.y := k*v.y;
- e.z := k*v.z;
- e.q := k*v.q;
- END;
-
- PROCEDURE verbinde(p1, p2 : vektor; VAR v : vektor);
- BEGIN
- v.x := p2.x - p1.x; (* ergibt den Vektor von *)
- v.y := p2.y - p1.y; (* p1 nach p2 (p1,p2 sind *)
- v.z := p2.z - p1.z; (* hier Punkte,bzw. Orts- *)
- v.q := p2.q - p1.q; (* vektoren) *)
- END;
-
- PROCEDURE drehe(VAR e1, e2 : vektor);
- VAR v, h1, h2 : vektor;
- BEGIN
- verbinde(e1, e2, v);
- mal(schrittw, v, v);
- plus(e1, v, h1);
- mal(1/L(h1), h1, h1);
- mal(-1, e1, e1);
- verbinde(e2, e1, v);
- mal(schrittw, v, v);
- plus(e2, v, h2); (* dreht die Vektoren e1 e2 in *)
- mal(1/L(h2), h2, h2); (* ihrer Ebene in Abhängigkeit *)
- e1 := h1; (* von der globalen Variablen *)
- e2 := h2; (* Scrittw in Richtung e2. *)
- END;
-
- PROCEDURE drehKoord4(VAR p : vektor);
- VAR h : vektor;
- BEGIN
- h.x := skprod(p, e4x); (* ergibt die Koordinaten von p *)
- h.y := skprod(p, e4y); (* in einem gedrehtem Koordinaten*)
- h.z := skprod(p, e4z); (* system, das e4x, e3y, e4z e4q *)
- h.q := skprod(p, e4q); (* als Einheitsvektoren hat *)
- p := h;
- END;
-
- PROCEDURE drehKoord3(VAR p : vektor);
- VAR h : vektor; (* entspricht drehKoord4 , wobei *)
- BEGIN (* hier die Einheitsvektoren für *)
- h.x := skprod(p, e3x); (* den Beobachter im dreidimen- *)
- h.y := skprod(p, e3y); (* sionalen Raum genommen werden *)
- h.z := skprod(p, e3z);
- p := h;
- END;
-
- PROCEDURE bildeab43(po : vektor; VAR pb : vektor);
- VAR k : REAL; (* Hier wird angenommen, daß *)
- BEGIN (* der Beobachter auf der q- *)
- k := schirmentf4/(schirmentf4 + po.q);
- pb.x := k*po.x; (* Achse sitzt, und zwar in *)
- pb.y := k*po.y; (* der durch schirmentf4 an- *)
- pb.z := k*po.z; (* gegebenen Entfernung vom *)
- pb.q := 0; (* Ursprung in negativer *)
- END; (* Richtung. x,y und z-Achse *)
- (* bilden eine 'dreidimen- *)
- (* sionale Projetionswand'. *)
-
- PROCEDURE bildeab32(po : vektor; VAR pb : vektor);
- VAR k : REAL;
- BEGIN
- k := schirmentf3/(schirmentf3 + po.z);
- pb.x := k*po.x; (* Hier bilden x und y-Achse *)
- pb.y := k*po.y; (* eine Projektionswand. *)
- pb.z := 0; (* Der Beobachter sitzt auf *)
- pb.q := 0; (* der z-Achse. *)
- END;
-
- PROCEDURE Ausgangswerte; (* Berechnung der Koordinaten der*)
- VAR i : INTEGER; (* 16 Ecken des 'Hyperwürfels' *)
- BEGIN
- FOR i := 1 TO 16 DO WITH ecken[i] DO BEGIN
- x := ((i-1) MOD 2)*2-1;
- y := (((i-1) MOD 4) DIV 2)*2 - 1;
- z := (((i-1) MOD 8) DIV 4)*2 - 1;
- q := ((i-1) DIV 8)*2 - 1;
- END;
- WITH e4x DO BEGIN
- x := 1;
- y := 0; (* Die Einheitsvektoren bekommen hier *)
- z := 0; (* die Richtung des zugrundeliegenden *)
- q := 0; (* Koordinatensystems. Im Laufe des *)
- END; (* Programms können sie verdreht werden.*)
- WITH e4y DO BEGIN
- x := 0; y := 1; z := 0; q := 0;
- END;
- WITH e4z DO BEGIN
- x := 0; y := 0; z := 1; q := 0;
- END;
- WITH e4q DO BEGIN
- x := 0; y := 0; z := 0; q := 1;
- END;
- WITH e3x DO BEGIN
- x := 1; y := 0; z := 0; q := 0;
- END;
- WITH e3y DO BEGIN
- x := 0; y := 1; z := 0; q := 0;
- END;
- WITH e3z DO BEGIN
- x := 0; y := 0; z := 1; q := 0;
- END;
- WITH o DO BEGIN
- x := 0; y := 0; z := 0; q := 0;
- END;
- WITH position3 DO BEGIN
- x := 0; y := 0;
- z := -5; (* Die Position des Beobachters *)
- q := 0; (* im dreidimensionalen *)
- END;
- WITH position4 DO BEGIN (* und im 4d- Raum *)
- x := 0; y := 0; z := 0; q := -5;
- END;
- schirmentf3 := 2; (* Die Entfernungen *)
- schirmentf4 := 2; (* der Projektionswände *)
- dim := 'd';
- ebene := '1';
- schrittw := 1/8;
- END;
-
- PROCEDURE zeichneLinie(x1, y1, x2, y2 : REAL);
- VAR k : REAL;
- px1, px2, py1, py2 : INTEGER;
- BEGIN
- (* Umrechnung der Ebenenkoordinaten ( 2d Pro- *)
- (* jektionswand) in Bildschirmkoordinaten, *)
- (* zeichnen der Linie bis zur Bildschirmkante *)
-
- IF ((x1<lx) OR (x2<lx)) AND ((x1>-lx) OR (x2>-lx)) AND
- ((y1<ly) OR (y2<ly)) AND ((y1>-ly) OR (y2>-ly)) THEN
- BEGIN
- (* Soll heißen: Nicht beide zu tief und nicht *)
- (* beide zu hoch und nicht beide jenseits des *)
- (* linken und nicht jenseits des rechten Randes *)
- IF x1>lx THEN BEGIN
-
- (* Schnittpunkt der Verbindungsgeraden mit der *)
- (* rechten Bildschirmkante *)
- k := (lx-x2)/(x1-x2); y1 := y2+k*(y1-y2);
- x1 := lx;
- END;
- IF x2 > lx THEN BEGIN
- k := (lx-x1)/(x2-x1); y2 := y1+k*(y2-y1);
- x2 := lx;
- END;
- IF x1 < -lx THEN BEGIN
- k := (-lx-x2)/(x1-x2); y1 := y2+k*(y1-y2);
- x1 := -lx;
- END;
- IF x2<-lx THEN BEGIN
- k := (-lx-x1)/(x2-x1); y2 := y1+k*(y2-y1);
- x2 := -lx;
- END;
- IF y1 > ly THEN BEGIN
- k := (ly-y2)/(y1-y2); x1 := x2+k*(x1-x2);
- y1 := ly;
- END;
- IF y2 > ly THEN BEGIN
- k := (ly-y1)/(y2-y1); x2 := x1+k*(x2-x1);
- y2 := ly;
- END;
- IF y1 < -ly THEN BEGIN
- k := (-ly-y2)/(y1-y2); x1 := x2+k*(x1-x2);
- y1 := -ly;
- END;
- IF y2 < -ly THEN BEGIN
- k := (-ly-y1)/(y2-y1); x2 := x1+k*(x2-x1);
- y2 := -ly;
- END;
- px1 := Trunc(x1/lx*xpix) + xpix;
- px2 := Trunc(x2/lx*xpix) + xpix;
- py1 := ypix - Trunc(y1/ly*ypix);
- py2 := ypix - Trunc(y2/ly*ypix);
- Draw(px1, py1, px2, py2, 1);
- END;
- END;
-
- PROCEDURE kante(p1, p2 : vektor);
- VAR v : vektor; (* Zeichnet das Bild der Kante von *)
- k : REAL; (* p1 nach p2. *)
- BEGIN
- mal(-1, position4, v); (* Verschiebung der Koordinaten,*)
- plus(p1, v, p1); (* so daß der Beobachter im Ur- *)
- plus(p2, v, p2); (* sprung ist. *)
- drehKoord4(p1); (* Umrechnung der Koordinaten in*)
- drehKoord4(p2); (* ein von der Blickrichtung *)
- p1.q := p1.q - schirmentf4; (* normiertes System *)
- p2.q := p2.q - schirmentf4; (* Verschieben, Schirm in *)
- (* den Ursprung *)
- IF (p1.q > -schirmentf4*0.99) OR
- (p2.q > -schirmentf4*0.99) THEN BEGIN
-
- (* Wenn ein Punkt vor dem Beobachter liegt *)
- (* wird eine Linie gezeichnet. *)
-
- IF (p1.q <= -schirmentf4*0.99) THEN BEGIN
-
- (* Wenn p1 hinter dem Beobachter liegt, *)
- (* also nicht gesehen werden kann, wird ein*)
- (* Punkt auf der Geraden p1 p2 berechnet, *)
- (* der dicht vor dem Beobachter liegt. *)
-
- mal(-1, p2, v);
- plus(p1, v, v);
- k := (schirmentf4*0.99 + p2.q)/(-p1.q + p2.q);
- mal(k, v, v);
- plus(p2, v, p1);
- END;
- IF (p2.q <= -schirmentf4*0.99) THEN BEGIN
- (* Entsprechend wie oben, wenn p2 *)
- (* hinter dem Beobachter liegt. *)
- mal(-1, p1, v);
- plus(p2, v, v);
- k := (schirmentf4*0.99 + p1.q)/(-p2.q + p1.q);
- mal(k, v, v);
- plus(p1, v, p2);
- END;
- bildeab43(p1, p1); (* Berechnung Bildpunkte *)
- bildeab43(p2, p2);
- mal(-1, position3, v); (* Entsprechend 4-dim *)
- plus(p1, v, p1); (* Umrechnung der Koordinaten *)
- plus(p2, v, p2); (* in ein Koordinatensystem, *)
- drehKoord3(p1); (* in dem der Beobachter auf *)
- drehKoord3(p2); (* der x-Achse bei *)
- (* -schirmentf3 sitzt. *)
- p1.z := p1.z - schirmentf3;
- p2.z := p2.z - schirmentf3;
- IF (p1.z > -schirmentf3*0.99) OR
- (p2.z > -schirmentf3*0.99) THEN BEGIN
-
- (* Berücksichtigung von Punkten hinter dem Beobachter *)
-
- IF (p1.z <= -schirmentf3*0.99) THEN BEGIN
- mal(-1, p2, v);
- plus(p1, v, v);
- k := (schirmentf3*0.99 + p2.z)/(-p1.z + p2.z);
- mal(k, v, v);
- plus(p2, v, p1);
- END;
- IF (p2.z <= -schirmentf3*0.99) THEN BEGIN
- mal(-1, p1, v);
- plus(p2, v, v);
- k := (schirmentf3*0.99 + p1.z)/(-p2.z + p1.z);
- mal(k, v, v);
- plus(p1, v, p2);
- END;
- bildeab32(p1, p1);
- bildeab32(p2, p2);
- zeichneLinie(p1.x, p1.y, p2.x, p2.y);
- END;
- END;
- END;
-
-
- PROCEDURE zeichne; (* Die 32 Kanten des 'Hyperwürfels' *)
- BEGIN
- HiRes;
- kante(ecken[ 1], ecken[ 2]); kante(ecken[ 1], ecken[ 3]);
- kante(ecken[ 1], ecken[ 5]); kante(ecken[ 1], ecken[ 9]);
- kante(ecken[ 2], ecken[ 4]); kante(ecken[ 2], ecken[ 6]);
- kante(ecken[ 2], ecken[10]); kante(ecken[ 3], ecken[ 4]);
- kante(ecken[ 3], ecken[ 7]); kante(ecken[ 3], ecken[11]);
- kante(ecken[ 4], ecken[ 8]); kante(ecken[ 4], ecken[12]);
- kante(ecken[ 5], ecken[ 6]); kante(ecken[ 5], ecken[ 7]);
- kante(ecken[ 5], ecken[13]); kante(ecken[ 6], ecken[ 8]);
- kante(ecken[ 6], ecken[14]); kante(ecken[ 7], ecken[ 8]);
- kante(ecken[ 7], ecken[15]); kante(ecken[ 8], ecken[16]);
- kante(ecken[ 9], ecken[10]); kante(ecken[ 9], ecken[11]);
- kante(ecken[ 9], ecken[13]); kante(ecken[10], ecken[12]);
- kante(ecken[10], ecken[14]); kante(ecken[11], ecken[12]);
- kante(ecken[11], ecken[15]); kante(ecken[12], ecken[16]);
- kante(ecken[13], ecken[14]); kante(ecken[13], ecken[15]);
- kante(ecken[14], ecken[16]); kante(ecken[15], ecken[16]);
- END;
-
-
- BEGIN
- ausgangswerte;
- HiRes;
- REPEAT
- zeichne;
- REPEAT (* Änderungen der Parameter *)
- IF dim = 'd' THEN BEGIN
- GotoXY(1,24);
- Write('Position:(',position3.x:4:2,'/',
- position3.y:4:2,'/',position3.z:4:2,') ');
- GotoXY(1,25);
- Write('Richtung:(',e3z.x:4:2,'/',e3z.y:4:2,
- '/',e3z.z:4:2,') ');
- GotoXY(56,24);
- Write('Schirmentfernung: ', schirmentf3:4:2, ' ');
- END;
- IF dim = 'v' THEN BEGIN
- GotoXY(1,24);
- Write('Position:(',position4.x:4:2,'/',
- position4.y:4:2,'/',position4.z:4:2,
- '/',position4.q:4:2,') ');
- GotoXY(1,25);
- Write('Richtung:(',e4q.x:4:2,'/',e4q.y:4:2,
- '/',e4q.z:4:2,'/',e4q.q:4:2,') ');
- GotoXY(56,24);
- Write('Schirmentfernung: ', schirmentf4:4:2,' ');
- END;
- GotoXY(34,24); Write('Schrittweite: ',schrittw:7:3);
- GotoXY(34,25);
- IF bewegen THEN Write('Bewegen ')
- ELSE Write('Richtung ');
- taste := ReadKey;
- CASE taste OF
- 'd','v' : dim := taste;
- '1','2','3',
- '4','5','6' : ebene := taste;
- 'g' : schrittw := schrittw*2;
- 'k' : schrittw := schrittw/2;
- 'r' : bewegen := FALSE;
- 'b' : bewegen := TRUE;
- 'n' : IF dim = 'd' THEN
- schirmentf3:=schirmentf3-schrittw
- ELSE
- schirmentf4:=schirmentf4-schrittw;
- 'w' : IF dim = 'd' THEN
- schirmentf3:=schirmentf3+schrittw
- ELSE
- schirmentf4:=schirmentf4+schrittw;
- END;
- IF taste = '+' THEN
- IF bewegen THEN
- IF dim = 'd' THEN BEGIN
- mal(0, v, v);
- CASE ebene OF
- '1': mal(schrittw, e3z, v);
- '2': mal(schrittw, e3x, v);
- '3': mal(schrittw, e3y, v);
- END;
- plus(position3, v, position3);
- END ELSE BEGIN
- mal(0, v, v);
- CASE ebene OF
- '1': mal(schrittw, e4q, v);
- '2': mal(schrittw, e4x, v);
- '3': mal(schrittw, e4y, v);
- '4': mal(schrittw, e4z, v);
- END;
- plus(position4, v, position4);
- END ELSE
- IF dim = 'd' THEN
- CASE ebene OF
- '1': drehe(e3z, e3x);
- '2': drehe(e3z, e3y);
- '3': drehe(e3x, e3y);
- END ELSE
- CASE ebene OF
- '1': drehe(e4q, e4x);
- '2': drehe(e4q, e4y);
- '3': drehe(e4q, e4z);
- '4': drehe(e4z, e4y);
- '5': drehe(e4z, e4x);
- '6': drehe(e4y, e4x);
- END;
- IF taste = '-' THEN
- IF bewegen THEN
- IF dim = 'd' THEN BEGIN
- mal(0, v, v);
- CASE ebene OF
- '1': mal(-schrittw, e3z, v);
- '2': mal(-schrittw, e3x, v);
- '3': mal(-schrittw, e3y, v);
- END;
- plus(position3, v, position3);
- END ELSE BEGIN
- mal(0, v, v);
- CASE ebene OF
- '1': mal(-schrittw, e4q, v);
- '2': mal(-schrittw, e4x, v);
- '3': mal(-schrittw, e4y, v);
- '4': mal(-schrittw, e4z, v);
- END;
- plus(position4, v, position4);
- END ELSE
- IF dim = 'd' THEN
- CASE ebene OF
- '1': drehe(e3x,e3z);
- '2': drehe(e3y,e3z);
- '3': drehe(e3y,e3x);
- END ELSE
- CASE ebene OF
- '1': drehe(e4x,e4q);
- '2': drehe(e4y,e4q);
- '3': drehe(e4z,e4q);
- '4': drehe(e4y,e4z);
- '5': drehe(e4x,e4z);
- '6': drehe(e4x,e4y);
- END;
- UNTIL (taste=#13) OR (taste=#27);
- UNTIL taste = #27;
- END.
- (* ------------------------------------------------------ *)
- (* Ende von WUERFEL.PAS *)
-