VGA – Tutorial 9 – Denthor

                       --==[ PARTE 9 ]==--

Para obter os programas mencionados neste tutorial, por favor baixe o zip com a versão antiga do tutorial, neste link.

[Nota: essas coisas entre colchetes foram adicionadas pelo Snownan. O texto original ficou quase todo inalterado, exceto pela inclusão do material em C++]

Introdução

Olá! ASPHYXIA ESTÁ DE VOLTA com nosso primeiro MegaDemo, Psycho Neurosis! Um mero download de 1.3Mb é tudo o que leva para ver a primeira grande produção do grupo de Durbs! Estamos muito orgulhosos, e acho que você deveria ver isso 😉

Em segundo, lancei um pequeno treinamento (um “treinamentinho” ;-)) no RsaPROG e na Connectix BBS, também na ASPHYXIA BBS, com o nome de COPPERS.ZIP. É um pequeno programa em Pascal demonstrando como mostrar barras de cobre em modo texto. Também inclui uma verificação para o retrace horizontal (um monte de pessoas queriam isso, por isso que escrevi o programa (ASPHYXIA… o primeiro com goodies de treinamento 😉 aaargh, desculpa, eu tinha que fazer isso ))

Em terceiro, desculpe pelos problemas no Tutorial 8! Se você tivesse todas as verificações ligadas, o tutorial provavelmente morreria nos primeiros pontos. A razão é essa: no primeiro loop, temos DrawPoints e então RotatePoints. As variáveis usadas em DrawPoints são setadas em RotatePoints, então, se você colocar RotatePoints antes de DrawPoints, o programa deveria funcionar bem. Alternativamente, desligue a checagem de erros 😎

Em quarto, tenho recebido uma enorme quantidade de pessoas dizendo que “Eu recebo essa estranha mensagem ‘286 instructions not enabled’! O que tem de errado com seu código cara?” para todos vocês, entre no Pascal, tecle Alt-O (para acessar as opções), tecle ENTER, e um 2 (para habilitar as instruções 286). Difícil, não? Ninguém NUNCA configura seu Pascal?

E agora, vamos ao tutorial de hoje! Sólidos em 3D. Isso é o que as pessoas queriam, é o que as pessoas vão ter! Esse tutorial é principalmente sobre como desenhar o polígono na tela. Para mais detalhes sobre como o 3D funciona, veja o tutorial 8.

Se você gostaria de me contactar, ou ao time, há muitos modos que você pode fazê-lo:
1) Escrever uma mensagem para Grant Smith/Denthor/Asphyxia em email privado na ASPHYXIA BBS.
2) Escrever para Denthor, Eze ou Livewire na Connectix.
3) Escrever para:
Grant Smith
P.O.Box 270 Kloof
3640
Natal
4) Ligar para mim (Grant Smith) no número (031) 73 2129
(deixe uma mensagem se você ligar quando eu estiver na faculdade)
5) Escreva para mcphail@beastie.cs.und.ac.za na InterNet, e
mencione a palavra Denthor perto do topo da carta.

OBS1 : Se você é um representante de uma companhia ou BBS e quer que a ASPHYXIA faça um demo para você, mande um email pra mim; podemos discutir.
OBS2 : Se você fez/tentou fazer um demo, MANDE PARA MIM! Estamos nos sentindo muito solitários e queremos encontrar/ajudar/trocar código com outros grupos de demos. O que você tem a perder? Mande uma mensagem aqui e podemos ver como transferir. Nós realmente queremos ouvir de você.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

Como desenhar um polígono

Parece bastante fácil, certo? ERRADO! Há muitos, muitos modos de fazer isso, e hoje vou te mostrar um deles. Por favor, não ache que o que está escrito aqui é o melhor método, apenas está aqui para você entender como funciona…

O procedimento que usarei é baseado em algo que a maioria de nós aprendeu na oitava série… eu acho. Parece que me lembro de fazer algo desse tipo nas aulas de matemática do Sr. Reids há muitos anos atrás 😉

Pegue dois pontos, x1,y1 e x2,y1. Desenhe-os:

              + (x1,y1)
               \
                 \  <-- Aponta pra algum lugar na reta
                   \
                     + (x2,y2)

Certo, então o que temos que fazer é isso: se sabemos a coordenada Y de a, qual é a sua coordenada X? Para provar o método, vamos dar valores aleatórios aos pontos.

             + (2,10)
              \
                \  <-- a.y = 12
                  \
                    +  (15,30)

Certo, bem simples esse problema. É assim que fazemos:

(a.y-y1) = (12 - 10)  { para pegar a.y como se y1 fosse zero}
*(x2-x1) = *(15 - 2)  { o tamanho total em X da reta}
 /(y2-y1) = /(30 - 10) { o tamanho total em X da reta}
      +x1 = +2         { levar a equação de volta às coordenadas reais}

Assim, nossa equação é:(a.y-y1)(x2-x1)/(y2-y1)+x4 ou (12-10)(15-2)/(30-10)+2
que te dá:
2*13/20+2 = 26/20+2
= 3.3

Isso significa, que, ao longo da reta, com y=12, x é igual a 3.3. Se não levarmos em conta a casa decimal, podemos trocar o / por um div, e o Pascal te dá um resultado inteiro, que é mais rápido também. Tudo bom e bem, ouço vocês gritando, mas o que isso tem a ver com polígonos em geral. A resposta é simples. Para cada um dos quatro lados do polígono fazemos o teste acima para cada linha Y. Nós armazenamos o maior e o menor valores de X em variáveis separadas para cada reta, e desenhamos uma reta horizontal entre eles. Ta-dah! Temos um polígono maneiro!

Por exemplo, duas retas descendo:

            +             +
           / <-x1     x2->|   <-- para essa reta Y
         /                |
       +                  +

Encontre x1 e y1 para aquele y, e então desenhe uma linhe entre eles. Repita para todos os valores de y.

É claro, não é tão simples como parece. Temos que nos certificar de checar somente as linhas Y que contém o polígono (um teste simples de min y, max y para todos os pontos). Também temos que checar que a linha que estamos calculando realmente vai tão longe quanto nosso Y atual é (checar que o ponto está entre os dois y’s). Temos que comparar cada X para ver se é menor que o mínimo ou maior que o máximo (o x min original é setado como um número grande e o x max é um número pequeno). Devemos também testar que só podemos desenhar no lugar que podemos ver (0-319 para X e 0 -199 para Y (o tamanho da tela MCGA)).

Para ver como isso se parece na prática, dê uma olhada no programa de amostra. (O sr. Reids me mataria pela explicação acima, já que quando você aprende na escola, você divide em milhares de equações menores para conseguir a mesma resposta ;))

OK, é isso! Isso o quê? Como desenhar uma linha vertical? Isso é fácil…

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

Desenhando uma linha vertical

Certo, isso é muito mais fácil que desenhar uma reta comum (tutorial 5… eu acho), porque você fica no mesmo valor de Y. Então, o que você tem que fazer é setar ES para a tela que você quer escrever, e apontar DI para o início da linha Y (veja treinamentos anteriores uma descrição de como o SEGMENTO:OFFSET funciona).

ENTRADA: x1 , x2, y, color, where

       asm
         mov    ax,where
         mov    es,ax
         mov    di,y
         mov    ax,y
         shl    di,8   { di:=di*256 }
         shl    ax,6   { ax:=ax*64 }
         add    di,ax  { di := (y*256)+(y*64) := y*320  Mais rápido que uma multiplicação }

Certo, agora você adiciona o primeiro valor de X para pegar o início.
add di,x1
Mova a cor a armazenar em ah e al
mov al,color
mov ah,al { ah:=al:=color }
então faça CX igual a quantos pixels você quer andar
mov cx,x2
sub cx,x1 { cx:=x2-x1 }
Ok, como todos sabemos, mover uma word é muito mais rápido que um byte, então dividimos CX pela metade
shr cx,1 { cx:=cx/2 }
mas o que acontece se CX era um número ímpar? Após o shift, o valor do último número é colocado no flag de carry, então o que fazemos é pular uma movimentação de byte se o flag é zero, ou executar se é 1.

        jnc     @Start  { Se não há "vai-um" (carry), pule para o label Start }
        stosb           { ES:[DI]:=al ; incrementa DI }
    @Start :            { Label Start }
        rep     stosw   { ES:[DI]:=ax ; DI:=DI+2; repete CX vezes }

Certo, o produto final se parece com isso:

[Pascal]
Procedure Hline (x1,x2,y:word;col:byte;where:word); assembler;
     { Isso desenha uma linha horizontal de x1 a x2 na linha Y com cor col }
   asm
     mov   ax,where
     mov   es,ax
     mov   ax,y
     mov   di,ax
     shl   ax,8
     shl   di,6
     add   di,ax
     add   di,x1
     mov   al,col
     mov   ah,al 
     mov   cx,x2 
     sub   cx,x1 
     shr   cx,1 
     jnc   @start 
     stosb
 @Start :
     rep   stosw
   end;


 [C++]
 void Hline (word X1, word X2, word Y, byte Col, word Where) {
     asm {
       mov     ax, [Where]  // move o segmento de Where para AX
       mov     es, ax       // seta ES para o segmento de Where
       mov     ax, [Y]      // seta AX para Y
       mov     di, ax       // seta DI para Y
       shl     ax, 8        // shifta AX à esquerda 8 casas (multiplica Y por 256)
       shl     di, 6        // shifta DI à esquerda 6 casas (multiplica Y por 64)
       add     di, ax       // soma AX a DI (Y64 + Y256 = Y*320)
       add     di, [X1]     // soma o offset de X1 a DI
       mov     al, [Col]    // move Col para AL
       mov     ah, al       // move Col para AH (queremos 2 cópias para cada movimentação de word)
       mov     cx, [X2]     // move X2 para CX
       sub     cx, [X1]     // move o resto em X para CX
       shr     cx, 1        // divide o resto em X por 2 (para mover em word)
       jnc     Start        // se temos um número par, vá para Start
       stosb                // senão, mova mais um byte
     }
     Start: asm {
       rep     stosw        // faz!
     }
   }

Feito!

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

Fechando

Esse sistema 3D ainda não é perfeito. ele precisa ser mais rápido, e agora eu joguei o problema na sua cara. Nyahahahaha!

       [ Minha irmã e eu estávamos passeando outro dia, quando ela
    me perguntou o que eu queria pro meu computador.
     Eu pensei bastante nisso e cheguei à seguinte hipótese.
    Quando uma garota ganha uma Barbie, ela então quer
    os acessórios extras para a boneca, a escova de cabelos, 
    o carro, e a casa, e os amigos, etc.
     Quando um cara ganha um computador, ele quer a memória extra,
    o HD maior, o co-processador matemático, a melhor placa-mãe,
    o monitor maior, etc.
     Eu disse para a minha irmã tudo isso, e terminei com: "Assim,
    como você pode ver, computadores são as Barbies para 
    os HOMENS!"
     Ela me chamou de chauvinista. E me bateu. Muito.
                                                               ]
                                                   - Grant Smith
                                                       19:24
                                                         26/2/94

Vejo vocês na próxima!

  • Denthor
  • Krull

A Nova Krull's HomePage