你好,欢迎来到电脑编程技巧与维护杂志社! 杂志社简介广告服务读者反馈编程社区  
合订本订阅
 
 
您的位置:杂志经典 / 编程语言
空间曲面真实感图形生成和显示技术(下)
 

三、代码实现

本实例程序用Turbo C 2.0Large模式下编译通过。程序用绿色生成曲面z=sin(x*y)x [-3,3]y [-3,3]的真实感图形,并将其写入BMP格式的文件。笔者作过比较,在同等条件下,按照文中开始陈述的方法在WINDOWS下显示曲面的真实感图形需8秒,而应用扩展内存技术实现曲面真实感图形的生成和显示只需1.5秒,效果相当不错。由于采用文件存放图形数据,所以很容易实现DOSWINDOWS下的快速显示。限于篇幅,本文略出快速显示BMP文件的部分,读者可以用WIN95的画图在真彩色下显示

/*xms.h*/

#include<dos.h>

#include<conio.h>

union address {

  unsigned int part[2];

  long offset;

 };

 

struct emm {

  long length;

  unsigned int source_handle;

  union address source;

  unsigned int target_handle;

  union address target;

 };

 

void far(* _p)( );

 

char xms_installed( )

 {

  _AX=0x4300;

  geninterrupt(0x2f);

  if(_AL!=0x80)   {

    textmode(3);

    printf("XMS is not installed\n!");

    exit(1);

   }

  return(_AL);

 }

 

void xms_entry( )

 {

  _AX=0x4310;

  geninterrupt(0x2f);

  _p=MK_FP(_ES,_BX);

  return;

 }

 

void test_xms(unsigned int size)

 {

  _AH=8;  _p( );

  if(_AX<size)   {

    textmode(3);

    printf("No enough XMS to be used!\n");

    exit(1);

   }

 }

unsigned int alloc_xms(unsigned int size)

 {

  _DX=size;  _AH=9;

  _p( );

  if(_AX!=1)   {

    textmode(3);

    printf("XMS allocation is error\n");

    exit(1);

   }

  return(_DX);

 }

 

void move_xms(struct emm *xms)

 {

  _DS=FP_SEG(xms);

  _SI=FP_OFF(xms);

  _AH=0x0b;  _p( );

  if(_AX!=1)   {

    textmode(3);

    printf("XMS move error! %d\n",_BL);

    exit(1);

   }

  return;

 }

 

void free_xms(unsigned int handle)

 {

  _DX=handle;  _AH=0x0a;

  _p( );

 }

 

/*surface.c*/

 #include<stdio.h>

 #include<dos.h>

 #include<math.h>

 #include<alloc.h>

 #include<mem.h>

 #include<conio.h>

 #include<stdlib.h>

 #include<xms.h>

 #define PI 3.1415927

 

 int ox,oy,length,width,height,N;

 float sita,gama,dx,dy,deltax,deltay;

 float xmin,xmax,ymin,ymax,zmin,zmax;

 int v[5][2],vx[100][4],num[100],vymin,vymax;

 struct emm xms;

 unsigned int handle;

 int WIDTH,HEIGHT;

 int left,top,right,bottom,byteperpixel;

 struct{

  unsigned char type[2];

  long size;

  long reserved;

  long offset;

  }head;

 struct{

  long size;

  long width;

  long height;

  int plane;

  int bitcount;

  long compression;

  long imagesize;

  long xpels;

  long ypels;

  long colorused;

  long colorimportant;

  }bmp;

 

 void xmsinitial(int size)

  {

   xms_installed( );

   xms_entry( );

   test_xms(size);

   handle=alloc_xms(size);

  }

 

 void putpixel(long x,long y,unsigned char red,

      unsigned char green,unsigned char blue)

  {

   unsigned char *pixel;

   pixel=malloc(byteperpixel*

               sizeof(unsigned char));

   pixel[0]=blue;  pixel[1]=green;

   pixel[2]=red;   pixel[3]=0;

   xms.target.offset=byteperpixel*(WIDTH*y+x);

   xms.length=byteperpixel;

   xms.source_handle=0;

   xms.source.part[0]=FP_OFF(pixel);

   xms.source.part[1]=FP_SEG(pixel);

   xms.target_handle=handle;

   move_xms(&xms);

   free(pixel);

  }

 

 void level(long left,long right,long y,

     unsigned char red,unsigned char green,

     unsigned char blue)

  {

   long i;

   unsigned char *pixel;

   pixel=malloc(byteperpixel*(right-

        left+1)*sizeof(unsigned char));

   for(i=0;i<=right-left;i++)   {

     pixel[4*i]=blue;

     pixel[4*i+1]=green;

     pixel[4*i+2]=red;

    }   xms.target.offset=byteperpixel*(WIDTH*y+left);

xms.length=byteperpixel*((right-left+1));

xms.source_handle=0;

xms.source.part[0]=FP_OFF(pixel);

xms.source.part[1]=FP_SEG(pixel);

xms.target_handle=handle;

move_xms(&xms);

free(pixel);

}

 

 void line(int x1,int y1,int x2,int y2,

     unsigned char red,unsigned char green,

     unsigned char blue)

  {

   int e,i,x,y,dx,dy,incx,incy;

   x=x1;y=y1;

   dx=abs(x2-x1);dy=abs(y2-y1);

   if(x1<=x2)    incx=1;

   else         incx=-1;

   if(y1<=y2)    incy=1;

   else         incy=-1;

   if(dx>dy)    {

     e=2*dy-dx;

     for(i=0;i<=dx;i++)      {

       putpixel(x,y,red,green,blue);

       x=x+incx;

       if(e>=0)    e=e+2*dy-2*dx;

       else     e=e+2*dy;

       if(e>=0)     y=y+incy;

      }

    }

   else    {

     e=2*dx-dy;

     for(i=0;i<=dy;i++)   {

       putpixel(x,y,red,green,blue);

       y=y+incy;

       if(e>=0)    e=e+2*dx-2*dy;

       else       e=e+2*dx;

       if(e>=0)    x=x+incx;

      }

    }

  }

 

 void rectangle(int left,int top,int right,int bottom,

     unsigned char red,unsigned char green,

     unsigned char blue)

  {

   level(left,right,top,red,green,blue);

   line(right,top,right,bottom,red,green,blue);

   level(left,right,bottom,red,green,blue);

   line(left,bottom,left,top,red,green,blue);

  }

 

 void bar(int left,int top,int right,int bottom,

     unsigned char red,unsigned char green,

     unsigned char blue)

  {

   int y;

   for(y=top;y<=bottom;y++)

    level(left,right,y,red,green,blue);

  }

 

 void cleardevice(unsigned char red,

     unsigned char green,unsigned char blue)

  {

   bar(0,0,WIDTH-1,HEIGHT-1,red,green,blue);

  }

 void dashedline(int x1,int y1,int x2,int y2,

     unsigned char red,unsigned char green,

     unsigned char blue)

  {

   int e,i,x,y,dx,dy,incx,incy;

   x=x1;y=y1;

   dx=abs(x2-x1);dy=abs(y2-y1);

   if(x1<=x2)    incx=1;

   else         incx=-1;

   if(y1<=y2)    incy=1;

   else         incy=-1;

   if(dx>dy)   {

     e=2*dy-dx;

     for(i=0;i<=dx;i++)      {

       if(4*(i/4)!=i)

       putpixel(x,y,red,green,blue);

       x=x+incx;

       if(e>=0)    e=e+2*dy-2*dx;

       else    e=e+2*dy;

       if(e>=0)    y=y+incy;

      }

    }

   else   {

     e=2*dx-dy;

     for(i=0;i<=dy;i++)   {

       if(4*(i/4)!=i)

        putpixel(x,y,red,green,blue);

       y=y+incy;

       if(e>=0)    e=e+2*dx-2*dy;

       else     e=e+2*dx;

       if(e>=0)     x=x+incx;

      }

    }

  }

 

float f(float x0,float y0)

 {

  return(sin(x0*y0));

 }

 

void getvertex(int i,int j,int s)

 {

  float x,y;

  x=xmin+(xmax-xmin)*i/N;

  y=ymin+(ymax-ymin)*j/N;

  v[s][0]=ox+dx*j+deltax*i;

  v[s][1]=oy-dy*j+deltay*i-

     height*(f(x,y)-zmin)/(zmax-zmin);

 }

 

void vertex(int x1,int y1,int x2,int y2)

 {

  int e,i,x,y,dx,dy,incx,incy,k;

  if(y1>y2){

  x=x1;y=y1;x1=x2;y1=y2;x2=x;y2=y;

  }

  x=x1;y=y1;

  dx=abs(x2-x1);dy=abs(y2-y1);

  if(x1<=x2)    incx=1;

  else         incx=-1;

  if(y1<=y2)    incy=1;

  else         incy=-1;

  if(dx>dy)    {

    e=2*dy-dx;

    for(i=0;i<dx;i++)  {

      if(e>=0) {

       k=num[y];vx[y][k]=x;num[y]++;

       e=e+2*dy-2*dx;x=x+incx;y=y+incy;

      }

      else   {  

       x=x+incx;   e=e+2*dy;

      }

     }

   }

  else  {

    e=2*dx-dy;

    for(i=0;i<dy;i++)      {

      k=num[y];      vx[y][k]=x;

      num[y]++;      y=y+incy;

      if(e>=0){

       e=e+2*dx-2*dy;x=x+incx;

      }

      else          e=e+2*dx;

     }

   }

 }

 

void drawline(int y,unsigned char red,

    unsigned char green, unsigned char blue)

 {

  int i,x1,x2,x3,x4;

  switch(num[y])  {

case 1:         

  putpixel(vx[y][0],y+vymin,red,green,blue);

  break;

    case 2:

       x1=vx[y][0];x2=vx[y][1];

       vx[y][0]=min(x1,x2);vx[y][1]=max(x1,x2);    

  level(vx[y][0],vx[y][1],y+vymin,red,green,blue);

       break;

    case 3:

           for(i=0;i<4;i++)

            if(v[i][1]==y+vymin){

             vx[y][3]=v[i][0];break;

        }

    case 4:

       x1=min(vx[y][0],vx[y][1]);

       x2=max(vx[y][0],vx[y][1]);

       x3=min(vx[y][2],vx[y][3]);

       x4=max(vx[y][2],vx[y][3]);

       vx[y][0]=min(x1,x3);vx[y][3]=max(x2,x4);

       vx[y][1]=min(max(x1,x3),min(x2,x4));

       vx[y][2]=max(max(x1,x3),min(x2,x4));

   level(vx[y][0],vx[y][1],y+vymin,red,green,blue);

   level(vx[y][2],vx[y][3],y+vymin,red,green,blue);

   }

 }

 

void fill(unsigned char red,

    unsigned char green,unsigned char blue)

 {

  int i,y;

  for(i=0;i<=vymax-vymin;i++)

   num[i]=0;

  for(i=0;i<4;i++)

   vertex(v[i][0],v[i][1]-vymin,v[i+1][0],

         v[i+1][1]-vymin);

  for(y=0;y<(vymax-vymin);y++)

   drawline(y,red,green,blue);

 }

 

void draw3d( )

 {

  int i,j,k;

  float x,y;

  unsigned char red=0,green=0,blue=0;

  dx=width*sin(gama)/N;

  dy=width*cos(gama)/N;

  deltax=length*cos(sita)/N;

  deltay=length*sin(sita)/N;

  for(j=N-1;j>=0;j--){

   y=ymin+(ymax-ymin)*(j+0.5)/N;

   getvertex(N,j,1);

   getvertex(N,j+1,2);

   for(i=N-1;i>=0;i--)    {

     x=xmin+(xmax-xmin)*(i+0.5)/N;

     green=192+63*f(x,y);

     getvertex(i,j,0);

     getvertex(i,j+1,3);

     vymin=v[0][1];vymax=v[0][1];

     for(k=1;k<4;k++)   {

       if(vymin>v[k][1])

       vymin=v[k][1];

       if(vymax<v[k][1])

       vymax=v[k][1];

       }

     v[4][0]=v[0][0];v[4][1]=v[0][1];

     fill(red,green,blue);

     v[1][0]=v[0][0];v[1][1]=v[0][1];

     v[2][0]=v[3][0];v[2][1]=v[3][1];

    }

  }

 }

 

void surface( )

 {

  int i,j,k,vx[8],vy[8],dashed[3]={0,2,7};

  int solid[12]={0,1,2,6,5,1,5,4,0,4,7,6};

  ox=100;oy=320;length=280;

  width=180;height=80;

  xmin=-3;xmax=3;ymin=-3;ymax=3;

  zmin=-1;zmax=1;N=199;

  sita=PI/12;gama=PI/4;

  vx[0]=ox;vy[0]=oy;

  vx[1]=ox+length*cos(sita);

  vy[1]=oy+length*sin(sita);

  vx[2]=vx[1]+width*sin(gama);

  vy[2]=vy[1]-width*cos(gama);

  vx[3]=ox+width*sin(gama);

  vy[3]=oy-width*cos(gama);

  vx[4]=vx[0];vy[4]=vy[0]-height;

  vx[5]=vx[1];vy[5]=vy[1]-height;

  vx[6]=vx[2];vy[6]=vy[2]-height;

  vx[7]=vx[3];vy[7]=vy[3]-height;

  for(i=0;i<3;i++){

   j=dashed[i];

   dashedline(vx[3],vy[3],vx[j],vy[j],255,255,255);

   }

  draw3d( );

  for(i=0;i<11;i++){

    j=solid[i];k=solid[i+1];

    line(vx[j],vy[j],vx[k],vy[k],255,255,255);

   }

}

 

 void getline(int line,unsigned char *pixel)

  {

   xms.target.part[0]=FP_OFF(pixel);

   xms.target.part[1]=FP_SEG(pixel);

   xms.target_handle=0;

   xms.length=byteperpixel*(right-left);

   xms.source_handle=handle;

   xms.source.offset=byteperpixel*((unsigned  

                    long)WIDTH*line+left);

   move_xms(&xms);

  }

 

 void formbmp( )

  {

   int i,line,bmpwidth,bmpheight;

   unsigned char *pixel;

   FILE *fp;

   if((fp=fopen("surface.bmp","wb"))==NULL) {

     printf("Can't write to file %s!\n",

           "surface.bmp");

     exit(1);

    }

  bmpwidth=right-left;bmpheight=bottom-top;

  head.type[0]='B';head.type[1]='M';

  head.size=(long)bmpwidth*bmpheight*3+0x36;

  head.reserved=0;

  head.offset=0x36;

  fwrite(&head,sizeof(head),1,fp);

  bmp.size=0x28;

  bmp.width=bmpwidth;

  bmp.height=bmpheight;

  bmp.plane=1;

  bmp.bitcount=0x18;

  bmp.compression=0;

  bmp.imagesize=(long)bmpwidth*bmpheight*3;

  bmp.xpels=0xece;

  bmp.ypels=0xec4;

  bmp.colorused=0;

  bmp.colorimportant=0;

  fwrite(&bmp,sizeof(bmp),1,fp);

  pixel=malloc(4*bmpwidth*sizeof

             (unsigned char));

   for(line=bottom;line>top;line--)   {

     getline(line,pixel);

     for(i=0;i<bmpwidth;i++)  {

       fputc(pixel[4*i],fp);

       fputc(pixel[4*i+1],fp);

       fputc(pixel[4*i+2],fp);

      }

    }

   fclose(fp);  free(pixel);

  }

 

 main( )

  {

   int size;

   unsigned long offset;

   WIDTH=640;HEIGHT=480;byteperpixel=4;

   left=100;top=100;right=500;bottom=420;

   offset=(unsigned long)byteperpixel

         *WIDTH*HEIGHT;

   size=offset>>10;

   xmsinitial(size+100);

   cleardevice(0,0,0);

   surface( );

   formbmp( );

   free_xms(handle);

   textmode(0x3);

  }

  推荐精品文章

·2024年9月目录 
·2024年8月目录 
·2024年7月目录 
·2024年6月目录 
·2024年5月目录 
·2024年4月目录 
·2024年3月目录 
·2024年2月目录 
·2024年1月目录
·2023年12月目录
·2023年11月目录
·2023年10月目录
·2023年9月目录 
·2023年8月目录 

  联系方式
TEL:010-82561037
Fax: 010-82561614
QQ: 100164630
Mail:gaojian@comprg.com.cn

  友情链接
 
Copyright 2001-2010, www.comprg.com.cn, All Rights Reserved
京ICP备14022230号-1,电话/传真:010-82561037 82561614 ,Mail:gaojian@comprg.com.cn
地址:北京市海淀区远大路20号宝蓝大厦E座704,邮编:100089