⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 animpoly.c

📁 nucleus 文件系统,内核和彩色图形系统,在小系统上非常好用
💻 C
字号:
/*  %kw # %v    %n    %d    %t # */
/* Version # 2    ANIMPOLY.C    22-Feb-96    12:02:10 # */
/***************************************************************/
/*   METAGRAPHICS SOFTWARE CORPORATION (c) 1994                */
/*                                                             */
/* Description: This program is an example of how to do        */
/* 3D polygon animation using page flipping                    */
/*                                                             */
/* 3D examples taken from "Flights of Fantasy" by              */
/* Chistopher Lampton, Waite Group Press, ISBN 1-878739-18-2   */
/* An excellent book on 3D graphics, highly recommended.       */
/*                                                             */
/***************************************************************/
#define byte unsigned char
#define word unsigned short
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include "metawndo.h"      /* master MetaWINDOW include file */

/* special stack size declaration if using Turbo or Borland C++ */
#ifdef      TurboC
extern unsigned _stklen = 14336U;  /* stack size 14K */
#endif


// Variable structures to hold shape data:

typedef struct  { // Structure for individual vertices
  long lx,ly,lz,lt;	// Local coordinates of vertex
  long wx,wy,wz,wt;	// World coordinates of vertex
  long sx,sy,st;		// Screen coordinates of vertex
} vertex_type;

typedef struct  {
   int   number_of_vertices;  // Number of vertices in polygon
   int   *vertexList;         // List of vertices in poly
   int   color;               // Color of polygon
} polygon_type;

typedef struct {
   int   number_of_vertices;  // Number of vertices in object
   int   number_of_polygons;  // Number of polygons in object
   polygon_type *polygon;     // List of polygons in object
   vertex_type *vertex;       // Array of vertices in object
} object_type;


// define a pyramid object 

// vertex list
vertex_type pyramid_vtx[5] = {
   {-10, 10,-10,1, 0,0,0,1, 0,0,0},   // Vertex #0
   { 10, 10,-10,1, 0,0,0,1, 0,0,0},   // Vertex #1
   {  0,-10,  0,1, 0,0,0,1, 0,0,0},   // Vertex #2
   { 10, 10, 10,1, 0,0,0,1, 0,0,0},   // Vertex #3
   {-10, 10, 10,1, 0,0,0,1, 0,0,0}    // Vertex #4
};

// polygon list
int p1[] = { 1,2,0 };
int p2[] = { 3,2,1 };
int p3[] = { 4,2,3 };
int p4[] = { 0,2,4 };
int p5[] = { 4,3,1,0 };

polygon_type pyramid_ply[5] = {

   { 3, p1, Red },
   { 3, p2, Green },
   { 3, p3, Blue },
   { 3, p4, White },
   { 4, p5, Magenta }
};

object_type pyramid = { 5, 5, pyramid_ply, pyramid_vtx };


// Function prototypes:

void  draw_object(object_type *object );
int   backface(polygon_type *polygon, vertex_type *vertex);
void  transform(object_type *object);
void  project(object_type *object,int distance, int xorg, int yorg);

void  inittrans(void);
void  scale(float sf);
void  rotate(float ax,float ay,float az);
void  translate(int xt,int yt,int zt);
void  matmult(float result[4][4],float mat1[4][4],float mat2[4][4]);
void  matcopy(float dest[4][4],float source[4][4]);

// Global transformation arrays:

float matrix[4][4];  // Master transformation matrix
float smat[4][4];    // Scaling matrix
float zmat[4][4];    // Z rotation matrix
float xmat[4][4];    // X rotation matrix
float ymat[4][4];    // Y rotation matrix
float tmat[4][4];    // Translation matrix



void animpoly()
{
//   int   i;
	void quit(void);
   int   page;
   grafPort *scrnport, *page1Port, *page2Port;
   rect scrnR;

   float xangle, yangle, zangle, sf;
   int   xpos, ypos, zpos;
   int   zdelta;
   int count=0;
	mwEvent waitEvent;

//   i = InitGraphics( 2 );
//   if( i != 0 ) {
//      printf( "MetaWINDOW InitGraphics error - %d\n",i );
//      exit(1);
//   }

   SetDisplay( GrafPg0 );

   /* get pointer to current (default) port */
   GetPort( &scrnport );

   /* extend the ports bitmap to cover both display pages */
   ScreenRect( &scrnR );
   BackColor(0);
   page1Port = CreateBitmap(cMEMORY, scrnR.Xmax, scrnR.Ymax);
   if (page1Port == NULL) return;
   page2Port = CreateBitmap(cMEMORY, scrnR.Xmax, scrnR.Ymax);
   if (page2Port == NULL)
   {
	   DestroyBitmap(page1Port);
	   return;
   }

   SetPort(page1Port);
   // set initial values
   xangle = yangle = zangle = 0;
   xpos = 0; ypos = 0; zpos = 0;
   sf = (float) ((scrnR.Ymax + 1) / 100);
   if (sf < 1) sf = 1;
   zdelta = 1;
   page = 0;

//   while( count++ < 32 ) {
   while( count++ < 50 ) {

      // advance rotation settings
      xangle += (float) .02;
      yangle += (float) .05;
      zangle += (float) .1;

      // change z
      zpos += zdelta;
      if( zpos <= -300 || zpos > 300 )
         zdelta = -zdelta;

      inittrans();                     // Initialize translations
      scale(sf);                       // Create scaling matrix
      rotate(xangle,yangle,zangle);    // Create rotation matrices
      translate( xpos, ypos, zpos );   // Create translation matrix

      transform(&pyramid);                  // Transform OBJECT using MATRIX
     // Perform perspective projection
      project(&pyramid,scrnR.Xmax, (scrnR.Xmax / 2), (scrnR.Ymax / 2) );

      EraseRect( &scrnR );
      draw_object(&pyramid);                // Draw transformed object
            
      /* use other page */
      if( page )
	  {
		 CopyBlit(page2Port, scrnport, &scrnR, &scrnR);
         page = 0;
		 SetPort(page1Port);
	  }
      else
	  {
		 CopyBlit(page1Port, scrnport, &scrnR, &scrnR);
         page = 1;
		 SetPort(page2Port);
	  }


   }

   SetPort(scrnport);
   DestroyBitmap(page1Port);
   DestroyBitmap(page2Port);
#ifndef CYCLE
	MoveTo( 0,scrnR.Ymax - 20 );
	DrawString( "Press 'x' to exit" );
	MoveTo( 0,scrnR.Ymax - 10 );
	DrawString( "any other key to continue" );
	  while(!KeyEvent(1, &waitEvent));
	  if((waitEvent.eventChar == 'x') || (waitEvent.eventChar == 'X')) quit();
#else
#ifdef _MNT_
	  KeyEvent(0, &waitEvent);
	  if((waitEvent.eventChar == 'x') || (waitEvent.eventChar == 'X')) quit();
#endif
   Waiting(150);

#endif
}



void draw_object(object_type *object )
// Draw object in structure OBJECT
{
   int p, n;
   polygon_type *poly;
   point pts[50];

	// Loop through all polygons in object:
	for( p = 0; p < object->number_of_polygons; p++ ) {

      poly = &(object->polygon[p]);

      // remove any backface polygons
      if( backface( poly, object->vertex ) )
         continue;

      for( n = 0; n < poly->number_of_vertices; n++ ) {
         pts[n].X =  (short) object->vertex[ poly->vertexList[n] ].sx;
         pts[n].Y =  (short) object->vertex[ poly->vertexList[n] ].sy;
      }
      PenColor( poly->color );
      FillPolygon( pts, n, coordAbs, shapeConvex );

	}
}


int	backface(polygon_type *p, vertex_type *v )
{

//    Returns 0 if POLYGON is visible, -1 if not.
//    POLYGON must be part of a convex polyhedron

	vertex_type *v0,*v1,*v2;  // Pointers to three vertices
	long z;

   // Point to vertices:
   v0 = &v[ p->vertexList[0] ];
   v1 = &v[ p->vertexList[1] ];
   v2 = &v[ p->vertexList[2] ];
   z = (v1->sx-v0->sx)*(v2->sy-v0->sy)-(v1->sy-v0->sy)*(v2->sx-v0->sx);
   return( z >= 0);
}

void transform(object_type *object)
{
	// Multiply all vertices in OBJECT with master transformation matrix:
   int v;
   vertex_type *vptr;

	for( v = 0; v < object->number_of_vertices; v++) {

      vptr = &(object->vertex[v]);

		vptr->wx = (long)(vptr->lx * matrix[0][0] + vptr->ly * matrix[1][0]
       +vptr->lz*matrix[2][0]+matrix[3][0]);
		vptr->wy=(long)(vptr->lx*matrix[0][1]+vptr->ly*matrix[1][1]
       +vptr->lz*matrix[2][1]+matrix[3][1]);
		vptr->wz=(long)(vptr->lx*matrix[0][2]+vptr->ly*matrix[1][2]
       +vptr->lz*matrix[2][2]+matrix[3][2]);
	}
}

void project(object_type *object,int distance, int xorg, int yorg)
{

// Project object onto screen with perspective projection

	int v;
	vertex_type *vptr;

   for( v = 0; v < object->number_of_vertices; v++) { // Loop through vertices

      vptr = &(object->vertex[v]);  // Point to current vertex

      vptr->sx = distance*vptr->wx/(distance-vptr->wz)+xorg;  // ...divide world x&y coords
      vptr->sy = distance*vptr->wy/(distance-vptr->wz)+yorg;  // ... by z coordinates
   }

}


// Transformation functions:

void inittrans()
{

// Initialize master transformation matrix to the identity matrix

  matrix[0][0]=1; matrix[0][1]=0; matrix[0][2]=0; matrix[0][3]=0;
  matrix[1][0]=0; matrix[1][1]=1; matrix[1][2]=0; matrix[1][3]=0;
  matrix[2][0]=0; matrix[2][1]=0; matrix[2][2]=1; matrix[2][3]=0;
  matrix[3][0]=0; matrix[3][1]=0; matrix[3][2]=0; matrix[3][3]=1;
}

void scale(float sf)
{
  float mat[4][4];

	// Initialize scaling matrix:

	smat[0][0] = sf; smat[0][1] = 0;  smat[0][2] = 0;  smat[0][3] = 0;
	smat[1][0] = 0;  smat[1][1] = sf; smat[1][2] = 0;  smat[1][3] = 0;
	smat[2][0] = 0;  smat[2][1] = 0;  smat[2][2] = sf; smat[2][3] = 0;
	smat[3][0] = 0;  smat[3][1] = 0;  smat[3][2] = 0;  smat[3][3] = 1;

  // Concatenate with master matrix:

  matmult(mat,smat,matrix);
  matcopy(matrix,mat);
}

void rotate(float ax,float ay,float az)
{

  // Create three rotation matrices that will rotate an object
  // AX radians on the X axis, AY radians on the Y axis and
  // AZ radians on the Z axis

  float mat1[4][4];
  float mat2[4][4];

	// Initialize X rotation matrix:

   xmat[0][0]=1;  xmat[0][1]=0;        xmat[0][2]=0;       xmat[0][3]=0;
   xmat[1][0]=0;  xmat[1][1]=(float)cos(ax);  xmat[1][2]=(float)sin(ax); xmat[1][3]=0;
   xmat[2][0]=0;  xmat[2][1]=(float)(-sin(ax)); xmat[2][2]=(float)cos(ax); xmat[2][3]=0;
   xmat[3][0]=0;  xmat[3][1]=0;        xmat[3][2]=0;       xmat[3][3]=1;

   // Concatenate this matrix with master matrix:

   matmult(mat1,xmat,matrix);

   // Initialize Y rotation matrix:

   ymat[0][0]=(float)cos(ay); ymat[0][1]=0; ymat[0][2]=(float)(-sin(ay)); ymat[0][3]=0;
   ymat[1][0]=0;       ymat[1][1]=1; ymat[1][2]=0;        ymat[1][3]=0;
	ymat[2][0]=(float)sin(ay); ymat[2][1]=0; ymat[2][2]=(float)cos(ay);  ymat[2][3]=0;
	ymat[3][0]=0;       ymat[3][1]=0; ymat[3][2]=0;        ymat[3][3]=1;

   // Concatenate this matrix with master matrix:

   matmult(mat2,ymat,mat1);

   // Initialize Z rotation matrix:

   zmat[0][0]=(float)cos(az);  zmat[0][1]=(float)sin(az);  zmat[0][2]=0;  zmat[0][3]=0;
   zmat[1][0]=(float)(-sin(az)); zmat[1][1]=(float)cos(az);  zmat[1][2]=0;  zmat[1][3]=0;
   zmat[2][0]=0;        zmat[2][1]=0;        zmat[2][2]=1;  zmat[2][3]=0;
   zmat[3][0]=0;        zmat[3][1]=0;        zmat[3][2]=0;  zmat[3][3]=1;

   // Concatenate this matrix with master matrix:

   matmult(matrix,zmat,mat2);
}

void translate(int xt,int yt,int zt)
{

// Create a translation matrix that will translate an object an
// X distance of XT, a Y distance of YT, and a Z distance of ZT
// from the screen origin

  float mat[4][4];

  tmat[0][0]=1;  tmat[0][1]=0;  tmat[0][2]=0;  tmat[0][3]=0;
  tmat[1][0]=0;  tmat[1][1]=1;  tmat[1][2]=0;  tmat[1][3]=0;
  tmat[2][0]=0;  tmat[2][1]=0;  tmat[2][2]=1;  tmat[2][3]=0;
  tmat[3][0]=(float)xt; tmat[3][1]=(float)yt; tmat[3][2]=(float)zt; tmat[3][3]=1;

  // Concatenate with master matrix:

  matmult(mat,matrix,tmat);
  matcopy(matrix,mat);
}


void matmult(float result[4][4],float mat1[4][4],float mat2[4][4])
{

// Multiply matrix MAT1 by matrix MAT2, returning the result in RESULT
   int i, j, k;

   for( i=0; i<4; i++)
      for( j=0; j<4; j++) {
         result[i][j]=0;
         for( k=0; k<4; k++)
            result[i][j]+=mat1[i][k] * mat2[k][j];
      }
}

void matcopy(float dest[4][4],float source[4][4])
{

// Copy matrix SOURCE to matrix DEST
   int i, j;

   for( i=0; i<4; i++)
      for( j=0; j<4; j++)
         dest[i][j]=source[i][j];
}







⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -