📄 animpoly.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 + -