home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 109 / EnigmaAmiga109CD.iso / software / testi / corsoasm / sorgenti_3d / texture_wasb.txt < prev    next >
Text File  |  1998-03-18  |  8KB  |  228 lines

  1. HAHAAA!! Non avrei mai pensato che avrei scritto un doc sul tmap; ce ne sono
  2. così tanti su internet; se ne vuoi prendere uno interessante vai su
  3. www.altavista.digital.com e ricerca "texture mapping" (rigorosamente con le
  4. <">) e dovresti trovare un file di ~63k; prendilo è molto interessante
  5. perchè spiega le basi; per il resto dovresti avere tutto quello che ti serve
  6. :-)
  7.  
  8. Innanzitutto ce l'hai una routine di scanline? Se non ce l'hai leggi
  9. qua altrimenti salta direttamente a dopo.
  10.  
  11. *** Scanline ***
  12.  
  13. Che cos'è una routine di scanline?
  14. Dato che lo schermo è fatto di linee quando si deve riempire un poligono (di
  15. qualsiasi forma), tale poligono deve essere "convertito" in linee
  16. orizzontali in modo da riempire solo linee sullo schermo. Per esempio
  17. un triangolo così verrà convertito in linee orizzontali
  18.          .                   .
  19.         / \       --\       ...
  20.        /   \      --/      .....
  21.       /     \             .......
  22.       ¯¯¯¯¯¯¯
  23. Quindi per fillare un poligono bisogna sapere di quante linee orizzontali è
  24. formato, più gli estremi delle linee. Per fare questo in genere si usano due
  25. tabelle grandi quanto la lunghezza in linee dello schermo; una contiene gli
  26. estremi di destra delle linee e l'altra per quelli di sinistra.
  27.  
  28. A questo punto ti starai chiedendo come fare le tabelle no? Bene è tutto
  29. molto semplice, non devi far altro che interpolare la coordinata x lungo la
  30. y (a me hanno consigliato di non usare l'algoritmo di bresenham perchè
  31. quello normale di interpolazione è leggermente più veloce).
  32.  
  33. Allora riprendiamo il triangolo (considerando i vertici)
  34.  
  35.       1->.         p1=(25,0)
  36.         / \        p2=(0,25)
  37.        /   \       p3=(50,25)
  38.    2->/     \<-3
  39.       ¯¯¯¯¯¯¯
  40. quindi nelle tabelle dovrai avere qualcosa così:
  41.  
  42.      tab1   tab2      per fare le tabelle si fa ± così:
  43. 0     25     25
  44. 1     24     26       dx=(p2.x-p1.x)/(p2.y-p1.y)
  45. 2     23     27       poi
  46. 3     22     28       x=p1.x;
  47. 4     21     29       for y=p1.y to p2.y
  48. 5     20     30        if tab1[y]<>0 then tab1[y]=x else tab2[y]=p1.x
  49. 6     19     31        x=x+dx
  50. :     :      :        next
  51. :     :      :
  52. 23    2      48
  53. 24    1      49
  54. 25    0      50
  55. :
  56. :
  57. (altri valori che non c'interessano)
  58.  
  59. ci 6? A questo punto ti fai un ciclo che per ogni valore di y vede se c'e' da
  60. tracciare una linea orizzontale (ovvero se tab1[y] e tab2[y] sono diversi
  61. da 0) così hai gli estremi della linea e la sua coordinata y.
  62. Nell'esempio fai un ciclo tipo:
  63. for y=0 to 50
  64.  line (tab1[y],y,tab2[y],y)
  65. next
  66. ed è fatto! Hai riempito un triangolo1! :-))
  67. Spero di essere stato abbastanza semplice nella spiegazione :-)
  68.  
  69. *** Texture Mapping ***
  70.  
  71. Allora cos'è il texture mapping? Non si tratta altro che riempire un
  72. poligono invece di usare sempre lo stesso colore, una serie di colori presi
  73. da un'altra immagine. Il problema sta nel prendere i colori nell'ordine
  74. giusto e per questo ci sono vari algoritmi:
  75. 1) polygon grandients: calcola dei valori (tratti da alcuni calcoli
  76.    vettoriali) e li usa per calcolare il colore del pixel con le formule
  77.    u=k1+a/c
  78.    v=k2+b/c
  79.    colore = txt[u,v] -> abituati xchè le coordinate sulla texture sono
  80.                         sempre individuate dalle variabili u,v :)
  81.    Questo è il metodo di texturare i poligoni in 3d; bel senso che la
  82.    texture viene vista come un piano 3d; è il metodo "perspective
  83.    correction" che (penso) venga usato negli acceleratori 3d via hardware :)
  84.    farlo via software è lentissimo!!
  85. 2) due div per scanline: calcola le u,v agli estremi della scanline (come
  86.    nella scanline, solo che invece di interpolare solo la x, qui si
  87.    interpolano anche le u,v sui lato del poligono) e poi si interpolano le
  88.    u,v lungo la scanline:
  89.    u=u0+du*(x-x0)
  90.    v=v0+dv*(x-x0)
  91.    dove
  92.    u0=u all'inizio della scanline   u1=u alla fine
  93.    v0=v  """""""""""""""""""""""    v1=v  "    "
  94.    du=(u1-u0)/(tab2[y]-tab1[y])
  95.    dv=(v1-v0)/ """"""""""""""
  96.    x-x0=differenza tra la x corrente (x) e la x all'inizio della scanline
  97.    >>>Funziona con qualsiasi poligono
  98. 3) due div per poligono: calcola gli incrementi dv/dx e du/dx per l'intero
  99.    poligono e le usa per interpolare le coordinate:
  100.    u=u0+du*(x-x0)
  101.    v=v0+dv*(x-x0)
  102.    du=(u1-u0)/(lunghezza della massima scanline)
  103.    dv=(v1-v0)/("""""""""""""""""""""""""""""""")
  104.    u1,u0,v1,v0: valori di u,v agli estremi della massima scanline
  105.    >>>> Funziona solo con triangoli
  106.    Questi due metodi sono i cosiddetti "texture mapping" a 2d perchè in
  107.    pratica si "scala" la texture tra i vertici dei poligoni, assegnando ad
  108.    ogni vertice del poligono un punto sulla texture e poi s'interpolano
  109.    linearmente le u,v lungo la scanline. Usando questi metodi si ha un
  110.    texture mapping molto veloce, ma aimè molto impreciso xchè si possono
  111.    notare delle distorsioni lungo la texture (soprattutto quando si usano
  112.    triangoli :( e io ne so qualcosa! Prova a vedere il tmap che ho fatto io
  113.    e noterai che quando ruota si nota che la texture viene "divisa" in due
  114.    lungo la diagonale della faccia!
  115.  
  116. Fondamentalmente queste sono le routine più famose per fare il texture
  117. mapping; adesso ti faccio faccio vedere un esempio di un possibile ciclo di
  118. texture mapping (pwr triangoli):
  119.  
  120. loop:
  121.  scanline(); <- calcola le tabelle delle scanline
  122.  tmap()
  123.  goto loop;
  124.  
  125. tmap()
  126.  calcola du/dy,dv/dy
  127.  interpola le u,v lungo il lato sinistro del triangolo
  128.  calcola du/dx,dv/dx per la scanline massima
  129.  for y=ymin to ymax (del triangolo)
  130.   u=u[y]
  131.   v=v[y]
  132.   for x=tab1[y] to tab2[y]
  133.    plot(x,y,txt[u,v])
  134.    u=u+du
  135.    v=v+dv
  136.   next x
  137.  next y
  138. endproc tmap
  139.  
  140. Adesso sai ± o meno ciò che so anch'io sul tmap; si tratta solo di tradurre
  141. il tutto in asm e incominciare a far girare qualcosa.... :)
  142. Io adesso sono arrivato a fare l'env-mapping di oggetti molto più complessi
  143. del "solito" cubo; mi faccio gli oggetti con imagine e poi li converto con
  144. il tddd2raw+un'altro convertitore fatto da me e ho passato a Modem
  145. un'esempio di env-map. Risultato? Sul mio misero a1200 le routine vanno a
  146. 1x1 in 5fps; sul suo a 50fps!!!! :))) Tutto si spiega dal fatto che lo 030
  147. ha la data cache, e il suo amy ha la fast (importantissima).
  148.  
  149. Se hai qualcos'altro da chiedere, fai pure! :-)
  150.  
  151. Ps: ho rivisto ancora il rotator xchè volevo vedere alcune cose; a quanto
  152.     pare tu non conosci come si fanno le addizioni in decimale! Per questo
  153.     il rotator non è così preciso come vorresti; adesso ti spiego questo
  154.     "trucchetto" (spiegato a me da Hedgehog):
  155.  
  156. Quando devi interpolare qualsiasi cosa ti ritrovi a fare qualcosa del tipo:
  157.  
  158. x=a0+da/db*b
  159. che si traduce in un ciclo
  160. a=a0
  161. loop:
  162.  a=a+da/db  da/db è l'incremento di "a" quando ci si muove su "b"
  163.  :
  164. goto loop
  165.  
  166. in assembler il tutto si traduce in:
  167.  
  168. ; calcolo da/db
  169. ; a1,a0 valori da interpolare lungo b1,b0
  170. move.w   a1,d0
  171. sub.w    a0,d0 ; a1-a0
  172. move.w   b1,d1
  173. sub.w    b0,d1 ; b1-b0
  174. swap     d0    ; (a1-a0)<<16
  175. divs.l   d1,d0 ; da/db incremento shiftato di 16 per la parte decimale
  176.                ; in modo tale che  bit 31..16  15..0
  177.                ;                   d0= intero  decimale
  178.  
  179. move.l   d0,dadb  ; salva l'incremento
  180. :
  181. : altre istruzioni
  182. :
  183. move.w   a0,d0 ; valore iniziale
  184. swap     d0    ; a0<<16
  185. move.l   dadb,d1
  186. loop:
  187. add.l    d1,d0 ; (a+da/db)<<16
  188. move.l   d0,d2
  189. swap     d2    ; valore intero in d2.w che serve
  190. :
  191. :
  192. dbra     d4,loop
  193.  
  194. Il tutto si può semplificare (e soprattutto levare 1 o anche 2 istruzioni
  195. nel loop) usando l'addx:
  196.  
  197. il calcolo di da/db va bene solo che prima di salvarlo fai uno "swap d0"
  198. in modo da avere nella word alta la parte decimale, e nella word bassa la
  199. parte intera (quella che più c'interessa); poi quando devi addizionare
  200. l'icremento alla variabile corrente fai così:
  201.  
  202. add.l    d1,d0
  203. addx.w   d3,d0 ; >>> in d3 ci deve essere 0!!! <<<
  204.  
  205. così in d0.w hai subito la variabile da usare e hai risparmiato uno swap!
  206. (4 cicli su no 020) che non è male! ;))
  207. L'addx serve perchè nel caso c'è il riporto dalla parte decimale, viene
  208. addizionato (per questo d3 deve essere uguale a 0), così viene sfruttata la
  209. parte decimale ;))
  210. Non a caso, nel file con gl'inner loop più veloci trovi le addx invece che
  211. delle add seguite da uno swap!
  212.  
  213. Pss: se vuoi, passalo pure questo doc, così magari divento più famoso! ;))
  214.  
  215.  
  216. Amighevolmente,
  217.  
  218. /
  219. \/\/ashburn / X-Zone & DeGeNeRaTiOn
  220.  
  221. Email: simon@digicolor.lognet.it
  222. Snail:
  223.  Aversa Simone
  224.  Via F.Novati 27
  225.  26100 Cremona
  226.  Italy
  227.  
  228.