Páginas

sábado, 4 de março de 2023

sábado, 4 de março de 2023

Type-in: Gráficos em 3D (1990)


Na edição nº27 da revista RS232 encontramos uma listagem de código de Fernando Preces para o QuickBASIC, a qual fez parte de uma sequência de artigos sobre gráficos em 3D. 


Este programa apresenta uma animação simples da rotação de um objeto em 3D (wireframe) em torno do seu eixo vertical. Cada frame de animação objeto é pré-desenhado e armazenado em memória. A animação, relativamente fluída, é conseguida com a troca das páginas 0 e 1 no modo gráfico 9. Quando um passo da animação é exibido numa das páginas, na outra é guardado o passo seguinte.

A listagem dispõe de dados para duas figuras, sendo só apresentada uma deles. Basta trocar as labels "dados" e "dados1" para mudarmos a silhueta apresentada. Também há código comentado para a inserção manual das silhuetas pelo utilizador.

Segue a listagem:

'F.A.Preces - Fev 90
'Gráficos em 3D

CONST pi = 3.1416   'Valor aproximado de PI

w = 5500: ap% = 1: vp% = 0

'Espaço para as 6 figuras do movimento rotativo
DIM cubo1(w), cubo2(w), cubo3(w)
DIM cubo4(w), cubo5(w), cubo6(w)

'Reserva de espaço para os valores dos 3 eixos
DIM x(17, 8), y(17, 8), z(17, 8)

'Porçao da figura a rodar
seno = SIN(pi / 4): coseno = COS(pi / 4)

aa = 320: bb = 50   'Coordenadas de arranque

'Coordenada do Ecran em EGA
SCREEN 9: WINDOW (0, 0)-(640, 350): COLOR 6, 1: CLS

RESTORE dados
READ x: x(15, 1) = x: READ y: y(1, 1) = y: z(1, 1) = 0

'leitura dos dados da Silhueta
FOR c = 2 TO 16
    READ x: 'ou por GOSUB limpa: INPUT "Comprimento "; x
    x(c, 1) = x
    READ y: 'ou por GOSUB limpa: INPUT "Altura "; y
    y(c, 1) = y
    z(c, 1) = 0
    x1 = x(c - 1, 1) + aa: y1 = y(c - 1, 1) + bb
    x2 = aa + x(c, 1): y2 = bb + y(c, 1)
    LINE (x1, y1)-(x2, y2) 'Desenha a silhueta
NEXT c

'Prepara a figura em 3D
FOR q = 1 TO 6
    FOR B = 2 TO 8
        FOR a = 1 TO c - 1
            x(a, B) = x(a, B - 1) * coseno - z(a, B - 1) * seno
            z(a, B) = z(a, B - 1) * coseno + x(a, B - 1) * seno
            y(a, B) = y(a, B - 1)
        NEXT a
    NEXT B
    CLS
    'Desenha as seis imagens para a rotaç?o
    FOR B = 1 TO 7
        FOR a = 1 TO c - 1
            x1 = aa + x(a, B): y1 = bb + (y(a, B) - .5 * z(a, B))
            x2 = x1 + x(a, B + 1) - x(a, B)
            y2 = y1 + (y(a, B + 1) - .5 * z(a, B + 1)) - (y(a, B) - .5 * z(a, B))
            LINE (x1, y1)-(x2, y2), 6
            x1 = x2: y1 = y2
            x2 = x1 + x(a + 1, B + 1) - x(a, B + 1)
            y = y1 + y(a + 1, B + 1) - .5 * z(a + 1, B + 1)
            y2 = y - (y(a, B + 1) - .5 * z(a, B + 1))
            LINE (x1, y1)-(x2, y2), 5
        NEXT a
    NEXT B
    FOR a = 1 TO c - 1
        x1 = aa + x(a, 8): y1 = bb + (y(a, 8) - .5 * z(a, 8))
        x2 = x1 + x(a, 1) - x(a, 8)
        y2 = y1 + (y(a, 1) - .5 * z(a, 1)) - (y(a, 8) - .5 * z(a, 8))
        LINE (x1, y1)-(x2, y2), 6
        x1 = x2: y1 = y2
        x2 = x1 + x(a + 1, 1) - x(a, 1)
        y2 = y1 + (y(a + 1, 1) - .5 * z(a + 1, 1)) - (y(a, 1) - .5 * z(a, 1))
        LINE (x1, y1)-(x2, y2), 5
    NEXT a

    'Memoriza as 6 imagens
    IF q = 1 THEN GET (220, 42)-(440, 235), cubo1
    IF q = 2 THEN GET (220, 42)-(440, 235), cubo2
    IF q = 3 THEN GET (220, 42)-(440, 235), cubo3
    IF q = 4 THEN GET (220, 42)-(440, 235), cubo4
    IF q = 5 THEN GET (220, 42)-(440, 235), cubo5
    IF q = 6 THEN GET (220, 42)-(440, 235), cubo6

    'Prepara o desfazamento entre imagens
    FOR a = 1 TO c - 1
        xn = x(a, 1) * COS(pi / 24) - z(a, 1) * SIN(pi / 24)
        zn = z(a, 1) * COS(pi / 24) + x(a, 1) * SIN(pi / 24)
        x(a, 1) = xn: z(a, 1) = zn
    NEXT a
NEXT q: CLS

'As 6 imagens s?o memorizadas no Buffer de Imagens gradualmente,
'em 2 páginas sucessivas de ecran (apresenta uma e grava outra)

ciclo:
FOR q% = 1 TO 6
    SCREEN 9, , ap%, vp%
    CLS 1
    IF q% = 1 THEN PUT (220, 42), cubo1
    IF q% = 2 THEN PUT (220, 42), cubo2
    IF q% = 3 THEN PUT (220, 42), cubo3
    IF q% = 4 THEN PUT (220, 42), cubo4
    IF q% = 5 THEN PUT (220, 42), cubo5
    IF q% = 6 THEN PUT (220, 42), cubo6

    SWAP ap%, vp%   'Troca de página

NEXT q%

IF INKEY$ <> "" THEN END
GOTO ciclo
END

limpa:
    LOCATE 1, 1: PRINT STRING$(79, " "): LOCATE 1, 1
    RETURN

dados1:  'Silhueta de reserva
DATA 40, 40, 40, 40, 80, 40, 85, 45, 85, 100, 80, 100, 60, 100, 80, 100, 80, 125
DATA 40, 125, 40, 125, 55, 125, 55, 125, 40, 125, 40, 40, 0, 40

dados:    'Silhueta apresentada
DATA 0, 0, 25, 5, 35, 20, 80, 30, 80, 80, 30, 120, 30, 150, 45, 160, 20, 160
DATA 20, 110, 70, 70, 70, 35, 0, 20, 0, 20, 0, 20, 0, 20

2 comentários:

  1. Está excelente e muito interessante, Filipe. Um grande abraço.

    ResponderEliminar
    Respostas
    1. Obrigado João! Para a semana publicarei mais um type-in! :)

      Eliminar