Autor Beitrag
dr. rom4o
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 59


TMT-Pascal, D3 Prof, C++Builder
BeitragVerfasst: Mo 09.08.04 22:10 
Hi Leute,
ich hab mir in tmt-pascal ein ganz einfaches aber funktionierendes 3d script gebaut.
Es wird ein rotierender Würfel dargestellt, welcher jedoch absolut statisch ist.
Das beste ist jedenfals, dass es funktioniert.
Nun habe ich ein problem, und zwar kenne ich den Koeffizienten
bzw. das Verhältnis zwischen Objektgrösse und Entfernung.
Kann mir da vielleicht jemand von euch weiter helfen??????

Bis jetzt habe ich die Grössenabnahme mit steigender Entfernung so gelöst
ausblenden Quelltext
1:
xref1:=round(xF-( (xF-x1) / ( log10(z1){*log10(z1)} ) ) );					

also entweder mit dem dekadischen Logarithmus bzw dem Quadrat von ihm.
aber wenn man sich die Simulation anschaut merkt man, dass der Raum extrem
verzehrt wird.

Ich bin sehr dankbar für hilfe.

hier is das ganze script(mit tmt-pascal) krigt man es kompiliert...
ausblenden volle Höhe Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
program mathe_gr;
{eine sich y-stabil drehender Würfel}
uses crt,dos,graph,math;

const   x_max = 639;
        y_max = 479;
        max_anz = 10000;
        xF = 320;
        yF = 240;
var
  treiber, modus            : Integer;

  Color                     : Byte;
  x_m, y_m, x_pos, y_pos    : integer;

  x1,x2,xref1,xref2         : 0..639;
  y1,y2,yref1,yref2         : 0..479;
  x3,x4,xref3,xref4         : 0..639;
  y3,y4,yref3,yref4         : 0..479;
  x5,x6,xref5,xref6         : 0..639;
  y5,y6,yref5,yref6         : 0..479;
  x7,x8,xref7,xref8         : 0..639;
  y7,y8,yref7,yref8         : 0..479;

  z1,z2,z3,z4,z5,z6,z7,z8   : real;
  z                         : longint;
  k1,k2                     : 0..360;
  zahl,lauf,laufend,radius  : word;
  winkel                    : real;
  spei_x               : array[1..max_anz] of integer;
  spei_y               : array[1..max_anz] of integer;

function sinus(winkel:real):real;
    begin
         sinus:=sin(winkel * pi/180);
    end;
function cosinus(winkel:real):real;
    begin
         cosinus:=cos(winkel * pi/180);
    end;
procedure kreis;
    begin
         radius:=230; {Kreisradius beträgt 170LE(Pixel)}
         lauf:=0;
         winkel:=0;
         repeat
                lauf:=lauf+1;
                winkel:=winkel+0.05;
                //delay(5);
                x_pos:=round(cosinus(winkel)*radius)+xF;
                y_pos:=round(sinus(winkel)*radius)+yF;
                //putpixel(x_pos,y_pos,4);
                spei_x[lauf]:=x_pos;
                spei_y[lauf]:=y_pos;
          until winkel>=360;


    end;

begin
   clrscr;
   treiber := detect;
   initgraph(treiber, modus, '');
   if graphresult = 0 then begin

   cleardevice;
    x1:=0;
    x2:=0;
    y1:=0;
    y2:=0;
    z1:=10;
    x_m:=0;
    y_m:=0;
    color:=0;
    zahl:=0;
    setbkcolor(0);
    winkel:=0;
    lauf:=0;
    {begin}
    x1:=100; y1:=70;
    x2:=540; y2:=70;
    x3:=100; y3:=410;
    x4:=540; y4:=410;

    x5:=100; y5:=70;
    x6:=540; y6:=70;
    x7:=100; y7:=410;
    x8:=540; y8:=410;

    setcolor(7);
{    line(x1,y1,x2,y2);
    line(x1,y1,x3,y3);
    line(x3,y3,x4,y4);
    line(x4,y4,x2,y2);}
    putpixel(320,240,12);
    kreis;
    readln;
    lauf:=0;
    repeat
       begin

            lauf:=lauf+1;
            x1:=spei_x[lauf];
            x2:=spei_x[lauf+1800];
            x3:=spei_x[lauf];
            x4:=spei_x[lauf+1800];
            z1:=spei_y[lauf];
            z2:=spei_y[lauf+1800];
            z3:=spei_y[lauf];
            z4:=spei_y[lauf+1800];

            x5:=spei_x[lauf+3600];
            x6:=spei_x[lauf+5400];
            x7:=spei_x[lauf+3600];
            x8:=spei_x[-lauf+5400];
            z5:=spei_y[lauf+3600];
            z6:=spei_y[lauf+5400];
            z7:=spei_y[lauf+3600];
            z8:=spei_y[-lauf+5400];

//4Koordinaten
            xref1:=round(xF-( (xF-x1) / ( log10(z1){*log10(z1)} ) ) );
            xref2:=round(xF+( (x2-xF) / ( log10(z2){*log10(z2)} ) ) );
            yref1:=round(yF-( (yF-y1) / ( log10(z1){*log10(z1)} ) ) );
            yref2:=round(yF-( (yF-y2) / ( log10(z2){*log10(z2)} ) ) );

            xref3:=round(xF-( (xF-x3) / ( log10(z3){*log10(z3)} ) ) );
            xref4:=round(xF+( (x4-xF) / ( log10(z4){*log10(z4)} ) ) );
            yref3:=round(yF-( (yF-y3) / ( log10(z3){*log10(z3)} ) ) );
            yref4:=round(yF-( (yF-y4) / ( log10(z4){*log10(z4)} ) ) );
//4Koordinaten
            xref5:=round(xF-( (xF-x5) / ( log10(z5){*log10(z5)} ) ) );
            xref6:=round(xF+( (x6-xF) / ( log10(z6){*log10(z6)} ) ) );
            yref5:=round(yF-( (yF-y5) / ( log10(z5){*log10(z5)} ) ) );
            yref6:=round(yF-( (yF-y6) / ( log10(z6){*log10(z6)} ) ) );

       {    xref7:=round(xF+( (xF-x7) / ( log10(z7)*log10(z7) ) ) );
            xref8:=round(xF-( (x8-xF) / ( log10(z8)*log10(z8) ) ) );
            yref7:=round(yF+( (yF-y7) / ( log10(z7)*log10(z7) ) ) );
            yref8:=round(yF+( (yF-y8) / ( log10(z8)*log10(z8) ) ) ); }

            xref7:=round(xF-( (xF-x7) / ( log10(z7){*log10(z7)} ) ) );
            xref8:=round(xF+( (xF-x8) / ( log10(z8){*log10(z8)} ) ) );
            yref7:=round(yF-( (yF-y7) / ( log10(z7){*log10(z7)} ) ) );
            yref8:=round(yF-( (yF-y8) / ( log10(z8){*log10(z8)} ) ) );



            setcolor(7);
            line(xref1,yref1,xref2,yref2);
            line(xref1,yref1,xref3,yref3);
            line(xref3,yref3,xref4,yref4);
            line(xref4,yref4,xref2,yref2);

            line(xref5,yref5,xref2,yref2);
            line(xref5,yref5,xref6,yref6);
            line(xref6,yref6,xref1,yref1);
            line(xref7,yref7,xref8,yref8);
            line(xref7,yref7,xref5,yref5);

            line(xref8,yref8,xref3,yref3);
            line(xref8,yref8,xref6,yref6);
            line(xref7,yref7,xref4,yref4);

{            putpixel(xref7,yref7,12);
            putpixel(xref8,yref8,15);}

            delay(2);

            setcolor(0);
            line(xref1,yref1,xref2,yref2);
            line(xref1,yref1,xref3,yref3);
            line(xref3,yref3,xref4,yref4);
            line(xref4,yref4,xref2,yref2);

            line(xref5,yref5,xref2,yref2);
            line(xref5,yref5,xref6,yref6);
            line(xref6,yref6,xref1,yref1);
            line(xref7,yref7,xref8,yref8);
            line(xref7,yref7,xref5,yref5);

            line(xref8,yref8,xref3,yref3);
            line(xref8,yref8,xref6,yref6);
            line(xref7,yref7,xref4,yref4);

{            putpixel(xref7,yref7,0);
            putpixel(xref8,yref8,0);}

            if lauf=1800 then    begin
                                      lauf:=0;
                                      if zahl=4 then zahl:=0;
                                      zahl:=zahl+1;
                                 end;
                   end;
    until keypressed;
   readln;
    {end}
   CloseGraph;
   end;
end.

_________________
Sei frei!!! ...doch eigentlich bist du es nie...denn Alles ist determiniert
Udontknow
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2596

Win7
D2006 WIN32, .NET (C#)
BeitragVerfasst: Di 10.08.04 13:25 
Hallo!

Stelle dir doch mal deinen Monitor als Fenster vor: Der Bereich, den du renderst, ist ja sozusagen ein "Pyramidenstumpf". Dein Auge bildet also die Spitze der "Pyramide", die Seiten des Monitors bilden den Anfang des Stumpfs, der sich hinter dem Monitor ausdehnt.

Wenn also nun Licht von einem Objekt durch dieses "Fenster" auf dein Auge fällt, so muß es sich innerhalb dieses Pyramidenstumpfes befinden. Der Punkt ist nun der, daß ein Rendermechanismus die Linie zwischen imaginärem zu rendernden Objekt und dem Auge auf den Monitor projizieren muss. Du musst sozusagen den Schnittpunkt zwischen der Fenster-Ebene und dem Lichtstrahl nachgehen.

Nehmen wir mal an, eine Distanz von 50 cm hätte dein Auge zum Monitor.
Nun willst du einen Würfel rendern, der sich 10 m in Z-Richtung (also in den Monitor hinein) und 5 m in x-Richtung (also nach rechts von dir) befindet.

Der Vektor vom Würfel zum Auge ist also v=(5,0,10). Dann gilt, daß der zu rendernde Punkt sich bei (v.x/v.z*AbstandZumMonitor;v.y/v.z*AbstandzumMonitor) ist, was in diesem Falle also wäre:

ausblenden Quelltext
1:
2:
x=5/10*0.5=0.25
y=0/10*0.5=0


Der Mittelpunkt des Würfels wäre also 25 cm von der Bildschirm-Mitte entfernt. Wenn das ausserhalb des Monitors liegt, so kann nicht dargestellt werden, es liegt außerhalb des Stumpfes, der auch Kamera- oder Viewing-Frustrum genannt wird.

Das Beispiel mit dem Pyramidenstumpf verdeutlicht, daß es sich nicht um ein quadratisches oder gar exponentielles Verhältnis zwischen Entfernung und Abstand des projizierten Punkts zum künstlichen Horizont handelt, sondern um eine lineare antiproportionale Beziehung.

Es gilt einfach

ausblenden Quelltext
1:
2:
xproj=v.x/vz*AbstandZumMonitor
yproj=v.y/vz*AbstandZumMonitor


Cu,
Udontknow
JanHH
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 46
Erhaltene Danke: 1



BeitragVerfasst: Di 10.08.04 18:05 
Ich würde ein bisschen generell 3d-Nachhilfe empfehlen.. was sich dahinter mathetmatisch verbirgt, usw. Solche Koeffizienten braucht man jedenfalls normalerweise nicht zu berechnen.

Wenn man sich vorstelle dass der Punkt 0/0 in der Mitte des Bildschirms liegt (und nicht links oben oder links unten), wird die perspektivische Verkürzung dadurch gelöst, dass jede Koordinate durch ihre Entfernung vom Betrachter geteilt wird. Weil das dann zu kleine Werte werden, muss das noch mit einem Faktor multipliziert werden, dieser kann soweit ich weiss sogar als Brennweite betrachtet werden. also x' = (x/z)*faktor, y' = (y/z)*faktor. In der Praxis wird dies allerdings mit Matritzen gelöst, die alle Transformationen und Drehungen des Objektes enthalten, und mit denen dann jede Koordinate einfach multipliziert wird, um die Bildschirmkoordinate zu ermitteln. Viele Infos gibts unter www.opengl.org.

Gruß
Jan
dr. rom4o Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 59


TMT-Pascal, D3 Prof, C++Builder
BeitragVerfasst: Do 12.08.04 13:16 
Titel: Dank
Hey Leute ich danke euch für die guten Tips.
Das hilft mir auf jeden Fall weiter.

also dann ciao

_________________
Sei frei!!! ...doch eigentlich bist du es nie...denn Alles ist determiniert