HAHAAA!! Non avrei mai pensato che avrei scritto un doc sul tmap; ce ne sono
cos tanti su internet; se ne vuoi prendere uno interessante vai su
www.altavista.digital.com e ricerca "texture mapping" (rigorosamente con le
<">) e dovresti trovare un file di ~63k; prendilo  molto interessante
perch spiega le basi; per il resto dovresti avere tutto quello che ti serve
:-)

Innanzitutto ce l'hai una routine di scanline? Se non ce l'hai leggi
qua altrimenti salta direttamente a dopo.

*** Scanline ***

Che cos' una routine di scanline?
Dato che lo schermo  fatto di linee quando si deve riempire un poligono (di
qualsiasi forma), tale poligono deve essere "convertito" in linee
orizzontali in modo da riempire solo linee sullo schermo. Per esempio
un triangolo cos verr convertito in linee orizzontali
         .                   .
        / \       --\       ...
       /   \      --/      .....
      /     \             .......
      
Quindi per fillare un poligono bisogna sapere di quante linee orizzontali 
formato, pi gli estremi delle linee. Per fare questo in genere si usano due
tabelle grandi quanto la lunghezza in linee dello schermo; una contiene gli
estremi di destra delle linee e l'altra per quelli di sinistra.

A questo punto ti starai chiedendo come fare le tabelle no? Bene  tutto
molto semplice, non devi far altro che interpolare la coordinata x lungo la
y (a me hanno consigliato di non usare l'algoritmo di bresenham perch
quello normale di interpolazione  leggermente pi veloce).

Allora riprendiamo il triangolo (considerando i vertici)

      1->.         p1=(25,0)
        / \        p2=(0,25)
       /   \       p3=(50,25)
   2->/     \<-3
      
quindi nelle tabelle dovrai avere qualcosa cos:

     tab1   tab2      per fare le tabelle si fa  cos:
0     25     25
1     24     26       dx=(p2.x-p1.x)/(p2.y-p1.y)
2     23     27       poi
3     22     28       x=p1.x;
4     21     29       for y=p1.y to p2.y
5     20     30        if tab1[y]<>0 then tab1[y]=x else tab2[y]=p1.x
6     19     31        x=x+dx
:     :      :        next
:     :      :
23    2      48
24    1      49
25    0      50
:
:
(altri valori che non c'interessano)

ci 6? A questo punto ti fai un ciclo che per ogni valore di y vede se c'e' da
tracciare una linea orizzontale (ovvero se tab1[y] e tab2[y] sono diversi
da 0) cos hai gli estremi della linea e la sua coordinata y.
Nell'esempio fai un ciclo tipo:
for y=0 to 50
 line (tab1[y],y,tab2[y],y)
next
ed  fatto! Hai riempito un triangolo1! :-))
Spero di essere stato abbastanza semplice nella spiegazione :-)

*** Texture Mapping ***

Allora cos' il texture mapping? Non si tratta altro che riempire un
poligono invece di usare sempre lo stesso colore, una serie di colori presi
da un'altra immagine. Il problema sta nel prendere i colori nell'ordine
giusto e per questo ci sono vari algoritmi:
1) polygon grandients: calcola dei valori (tratti da alcuni calcoli
   vettoriali) e li usa per calcolare il colore del pixel con le formule
   u=k1+a/c
   v=k2+b/c
   colore = txt[u,v] -> abituati xch le coordinate sulla texture sono
                        sempre individuate dalle variabili u,v :)
   Questo  il metodo di texturare i poligoni in 3d; bel senso che la
   texture viene vista come un piano 3d;  il metodo "perspective
   correction" che (penso) venga usato negli acceleratori 3d via hardware :)
   farlo via software  lentissimo!!
2) due div per scanline: calcola le u,v agli estremi della scanline (come
   nella scanline, solo che invece di interpolare solo la x, qui si
   interpolano anche le u,v sui lato del poligono) e poi si interpolano le
   u,v lungo la scanline:
   u=u0+du*(x-x0)
   v=v0+dv*(x-x0)
   dove
   u0=u all'inizio della scanline   u1=u alla fine
   v0=v  """""""""""""""""""""""    v1=v  "    "
   du=(u1-u0)/(tab2[y]-tab1[y])
   dv=(v1-v0)/ """"""""""""""
   x-x0=differenza tra la x corrente (x) e la x all'inizio della scanline
   >>>Funziona con qualsiasi poligono
3) due div per poligono: calcola gli incrementi dv/dx e du/dx per l'intero
   poligono e le usa per interpolare le coordinate:
   u=u0+du*(x-x0)
   v=v0+dv*(x-x0)
   du=(u1-u0)/(lunghezza della massima scanline)
   dv=(v1-v0)/("""""""""""""""""""""""""""""""")
   u1,u0,v1,v0: valori di u,v agli estremi della massima scanline
   >>>> Funziona solo con triangoli
   Questi due metodi sono i cosiddetti "texture mapping" a 2d perch in
   pratica si "scala" la texture tra i vertici dei poligoni, assegnando ad
   ogni vertice del poligono un punto sulla texture e poi s'interpolano
   linearmente le u,v lungo la scanline. Usando questi metodi si ha un
   texture mapping molto veloce, ma aim molto impreciso xch si possono
   notare delle distorsioni lungo la texture (soprattutto quando si usano
   triangoli :( e io ne so qualcosa! Prova a vedere il tmap che ho fatto io
   e noterai che quando ruota si nota che la texture viene "divisa" in due
   lungo la diagonale della faccia!

Fondamentalmente queste sono le routine pi famose per fare il texture
mapping; adesso ti faccio faccio vedere un esempio di un possibile ciclo di
texture mapping (pwr triangoli):

loop:
 scanline(); <- calcola le tabelle delle scanline
 tmap()
 goto loop;

tmap()
 calcola du/dy,dv/dy
 interpola le u,v lungo il lato sinistro del triangolo
 calcola du/dx,dv/dx per la scanline massima
 for y=ymin to ymax (del triangolo)
  u=u[y]
  v=v[y]
  for x=tab1[y] to tab2[y]
   plot(x,y,txt[u,v])
   u=u+du
   v=v+dv
  next x
 next y
endproc tmap

Adesso sai  o meno ci che so anch'io sul tmap; si tratta solo di tradurre
il tutto in asm e incominciare a far girare qualcosa.... :)
Io adesso sono arrivato a fare l'env-mapping di oggetti molto pi complessi
del "solito" cubo; mi faccio gli oggetti con imagine e poi li converto con
il tddd2raw+un'altro convertitore fatto da me e ho passato a Modem
un'esempio di env-map. Risultato? Sul mio misero a1200 le routine vanno a
1x1 in 5fps; sul suo a 50fps!!!! :))) Tutto si spiega dal fatto che lo 030
ha la data cache, e il suo amy ha la fast (importantissima).

Se hai qualcos'altro da chiedere, fai pure! :-)

Ps: ho rivisto ancora il rotator xch volevo vedere alcune cose; a quanto
    pare tu non conosci come si fanno le addizioni in decimale! Per questo
    il rotator non  cos preciso come vorresti; adesso ti spiego questo
    "trucchetto" (spiegato a me da Hedgehog):

Quando devi interpolare qualsiasi cosa ti ritrovi a fare qualcosa del tipo:

x=a0+da/db*b
che si traduce in un ciclo
a=a0
loop:
 a=a+da/db  da/db  l'incremento di "a" quando ci si muove su "b"
 :
goto loop

in assembler il tutto si traduce in:

; calcolo da/db
; a1,a0 valori da interpolare lungo b1,b0
move.w   a1,d0
sub.w    a0,d0 ; a1-a0
move.w   b1,d1
sub.w    b0,d1 ; b1-b0
swap     d0    ; (a1-a0)<<16
divs.l   d1,d0 ; da/db incremento shiftato di 16 per la parte decimale
               ; in modo tale che  bit 31..16  15..0
               ;                   d0= intero  decimale

move.l   d0,dadb  ; salva l'incremento
:
: altre istruzioni
:
move.w   a0,d0 ; valore iniziale
swap     d0    ; a0<<16
move.l   dadb,d1
loop:
add.l    d1,d0 ; (a+da/db)<<16
move.l   d0,d2
swap     d2    ; valore intero in d2.w che serve
:
:
dbra     d4,loop

Il tutto si pu semplificare (e soprattutto levare 1 o anche 2 istruzioni
nel loop) usando l'addx:

il calcolo di da/db va bene solo che prima di salvarlo fai uno "swap d0"
in modo da avere nella word alta la parte decimale, e nella word bassa la
parte intera (quella che pi c'interessa); poi quando devi addizionare
l'icremento alla variabile corrente fai cos:

add.l    d1,d0
addx.w   d3,d0 ; >>> in d3 ci deve essere 0!!! <<<

cos in d0.w hai subito la variabile da usare e hai risparmiato uno swap!
(4 cicli su no 020) che non  male! ;))
L'addx serve perch nel caso c' il riporto dalla parte decimale, viene
addizionato (per questo d3 deve essere uguale a 0), cos viene sfruttata la
parte decimale ;))
Non a caso, nel file con gl'inner loop pi veloci trovi le addx invece che
delle add seguite da uno swap!

Pss: se vuoi, passalo pure questo doc, cos magari divento pi famoso! ;))


Amighevolmente,

/
\/\/ashburn / X-Zone & DeGeNeRaTiOn

Email: simon@digicolor.lognet.it
Snail:
 Aversa Simone
 Via F.Novati 27
 26100 Cremona
 Italy

