Az úgy volt, hogy békés, délutánba nyúló szombati ebédem közepette felhívott R4S (főszerkesztő), hogy ugyanmár vasárnapra vigyem má' a két cikket. (Igaz, hogy már két hete emlegette, de nem szoktaml komolyan venni). Szóval így esett, hogy teli hassal, befeküdtem a számítógép elé, és elkezdtem igen aktívan gondolkozni, ugyan mit is kéne csinálni. Aktív, szunyálásokkal tűzdelt gondolkodásom közben, mi történik? Elindult a Dos Navigátor egyik screensavere. Tudod, az a pontforgatós, szövegírogatós. Endzsoj dos navigator, meg ilyenek. Na, ilyet én is tudok! Aztán már csináltam is. Igy esett, hogy most ez lesz a téma. Olvasói levelek is érkeztek ám hozzám, ezúttal is köszi, a d3d-ről, meg ilyenekről érdeklődtek. Az a helyzet hogy ilyen nagy lélegzetű témákhoz most nem éreztem elég erőt magamban. (más szóval még nem sok közöm van hozzá) De az ötlet jó, majd igyekszem jobban belemélyedni a témába. Most azonban jöjjön aminek jönnie kell.

Az az ominózus screen saver.

Mit is csinál ez a progi. Van egy ponthalmaz, amit térben forgat, és vele együtt egy kicsit sinusz hullámozó pörgő forgó kifele úszó térbeli szöveget. Meg közben van egy kis motion blur is. Sima Liba. Mit is nézzünk először. Mondjuk a legegyszerűbbet.

A motion Blur ról már volt szó. Akkor a paletta sötétítésével próbáltam megoldani a problémát, mondjuk lehet hogy hülyeség volt. Most más módszert nézünk. Végigmászunk az egész képernyőn, és ahol nem nulla a szín, ott kivonunk belőle egyet. Nem nehéz rájönni, hogy így megspóroltuk a képernyőtörlést. A következő fázist, pedig simán felnyomjuk a képre. Ehez egy világosodó paletta kell. Most az egyszerűség kedvéért 4 színű palettát használtam. Ja, gondolom mindenki örömére szolgál, hogy a progi ezúttal pascalban született. Tehát egy olyan rutin ami ezt elvégzi:

procedure blur; assembler;
asm
  push ds
  mov ds, ScreenSeg
  xor si,si
  mov cx,64000
  mov al,0
@cik:
  cmp [si],al
  jz @tov
  mov ah,[si]
  dec ah
  mov [si],ah
@tov:
  inc si
  loop @cik
  pop ds
end;

Ez egyszerű. Modjuk a rutin enyhén szólva nincs optimalizálva, de legalább működik.

A ponthalmaz kirakása is nagyon egyszerű. az ember fog egy tömböt, ami a pontok koordinátáit tartalmazza, megforgatja, egymás után kirakja. A koordináták tárolására olyan rekordot használok, ami egyszerre tartalmazza az eredeti 3d-s, megforgatott 3d-s, és a leképezett képernyőkoordinátákat.

 

Type
  T3d=Record
           x : longint;
           y : longint;
           z : longint;
  end;
  T2d=Record
           x : longint;
           y : longint;
  end;

  Tpoint = Record
              map : T3d; {eredeti }
              coords : T3d; {forgatott}
              ScreenCoords : T2d; {lekepezett}
  end;

A pontok feltöltése simán randommal megy, nem kell rajta sokat vacakolni. Két kitüntetett pont van, az 1. és a 2. ezekre majd akkor lesz szükség, mikor a szöveget rá kell illeszteni a ponthalmazra.

Magát a forgatást nem magyarázom el, ugyanaz, ahogy eddig csináltuk.

Ami viszont érdekes, hogy honnan lesz fontkészletünk, amivel írogatni tudunk. Lehet eltároni külön file-ban, vagy belelinkelni az exe-be. De legegyszerűbb lekérdezni a BIOS-tól. mondjuk a 8X8-asat.

Procedure GetCharSet(buffer : word); Assembler;
asm
  push ds
  push es
  push bp
  mov ax,1130h
  mov bh,03h
  int 10h
  mov cx,2048
  mov si,bp
  pop bp
  push es
  push ds
  pop es
  pop ds
  mov di,buffer
  rep movsb
  pop es
  pop ds
end;

Ez a Get EGA Information nevű funkció.

ax= 1130
bh=fontkészlet (0,1-aktuális fontkészlet, 2-8X14, 3-8X8, 5-9X14)

Az es:bp-n kapjuk meg a kért készlet címét, amit nem árt gyorsan megmenteni magunknak. A bp-vel vigyázni kell, hiszen a magasszintű nyelvek ezzel címzik a paramétereket, ezért, ha paraméterre hivatkozunk előtte vissza kell állítani.

Az érdekes az, hogy hogyan tudunk a kétdimenziós bittérképből 3 dimenziós objektumot csinálni:

 

const ztab : array[1..8] of integer=(8,6,3,2,2,3,6,8);

function bitset(d : byte; b : byte) : boolean;
begin
  if (d and (1 shl b))<>0 then bitset:=true else bitset:=false;
end;

procedure buildtext;
var
  cnx,cny,actchar : integer;
  chx,chy,tp :integer;
begin
  cny:=4;
  cnx:=-160;
  tp:=1;
  for actchar:=1 to length(szoveg[actsor]) do
  begin
    for chx:=1 to 8 do
    for chy:=1 to 8 do
    begin
      if bitset(charset[8*word(szoveg[actsor][actchar])+chy],chx) then
      begin
        text[tp].map.x:=(actchar*8-chx)*4-cnx;
        text[tp].map.y:=(chy-1)*4-cny;
        text[tp].map.z:=ztab[chx];
        tp:=tp+1;
      end;
    end;
  end;
  tpoints:=tp-1;
end;

Végig kell menni az adott karakter bitmapjén, ahol az adott bit 1, ott mi is beleteszünk egy pontot a 3d-s tömbünkbe. A z koordinátáját pedig egy előzőleg feltöltött tömbből vesszük. A karakteren belül minden oszlopban ugyanannyi a Z, mivel a tömbben egy 'púp' van, így a betűk térben egy kicsit púposak lesznek. Persze nem egy karakert tárolunk egyben, hanem egy sort. A szöveg kitolása is egyszerűbb így, hiszen mindig elég csak a map-mezők x-ét növelni.

A szöveg kirakása, forgatása így már majdnem ugyanúgy történik, mint a pontoké, azzal a különbséggel, hogy itt egy pont nem egy pont, hanem egy olyan nagy gümecs, hogy a betűk tényleg térbeliek legyenek.

És forgatásnál beleteszünk egy kis sinust.

 
Aztán vannak még olyan apróságok, mint például az, hogy a szöveg ne lógjon le a ponthalmazról. Ehhez kell az a két kitüntetett pont. Ez a két pont határozza meg a halmaz két szélét. Ha a szöveg adott pontjának x-e közéjük esik, akkor a mugli kirakható.

Asszem ennyi.
 

Kimmel Tamás
eMail:PC-XUser@FREEMAIL.C3.HU, Subject: "DEMO rovat"
KUMM@MI.STUD.PMMFK.JPTE.HU