/* * BB: The portable demo * * (C) 1997 by AA-group (e-mail: aa@horac.ta.jcu.cz) * * 3rd August 1997 * version: 1.2 [final3] * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public Licences as by published * by the Free Software Foundation; either version 2; or (at your option) * any later version * * This program is distributed in the hope that it will entertaining, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILTY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Publis License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc. * 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include "bb.h" #define DEG (M_PI/180) #define X_s aa_imgwidth(context) #define Y_s aa_imgheight(context) #define data context->imagebuffer #define X_S (X_s/2) #define Y_S (Y_s/2) #define Tx 127 #define Ty 127 #define XRATIO X_s*zoom/320 #define YRATIO Y_s*zoom*aa_mmwidth(context)/aa_mmheight(context)/320 #define Bufflen 768 #define VERT 3 #define ArC 12000 #define MaxFaces 500 typedef unsigned char byte; typedef unsigned short int word; typedef unsigned long dword; typedef struct { unsigned short int x, y; } INFO; typedef long TBL[361]; typedef struct POL { long x, y, z, n_x, n_y, n_z; } POLYS[3]; typedef struct { long x, y, z, nx, ny, nz; } TRANSFORMED; typedef TRANSFORMED TRANS[MaxFaces][3]; static TBL sinn, coss; static int nFaces; dword alfa, beta, gama; int centerx, centery, centerz; float zoom = 2.0; static byte *envmapa; static POLYS *obj, rot[MaxFaces]; static TRANS polyg; static int *zbuff; #include "patnik.h" #include "torus.h" static void precalculate(void) { unsigned i; for (i = 0; i <= 360; i++) { sinn[i] = (long) (sin(i * DEG) * 65536); coss[i] = (long) (cos(i * DEG) * 65536); } } void set_zbuff() { zbuff = (int *) malloc(X_s * Y_s * sizeof(int)); } void unset_zbuff() { free(zbuff); } static inline void clear_zbuff() { memset(zbuff, 0x55, (X_s * Y_s * sizeof(long))); } static inline void makej(long x1, long x2, long n1z, long n2z, long ii, long n1x, long n1y, long n2x, long n2y) { register byte *off, *off1; register int *zbptr = zbuff + (ii * X_s) + x1; long n3x; long n3y; long n3z; long n3Dx; long n3Dy; long n3Dz; long e, rx, ry; if (ii >= Y_s || ii < 0 || x2 < 0 || x1 >= X_s) return; if (x1 < 0) x1 = 0; if (x2 >= X_s) x2 = X_s - 1; e = x2 - x1; if (!e) return; n3Dx = (n2x - n1x) / e; n3x = n1x; n3Dy = (n2y - n1y) / e; n3y = n1y; n3Dz = (n2z - n1z) / e; n3z = n1z; off = data + (ii * X_s) + x1; off1 = off + x2 - x1; for (; off <= off1;) { ry = (abs(n3y) >> 7) + 64; rx = (abs(n3x) >> 7) + 64; if (((n3z >> 8) - *zbptr) < 500) { *off = *(envmapa + (((unsigned int) ((ry << 7) + rx)) & (128 * 128 - 1))); *zbptr = n3z >> 8; } off++; zbptr++; n3x += n3Dx; n3y += n3Dy; n3z += n3Dz; } } static void optfsp(unsigned wh) { byte pivot, maxy, a, b, c; long ii, aa, bb; long x1, x2, d1, d2, m1, m2, m3; long n1x, n1y, n1z; long n2x, n2y, n2z; long n1Dx, n1Dy, n1Dz; long n2Dx, n2Dy, n2Dz; pivot = maxy = 0; if (polyg[wh][pivot].y > polyg[wh][1].y) pivot = 1; if (polyg[wh][pivot].y > polyg[wh][2].y) pivot = 2; if (polyg[wh][maxy].y < polyg[wh][1].y) maxy = 1; if (polyg[wh][maxy].y < polyg[wh][2].y) maxy = 2; a = b = pivot; c = maxy; a01: if (b == 2) b = 0; else b++; if ((b == pivot) || (b == maxy)) goto a01; m1 = polyg[wh][c].y - polyg[wh][a].y; m2 = polyg[wh][b].y - polyg[wh][a].y; m3 = polyg[wh][c].y - polyg[wh][b].y; if (m1) { d1 = ((polyg[wh][c].x - polyg[wh][a].x) << 16) / m1; x1 = polyg[wh][a].x << 16; n1Dx = (rot[wh][c].n_x - rot[wh][a].n_x) / m1; n1x = rot[wh][a].n_x; n1Dy = (rot[wh][c].n_y - rot[wh][a].n_y) / m1; n1y = rot[wh][a].n_y; n1Dz = (polyg[wh][c].z - polyg[wh][a].z) / m1; n1z = polyg[wh][a].z; ii = 0; if (m2) { d2 = ((polyg[wh][b].x - polyg[wh][a].x) << 16) / m2; x2 = polyg[wh][a].x << 16; n2Dx = (rot[wh][b].n_x - rot[wh][a].n_x) / m2; n2x = rot[wh][a].n_x; n2Dy = (rot[wh][b].n_y - rot[wh][a].n_y) / m2; n2y = rot[wh][a].n_y; n2Dz = (polyg[wh][b].z - polyg[wh][a].z) / m2; n2z = polyg[wh][a].z; for (ii = polyg[wh][a].y; ii <= polyg[wh][b].y; ii++) { aa = x1 >> 16; bb = x2 >> 16; if (aa > bb) makej(bb, aa, n2z, n1z, ii, n2x, n2y, n1x, n1y); if (aa < bb) makej(aa, bb, n1z, n2z, ii, n1x, n1y, n2x, n2y); x1 += d1; x2 += d2; n1x += n1Dx; n1y += n1Dy; n1z += n1Dz; n2x += n2Dx; n2y += n2Dy; n2z += n2Dz; } } if (m3) { d2 = ((polyg[wh][c].x - polyg[wh][b].x) << 16) / m3; x2 = polyg[wh][b].x << 16; n2Dx = (rot[wh][c].n_x - rot[wh][b].n_x) / m3; n2x = rot[wh][b].n_x; n2Dy = (rot[wh][c].n_y - rot[wh][b].n_y) / m3; n2y = rot[wh][b].n_y; n2Dz = (polyg[wh][c].z - polyg[wh][b].z) / m3; n2z = polyg[wh][b].z; for (ii = polyg[wh][b].y + 1; ii <= polyg[wh][c].y; ii++) { aa = x1 >> 16; bb = x2 >> 16; if (aa > bb) makej(bb, aa, n2z, n1z, ii, n2x, n2y, n1x, n1y); if (aa < bb) makej(aa, bb, n1z, n2z, ii, n1x, n1y, n2x, n2y); x1 += d1; x2 += d2; n1x += n1Dx; n1y += n1Dy; n1z += n1Dz; n2x += n2Dx; n2y += n2Dy; n2z += n2Dz; } } } } static void show(void) { double ZZ; unsigned i, j; for (i = 0; i < nFaces; i++) for (j = 0; j < 3; j++) { polyg[i][j].x = ((rot[i][j].x << 8) / (256 + rot[i][j].z)) * XRATIO + X_S; polyg[i][j].y = ((rot[i][j].y << 8) / (256 + rot[i][j].z)) * YRATIO + Y_S; polyg[i][j].z = rot[i][j].z << 16; } for (i = 0; i < nFaces; i++) { ZZ = (polyg[i][2].x - polyg[i][0].x) * (polyg[i][1].y - polyg[i][0].y) - (polyg[i][1].x - polyg[i][0].x) * (polyg[i][2].y - polyg[i][0].y); if (ZZ <= 0) optfsp(i); } } void disp3d(void) { int i, j; for (i = 0; i < nFaces; i++) for (j = 0; j < 3; j++) { int x = obj[i][j].x + centerx, y = obj[i][j].y + centery, z = obj[i][j].z + centerz; rot[i][j].x = (z * coss[alfa] - x * sinn[alfa]) >> 16; rot[i][j].z = (z * sinn[alfa] + x * coss[alfa]) >> 16; x = (y * coss[beta] - rot[i][j].z * sinn[beta]) >> 16; rot[i][j].z = (y * sinn[beta] + rot[i][j].z * coss[beta]) >> 16; rot[i][j].y = x; x = (rot[i][j].y * coss[gama] - rot[i][j].x * sinn[gama]) >> 16; rot[i][j].x = (rot[i][j].y * sinn[gama] + rot[i][j].x * coss[gama]) >> 16; rot[i][j].y = x; x = obj[i][j].n_x + centerx, y = obj[i][j].n_y + centery, z = obj[i][j].n_z + centerz; rot[i][j].n_x = (z * coss[alfa] - x * sinn[alfa]) >> 16; rot[i][j].n_z = (z * sinn[alfa] + x * coss[alfa]) >> 16; x = (y * coss[beta] - rot[i][j].z * sinn[beta]) >> 16; rot[i][j].n_z = (y * sinn[beta] + rot[i][j].z * coss[beta]) >> 16; rot[i][j].n_y = x; x = (rot[i][j].n_y * coss[gama] - rot[i][j].n_x * sinn[gama]) >> 16; rot[i][j].n_x = (rot[i][j].n_y * sinn[gama] + rot[i][j].n_x * coss[gama]) >> 16; rot[i][j].n_y = x; } clear_zbuff(); memset(data, 0, X_s * Y_s); show(); } void patnikconstructor(void) { long i, j; unsigned char table[256]; for (i = 0; i < 256; i++) { table[i] = pow(i / 256.0, 2.0) * 256.0; } precalculate(); nFaces = patniknFaces; obj = patnikobj; envmapa = (byte *) malloc(128 * 128); for (i = 0; i <= 127; i++) for (j = 0; j <= 127; j++) *(envmapa + i * 128 + j) = table[(unsigned char) (0x0007A120 / ((i - 64) * (i - 64) + (j - 64) * (j - 64) + 2100))]; memcpy(&rot, &obj, sizeof(obj)); } void torusconstructor(void) { long i, j; unsigned char table[256]; for (i = 0; i < 256; i++) { table[i] = pow(i / 256.0, 3.0) * 200.0; } precalculate(); nFaces = torusnFaces; obj = torusobj; envmapa = (byte *) malloc(128 * 128); for (i = 0; i <= 127; i++) for (j = 0; j <= 127; j++) *(envmapa + i * 128 + j) = table[(unsigned char) (0x0007A120 / ((i - 64) * (i - 64) + (j - 64) * (j - 64) + 2100))]; memcpy(&rot, &obj, sizeof(obj)); } void destructor() { free(envmapa); }