next up previous
Next: Hardwarová přerušení na PC Up: No Title Previous: Jiná sada nástrojů

Dinogram aneb Šilhám, abych tě lépe viděla

Zruš rámečky
Luboš Motl

Druhá část názvu je vybrána ze známé pohádky Karkulka a zánik dinosaurů, a to z okamžiku, kdy dinosaurus přichází k posteli, ve které spí Karkulka, a ptá se jí:

``Proč máš tak šilhavé oči?''

``Abych tě lépe viděla.''

``A proč máš tak špičaté zuby?''

``Protože si je čistím zubní pastou Colgate.''

Co se týká prvé části názvu nebo také označení pro objekt, o němž jde řeč, mohli bychom dnes tvrdit, že jde o akronym za ``3-DImensionální NOvé GRAfické Možnosti''. Pravda je však taková, že název vyplývá z faktu, že první dinogram, který zhlédlo oko matfyzáka, obsahoval obrázek s dinosaury. (Mezi alternativní názvy patří holovision, stereogram, trojrozměrný šum atd.)

Ale přejděme již k tématu. Dinogram je dvojrozměrný obrázek, na němž při prvním pohledu vidíme kvaziperiodickou strukturu -- strukturu různých barevných skvrnek, které se více či méně opakují ve směru vodorovné osy. Při pozorném prvním pohledu nám neujde ani skutečnost, že perioda není všude stejně veliká.

Ale již při druhém pohledu se začnou dít podivuhodné věci. Unaví-li se nám zrak, případně podaří-li se nám oči zamířit asi půl metru za rovinu obrazu (třeba tak, že zaostříme na svůj vlastní obraz v obrazovce nebo na obraz nějaké blízké lampy), uvidíme sice zřetelně týž tapetový vzor, jenž jsme spatřili již při pohledu prvém, ale nyní jím bude pokryta nikoliv plochá rovina, nýbrž povrch členitého trojrozměrného objektu umístěného za rovinou obrazu jakoby v akváriu.

Jak takový dinogram funguje a jak ho lze sestrojit? Základní idea může být vysvětlena kupříkladu následujícím způsobem.

Oči se při druhém pohledu na dinogram dívají tak, že oko levé sleduje obraz o jednu periodu vlevo vůči oku pravému. Chceme-li tedy, aby oči viděly nějaký bod tex2html_wrap_inline604 znázorňované plochy za rovinou obrazovky, spojíme tento bod s oběma očima a průsečíky tex2html_wrap_inline606 s rovinou obrazovky vyznačíme jako tečku na monitor. Pokud teď tedy levé oko bude sledovat levý průsečík a pravé ten pravý, budou mít oči dojem, že pozorují bod tex2html_wrap_inline604 . (Efekt nikterak nesouvisí se zaostřováním čoček, natož s vlnovými vlastnostmi světla, pouze se stereografičností vjemu danou počtem očí dva.)

picture64


Ovšem puntík tex2html_wrap_inline628 určený pro levé oko působí rušivě, neboť ho vidí i oko pravé a stejně tak tex2html_wrap_inline630 určený pro pravé oko vidí i oko levé. Bez újmy na obecnosti se zabývejme druhou z nesnází. Potíž vyřešíme jednoduše tak, že bod tex2html_wrap_inline630 , který vidí i levé oko, prohlásíme za obraz nějakého dalšího bodu tex2html_wrap_inline634 znázorňované plochy, což je průsečík znázorňované plochy s přímkou spojující levé oko a bod tex2html_wrap_inline630 . Nezbývá než spojit tento bod tex2html_wrap_inline634 s pravým okem a vyznačit na obrazovce průsečík s touto přímkou tex2html_wrap_inline640 . Ten opět spojíme s levým okem, abychom získali tex2html_wrap_inline642 , pak tex2html_wrap_inline644 atd., až dojedeme na pravý okraj obrazovky a průsečík roviny obrazovky a spojnice bodu tex2html_wrap_inline646 s pravým okem již bude ležet mimo monitor, takže jej nebudeme moci znázornit. To však nebude působit uměle, protože zrak situaci pochopí tak, že pravé oko již tex2html_wrap_inline646 nevidí, neboť je zastíněn okrajem obrazovky. Stejně tak nenastane problém nalevo, jelikož levé oko již nevidí bod tex2html_wrap_inline650 kreslené plochy, který leží na spojnici tex2html_wrap_inline628 s pravým okem.

Dostaneme tedy posloupnost bodů na jedné řádce monitoru. Vzdálenost mezi nimi bude menší tam, kde je plocha blíže rovině obrazovky. Podobně můžeme jinou barvou zobrazit body tex2html_wrap_inline654 , tex2html_wrap_inline656 atd. jakožto obrazy bodů tex2html_wrap_inline658 , tex2html_wrap_inline656 atd. a podobně dalšími barvami obrazy dalších bodů ležících mezi tex2html_wrap_inline604 a tex2html_wrap_inline634 .

Další řádky obrazu získáme zcela nezávisle a naprosto tímtéž způsobem.

Pro úplnost ještě uveďme nejzákladnější verzi programu.

{$N+,E+}
program Dino3Dgram;

uses graph;

const v = 7; {vzdalenost oci v cm}
      d = 40; {vzdalenost oci a obrazovky v cm}
      osm = 15; {pocet deleni periody}
      NovychBarev = 3;
      xb = 0.037; {sirka bodu v cm}
      yb = 0.037; {vyska}

var i,gd,gm,x,y,k,od,pod,nc: integer;
    ix: array [0..osm] of double; {poloha bodu v cm}
    PrvniKolo: boolean;
    color: array [0..osm] of integer;

 function h(x: double; y: integer): double;
  {kolmy prumet hloubky bodu na primce leve oko/bod x,y na obr. v cm}
  {x a y je v obrazovkovych bodech}
   var zatim: double;
 begin
  zatim := abs(x-250);
  if abs(y-240)*4/3 > zatim then zatim := abs(y-240)*4/3;
  if zatim > 200 then zatim := 200;
  if zatim <  30 then zatim := 30;
  h := zatim/15 + 10;
 end;

 function zac(y: longint): double;
 begin zac := -1 + sin(y/480*pi) + Random(100)/50*xb end;

 procedure carka(od,pod,y: longint; barva: byte);
 begin for gd := trunc(od) to trunc(pod)-1 do putpixel(gd, y, barva) end;

begin
 gd := Detect;
 initgraph(gd, gm, 'i:\jazyky\bp\bgi');
 for i := 0 to osm-1 do color[i] := i;
 nc := 0;  {index menene barvy}
 for y := 0 to getmaxy do begin
   k := 0;
   for i := 1 to NovychBarev do begin
     color[nc] := random(16);
     nc := (nc+1) mod osm;
   end;
   PrvniKolo := true; ix[0] := zac(y); od := 0;
   ix[osm] := (1 - d/(d + h(ix[0]/xb,y)))*v + ix[0];
   for i := 1 to osm-1 do ix[i] := (ix[osm] - ix[0])/osm*i + ix[0];

   repeat
    k := (k+1) mod osm;
    if not(PrvniKolo) then ix[k] := (1 - d/(d + h(ix[k]/xb,y)))*v + ix[k];
    pod := trunc(ix[k]/xb);
    carka(od, pod, y, color[k]);
    od := pod;
    if k = osm-1 then PrvniKolo := false;
   until od >= getmaxx;
 end; {for y}
 readln; {nakonec stiskni enter}
 closegraph;
end.


next up previous
Next: Hardwarová přerušení na PC Up: No Title Previous: Jiná sada nástrojů

Lubos Lumo Motl
Sat Oct 25 18:44:41 EDT 1997